private AFPDataObjectInfo encodeImage()

in fop-core/src/main/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java [276:395]


        private AFPDataObjectInfo encodeImage(
            AFPImageObjectInfo imageObjectInfo,
             AFPPaintingState paintingState)
                throws IOException {

            RenderedImage renderedImage = imageRendered.getRenderedImage();
            FunctionSet functionSet = useFS10 ? FunctionSet.FS10 : FunctionSet.FS11;

            if (usePageSegments) {
                assert resampledDim != null;
                //Resize, optionally resample and convert image

                imageObjectInfo.setCreatePageSegment(true);

                float ditheringQuality = paintingState.getDitheringQuality();
                if (this.resample) {
                    if (log.isDebugEnabled()) {
                        log.debug("Resample from " + intrinsicSize.getDimensionPx()
                                + " to " + resampledDim);
                    }
                    renderedImage = BitmapImageUtil.convertToMonochrome(renderedImage,
                            resampledDim, ditheringQuality);
                } else if (ditheringQuality >= 0.5f) {
                    renderedImage = BitmapImageUtil.convertToMonochrome(renderedImage,
                            intrinsicSize.getDimensionPx(), ditheringQuality);
                }
            }

            imageObjectInfo.setUseIocaImages(paintingState.isUseIocaImages());

            //TODO To reduce AFP file size, investigate using a compression scheme.
            //Currently, all image data is uncompressed.
            ColorModel cm = renderedImage.getColorModel();
            if (log.isTraceEnabled()) {
                log.trace("ColorModel: " + cm);
            }
            int pixelSize = cm.getPixelSize();
            if (cm.hasAlpha()) {
                pixelSize -= 8;
            }

            byte[] imageData = null;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            boolean allowDirectEncoding = true;
            if (allowDirectEncoding && (pixelSize <= maxPixelSize)) {
                //Attempt to encode without resampling the image
                ImageEncodingHelper helper = new ImageEncodingHelper(renderedImage,
                        pixelSize == 32);
                ColorModel encodedColorModel = helper.getEncodedColorModel();
                boolean directEncode = true;
                if (helper.getEncodedColorModel().getPixelSize() > maxPixelSize) {
                    directEncode = false; //pixel size needs to be reduced
                }
                if (BitmapImageUtil.getColorIndexSize(renderedImage) > 2) {
                    directEncode = false; //Lookup tables are not implemented, yet
                }
                if (useFS10
                        && BitmapImageUtil.isMonochromeImage(renderedImage)
                        && BitmapImageUtil.isZeroBlack(renderedImage)) {
                    directEncode = false;
                    //need a special method to invert the bit-stream since setting the
                    //subtractive mode in AFP alone doesn't seem to do the trick.
                    if (encodeInvertedBilevel(helper, imageObjectInfo, baos)) {
                        imageData = baos.toByteArray();
                    }
                }
                if (directEncode) {
                    log.debug("Encoding image directly...");
                    imageObjectInfo.setBitsPerPixel(encodedColorModel.getPixelSize());
                    if (pixelSize == 32) {
                        functionSet = FunctionSet.FS45; //IOCA FS45 required for CMYK
                    }

                    //Lossy or loss-less?
                    if (!paintingState.canEmbedJpeg()
                            && paintingState.getBitmapEncodingQuality() < 1.0f) {
                        try {
                            if (log.isDebugEnabled()) {
                                log.debug("Encoding using baseline DCT (JPEG, q="
                                        + paintingState.getBitmapEncodingQuality() + ")...");
                            }
                            encodeToBaselineDCT(renderedImage,
                                    paintingState.getBitmapEncodingQuality(),
                                    paintingState.getResolution(),
                                    baos);
                            imageObjectInfo.setCompression(ImageContent.COMPID_JPEG);

                            if (!paintingState.isUseIocaImages()) {
                                imageObjectInfo.setMimeType("image/jpeg");
                            }
                        } catch (IOException ioe) {
                            //Some JPEG codecs cannot encode CMYK
                            helper.encode(baos);
                        }
                    } else {
                        helper.encode(baos);
                    }
                    imageData = baos.toByteArray();
                }
            }
            if (imageData == null) {
                log.debug("Encoding image via RGB...");
                imageData = encodeViaRGB(renderedImage, imageObjectInfo, paintingState, baos);
            }
            // Should image be FS45?
            if (paintingState.getFS45()) {
                functionSet = FunctionSet.FS45;
            }
            //Wrapping 300+ resolution FS11 IOCA in a page segment is apparently necessary(?)
            imageObjectInfo.setCreatePageSegment(
                    (functionSet.equals(FunctionSet.FS11) || functionSet.equals(FunctionSet.FS45))
                    && paintingState.getWrapPSeg()
            );
            if (imageObjectInfo.getMimeType() == null) {
                imageObjectInfo.setMimeType(functionSet.getMimeType());
            }

            imageObjectInfo.setData(imageData);
            return imageObjectInfo;
        }