blob: e2a8d7de680b5c9269026bd4e2939849e29064fe [file] [log] [blame]
/*
* 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();
}
}