001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Viskov Nikolay
019: * @version $Revision$
020: */package org.apache.harmony.x.imageio.plugins.png;
021:
022: import java.awt.image.BufferedImage;
023: import java.awt.image.ColorModel;
024: import java.awt.image.DataBufferByte;
025: import java.awt.image.IndexColorModel;
026: import java.awt.image.Raster;
027: import java.awt.image.RenderedImage;
028: import java.awt.image.WritableRaster;
029: import java.io.IOException;
030:
031: import javax.imageio.IIOImage;
032: import javax.imageio.ImageTypeSpecifier;
033: import javax.imageio.ImageWriteParam;
034: import javax.imageio.ImageWriter;
035: import javax.imageio.metadata.IIOMetadata;
036: import javax.imageio.spi.ImageWriterSpi;
037: import javax.imageio.stream.ImageOutputStream;
038:
039: import org.apache.harmony.x.imageio.internal.nls.Messages;
040:
041: import org.apache.harmony.luni.util.NotImplementedException;
042:
043: public class PNGImageWriter extends ImageWriter {
044: private static int[][] BAND_OFFSETS = { {}, { 0 }, { 0, 1 },
045: { 0, 1, 2 }, { 0, 1, 2, 3 } };
046:
047: // Each pixel is a grayscale sample.
048: private static final int PNG_COLOR_TYPE_GRAY = 0;
049: // Each pixel is an R,G,B triple.
050: private static final int PNG_COLOR_TYPE_RGB = 2;
051: // Each pixel is a palette index, a PLTE chunk must appear.
052: private static final int PNG_COLOR_TYPE_PLTE = 3;
053: // Each pixel is a grayscale sample, followed by an alpha sample.
054: private static final int PNG_COLOR_TYPE_GRAY_ALPHA = 4;
055: // Each pixel is an R,G,B triple, followed by an alpha sample.
056: private static final int PNG_COLOR_TYPE_RGBA = 6;
057:
058: private static native void initIDs(Class<ImageOutputStream> iosClass);
059:
060: static {
061: System.loadLibrary("pngencoder"); //$NON-NLS-1$
062: initIDs(ImageOutputStream.class);
063: }
064:
065: private native int encode(byte[] input, int bytesInBuffer,
066: int bytePixelSize, Object ios, int imageWidth,
067: int imageHeight, int bitDepth, int colorType,
068: int[] palette, int i, boolean b);
069:
070: protected PNGImageWriter(ImageWriterSpi iwSpi) {
071: super (iwSpi);
072: }
073:
074: @Override
075: public IIOMetadata convertStreamMetadata(IIOMetadata arg0,
076: ImageWriteParam arg1) throws NotImplementedException {
077: // TODO: implement
078: throw new NotImplementedException();
079: }
080:
081: @Override
082: public IIOMetadata convertImageMetadata(IIOMetadata arg0,
083: ImageTypeSpecifier arg1, ImageWriteParam arg2)
084: throws NotImplementedException {
085: // TODO: implement
086: throw new NotImplementedException();
087: }
088:
089: @Override
090: public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier arg0,
091: ImageWriteParam arg1) throws NotImplementedException {
092: // TODO: implement
093: throw new NotImplementedException();
094: }
095:
096: @Override
097: public IIOMetadata getDefaultStreamMetadata(ImageWriteParam arg0)
098: throws NotImplementedException {
099: // TODO: implement
100: throw new NotImplementedException();
101: }
102:
103: @Override
104: public void write(IIOMetadata streamMetadata, IIOImage iioimage,
105: ImageWriteParam param) throws IOException {
106: if (output == null) {
107: throw new IllegalStateException("Output not been set");
108: }
109: if (iioimage == null) {
110: throw new IllegalArgumentException("Image equals null");
111: }
112: if (iioimage.hasRaster() && !canWriteRasters()) {
113: throw new UnsupportedOperationException(
114: "Can't write raster");
115: }// ImageOutputStreamImpl
116:
117: int imageWidth, imageHeight;
118: int colorType = PNG_COLOR_TYPE_GRAY;
119: int bitDepth;
120: int numBands;
121:
122: DataBufferByte dbuffer;
123:
124: int[] palette = null;
125:
126: boolean isInterlace = true;
127:
128: RenderedImage image = iioimage.getRenderedImage();
129:
130: imageWidth = image.getWidth();
131: imageHeight = image.getHeight();
132:
133: numBands = image.getSampleModel().getNumBands();
134:
135: ColorModel colorModel = image.getColorModel();
136:
137: int pixelSize = colorModel.getPixelSize();
138:
139: int bytePixelSize = pixelSize / 8;
140:
141: bitDepth = pixelSize / numBands;
142:
143: // byte per band
144: int bpb = bitDepth > 8 ? 2 : 1;
145:
146: if (colorModel instanceof IndexColorModel) {
147: if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4
148: && bitDepth != 8) {
149: // Wrong bitDepth-numBands composition
150: throw new IllegalArgumentException(Messages
151: .getString("imageio.1"));//$NON-NLS-1$
152: }
153: if (numBands != 1) {
154: // Wrong bitDepth-numBands composition
155: throw new IllegalArgumentException(Messages
156: .getString("imageio.1"));//$NON-NLS-1$
157: }
158:
159: IndexColorModel icm = (IndexColorModel) colorModel;
160:
161: palette = new int[icm.getMapSize()];
162:
163: icm.getRGBs(palette);
164:
165: colorType = PNG_COLOR_TYPE_PLTE;
166:
167: } else if (numBands == 1) {
168: if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4
169: && bitDepth != 8 && bitDepth != 16) {
170: // Wrong bitDepth-numBands composition
171: throw new IllegalArgumentException(Messages
172: .getString("imageio.1"));//$NON-NLS-1$
173: }
174: colorType = PNG_COLOR_TYPE_GRAY;
175: } else if (numBands == 2) {
176: if (bitDepth != 8 && bitDepth != 16) {
177: // Wrong bitDepth-numBands composition
178: throw new IllegalArgumentException(Messages
179: .getString("imageio.1"));//$NON-NLS-1$
180: }
181: colorType = PNG_COLOR_TYPE_GRAY_ALPHA;
182: } else if (numBands == 3) {
183: if (bitDepth != 8 && bitDepth != 16) {
184: // Wrong bitDepth-numBands composition
185: throw new IllegalArgumentException(Messages
186: .getString("imageio.1")); //$NON-NLS-1$
187: }
188: colorType = PNG_COLOR_TYPE_RGB;
189: } else if (numBands == 4) {
190: if (bitDepth != 8 && bitDepth != 16) {
191: //Wrong bitDepth-numBands composition
192: throw new IllegalArgumentException(Messages
193: .getString("imageio.1")); //$NON-NLS-1$
194: }
195: colorType = PNG_COLOR_TYPE_RGBA;
196: }
197:
198: int dbufferLength = bytePixelSize * imageHeight * imageWidth;
199:
200: dbuffer = new DataBufferByte(dbufferLength);
201:
202: WritableRaster scanRaster = Raster.createInterleavedRaster(
203: dbuffer, imageWidth, imageHeight, bpb * numBands
204: * imageWidth, bpb * numBands,
205: BAND_OFFSETS[numBands], null);
206:
207: scanRaster
208: .setRect(((BufferedImage) image).getRaster()// image.getData()
209: .createChild(0, 0, imageWidth, imageHeight, 0,
210: 0, null));
211:
212: if (param instanceof PNGImageWriterParam) {
213: isInterlace = ((PNGImageWriterParam) param).getInterlace();
214: }
215:
216: try {
217: encode(dbuffer.getData(), dbufferLength, bytePixelSize,
218: (ImageOutputStream) getOutput(), imageWidth,
219: imageHeight, bitDepth, colorType, palette,
220: palette == null ? 0 : palette.length, isInterlace);
221:
222: } catch (RuntimeException e) {
223: e.printStackTrace();
224: }
225: }
226:
227: public ImageWriteParam getDefaultWriteParam() {
228: return new PNGImageWriterParam();
229: }
230: }
|