PDImageXObject encode()

in pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactory.java [343:500]


        PDImageXObject encode() throws IOException
        {
            Raster imageRaster = image.getRaster();
            final int elementsInRowPerPixel;

            // These variables store a row of the image each, the exact type depends
            // on the image encoding. Can be a int[], short[] or byte[]
            Object prevRow;
            Object transferRow;

            switch (imageType)
            {
                case BufferedImage.TYPE_CUSTOM:
                    switch (imageRaster.getTransferType())
                    {
                        case DataBuffer.TYPE_USHORT:
                            elementsInRowPerPixel = componentsPerPixel;
                            prevRow = new short[width * elementsInRowPerPixel];
                            transferRow = new short[width * elementsInRowPerPixel];
                            break;
                        case DataBuffer.TYPE_BYTE:
                            elementsInRowPerPixel = componentsPerPixel;
                            prevRow = new byte[width * elementsInRowPerPixel];
                            transferRow = new byte[width * elementsInRowPerPixel];
                            break;
                        default:
                            return null;
                    }
                    break;

                case BufferedImage.TYPE_3BYTE_BGR:
                case BufferedImage.TYPE_4BYTE_ABGR:
                    elementsInRowPerPixel = componentsPerPixel;
                    prevRow = new byte[width * elementsInRowPerPixel];
                    transferRow = new byte[width * elementsInRowPerPixel];
                    break;

                case BufferedImage.TYPE_INT_BGR:
                case BufferedImage.TYPE_INT_ARGB:
                case BufferedImage.TYPE_INT_RGB:
                    elementsInRowPerPixel = 1;
                    prevRow = new int[width * elementsInRowPerPixel];
                    transferRow = new int[width * elementsInRowPerPixel];
                    break;

                default:
                    // We can not handle this unknown format
                    return null;
            }

            final int elementsInTransferRow = width * elementsInRowPerPixel;

            // pre-size the output stream to half of the maximum size
            ByteArrayOutputStream stream = new ByteArrayOutputStream(
                    height * width * bytesPerPixel / 2);
            Deflater deflater = new Deflater(Filter.getCompressionLevel());
            DeflaterOutputStream zip = new DeflaterOutputStream(stream, deflater);

            int alphaPtr = 0;

            for (int rowNum = 0; rowNum < height; rowNum++)
            {
                imageRaster.getDataElements(0, rowNum, width, 1, transferRow);

                // We start to write at index one, as the predictor marker is in index zero
                int writerPtr = 1;
                Arrays.fill(aValues, (byte) 0);
                Arrays.fill(cValues, (byte) 0);

                final byte[] transferRowByte;
                final byte[] prevRowByte;
                final int[] transferRowInt;
                final int[] prevRowInt;
                final short[] transferRowShort;
                final short[] prevRowShort;

                if (transferRow instanceof byte[])
                {
                    transferRowByte = (byte[]) transferRow;
                    prevRowByte = (byte[]) prevRow;
                    transferRowInt = prevRowInt = null;
                    transferRowShort = prevRowShort = null;
                }
                else if (transferRow instanceof int[])
                {
                    transferRowInt = (int[]) transferRow;
                    prevRowInt = (int[]) prevRow;
                    transferRowShort = prevRowShort = null;
                    transferRowByte = prevRowByte = null;
                }
                else
                {
                    // This must be short[]
                    transferRowShort = (short[]) transferRow;
                    prevRowShort = (short[]) prevRow;
                    transferRowInt = prevRowInt = null;
                    transferRowByte = prevRowByte = null;
                }

                for (int indexInTransferRow = 0; indexInTransferRow < elementsInTransferRow;
                        indexInTransferRow += elementsInRowPerPixel, alphaPtr += bytesPerComponent)
                {
                    // Copy the pixel values into the byte array
                    if (transferRowByte != null)
                    {
                        copyImageBytes(transferRowByte, indexInTransferRow, xValues, alphaImageData,
                                alphaPtr);
                        copyImageBytes(prevRowByte, indexInTransferRow, bValues, null, 0);
                    }
                    else if (transferRowInt != null)
                    {
                        copyIntToBytes(transferRowInt, indexInTransferRow, xValues, alphaImageData,
                                alphaPtr);
                        copyIntToBytes(prevRowInt, indexInTransferRow, bValues, null, 0);
                    }
                    else
                    {
                        // This must be short[]
                        copyShortsToBytes(transferRowShort, indexInTransferRow, xValues, alphaImageData, alphaPtr);
                        copyShortsToBytes(prevRowShort, indexInTransferRow, bValues, null, 0);
                    }

                    // Encode the pixel values in the different encodings
                    int length = xValues.length;
                    for (int bytePtr = 0; bytePtr < length; bytePtr++)
                    {
                        int x = xValues[bytePtr] & 0xFF;
                        int a = aValues[bytePtr] & 0xFF;
                        int b = bValues[bytePtr] & 0xFF;
                        int c = cValues[bytePtr] & 0xFF;
                        dataRawRowNone[writerPtr] = (byte) x;
                        dataRawRowSub[writerPtr] = pngFilterSub(x, a);
                        dataRawRowUp[writerPtr] = pngFilterUp(x, b);
                        dataRawRowAverage[writerPtr] = pngFilterAverage(x, a, b);
                        dataRawRowPaeth[writerPtr] = pngFilterPaeth(x, a, b, c);
                        writerPtr++;
                    }

                    //  We shift the values into the prev / upper left values for the next pixel
                    System.arraycopy(xValues, 0, aValues, 0, bytesPerPixel);
                    System.arraycopy(bValues, 0, cValues, 0, bytesPerPixel);
                }

                byte[] rowToWrite = chooseDataRowToWrite();

                // Write and compress the row as long it is hot (CPU cache wise)
                zip.write(rowToWrite, 0, rowToWrite.length);

                // We swap prev and transfer row, so that we have the prev row for the next row.
                Object temp = prevRow;
                prevRow = transferRow;
                transferRow = temp;
            }
            zip.close();
            deflater.end();

            return preparePredictorPDImage(stream, bytesPerComponent * 8);
        }