Search in sources :

Example 16 with SampleModel

use of java.awt.image.SampleModel in project jdk8u_jdk by JetBrains.

the class PNGImageWriterSpi method canEncodeImage.

public boolean canEncodeImage(ImageTypeSpecifier type) {
    SampleModel sampleModel = type.getSampleModel();
    ColorModel colorModel = type.getColorModel();
    // Find the maximum bit depth across all channels
    int[] sampleSize = sampleModel.getSampleSize();
    int bitDepth = sampleSize[0];
    for (int i = 1; i < sampleSize.length; i++) {
        if (sampleSize[i] > bitDepth) {
            bitDepth = sampleSize[i];
        }
    }
    // Ensure bitDepth is between 1 and 16
    if (bitDepth < 1 || bitDepth > 16) {
        return false;
    }
    // Check number of bands, alpha
    int numBands = sampleModel.getNumBands();
    if (numBands < 1 || numBands > 4) {
        return false;
    }
    boolean hasAlpha = colorModel.hasAlpha();
    // the check below to fail and return false.
    if (colorModel instanceof IndexColorModel) {
        return true;
    }
    if ((numBands == 1 || numBands == 3) && hasAlpha) {
        return false;
    }
    if ((numBands == 2 || numBands == 4) && !hasAlpha) {
        return false;
    }
    return true;
}
Also used : SampleModel(java.awt.image.SampleModel) ColorModel(java.awt.image.ColorModel) IndexColorModel(java.awt.image.IndexColorModel) IndexColorModel(java.awt.image.IndexColorModel)

Example 17 with SampleModel

use of java.awt.image.SampleModel in project jdk8u_jdk by JetBrains.

the class PNGMetadata method initialize.

/**
     * Sets the IHDR_bitDepth and IHDR_colorType variables.
     * The <code>numBands</code> parameter is necessary since
     * we may only be writing a subset of the image bands.
     */
