| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| /** |
| * @author Viskov Nikolay |
| * @version $Revision$ |
| */ |
| package org.apache.harmony.x.imageio.plugins.png; |
| |
| import com.android.internal.awt.ImageOutputStreamWrapper; |
| |
| import java.awt.image.BufferedImage; |
| import java.awt.image.ColorModel; |
| import java.awt.image.DataBufferByte; |
| import java.awt.image.DataBufferInt; |
| import java.awt.image.IndexColorModel; |
| import java.awt.image.Raster; |
| import java.awt.image.RenderedImage; |
| import java.awt.image.SampleModel; |
| import java.awt.image.SinglePixelPackedSampleModel; |
| import java.awt.image.WritableRaster; |
| import java.io.IOException; |
| |
| import javax.imageio.IIOImage; |
| import javax.imageio.ImageTypeSpecifier; |
| import javax.imageio.ImageWriteParam; |
| import javax.imageio.ImageWriter; |
| import javax.imageio.metadata.IIOMetadata; |
| import javax.imageio.spi.ImageWriterSpi; |
| import javax.imageio.stream.ImageOutputStream; |
| |
| import org.apache.harmony.x.imageio.internal.nls.Messages; |
| |
| import org.apache.harmony.luni.util.NotImplementedException; |
| |
| import android.graphics.Bitmap; |
| import android.graphics.Bitmap.CompressFormat; |
| |
| public class PNGImageWriter extends ImageWriter { |
| |
| // /* ???AWT: Debugging |
| private static final boolean DEBUG = false; |
| private static Bitmap bm; |
| public static Bitmap getBitmap() { |
| return bm; |
| } |
| // */ |
| |
| private static int[][] BAND_OFFSETS = { |
| {}, { |
| 0 }, { |
| 0, 1 }, { |
| 0, 1, 2 }, { |
| 0, 1, 2, 3 } }; |
| |
| // Each pixel is a grayscale sample. |
| private static final int PNG_COLOR_TYPE_GRAY = 0; |
| // Each pixel is an R,G,B triple. |
| private static final int PNG_COLOR_TYPE_RGB = 2; |
| // Each pixel is a palette index, a PLTE chunk must appear. |
| private static final int PNG_COLOR_TYPE_PLTE = 3; |
| // Each pixel is a grayscale sample, followed by an alpha sample. |
| private static final int PNG_COLOR_TYPE_GRAY_ALPHA = 4; |
| // Each pixel is an R,G,B triple, followed by an alpha sample. |
| private static final int PNG_COLOR_TYPE_RGBA = 6; |
| |
| //???AWT: private static native void initIDs(Class<ImageOutputStream> iosClass); |
| |
| static { |
| //???AWT |
| /* |
| System.loadLibrary("pngencoder"); //$NON-NLS-1$ |
| initIDs(ImageOutputStream.class); |
| */ |
| } |
| |
| /* |
| private native int encode(byte[] input, int bytesInBuffer, int bytePixelSize, Object ios, int imageWidth, |
| int imageHeight, int bitDepth, int colorType, int[] palette, int i, boolean b); |
| */ |
| |
| protected PNGImageWriter(ImageWriterSpi iwSpi) { |
| super(iwSpi); |
| } |
| |
| @Override |
| public IIOMetadata convertStreamMetadata(IIOMetadata arg0, ImageWriteParam arg1) { |
| throw new NotImplementedException(); |
| } |
| |
| @Override |
| public IIOMetadata convertImageMetadata(IIOMetadata arg0, ImageTypeSpecifier arg1, ImageWriteParam arg2) { |
| throw new NotImplementedException(); |
| } |
| |
| @Override |
| public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier arg0, ImageWriteParam arg1) { |
| throw new NotImplementedException(); |
| } |
| |
| @Override |
| public IIOMetadata getDefaultStreamMetadata(ImageWriteParam arg0) { |
| throw new NotImplementedException(); |
| } |
| |
| @Override |
| public void write(IIOMetadata streamMetadata, IIOImage iioImage, ImageWriteParam param) throws IOException { |
| if (output == null) { |
| throw new IllegalStateException("Output not been set"); |
| } |
| if (iioImage == null) { |
| throw new IllegalArgumentException("Image equals null"); |
| } |
| // AWT???: I think this is not needed anymore |
| // if (iioImage.hasRaster() && !canWriteRasters()) { |
| // throw new UnsupportedOperationException("Can't write raster"); |
| //}// ImageOutputStreamImpl |
| |
| Raster sourceRaster; |
| RenderedImage img = null; |
| if (!iioImage.hasRaster()) { |
| img = iioImage.getRenderedImage(); |
| if (img instanceof BufferedImage) { |
| sourceRaster = ((BufferedImage) img).getRaster(); |
| } else { |
| sourceRaster = img.getData(); |
| } |
| } else { |
| sourceRaster = iioImage.getRaster(); |
| } |
| |
| SampleModel model = sourceRaster.getSampleModel(); |
| int srcWidth = sourceRaster.getWidth(); |
| int srcHeight = sourceRaster.getHeight(); |
| int numBands = model.getNumBands(); |
| |
| ColorModel colorModel = img.getColorModel(); |
| int pixelSize = colorModel.getPixelSize(); |
| int bytePixelSize = pixelSize / 8; |
| int bitDepth = pixelSize / numBands; |
| |
| // byte per band |
| int bpb = bitDepth > 8 ? 2 : 1; |
| |
| boolean isInterlace = true; |
| if (param instanceof PNGImageWriterParam) { |
| isInterlace = ((PNGImageWriterParam) param).getInterlace(); |
| } |
| |
| int colorType = PNG_COLOR_TYPE_GRAY; |
| int[] palette = null; |
| |
| if (colorModel instanceof IndexColorModel) { |
| if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4 && bitDepth != 8) { |
| // Wrong bitDepth-numBands composition |
| throw new IllegalArgumentException(Messages.getString("imageio.1"));//$NON-NLS-1$ |
| } |
| if (numBands != 1) { |
| // Wrong bitDepth-numBands composition |
| throw new IllegalArgumentException(Messages.getString("imageio.1"));//$NON-NLS-1$ |
| } |
| |
| IndexColorModel icm = (IndexColorModel) colorModel; |
| palette = new int[icm.getMapSize()]; |
| icm.getRGBs(palette); |
| colorType = PNG_COLOR_TYPE_PLTE; |
| } |
| else if (numBands == 1) { |
| if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4 && bitDepth != 8 && bitDepth != 16) { |
| // Wrong bitDepth-numBands composition |
| throw new IllegalArgumentException(Messages.getString("imageio.1"));//$NON-NLS-1$ |
| } |
| colorType = PNG_COLOR_TYPE_GRAY; |
| } |
| else if (numBands == 2) { |
| if (bitDepth != 8 && bitDepth != 16) { |
| // Wrong bitDepth-numBands composition |
| throw new IllegalArgumentException(Messages.getString("imageio.1"));//$NON-NLS-1$ |
| } |
| colorType = PNG_COLOR_TYPE_GRAY_ALPHA; |
| } |
| else if (numBands == 3) { |
| if (bitDepth != 8 && bitDepth != 16) { |
| // Wrong bitDepth-numBands composition |
| throw new IllegalArgumentException(Messages.getString("imageio.1")); //$NON-NLS-1$ |
| } |
| colorType = PNG_COLOR_TYPE_RGB; |
| } |
| else if (numBands == 4) { |
| if (bitDepth != 8 && bitDepth != 16) { |
| //Wrong bitDepth-numBands composition |
| throw new IllegalArgumentException(Messages.getString("imageio.1")); //$NON-NLS-1$ |
| } |
| colorType = PNG_COLOR_TYPE_RGBA; |
| } |
| |
| /* ???AWT: I think this is not needed anymore |
| int dbufferLenght = bytePixelSize * imageHeight * imageWidth; |
| DataBufferByte dbuffer = new DataBufferByte(dbufferLenght); |
| |
| WritableRaster scanRaster = Raster.createInterleavedRaster(dbuffer, imageWidth, imageHeight, bpb * numBands |
| * imageWidth, bpb * numBands, BAND_OFFSETS[numBands], null); |
| |
| scanRaster.setRect(((BufferedImage) image).getRaster()// image.getData() |
| .createChild(0, 0, imageWidth, imageHeight, 0, 0, null)); |
| */ |
| |
| if (DEBUG) { |
| System.out.println("**** raster:" + sourceRaster); |
| System.out.println("**** model:" + model); |
| System.out.println("**** type:" + colorType); |
| } |
| |
| if (model instanceof SinglePixelPackedSampleModel) { |
| DataBufferInt ibuf = (DataBufferInt)sourceRaster.getDataBuffer(); |
| int[] pixels = ibuf.getData(); |
| |
| // Create a bitmap with the pixel |
| bm = Bitmap.createBitmap(pixels, srcWidth, srcHeight, Bitmap.Config.ARGB_8888); |
| |
| // Use Bitmap.compress() to write the image |
| ImageOutputStream ios = (ImageOutputStream) getOutput(); |
| ImageOutputStreamWrapper iosw = new ImageOutputStreamWrapper(ios); |
| bm.compress(CompressFormat.PNG, 100, iosw); |
| } else { |
| // ???AWT: Add support for other color models |
| throw new RuntimeException("Color model not supported yet"); |
| } |
| } |
| |
| public ImageWriteParam getDefaultWriteParam() { |
| return new PNGImageWriterParam(); |
| } |
| } |