I have a requirement to convert a PNG file to PPM file. In the same project, I have used TwelveMonkey extension to convert a PPM to PNG and it results perfectly. But when trying the other way round, it results in error.
The output PPM file will always have height=16 and Width=60, so I also need to figure out a way to scale down the PNG without losing on quality drastically.
Dependencies :
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId>
<version>3.9.3</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.9.3</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-pnm</artifactId>
<version>3.9.3</version>
</dependency>
Code :
public static File convertPngToPPM(File pngFile, String fileName) {
File ppmFile=new File(fileName.concat(".ppm"));
try {
BufferedImage inputImage=ImageIO.read(pngFile);
int imageHeight=inputImage.getHeight()==16 ? inputImage.getHeight() : 16;
int imageWidth=inputImage.getWidth() == 60 ? inputImage.getWidth() : 60;
BufferedImage resizedImage=resizeImage(inputImage, imageWidth, imageHeight);
ImageIO.write(resizedImage, "ppm", ppmFile);
} catch (Exception e){
log.error(e.getMessage());
log.error("Error reading the PPM file");
}
return null;
}
private static BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) {
Image resultingImage = originalImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_SMOOTH);
BufferedImage outputImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
outputImage.getGraphics().drawImage(resultingImage, 0, 0, null);
return outputImage;
}
Error:
2022-11-10 17:42:31.438 ERROR 17389 --- [ XNIO-1 task-1] com.mycompany.utilities.ImageUtilities : Unsupported data type: 3
The error message just prints the exception message out of context, which isn't really that useful. If you instead print the full stack trace, you'll see that it points to a place in the code which says:
// TODO: Support TYPE_INT through conversion, if number of channels is 3 or 4 (TYPE_INT_RGB, TYPE_INT_ARGB)
In other words, BufferedImage.TYPE_INT_RGB
isn't currently supported.
This is easy to fix, just convert your image to TYPE_3BYTE_BGR
instead of TYPE_INT_RGB
, and your code works fine. In resizeImage
:
BufferedImage outputImage =
new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_3BYTE_BGR);
PS: Throwing this exception is not really good behavior from the PNM plugin, as it should instead just report that it doesn't support this input, and ImageIO.write
should return false
. So I think this could be classified as a bug.