public void initialize(ImageTypeSpecifier imageType, int numBands) {
    ColorModel colorModel = imageType.getColorModel();
    SampleModel sampleModel = imageType.getSampleModel();
    // Initialize IHDR_bitDepth
    int[] sampleSize = sampleModel.getSampleSize();
    int bitDepth = sampleSize[0];
    // Fixes bug 4413109
    for (int i = 1; i < sampleSize.length; i++) {
        if (sampleSize[i] > bitDepth) {
            bitDepth = sampleSize[i];
        }
    }
    // Multi-channel images must have a bit depth of 8 or 16
    if (sampleSize.length > 1 && bitDepth < 8) {
        bitDepth = 8;
    }
    // Round bit depth up to a power of 2
    if (bitDepth > 2 && bitDepth < 4) {
        bitDepth = 4;
    } else if (bitDepth > 4 && bitDepth < 8) {
        bitDepth = 8;
    } else if (bitDepth > 8 && bitDepth < 16) {
        bitDepth = 16;
    } else if (bitDepth > 16) {
        throw new RuntimeException("bitDepth > 16!");
    }
    IHDR_bitDepth = bitDepth;
    // Initialize IHDR_colorType
    if (colorModel instanceof IndexColorModel) {
        IndexColorModel icm = (IndexColorModel) colorModel;
        int size = icm.getMapSize();
        byte[] reds = new byte[size];
        icm.getReds(reds);
        byte[] greens = new byte[size];
        icm.getGreens(greens);
        byte[] blues = new byte[size];
        icm.getBlues(blues);
        // Determine whether the color tables are actually a gray ramp
        // if the color type has not been set previously
        boolean isGray = false;
        if (!IHDR_present || (IHDR_colorType != PNGImageReader.PNG_COLOR_PALETTE)) {
            isGray = true;
            int scale = 255 / ((1 << IHDR_bitDepth) - 1);
            for (int i = 0; i < size; i++) {
                byte red = reds[i];
                if ((red != (byte) (i * scale)) || (red != greens[i]) || (red != blues[i])) {
                    isGray = false;
                    break;
                }
            }
        }
        // Determine whether transparency exists
        boolean hasAlpha = colorModel.hasAlpha();
        byte[] alpha = null;
        if (hasAlpha) {
            alpha = new byte[size];
            icm.getAlphas(alpha);
        }
        if (isGray && hasAlpha && (bitDepth == 8 || bitDepth == 16)) {
            IHDR_colorType = PNGImageReader.PNG_COLOR_GRAY_ALPHA;
        } else if (isGray && !hasAlpha) {
            IHDR_colorType = PNGImageReader.PNG_COLOR_GRAY;
        } else {
            IHDR_colorType = PNGImageReader.PNG_COLOR_PALETTE;
            PLTE_present = true;
            PLTE_order = null;
            PLTE_red = (byte[]) reds.clone();
            PLTE_green = (byte[]) greens.clone();
            PLTE_blue = (byte[]) blues.clone();
            if (hasAlpha) {
                tRNS_present = true;
                tRNS_colorType = PNGImageReader.PNG_COLOR_PALETTE;
                PLTE_order = new int[alpha.length];
                // Reorder the palette so that non-opaque entries
                // come first.  Since the tRNS chunk does not have
                // to store trailing 255's, this can save a
                // considerable amount of space when encoding
                // images with only one transparent pixel value,
                // e.g., images from GIF sources.
                byte[] newAlpha = new byte[alpha.length];
                // Scan for non-opaque entries and assign them
                // positions starting at 0.
                int newIndex = 0;
                for (int i = 0; i < alpha.length; i++) {
                    if (alpha[i] != (byte) 255) {
                        PLTE_order[i] = newIndex;
                        newAlpha[newIndex] = alpha[i];
                        ++newIndex;
                    }
                }
                int numTransparent = newIndex;
                // positions following the non-opaque entries.
                for (int i = 0; i < alpha.length; i++) {
                    if (alpha[i] == (byte) 255) {
                        PLTE_order[i] = newIndex++;
                    }
                }
                // Reorder the palettes
                byte[] oldRed = PLTE_red;
                byte[] oldGreen = PLTE_green;
                byte[] oldBlue = PLTE_blue;
                // All have the same length
                int len = oldRed.length;
                PLTE_red = new byte[len];
                PLTE_green = new byte[len];
                PLTE_blue = new byte[len];
                for (int i = 0; i < len; i++) {
                    PLTE_red[PLTE_order[i]] = oldRed[i];
                    PLTE_green[PLTE_order[i]] = oldGreen[i];
                    PLTE_blue[PLTE_order[i]] = oldBlue[i];
                }
                // Copy only the transparent entries into tRNS_alpha
                tRNS_alpha = new byte[numTransparent];
                System.arraycopy(newAlpha, 0, tRNS_alpha, 0, numTransparent);
            }
        }
    } else {
        if (numBands == 1) {
            IHDR_colorType = PNGImageReader.PNG_COLOR_GRAY;
        } else if (numBands == 2) {
            IHDR_colorType = PNGImageReader.PNG_COLOR_GRAY_ALPHA;
        } else if (numBands == 3) {
            IHDR_colorType = PNGImageReader.PNG_COLOR_RGB;
        } else if (numBands == 4) {
            IHDR_colorType = PNGImageReader.PNG_COLOR_RGB_ALPHA;
        } else {
            throw new RuntimeException("Number of bands not 1-4!");
        }
    }
    IHDR_present = true;
}
Also used : SampleModel(java.awt.image.SampleModel) ColorModel(java.awt.image.ColorModel) IndexColorModel(java.awt.image.IndexColorModel) IndexColorModel(java.awt.image.IndexColorModel)

Example 18 with SampleModel

use of java.awt.image.SampleModel in project jdk8u_jdk by JetBrains.

the class PNGImageWriter method write.

