Storing DPI and Paper Size information in a JPEG with Java

前端 未结 4 1481
南笙
南笙 2021-01-13 03:13

I have the following code:

ImageIO.write(originalImage, OUTPUT_TYPE, resultOutput);

This is an invocation of the following javax.imag

4条回答
  •  Happy的楠姐
    2021-01-13 04:02

    Luckily, the java image I/O API lets you do just that. It also allows for setting the image metadata in a format-independent way. For example to specify the desired DPI, which was what I wanted to do.

    As it turned out, setting the dpi was less straightforward than expected…

    The java image I/O API is plug-in based, for every file format you wish to use an appropriate plug-in must be available. The API provides the necessary abstractions for writing plug-in neutral code and has a repository of available implementations that you can query at run-time. As of J2SE 6, every JRE has to provide plug-ins for PNG, JPG and BMP file formats (plus some others that I haven’t tried out yet).

    The spec for setting image metadata is the standard (plug-in neutral) metadata format specification. Strangely enough, the spec is an XML schema. That’s right, if you want to set the DPI, you’ll have to do it by building a DOM-tree using IIOMetadataNodes and merge it in with the rest! Sigh..

    Beware that plug-ins can differ in their support for the standard metadata :

    • some don’t support changing the standard metadata
    • some don’t support the standard metadata format at all
    • some don’t support merging your DOM-tree with the current metadata and will silently replace it

    Anyway, the relevant tags when you want to set the DPI are HorizontalPixelSize and VerticalPixelSize :

    
       
       
       
    
       
       
       
    

    Note that the spec clearly states that both have to be expressed in millimeters per dot. How to disregard your own spec, Sun style

    Sun has implemented this metadata spec for their PNG and JPG plug-ins and includes it in their current JDK and JRE distributions. The relevant classes are

    com.sun.imageio.plugins.png.PNGImageWriter
    com.sun.imageio.plugins.jpeg.JPEGImageWriter
    

    You can tell from the com.sun package that they’re not part of the J2SE API, but specific to Sun’s implementation.

    Remember how the spec required millimeters per dot? Well, have a look at the following table to see how Sun actually implemented the spec :

    plug-in          unit                 bug report   date reported
    PNGImageWriter   dots per millimeter  bug 5106305  23 sep 2004
    JPEGImageWriter  decimeter per dot    bug 6359243  05 dec 2005
    

    These bugs have been known for a very long time and their fixes are really simple. Unfortunately, they were given a low priority and haven’t even been evaluated at the time of writing (July 2008). Great. Now what?

    Well, because the workaround is so trivial I decided to stick with the image I/O API. If you give these classes what they want, the bitmaps will come out fine. To ensure that your export code also works on platforms that implement the spec correctly, it must check the actual implementation classes that are being used and compensate for the bugs.

    If you find yourself in a similar situation, make sure your workaround code will be able to cope when the bugs are fixed eventually. More on this in the article 'How bugs in the J2SE api can bite you twice'.

    Oh, and if you use instanceof to check for instances of a buggy class that is not guaranteed to exist on all platforms, be sure to catch NoClassDefFoundError ;)

提交回复
热议问题