public void writeImage()

in src/main/java/org/apache/commons/imaging/formats/pcx/PcxWriter.java [52:174]


    public void writeImage(final BufferedImage src, final OutputStream os) throws IOException {
        final PaletteFactory paletteFactory = new PaletteFactory();
        final SimplePalette palette = paletteFactory.makeExactRgbPaletteSimple(src, 256);
        @SuppressWarnings("resource") // Caller closes 'os'.
        final AbstractBinaryOutputStream bos = AbstractBinaryOutputStream.littleEndian(os);
        final int bitDepth;
        final int planes;
        if (palette == null || bitDepthWanted == 24 || bitDepthWanted == 32) {
            if (bitDepthWanted == 32) {
                bitDepth = 32;
                planes = 1;
            } else {
                bitDepth = 8;
                planes = 3;
            }
        } else if (palette.length() > 16 || bitDepthWanted == 8) {
            bitDepth = 8;
            planes = 1;
        } else if (palette.length() > 8 || bitDepthWanted == 4) {
            if (planesWanted == 1) {
                bitDepth = 4;
                planes = 1;
            } else {
                bitDepth = 1;
                planes = 4;
            }
        } else if (palette.length() > 4 || bitDepthWanted == 3) {
            bitDepth = 1;
            planes = 3;
        } else if (palette.length() > 2 || bitDepthWanted == 2) {
            if (planesWanted == 2) {
                bitDepth = 1;
                planes = 2;
            } else {
                bitDepth = 2;
                planes = 1;
            }
        } else {
            boolean onlyBlackAndWhite = true;
            if (palette.length() >= 1) {
                final int rgb = palette.getEntry(0);
                if (rgb != 0 && rgb != 0xffffff) {
                    onlyBlackAndWhite = false;
                }
            }
            if (palette.length() == 2) {
                final int rgb = palette.getEntry(1);
                if (rgb != 0 && rgb != 0xffffff) {
                    onlyBlackAndWhite = false;
                }
            }
            if (onlyBlackAndWhite) {
                bitDepth = 1;
                planes = 1;
            } else {
                bitDepth = 1;
                planes = 2;
            }
        }

        int bytesPerLine = (bitDepth * src.getWidth() + 7) / 8;
        if (bytesPerLine % 2 != 0) {
            // must be even:
            bytesPerLine++;
        }

        final byte[] palette16 = new byte[16 * 3];
        // TODO What's the right thing to do here for a null palette?
        final int paletteLen = palette != null ? palette.length() : 0;
        for (int i = 0; i < 16; i++) {
            final int rgb;
            if (i < paletteLen) {
                rgb = palette.getEntry(i);
            } else {
                rgb = 0;
            }
            palette16[3 * i + 0] = (byte) (0xff & rgb >> 16);
            palette16[3 * i + 1] = (byte) (0xff & rgb >> 8);
            palette16[3 * i + 2] = (byte) (0xff & rgb);
        }

        // PCX header
        bos.write(10); // manufacturer
        bos.write(bitDepth == 1 && planes == 1 ? 3 : 5); // version. Some apps only open black and white PCX with version=3.
        bos.write(encoding); // encoding
        bos.write(bitDepth); // bits per pixel
        bos.write2Bytes(0); // xMin
        bos.write2Bytes(0); // yMin
        bos.write2Bytes(src.getWidth() - 1); // xMax
        bos.write2Bytes(src.getHeight() - 1); // yMax
        bos.write2Bytes((short) Math.round(pixelDensity.horizontalDensityInches())); // hDpi
        bos.write2Bytes((short) Math.round(pixelDensity.verticalDensityInches())); // vDpi
        bos.write(palette16); // 16 color palette
        bos.write(0); // reserved
        bos.write(planes); // planes
        bos.write2Bytes(bytesPerLine); // bytes per line
        bos.write2Bytes(1); // palette info
        bos.write2Bytes(0); // hScreenSize
        bos.write2Bytes(0); // vScreenSize
        bos.write(new byte[54]);

        if (bitDepth == 32) {
            writePixels32(src, bytesPerLine, bos);
        } else {
            writePixels(src, bitDepth, planes, bytesPerLine, palette, bos);
        }

        if (bitDepth == 8 && planes == 1) {
            // 256 color palette
            bos.write(12);
            for (int i = 0; i < 256; i++) {
                final int rgb;
                if (i < palette.length()) {
                    rgb = palette.getEntry(i);
                } else {
                    rgb = 0;
                }
                bos.write(rgb >> 16 & 0xff);
                bos.write(rgb >> 8 & 0xff);
                bos.write(rgb & 0xff);
            }
        }
    }