public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IIOException {
    if (stream == null) {
        throw new IllegalStateException("output == null!");
    }
    if (image == null) {
        throw new IllegalArgumentException("image == null!");
    }
    if (image.hasRaster()) {
        throw new UnsupportedOperationException("image has a Raster!");
    }
    RenderedImage im = image.getRenderedImage();
    SampleModel sampleModel = im.getSampleModel();
    this.numBands = sampleModel.getNumBands();
    // Set source region and subsampling to default values
    this.sourceXOffset = im.getMinX();
    this.sourceYOffset = im.getMinY();
    this.sourceWidth = im.getWidth();
    this.sourceHeight = im.getHeight();
    this.sourceBands = null;
    this.periodX = 1;
    this.periodY = 1;
    if (param != null) {
        // Get source region and subsampling factors
        Rectangle sourceRegion = param.getSourceRegion();
        if (sourceRegion != null) {
            Rectangle imageBounds = new Rectangle(im.getMinX(), im.getMinY(), im.getWidth(), im.getHeight());
            // Clip to actual image bounds
            sourceRegion = sourceRegion.intersection(imageBounds);
            sourceXOffset = sourceRegion.x;
            sourceYOffset = sourceRegion.y;
            sourceWidth = sourceRegion.width;
            sourceHeight = sourceRegion.height;
        }
        // Adjust for subsampling offsets
        int gridX = param.getSubsamplingXOffset();
        int gridY = param.getSubsamplingYOffset();
        sourceXOffset += gridX;
        sourceYOffset += gridY;
        sourceWidth -= gridX;
        sourceHeight -= gridY;
        // Get subsampling factors
        periodX = param.getSourceXSubsampling();
        periodY = param.getSourceYSubsampling();
        int[] sBands = param.getSourceBands();
        if (sBands != null) {
            sourceBands = sBands;
            numBands = sourceBands.length;
        }
    }
    // Compute output dimensions
    int destWidth = (sourceWidth + periodX - 1) / periodX;
    int destHeight = (sourceHeight + periodY - 1) / periodY;
    if (destWidth <= 0 || destHeight <= 0) {
        throw new IllegalArgumentException("Empty source region!");
    }
    // Compute total number of pixels for progress notification
    this.totalPixels = destWidth * destHeight;
    this.pixelsDone = 0;
    // Create metadata
    IIOMetadata imd = image.getMetadata();
    if (imd != null) {
        metadata = (PNGMetadata) convertImageMetadata(imd, ImageTypeSpecifier.createFromRenderedImage(im), null);
    } else {
        metadata = new PNGMetadata();
    }
    if (param != null) {
        // Use Adam7 interlacing if set in write param
        switch(param.getProgressiveMode()) {
            case ImageWriteParam.MODE_DEFAULT:
                metadata.IHDR_interlaceMethod = 1;
                break;
            case ImageWriteParam.MODE_DISABLED:
                metadata.IHDR_interlaceMethod = 0;
                break;
        }
    }
    // Initialize bitDepth and colorType
    metadata.initialize(new ImageTypeSpecifier(im), numBands);
    // Overwrite IHDR width and height values with values from image
    metadata.IHDR_width = destWidth;
    metadata.IHDR_height = destHeight;
    this.bpp = numBands * ((metadata.IHDR_bitDepth == 16) ? 2 : 1);
    // Initialize scaling tables for this image
    initializeScaleTables(sampleModel.getSampleSize());
    clearAbortRequest();
    processImageStarted(0);
    try {
        write_magic();
        write_IHDR();
        write_cHRM();
        write_gAMA();
        write_iCCP();
        write_sBIT();
        write_sRGB();
        write_PLTE();
        write_hIST();
        write_tRNS();
        write_bKGD();
        write_pHYs();
        write_sPLT();
        write_tIME();
        write_tEXt();
        write_iTXt();
        write_zTXt();
        writeUnknownChunks();
        write_IDAT(im);
        if (abortRequested()) {
            processWriteAborted();
        } else {
            // Finish up and inform the listeners we are done
            writeIEND();
            processImageComplete();
        }
    } catch (IOException e) {
        throw new IIOException("I/O error writing PNG file!", e);
    }
}
Also used : Rectangle(java.awt.Rectangle) IIOException(javax.imageio.IIOException) IOException(java.io.IOException) IIOException(javax.imageio.IIOException) ImageTypeSpecifier(javax.imageio.ImageTypeSpecifier) IIOMetadata(javax.imageio.metadata.IIOMetadata) SampleModel(java.awt.image.SampleModel) RenderedImage(java.awt.image.RenderedImage)

Example 19 with SampleModel

use of java.awt.image.SampleModel in project jdk8u_jdk by JetBrains.

the class RenderableImageProducer method run.

/**
     * The runnable method for this class. This will produce an image using
     * the current RenderableImage and RenderContext and send it to all the
     * ImageConsumer currently registered with this class.
     */
public void run() {
    // First get the rendered image
    RenderedImage rdrdImage;
    if (rc != null) {
        rdrdImage = rdblImage.createRendering(rc);
    } else {
        rdrdImage = rdblImage.createDefaultRendering();
    }
    // And its ColorModel
    ColorModel colorModel = rdrdImage.getColorModel();
    Raster raster = rdrdImage.getData();
    SampleModel sampleModel = raster.getSampleModel();
    DataBuffer dataBuffer = raster.getDataBuffer();
    if (colorModel == null) {
        colorModel = ColorModel.getRGBdefault();
    }
    int minX = raster.getMinX();
    int minY = raster.getMinY();
    int width = raster.getWidth();
    int height = raster.getHeight();
    Enumeration icList;
    ImageConsumer ic;
    // Set up the ImageConsumers
    icList = ics.elements();
    while (icList.hasMoreElements()) {
        ic = (ImageConsumer) icList.nextElement();
        ic.setDimensions(width, height);
        ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES | ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME);
    }
    // Get RGB pixels from the raster scanline by scanline and
    // send to consumers.
    int[] pix = new int[width];
    int i, j;
    int numBands = sampleModel.getNumBands();
    int[] tmpPixel = new int[numBands];
    for (j = 0; j < height; j++) {
        for (i = 0; i < width; i++) {
            sampleModel.getPixel(i, j, tmpPixel, dataBuffer);
            pix[i] = colorModel.getDataElement(tmpPixel, 0);
        }
        // Now send the scanline to the Consumers
        icList = ics.elements();
        while (icList.hasMoreElements()) {
            ic = (ImageConsumer) icList.nextElement();
            ic.setPixels(0, j, width, 1, colorModel, pix, 0, width);
        }
    }
    // Now tell the consumers we're done.
    icList = ics.elements();
    while (icList.hasMoreElements()) {
        ic = (ImageConsumer) icList.nextElement();
        ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
    }
}
Also used : SampleModel(java.awt.image.SampleModel) Enumeration(java.util.Enumeration) ColorModel(java.awt.image.ColorModel) DirectColorModel(java.awt.image.DirectColorModel) ImageConsumer(java.awt.image.ImageConsumer) Raster(java.awt.image.Raster) RenderedImage(java.awt.image.RenderedImage) DataBuffer(java.awt.image.DataBuffer)

