1 7 8 package com.sun.imageio.plugins.wbmp; 9 10 import java.awt.Point ; 11 import java.awt.Rectangle ; 12 import java.awt.image.ColorModel ; 13 import java.awt.image.DataBuffer ; 14 import java.awt.image.DataBufferByte ; 15 import java.awt.image.IndexColorModel ; 16 import java.awt.image.MultiPixelPackedSampleModel ; 17 import java.awt.image.Raster ; 18 import java.awt.image.RenderedImage ; 19 import java.awt.image.SampleModel ; 20 import java.awt.image.WritableRaster ; 21 22 import java.io.IOException ; 23 24 import javax.imageio.IIOImage ; 25 import javax.imageio.IIOException ; 26 import javax.imageio.ImageTypeSpecifier ; 27 import javax.imageio.ImageWriteParam ; 28 import javax.imageio.ImageWriter ; 29 import javax.imageio.metadata.IIOMetadata ; 30 import javax.imageio.metadata.IIOMetadataFormatImpl ; 31 import javax.imageio.metadata.IIOInvalidTreeException ; 32 import javax.imageio.spi.ImageWriterSpi ; 33 import javax.imageio.stream.ImageOutputStream ; 34 35 import com.sun.imageio.plugins.common.I18N; 36 37 46 public class WBMPImageWriter extends ImageWriter { 47 48 private ImageOutputStream stream = null; 49 50 private static int getNumBits(int intValue) { 52 int numBits = 32; 53 int mask = 0x80000000; 54 while(mask != 0 && (intValue & mask) == 0) { 55 numBits--; 56 mask >>>= 1; 57 } 58 return numBits; 59 } 60 61 private static byte[] intToMultiByte(int intValue) { 63 int numBitsLeft = getNumBits(intValue); 64 byte[] multiBytes = new byte[(numBitsLeft + 6)/7]; 65 66 int maxIndex = multiBytes.length - 1; 67 for(int b = 0; b <= maxIndex; b++) { 68 multiBytes[b] = (byte)((intValue >>> ((maxIndex - b)*7))&0x7f); 69 if(b != maxIndex) { 70 multiBytes[b] |= (byte)0x80; 71 } 72 } 73 74 return multiBytes; 75 } 76 77 80 public WBMPImageWriter(ImageWriterSpi originator) { 81 super(originator); 82 } 83 84 public void setOutput(Object output) { 85 super.setOutput(output); if (output != null) { 87 if (!(output instanceof ImageOutputStream )) 88 throw new IllegalArgumentException (I18N.getString("WBMPImageWriter")); 89 this.stream = (ImageOutputStream )output; 90 } else 91 this.stream = null; 92 } 93 94 public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) { 95 return null; 96 } 97 98 public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, 99 ImageWriteParam param) { 100 WBMPMetadata meta = new WBMPMetadata(); 101 meta.wbmpType = 0; return meta; 103 } 104 105 public IIOMetadata convertStreamMetadata(IIOMetadata inData, 106 ImageWriteParam param) { 107 return null; 108 } 109 110 public IIOMetadata convertImageMetadata(IIOMetadata metadata, 111 ImageTypeSpecifier type, 112 ImageWriteParam param) { 113 return null; 114 } 115 116 public boolean canWriteRasters() { 117 return true; 118 } 119 120 public void write(IIOMetadata streamMetadata, 121 IIOImage image, 122 ImageWriteParam param) throws IOException { 123 124 if (stream == null) { 125 throw new IllegalStateException (I18N.getString("WBMPImageWriter3")); 126 } 127 128 if (image == null) { 129 throw new IllegalArgumentException (I18N.getString("WBMPImageWriter4")); 130 } 131 132 clearAbortRequest(); 133 processImageStarted(0); 134 if (param == null) 135 param = getDefaultWriteParam(); 136 137 RenderedImage input = null; 138 Raster inputRaster = null; 139 boolean writeRaster = image.hasRaster(); 140 Rectangle sourceRegion = param.getSourceRegion(); 141 SampleModel sampleModel = null; 142 143 if (writeRaster) { 144 inputRaster = image.getRaster(); 145 sampleModel = inputRaster.getSampleModel(); 146 } else { 147 input = image.getRenderedImage(); 148 sampleModel = input.getSampleModel(); 149 150 inputRaster = input.getData(); 151 } 152 153 checkSampleModel(sampleModel); 154 if (sourceRegion == null) 155 sourceRegion = inputRaster.getBounds(); 156 else 157 sourceRegion = sourceRegion.intersection(inputRaster.getBounds()); 158 159 if (sourceRegion.isEmpty()) 160 throw new RuntimeException (I18N.getString("WBMPImageWriter1")); 161 162 int scaleX = param.getSourceXSubsampling(); 163 int scaleY = param.getSourceYSubsampling(); 164 int xOffset = param.getSubsamplingXOffset(); 165 int yOffset = param.getSubsamplingYOffset(); 166 167 sourceRegion.translate(xOffset, yOffset); 168 sourceRegion.width -= xOffset; 169 sourceRegion.height -= yOffset; 170 171 int minX = sourceRegion.x / scaleX; 172 int minY = sourceRegion.y / scaleY; 173 int w = (sourceRegion.width + scaleX - 1) / scaleX; 174 int h = (sourceRegion.height + scaleY - 1) / scaleY; 175 176 Rectangle destinationRegion = new Rectangle (minX, minY, w, h); 177 sampleModel = sampleModel.createCompatibleSampleModel(w, h); 178 179 SampleModel destSM= sampleModel; 180 181 if(sampleModel.getDataType() != DataBuffer.TYPE_BYTE || 183 !(sampleModel instanceof MultiPixelPackedSampleModel ) || 184 ((MultiPixelPackedSampleModel )sampleModel).getDataBitOffset() != 0) { 185 destSM = 186 new MultiPixelPackedSampleModel (DataBuffer.TYPE_BYTE, 187 w, h, 1, 188 w + 7 >> 3, 0); 189 } 190 191 if (!destinationRegion.equals(sourceRegion)) { 192 if (scaleX == 1 && scaleY == 1) 193 inputRaster = inputRaster.createChild(inputRaster.getMinX(), 194 inputRaster.getMinY(), 195 w, h, minX, minY, null); 196 else { 197 WritableRaster ras = Raster.createWritableRaster(destSM, 198 new Point (minX, minY)); 199 200 byte[] data = ((DataBufferByte )ras.getDataBuffer()).getData(); 201 202 for(int j = minY, y = sourceRegion.y, k = 0; 203 j < minY + h; j++, y += scaleY) { 204 205 for (int i = 0, x = sourceRegion.x; 206 i <w; i++, x +=scaleX) { 207 int v = inputRaster.getSample(x, y, 0); 208 data[k + (i >> 3)] |= v << (7 - (i & 7)); 209 } 210 k += w + 7 >> 3; 211 } 212 inputRaster = ras; 213 } 214 } 215 216 if(!destSM.equals(inputRaster.getSampleModel())) { 218 WritableRaster raster = 219 Raster.createWritableRaster(destSM, 220 new Point (inputRaster.getMinX(), 221 inputRaster.getMinY())); 222 raster.setRect(inputRaster); 223 inputRaster = raster; 224 } 225 226 boolean isWhiteZero = false; 228 if(!writeRaster && input.getColorModel() instanceof IndexColorModel ) { 229 IndexColorModel icm = (IndexColorModel )input.getColorModel(); 230 isWhiteZero = icm.getRed(0) > icm.getRed(1); 231 } 232 233 int lineStride = 235 ((MultiPixelPackedSampleModel )destSM).getScanlineStride(); 236 int bytesPerRow = (w + 7)/8; 237 byte[] bdata = ((DataBufferByte )inputRaster.getDataBuffer()).getData(); 238 239 stream.write(0); stream.write(0); stream.write(intToMultiByte(w)); stream.write(intToMultiByte(h)); 245 if(!isWhiteZero && lineStride == bytesPerRow) { 247 stream.write(bdata, 0, h * bytesPerRow); 249 processImageProgress(100.0F); 250 } else { 251 int offset = 0; 253 if(!isWhiteZero) { 254 for(int row = 0; row < h; row++) { 256 if (abortRequested()) 257 break; 258 stream.write(bdata, offset, bytesPerRow); 259 offset += lineStride; 260 processImageProgress(100.0F * row / h); 261 } 262 } else { 263 byte[] inverted = new byte[bytesPerRow]; 265 for(int row = 0; row < h; row++) { 266 if (abortRequested()) 267 break; 268 for(int col = 0; col < bytesPerRow; col++) { 269 inverted[col] = (byte)(~(bdata[col+offset])); 270 } 271 stream.write(inverted, 0, bytesPerRow); 272 offset += lineStride; 273 processImageProgress(100.0F * row / h); 274 } 275 } 276 } 277 278 if (abortRequested()) 279 processWriteAborted(); 280 else { 281 processImageComplete(); 282 stream.flushBefore(stream.getStreamPosition()); 283 } 284 } 285 286 public void reset() { 287 super.reset(); 288 stream = null; 289 } 290 291 private void checkSampleModel(SampleModel sm) { 292 int type = sm.getDataType(); 293 if (type < DataBuffer.TYPE_BYTE || type > DataBuffer.TYPE_INT 294 || sm.getNumBands() != 1 || sm.getSampleSize(0) != 1) 295 throw new IllegalArgumentException (I18N.getString("WBMPImageWriter2")); 296 } 297 } 298 | Popular Tags |