in tools/src/main/java/org/apache/pdfbox/tools/ExtractImages.java [338:465]
private void write2file(PDImage pdImage, String prefix, boolean directJPEG,
boolean noColorConvert) throws IOException
{
String suffix = pdImage.getSuffix();
if (suffix == null || "jb2".equals(suffix))
{
suffix = "png";
}
else if ("jpx".equals(suffix))
{
// use jp2 suffix for file because jpx not known by windows
suffix = "jp2";
}
if (hasMasks(pdImage))
{
// TIKA-3040, PDFBOX-4771: can't save ARGB as JPEG
suffix = "png";
}
if (noColorConvert)
{
// We write the raw image if in any way possible.
// But we have no alpha information here.
BufferedImage image = pdImage.getRawImage();
if (image != null)
{
int elements = image.getRaster().getNumDataElements();
suffix = "png";
if (elements > 3)
{
// More than 3 channels: That's likely CMYK. We use tiff here,
// but a TIFF codec must be in the class path for this to work.
suffix = "tiff";
}
try (FileOutputStream imageOutput = new FileOutputStream(prefix + "." + suffix))
{
SYSOUT.println("Writing image: " + prefix + "." + suffix);
ImageIOUtil.writeImage(image, suffix, imageOutput);
imageOutput.flush();
}
return;
}
}
try (FileOutputStream imageOutput = new FileOutputStream(prefix + "." + suffix))
{
SYSOUT.println("Writing image: " + prefix + "." + suffix);
if ("jpg".equals(suffix))
{
String colorSpaceName = pdImage.getColorSpace().getName();
if (directJPEG ||
(PDDeviceGray.INSTANCE.getName().equals(colorSpaceName) ||
PDDeviceRGB.INSTANCE.getName().equals(colorSpaceName)))
{
// RGB or Gray colorspace: get and write the unmodified JPEG stream
InputStream data = pdImage.createInputStream(JPEG);
data.transferTo(imageOutput);
IOUtils.closeQuietly(data);
}
else
{
// for CMYK and other "unusual" colorspaces, the JPEG will be converted
BufferedImage image = pdImage.getImage();
if (image != null)
{
ImageIOUtil.writeImage(image, suffix, imageOutput);
}
}
}
else if ("jp2".equals(suffix))
{
String colorSpaceName = pdImage.getColorSpace().getName();
if (directJPEG
|| (PDDeviceGray.INSTANCE.getName().equals(colorSpaceName)
|| PDDeviceRGB.INSTANCE.getName().equals(colorSpaceName)))
{
// RGB or Gray colorspace: get and write the unmodified JPEG2000 stream
InputStream data = pdImage.createInputStream(
Collections.singletonList(COSName.JPX_DECODE.getName()));
data.transferTo(imageOutput);
IOUtils.closeQuietly(data);
}
else
{
// for CMYK and other "unusual" colorspaces, the image will be converted
BufferedImage image = pdImage.getImage();
if (image != null)
{
ImageIOUtil.writeImage(image, "jpeg2000", imageOutput);
}
}
}
else if ("tiff".equals(suffix) && pdImage.getColorSpace().equals(PDDeviceGray.INSTANCE))
{
BufferedImage image = pdImage.getImage();
if (image == null)
{
return;
}
// CCITT compressed images can have a different colorspace, but this one is B/W
// This is a bitonal image, so copy to TYPE_BYTE_BINARY
// so that a G4 compressed TIFF image is created by ImageIOUtil.writeImage()
int w = image.getWidth();
int h = image.getHeight();
BufferedImage bitonalImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);
// copy image the old-fashioned way - ColorConvertOp is slower!
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
bitonalImage.setRGB(x, y, image.getRGB(x, y));
}
}
ImageIOUtil.writeImage(bitonalImage, suffix, imageOutput);
}
else
{
BufferedImage image = pdImage.getImage();
if (image != null)
{
ImageIOUtil.writeImage(image, suffix, imageOutput);
}
}
imageOutput.flush();
}
}