Example 20 with SampleModel

use of java.awt.image.SampleModel in project jdk8u_jdk by JetBrains.

the class BMPImageWriter method write.

public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException {
    if (stream == null) {
        throw new IllegalStateException(I18N.getString("BMPImageWriter7"));
    }
    if (image == null) {
        throw new IllegalArgumentException(I18N.getString("BMPImageWriter8"));
    }
    clearAbortRequest();
    processImageStarted(0);
    if (param == null)
        param = getDefaultWriteParam();
    BMPImageWriteParam bmpParam = (BMPImageWriteParam) param;
    // Default is using 24 bits per pixel.
    int bitsPerPixel = 24;
    boolean isPalette = false;
    int paletteEntries = 0;
    IndexColorModel icm = null;
    RenderedImage input = null;
    Raster inputRaster = null;
    boolean writeRaster = image.hasRaster();
    Rectangle sourceRegion = param.getSourceRegion();
    SampleModel sampleModel = null;
    ColorModel colorModel = null;
    compImageSize = 0;
    if (writeRaster) {
        inputRaster = image.getRaster();
        sampleModel = inputRaster.getSampleModel();
        colorModel = ImageUtil.createColorModel(null, sampleModel);
        if (sourceRegion == null)
            sourceRegion = inputRaster.getBounds();
        else
            sourceRegion = sourceRegion.intersection(inputRaster.getBounds());
    } else {
        input = image.getRenderedImage();
        sampleModel = input.getSampleModel();
        colorModel = input.getColorModel();
        Rectangle rect = new Rectangle(input.getMinX(), input.getMinY(), input.getWidth(), input.getHeight());
        if (sourceRegion == null)
            sourceRegion = rect;
        else
            sourceRegion = sourceRegion.intersection(rect);
    }
    IIOMetadata imageMetadata = image.getMetadata();
    BMPMetadata bmpImageMetadata = null;
    if (imageMetadata != null && imageMetadata instanceof BMPMetadata) {
        bmpImageMetadata = (BMPMetadata) imageMetadata;
    } else {
        ImageTypeSpecifier imageType = new ImageTypeSpecifier(colorModel, sampleModel);
        bmpImageMetadata = (BMPMetadata) getDefaultImageMetadata(imageType, param);
    }
    if (sourceRegion.isEmpty())
        throw new RuntimeException(I18N.getString("BMPImageWrite0"));
    int scaleX = param.getSourceXSubsampling();
    int scaleY = param.getSourceYSubsampling();
    int xOffset = param.getSubsamplingXOffset();
    int yOffset = param.getSubsamplingYOffset();
    // cache the data type;
    int dataType = sampleModel.getDataType();
    sourceRegion.translate(xOffset, yOffset);
    sourceRegion.width -= xOffset;
    sourceRegion.height -= yOffset;
    int minX = sourceRegion.x / scaleX;
    int minY = sourceRegion.y / scaleY;
    w = (sourceRegion.width + scaleX - 1) / scaleX;
    h = (sourceRegion.height + scaleY - 1) / scaleY;
    xOffset = sourceRegion.x % scaleX;
    yOffset = sourceRegion.y % scaleY;
    Rectangle destinationRegion = new Rectangle(minX, minY, w, h);
    boolean noTransform = destinationRegion.equals(sourceRegion);
    // Raw data can only handle bytes, everything greater must be ASCII.
    int[] sourceBands = param.getSourceBands();
    boolean noSubband = true;
    int numBands = sampleModel.getNumBands();
    if (sourceBands != null) {
        sampleModel = sampleModel.createSubsetSampleModel(sourceBands);
        colorModel = null;
        noSubband = false;
        numBands = sampleModel.getNumBands();
    } else {
        sourceBands = new int[numBands];
        for (int i = 0; i < numBands; i++) sourceBands[i] = i;
    }
    int[] bandOffsets = null;
    boolean bgrOrder = true;
    if (sampleModel instanceof ComponentSampleModel) {
        bandOffsets = ((ComponentSampleModel) sampleModel).getBandOffsets();
        if (sampleModel instanceof BandedSampleModel) {
            // for images with BandedSampleModel we can not work
            //  with raster directly and must use writePixels()
            bgrOrder = false;
        } else {
            // In any other case we must use writePixels()
            for (int i = 0; i < bandOffsets.length; i++) {
                bgrOrder &= (bandOffsets[i] == (bandOffsets.length - i - 1));
            }
        }
    } else {
        if (sampleModel instanceof SinglePixelPackedSampleModel) {
            // BugId 4892214: we can not work with raster directly
            // if image have different color order than RGB.
            // We should use writePixels() for such images.
            int[] bitOffsets = ((SinglePixelPackedSampleModel) sampleModel).getBitOffsets();
            for (int i = 0; i < bitOffsets.length - 1; i++) {
                bgrOrder &= bitOffsets[i] > bitOffsets[i + 1];
            }
        }
    }
    if (bandOffsets == null) {
        // we will use getPixels() to extract pixel data for writePixels()
        // Please note that getPixels() provides rgb bands order.
        bandOffsets = new int[numBands];
        for (int i = 0; i < numBands; i++) bandOffsets[i] = i;
    }
    noTransform &= bgrOrder;
    int[] sampleSize = sampleModel.getSampleSize();
    //XXX: check more
    // Number of bytes that a scanline for the image written out will have.
    int destScanlineBytes = w * numBands;
    switch(bmpParam.getCompressionMode()) {
        case ImageWriteParam.MODE_EXPLICIT:
            compressionType = BMPCompressionTypes.getType(bmpParam.getCompressionType());
            break;
        case ImageWriteParam.MODE_COPY_FROM_METADATA:
            compressionType = bmpImageMetadata.compression;
            break;
        case ImageWriteParam.MODE_DEFAULT:
            compressionType = getPreferredCompressionType(colorModel, sampleModel);
            break;
        default:
            // ImageWriteParam.MODE_DISABLED:
            compressionType = BI_RGB;
    }
    if (!canEncodeImage(compressionType, colorModel, sampleModel)) {
        throw new IOException("Image can not be encoded with compression type " + BMPCompressionTypes.getName(compressionType));
    }
    byte[] r = null, g = null, b = null, a = null;
    if (compressionType == BI_BITFIELDS) {
        bitsPerPixel = DataBuffer.getDataTypeSize(sampleModel.getDataType());
        if (bitsPerPixel != 16 && bitsPerPixel != 32) {
            // we should use 32bpp images in case of BI_BITFIELD
            // compression to avoid color conversion artefacts
            bitsPerPixel = 32;
            // Setting this flag to false ensures that generic
            // writePixels() will be used to store image data
            noTransform = false;
        }
        destScanlineBytes = w * bitsPerPixel + 7 >> 3;
        isPalette = true;
        paletteEntries = 3;
        r = new byte[paletteEntries];
        g = new byte[paletteEntries];
        b = new byte[paletteEntries];
        a = new byte[paletteEntries];
        int rmask = 0x00ff0000;
        int gmask = 0x0000ff00;
        int bmask = 0x000000ff;
        if (bitsPerPixel == 16) {
            /* NB: canEncodeImage() ensures we have image of
                 * either USHORT_565_RGB or USHORT_555_RGB type here.
                 * Technically, it should work for other direct color
                 * model types but it might be non compatible with win98
                 * and friends.
                 */
            if (colorModel instanceof DirectColorModel) {
                DirectColorModel dcm = (DirectColorModel) colorModel;
                rmask = dcm.getRedMask();
                gmask = dcm.getGreenMask();
                bmask = dcm.getBlueMask();
            } else {
                // an exception related to unsupported image format
                throw new IOException("Image can not be encoded with " + "compression type " + BMPCompressionTypes.getName(compressionType));
            }
        }
        writeMaskToPalette(rmask, 0, r, g, b, a);
        writeMaskToPalette(gmask, 1, r, g, b, a);
        writeMaskToPalette(bmask, 2, r, g, b, a);
        if (!noTransform) {
            // prepare info for writePixels procedure
            bitMasks = new int[3];
            bitMasks[0] = rmask;
            bitMasks[1] = gmask;
            bitMasks[2] = bmask;
            bitPos = new int[3];
            bitPos[0] = firstLowBit(rmask);
            bitPos[1] = firstLowBit(gmask);
            bitPos[2] = firstLowBit(bmask);
        }
        if (colorModel instanceof IndexColorModel) {
            icm = (IndexColorModel) colorModel;
        }
    } else {
        // handle BI_RGB compression
        if (colorModel instanceof IndexColorModel) {
            isPalette = true;
            icm = (IndexColorModel) colorModel;
            paletteEntries = icm.getMapSize();
            if (paletteEntries <= 2) {
                bitsPerPixel = 1;
                destScanlineBytes = w + 7 >> 3;
            } else if (paletteEntries <= 16) {
                bitsPerPixel = 4;
                destScanlineBytes = w + 1 >> 1;
            } else if (paletteEntries <= 256) {
                bitsPerPixel = 8;
            } else {
                // Cannot be written as a Palette image. So write out as
                // 24 bit image.
                bitsPerPixel = 24;
                isPalette = false;
                paletteEntries = 0;
                destScanlineBytes = w * 3;
            }
            if (isPalette == true) {
                r = new byte[paletteEntries];
                g = new byte[paletteEntries];
                b = new byte[paletteEntries];
                a = new byte[paletteEntries];
                icm.getAlphas(a);
                icm.getReds(r);
                icm.getGreens(g);
                icm.getBlues(b);
            }
        } else {
            // Grey scale images
            if (numBands == 1) {
                isPalette = true;
                paletteEntries = 256;
                bitsPerPixel = sampleSize[0];
                destScanlineBytes = (w * bitsPerPixel + 7 >> 3);
                r = new byte[256];
                g = new byte[256];
                b = new byte[256];
                a = new byte[256];
                for (int i = 0; i < 256; i++) {
                    r[i] = (byte) i;
                    g[i] = (byte) i;
                    b[i] = (byte) i;
                    a[i] = (byte) 255;
                }
            } else {
                if (sampleModel instanceof SinglePixelPackedSampleModel && noSubband) {
                    /* NB: the actual pixel size can be smaller than
                         * size of used DataBuffer element.
                         * For example: in case of TYPE_INT_RGB actual pixel
                         * size is 24 bits, but size of DataBuffere element
                         * is 32 bits
                         */
                    int[] sample_sizes = sampleModel.getSampleSize();
                    bitsPerPixel = 0;
                    for (int size : sample_sizes) {
                        bitsPerPixel += size;
                    }
                    bitsPerPixel = roundBpp(bitsPerPixel);
                    if (bitsPerPixel != DataBuffer.getDataTypeSize(sampleModel.getDataType())) {
                        noTransform = false;
                    }
                    destScanlineBytes = w * bitsPerPixel + 7 >> 3;
                }
            }
        }
    }
    // actual writing of image data
    int fileSize = 0;
    int offset = 0;
    int headerSize = 0;
    int imageSize = 0;
    int xPelsPerMeter = 0;
    int yPelsPerMeter = 0;
    int colorsUsed = 0;
    int colorsImportant = paletteEntries;
    // Calculate padding for each scanline
    int padding = destScanlineBytes % 4;
    if (padding != 0) {
        padding = 4 - padding;
    }
    // FileHeader is 14 bytes, BitmapHeader is 40 bytes,
    // add palette size and that is where the data will begin
    offset = 54 + paletteEntries * 4;
    imageSize = (destScanlineBytes + padding) * h;
    fileSize = imageSize + offset;
    headerSize = 40;
    long headPos = stream.getStreamPosition();
    writeFileHeader(fileSize, offset);
    /* According to MSDN description, the top-down image layout
         * is allowed only if compression type is BI_RGB or BI_BITFIELDS.
         * Images with any other compression type must be wrote in the
         * bottom-up layout.
         */
    if (compressionType == BI_RGB || compressionType == BI_BITFIELDS) {
        isTopDown = bmpParam.isTopDown();
    } else {
        isTopDown = false;
    }
    writeInfoHeader(headerSize, bitsPerPixel);
    // compression
    stream.writeInt(compressionType);
    // imageSize
    stream.writeInt(imageSize);
    // xPelsPerMeter
    stream.writeInt(xPelsPerMeter);
    // yPelsPerMeter
    stream.writeInt(yPelsPerMeter);
    // Colors Used
    stream.writeInt(colorsUsed);
    // Colors Important
    stream.writeInt(colorsImportant);
    // palette
    if (isPalette == true) {
        // write palette
        if (compressionType == BI_BITFIELDS) {
            // write masks for red, green and blue components.
            for (int i = 0; i < 3; i++) {
                int mask = (a[i] & 0xFF) + ((r[i] & 0xFF) * 0x100) + ((g[i] & 0xFF) * 0x10000) + ((b[i] & 0xFF) * 0x1000000);
                stream.writeInt(mask);
            }
        } else {
            for (int i = 0; i < paletteEntries; i++) {
                stream.writeByte(b[i]);
                stream.writeByte(g[i]);
                stream.writeByte(r[i]);
                stream.writeByte(a[i]);
            }
        }
    }
    // Writing of actual image data
    int scanlineBytes = w * numBands;
    // Buffer for up to 8 rows of pixels
    int[] pixels = new int[scanlineBytes * scaleX];
    // Also create a buffer to hold one line of the data
    // to be written to the file, so we can use array writes.
    bpixels = new byte[destScanlineBytes];
    int l;
    if (compressionType == BI_JPEG || compressionType == BI_PNG) {
        // prepare embedded buffer
        embedded_stream = new ByteArrayOutputStream();
        writeEmbedded(image, bmpParam);
        // update the file/image Size
        embedded_stream.flush();
        imageSize = embedded_stream.size();
        long endPos = stream.getStreamPosition();
        fileSize = (int) (offset + imageSize);
        stream.seek(headPos);
        writeSize(fileSize, 2);
        stream.seek(headPos);
        writeSize(imageSize, 34);
        stream.seek(endPos);
        stream.write(embedded_stream.toByteArray());
        embedded_stream = null;
        if (abortRequested()) {
            processWriteAborted();
        } else {
            processImageComplete();
            stream.flushBefore(stream.getStreamPosition());
        }
        return;
    }
    int maxBandOffset = bandOffsets[0];
    for (int i = 1; i < bandOffsets.length; i++) if (bandOffsets[i] > maxBandOffset)
        maxBandOffset = bandOffsets[i];
    int[] pixel = new int[maxBandOffset + 1];
    int destScanlineLength = destScanlineBytes;
    if (noTransform && noSubband) {
        destScanlineLength = destScanlineBytes / (DataBuffer.getDataTypeSize(dataType) >> 3);
    }
    for (int i = 0; i < h; i++) {
        if (abortRequested()) {
            break;
        }
        int row = minY + i;
        if (!isTopDown)
            row = minY + h - i - 1;
        // Get the pixels
        Raster src = inputRaster;
        Rectangle srcRect = new Rectangle(minX * scaleX + xOffset, row * scaleY + yOffset, (w - 1) * scaleX + 1, 1);
        if (!writeRaster)
            src = input.getData(srcRect);
        if (noTransform && noSubband) {
            SampleModel sm = src.getSampleModel();
            int pos = 0;
            int startX = srcRect.x - src.getSampleModelTranslateX();
            int startY = srcRect.y - src.getSampleModelTranslateY();
            if (sm instanceof ComponentSampleModel) {
                ComponentSampleModel csm = (ComponentSampleModel) sm;
                pos = csm.getOffset(startX, startY, 0);
                for (int nb = 1; nb < csm.getNumBands(); nb++) {
                    if (pos > csm.getOffset(startX, startY, nb)) {
                        pos = csm.getOffset(startX, startY, nb);
                    }
                }
            } else if (sm instanceof MultiPixelPackedSampleModel) {
                MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel) sm;
                pos = mppsm.getOffset(startX, startY);
            } else if (sm instanceof SinglePixelPackedSampleModel) {
                SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sm;
                pos = sppsm.getOffset(startX, startY);
            }
            if (compressionType == BI_RGB || compressionType == BI_BITFIELDS) {
                switch(dataType) {
                    case DataBuffer.TYPE_BYTE:
                        byte[] bdata = ((DataBufferByte) src.getDataBuffer()).getData();
                        stream.write(bdata, pos, destScanlineLength);
                        break;
                    case DataBuffer.TYPE_SHORT:
                        short[] sdata = ((DataBufferShort) src.getDataBuffer()).getData();
                        stream.writeShorts(sdata, pos, destScanlineLength);
                        break;
                    case DataBuffer.TYPE_USHORT:
                        short[] usdata = ((DataBufferUShort) src.getDataBuffer()).getData();
                        stream.writeShorts(usdata, pos, destScanlineLength);
                        break;
                    case DataBuffer.TYPE_INT:
                        int[] idata = ((DataBufferInt) src.getDataBuffer()).getData();
                        stream.writeInts(idata, pos, destScanlineLength);
                        break;
                }
                for (int k = 0; k < padding; k++) {
                    stream.writeByte(0);
                }
            } else if (compressionType == BI_RLE4) {
                if (bpixels == null || bpixels.length < scanlineBytes)
                    bpixels = new byte[scanlineBytes];
                src.getPixels(srcRect.x, srcRect.y, srcRect.width, srcRect.height, pixels);
                for (int h = 0; h < scanlineBytes; h++) {
                    bpixels[h] = (byte) pixels[h];
                }
                encodeRLE4(bpixels, scanlineBytes);
            } else if (compressionType == BI_RLE8) {
                //System.arraycopy(bdata, pos, bpixels, 0, scanlineBytes);
                if (bpixels == null || bpixels.length < scanlineBytes)
                    bpixels = new byte[scanlineBytes];
                src.getPixels(srcRect.x, srcRect.y, srcRect.width, srcRect.height, pixels);
                for (int h = 0; h < scanlineBytes; h++) {
                    bpixels[h] = (byte) pixels[h];
                }
                encodeRLE8(bpixels, scanlineBytes);
            }
        } else {
            src.getPixels(srcRect.x, srcRect.y, srcRect.width, srcRect.height, pixels);
            if (scaleX != 1 || maxBandOffset != numBands - 1) {
                for (int j = 0, k = 0, n = 0; j < w; j++, k += scaleX * numBands, n += numBands) {
                    System.arraycopy(pixels, k, pixel, 0, pixel.length);
                    for (int m = 0; m < numBands; m++) {
                        // pixel data is provided here in RGB order
                        pixels[n + m] = pixel[sourceBands[m]];
                    }
                }
            }
            writePixels(0, scanlineBytes, bitsPerPixel, pixels, padding, numBands, icm);
        }
        processImageProgress(100.0f * (((float) i) / ((float) h)));
    }
    if (compressionType == BI_RLE4 || compressionType == BI_RLE8) {
        // Write the RLE EOF marker and
        stream.writeByte(0);
        stream.writeByte(1);
        incCompImageSize(2);
        // update the file/image Size
        imageSize = compImageSize;
        fileSize = compImageSize + offset;
        long endPos = stream.getStreamPosition();
        stream.seek(headPos);
        writeSize(fileSize, 2);
        stream.seek(headPos);
        writeSize(imageSize, 34);
        stream.seek(endPos);
    }
    if (abortRequested()) {
        processWriteAborted();
    } else {
        processImageComplete();
        stream.flushBefore(stream.getStreamPosition());
    }
}
Also used : Rectangle(java.awt.Rectangle) MultiPixelPackedSampleModel(java.awt.image.MultiPixelPackedSampleModel) ComponentSampleModel(java.awt.image.ComponentSampleModel) DataBufferInt(java.awt.image.DataBufferInt) DataBufferByte(java.awt.image.DataBufferByte) ImageTypeSpecifier(javax.imageio.ImageTypeSpecifier) DataBufferShort(java.awt.image.DataBufferShort) IndexColorModel(java.awt.image.IndexColorModel) DirectColorModel(java.awt.image.DirectColorModel) ColorModel(java.awt.image.ColorModel) BandedSampleModel(java.awt.image.BandedSampleModel) DirectColorModel(java.awt.image.DirectColorModel) DataBufferUShort(java.awt.image.DataBufferUShort) IndexColorModel(java.awt.image.IndexColorModel) Raster(java.awt.image.Raster) SinglePixelPackedSampleModel(java.awt.image.SinglePixelPackedSampleModel) BMPImageWriteParam(javax.imageio.plugins.bmp.BMPImageWriteParam) IOException(java.io.IOException) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IIOMetadata(javax.imageio.metadata.IIOMetadata) ComponentSampleModel(java.awt.image.ComponentSampleModel) SampleModel(java.awt.image.SampleModel) BandedSampleModel(java.awt.image.BandedSampleModel) MultiPixelPackedSampleModel(java.awt.image.MultiPixelPackedSampleModel) SinglePixelPackedSampleModel(java.awt.image.SinglePixelPackedSampleModel) RenderedImage(java.awt.image.RenderedImage)

