如何在java中将.jpeg图像转换为.jif? (Exif TO JFIF)

时间:2015-03-13 09:17:29

标签: java type-conversion jpeg

我要求客户以.JIF格式(JFIF)发送图像。我有java应用程序,但我不能google anithing如何转换为该图像类型的主题,我甚至可以很难google anithing to" .JIF"格式化本身。

已编辑: 有人可以建议如何在java中将Exif图像转换为JFIF吗?以及如何为此JFIF图像添加coments? (试图使用jheader库遗憾地以nullpointer异常结束,在google上没有更多的选择。)

2 个答案:

答案 0 :(得分:1)

首先,您需要阅读该图像,然后您必须将该图像写入您想要的尺寸和格式。 您必须使用 ImageIO 类和 BufferedReader 来读取图像 要编写它们,请使用 Graphics2D 类 将格式名称替换为 jif

 File inputFile = new File(inputImagePath);
    BufferedImage inputImage = ImageIO.read(inputFile);

    // creates output image
    BufferedImage outputImage = new BufferedImage(scaledWidth,
            scaledHeight, inputImage.getType());

    // scales the input image to the output image
    Graphics2D g2d = outputImage.createGraphics();
    g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);
    g2d.dispose();

    // extracts extension of output file
    String formatName = outputImagePath.substring(outputImagePath
            .lastIndexOf(".") + 1);

    // writes to output file
    ImageIO.write(outputImage, formatName, new File(outputImagePath));

答案 1 :(得分:1)

编辑:将Exif JPEG转换为JFIF JPEG:

如果您不介意失去一些质量(由于有损JPEG重新编码),您可以将图像转换为:

File inFile = ...;
File outFile = ...; // Feel free to use ".jif" as extension

if (!ImageIO.write(ImageIO.read(inFile), "JPEG", outFile)) {
    System.err.println("Could not write JPEG format"); // Should never happen
}

这样可行,因为默认的JPEGImageWriter插件仅支持JFIF格式。而且因为我们没有阅读元数据,旧的Exif信息就会丢失。但是,这样做不会允许您添加注释。

要添加注释,您仍然可以使用标准的ImageIO API,但我们必须访问元数据,使代码更加冗长。有关元数据格式的更多信息,请参阅JPEG Metadata Format Specification。如果您需要转换Exif元数据中的注释,请更新您的问题,因为它需要进一步解析元数据和当前不在ImageIO API中的额外支持。

File inFile = ...;
File outFile = ...; // Feel free to use ".jif" as extension

    BufferedImage image = ImageIO.read(inFile);

    ImageWriter jpegWriter = ImageIO.getImageWritersByFormatName("JPEG").next(); // Should be a least one

    // To write comments, we need to add it to the metadata
    ImageWriteParam param = jpegWriter.getDefaultWriteParam();
    IIOMetadata metadata = jpegWriter.getDefaultImageMetadata(ImageTypeSpecifier.createFromRenderedImage(image), param);
    IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree("javax_imageio_jpeg_image_1.0");
    IIOMetadataNode markerSequence = (IIOMetadataNode) root.getElementsByTagName("markerSequence").item(0); // Should be only one

    // Insert a "COM" marker, with our comment
    IIOMetadataNode com = new IIOMetadataNode("com");
    com.setAttribute("comment", "Hello JFIF!");
    markerSequence.appendChild(com);

    // Merge edited metadata 
    metadata.mergeTree("javax_imageio_jpeg_image_1.0", root);

    ImageOutputStream output = ImageIO.createImageOutputStream(outFile);
    try {
        jpegWriter.setOutput(output);

        // Write image along with metadata
        jpegWriter.write(new IIOImage(image, null, metadata));
    }
    finally {
        output.close();
    }

    jpegWriter.dispose();

这样,我们仍然会在有损JPEG中重新编码图像,但我们将从Exif转换为JFIF并添加注释。

