1

I am cropping the image by using the java buffered image. The problem is the cropped image is losing quality in terms of DPI. Say, for example, If the parent image has DPI of 200, the cropped image DPI is reduced to 96. Because of this, I am losing OCR accuracy.

Following is the code snippet I am using get the cropped Buffered Image.

BufferedImage cropImage( BufferedImage image, final int[] topLeft, int width, int height )
{
    int x = Math.max( topLeft[CoOrdinate.X.getValue()], image.getMinX() );
    int y = Math.max( topLeft[CoOrdinate.Y.getValue()], image.getMinY() );

    int imageWidth = image.getWidth();
    int imageHeight = image.getHeight();

    width = ( x + width ) > imageWidth ? imageWidth - x : width;
    height = ( y + height ) > imageHeight ? imageHeight - y : height;

    return image.getSubimage( x, y, width, height );
}

Then I save it using ImageIO

 File saveImage( String filePath, BufferedImage image )
{
    String formatName = FilenameUtils.getExtension( filePath );
    File croppedFile = new File( filePath );
    try {
        ImageIO.write( image, formatName,croppedFile );
        return croppedFile;
    } catch ( IOException e ) {
        LOG.error( "IO Exception occured while saving a buffered image" );
        throw new FileHandlingException( "IO Exception occured while saving a buffered image", e );
    }
}

How can I crop the image without losing DPI quality? I saw many solutions for Image Resizing and I understand resizing will lose quality. But cropping, preserving the DPI should be straightforward right?

EDIT:

ImageMagick's crop does exactly what I need. but I will have to use command line from java. Not an option for me right now.

Arun Gowda
  • 2,721
  • 5
  • 29
  • 50
  • 2
    DPI means “dots per inch” and requires an area whose size can be expressed in inch. A `BufferedImage` has no such area, hence, has no DPI at all. It’s just a raster of pixels. Some image formats store a DPI number in their meta information, which may affect the default size for rendering an image to a physical media, however, as soon as you choose the physical size yourself, the stored DPI number becomes meaningless, as the actual resolution is the quotient of pixel size and physical media size. – Holger Nov 06 '18 at 07:50
  • So what is the alternative if I have to do it in java? Is there any alternative for the buffered image? – Arun Gowda Nov 06 '18 at 09:31
  • 1
    Als @Holger already stated, the DPI are metadata stating how large the effective image should be in respect to it's actual raster dimensions. You can set and save the DPI information as follows: https://stackoverflow.com/questions/321736/how-to-set-dpi-information-in-an-image – Peter Walser Nov 06 '18 at 09:49
  • The ImageIO API has a class `IIOImage` that contains *both* the image data and the meta data. You can obtain it from the `ImageReader.readAll(...)` method, and pass it to the corresponding `ImageWriter.write(...)` method after you cropped the image data. – Harald K Nov 06 '18 at 13:21
  • @PeterWalser Do you mean the DPI being displayed is not actually the real DPI? like the cropped image internally has DPI of 200, same as parent image and it is just adulterated in the metadata? – Arun Gowda Nov 07 '18 at 13:53
  • If you scan an image, you get a bitmap, which is 2-dimensional array of pixels. This bitmap however contains no relation to the original size of the image, that's why you supplement the DPI. When scanning, the DPI tell the pixel density used to synthesize the bitmap. When adding the image to a document, the DPI serve as a hint on how large (in inches) the image is supposed to be, thus properly reconstructing the image dimension of the orignial. – Peter Walser Nov 07 '18 at 14:35

0 Answers0