Aggregations

SampleModel (java.awt.image.SampleModel)47 SinglePixelPackedSampleModel (java.awt.image.SinglePixelPackedSampleModel)22 ComponentSampleModel (java.awt.image.ComponentSampleModel)21 Point (java.awt.Point)20 ColorModel (java.awt.image.ColorModel)16 Rectangle (java.awt.Rectangle)15 DataBuffer (java.awt.image.DataBuffer)14 MultiPixelPackedSampleModel (java.awt.image.MultiPixelPackedSampleModel)14 IndexColorModel (java.awt.image.IndexColorModel)12 RasterFormatException (java.awt.image.RasterFormatException)9 WritableRaster (java.awt.image.WritableRaster)9 DataBufferByte (java.awt.image.DataBufferByte)8 PixelInterleavedSampleModel (java.awt.image.PixelInterleavedSampleModel)8 BufferedImage (java.awt.image.BufferedImage)7 DataBufferInt (java.awt.image.DataBufferInt)7 BandedSampleModel (java.awt.image.BandedSampleModel)6 DirectColorModel (java.awt.image.DirectColorModel)6 Raster (java.awt.image.Raster)6 ImageTypeSpecifier (javax.imageio.ImageTypeSpecifier)6 DataBufferShort (java.awt.image.DataBufferShort)5