现在,还有另一种选择,完全无损。但它确实需要对JIF段结构有更深入的了解,以及Exif和JFIF格式如何工作。不幸的是,没有标准的Java API(我知道)这样做,所以你必须自己动手。随意使用我的JPEG segment parsing code作为起点。您链接的JHeader项目看起来非常有前景,但我对此库没有任何经验,因此我无法在那里提供任何建议。

以下是基本想法:

  1. 解析/跳过标记段,直到SOS(扫描开始)段(SOS后面的数据为压缩图像数据)。
  2. 写SOI标记(0xffd8
  3. 创建一个APP0 /" JFIF"标记(我想你可以在这里使用默认值,详见JFIF segment)。您可以为拇指尺寸编写0,0,并跳过编写缩略图数据。
  4. 使用您需要的任何评论添加您的COM片段(可能从Exif元数据中提取)
  5. 从原始流中按原样编写SOF,DHT,DQT等标准段(跳过APP1 /" Exif"以及其他"自定义"段)。
  6. 写入SOS标记和原始流中的图像数据
  7. 从理论上讲,这应该有效。您可能会遇到一些较小的色彩空间问题,因为Exif数据可能包含不同的色彩空间(通常为sRGB或AdobeRGB1998),而JFIF doesn't have a defined color space。如果需要,可以添加APP2 /" ICC_PROFILE"具有所需配置文件的段(在步骤3之后)。

    祝你好运! : - )


    注意:这不是一个完整的答案,而是试图澄清为什么你需要与你的客户交谈,并弄清楚你的JPEG有什么问题以及他实际意味着什么" JIF"

    首先, JPEG不是文件格式JPEG是静止图像压缩标准。该标准的一部分(通常称为"附件B")是交换格式的描述,有时称为JIF。该标准还指定了一种称为SPIFF的完整文件格式,但这种格式并不是很普遍(我不认为这是你想要的)。

    您到处找到的文件,称为" JPEG文件" (我认为这就是你所说的" Classic JPEG"),通常是两种略有不同的基本相同的文件格式之一:

    最基本的格式是JFIF。这种格式以SOI标记开始,紧接着是带有" JFIF"的APP0标记。 (以null结尾)作为其标识符。根据{{​​3}}" JPEG文件交换格式与标准JPEG交换格式完全兼容; 唯一的附加要求是在SOI之后强制存在APP0标记。标记#&34; (此部分不在规范的original JFIF specification和ISO版本中,但仍然适用)。简而言之,JFIF将JPEG数据约束为1或3个分量,编码为Y或YCbCr,并强烈推荐基线DCT,霍夫曼编码压缩。

    另一种常见格式是ITU。这种格式以SOI标记开始,紧接着是带有" Exif"的APP1标记。 (以null结尾)作为其标识符。这种格式由数码相机制造商开发,并允许在文件中记录更丰富的元数据(以TIFF元数据结构的形式)。根据我的理解,Exif将JPEG数据限制为3个组件,编码为YCbCr,使用基线DCT,霍夫曼编码压缩(最后一部分可能只是一个互操作性推荐,规范中的语言有点难以阅读。 ..)。

    这两种格式都包含相同的"段"布局和图像数据是兼容的,但由于要求他们的"标记作为流中的第一个段(因此,还存在"第三个"格式,这是兼容性的JFIF,但仍包含用于更丰富的元数据的Exif段)。

    另一个" JPEG文件系列"缺少JFIF和Exif标记,但仍遵循相同的分段布局,SOI,APPn标记,SOF,DHT,DQT,SOS和EOI标记,如附录B" (JIF)。大多数解码器也会对这些图像进行解码。

    TL; DR:总结一下,所有" JPEG"文件格式有一个共同点,就是它们使用JPEG压缩,并遵循JIF结构。因此,通过将经典JPEG转换为JIF"

    ,有点难以理解某人的意思。

    " Classic JPEG" JIF。