KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > imageio > plugins > common > ImageUtil


1 /*
2  * @(#)ImageUtil.java 1.2 03/12/19 16:54:01
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.imageio.plugins.common;
9
10 import java.awt.Point JavaDoc;
11 import java.awt.Rectangle JavaDoc;
12 import java.awt.Transparency JavaDoc;
13 import java.awt.color.ColorSpace JavaDoc;
14 import java.awt.image.BufferedImage JavaDoc;
15 import java.awt.image.ColorModel JavaDoc;
16 import java.awt.image.ComponentColorModel JavaDoc;
17 import java.awt.image.ComponentSampleModel JavaDoc;
18 import java.awt.image.DataBuffer JavaDoc;
19 import java.awt.image.DataBufferByte JavaDoc;
20 import java.awt.image.DataBufferInt JavaDoc;
21 import java.awt.image.DataBufferShort JavaDoc;
22 import java.awt.image.DataBufferUShort JavaDoc;
23 import java.awt.image.DirectColorModel JavaDoc;
24 import java.awt.image.IndexColorModel JavaDoc;
25 import java.awt.image.MultiPixelPackedSampleModel JavaDoc;
26 import java.awt.image.Raster JavaDoc;
27 import java.awt.image.RenderedImage JavaDoc;
28 import java.awt.image.SampleModel JavaDoc;
29 import java.awt.image.SinglePixelPackedSampleModel JavaDoc;
30 import java.awt.image.WritableRaster JavaDoc;
31 import java.util.Arrays JavaDoc;
32
33 //import javax.imageio.ImageTypeSpecifier;
34

35 import javax.imageio.IIOException JavaDoc;
36 import javax.imageio.IIOImage JavaDoc;
37 import javax.imageio.ImageTypeSpecifier JavaDoc;
38 import javax.imageio.ImageWriter JavaDoc;
39 import javax.imageio.spi.ImageWriterSpi JavaDoc;
40
41 public class ImageUtil {
42     /* XXX testing only
43     public static void main(String[] args) {
44         ImageTypeSpecifier bilevel =
45             ImageTypeSpecifier.createIndexed(new byte[] {(byte)0, (byte)255},
46                                              new byte[] {(byte)0, (byte)255},
47                                              new byte[] {(byte)0, (byte)255},
48                                              null, 1,
49                                              DataBuffer.TYPE_BYTE);
50         ImageTypeSpecifier gray =
51             ImageTypeSpecifier.createGrayscale(8, DataBuffer.TYPE_BYTE, false);
52         ImageTypeSpecifier grayAlpha =
53             ImageTypeSpecifier.createGrayscale(8, DataBuffer.TYPE_BYTE, false,
54                                                false);
55         ImageTypeSpecifier rgb =
56             ImageTypeSpecifier.createInterleaved(ColorSpace.getInstance(ColorSpace.CS_sRGB),
57                                                  new int[] {0, 1, 2},
58                                                  DataBuffer.TYPE_BYTE,
59                                                  false,
60                                                  false);
61         ImageTypeSpecifier rgba =
62             ImageTypeSpecifier.createInterleaved(ColorSpace.getInstance(ColorSpace.CS_sRGB),
63                                                  new int[] {0, 1, 2, 3},
64                                                  DataBuffer.TYPE_BYTE,
65                                                  true,
66                                                  false);
67         ImageTypeSpecifier packed =
68             ImageTypeSpecifier.createPacked(ColorSpace.getInstance(ColorSpace.CS_sRGB),
69                                             0xff000000,
70                                             0x00ff0000,
71                                             0x0000ff00,
72                                             0x000000ff,
73                                             DataBuffer.TYPE_BYTE,
74                                             false);
75
76         SampleModel bandedSM =
77             new java.awt.image.BandedSampleModel(DataBuffer.TYPE_BYTE,
78                                                  1, 1, 15);
79
80         System.out.println(createColorModel(bilevel.getSampleModel()));
81         System.out.println(createColorModel(gray.getSampleModel()));
82         System.out.println(createColorModel(grayAlpha.getSampleModel()));
83         System.out.println(createColorModel(rgb.getSampleModel()));
84         System.out.println(createColorModel(rgba.getSampleModel()));
85         System.out.println(createColorModel(packed.getSampleModel()));
86         System.out.println(createColorModel(bandedSM));
87     }
88     */

89
90     /**
91      * Creates a <code>ColorModel</code> that may be used with the
92      * specified <code>SampleModel</code>. If a suitable
93      * <code>ColorModel</code> cannot be found, this method returns
94      * <code>null</code>.
95      *
96      * <p> Suitable <code>ColorModel</code>s are guaranteed to exist
97      * for all instances of <code>ComponentSampleModel</code>.
98      * For 1- and 3- banded <code>SampleModel</code>s, the returned
99      * <code>ColorModel</code> will be opaque. For 2- and 4-banded
100      * <code>SampleModel</code>s, the output will use alpha transparency
101      * which is not premultiplied. 1- and 2-banded data will use a
102      * grayscale <code>ColorSpace</code>, and 3- and 4-banded data a sRGB
103      * <code>ColorSpace</code>. Data with 5 or more bands will have a
104      * <code>BogusColorSpace</code>.</p>
105      *
106      * <p>An instance of <code>DirectColorModel</code> will be created for
107      * instances of <code>SinglePixelPackedSampleModel</code> with no more
108      * than 4 bands.</p>
109      *
110      * <p>An instance of <code>IndexColorModel</code> will be created for
111      * instances of <code>MultiPixelPackedSampleModel</code>. The colormap
112      * will be a grayscale ramp with <code>1&nbsp;<<&nbsp;numberOfBits</code>
113      * entries ranging from zero to at most 255.</p>
114      *
115      * @return An instance of <code>ColorModel</code> that is suitable for
116      * the supplied <code>SampleModel</code>, or <code>null</code>.
117      *
118      * @throws IllegalArgumentException If <code>sampleModel</code> is
119      * <code>null</code>.
120      */

121     public static final ColorModel JavaDoc createColorModel(SampleModel JavaDoc sampleModel) {
122         // Check the parameter.
123
if(sampleModel == null) {
124             throw new IllegalArgumentException JavaDoc("sampleModel == null!");
125         }
126
127         // Get the data type.
128
int dataType = sampleModel.getDataType();
129
130         // Check the data type
131
switch(dataType) {
132         case DataBuffer.TYPE_BYTE:
133         case DataBuffer.TYPE_USHORT:
134         case DataBuffer.TYPE_SHORT:
135         case DataBuffer.TYPE_INT:
136         case DataBuffer.TYPE_FLOAT:
137         case DataBuffer.TYPE_DOUBLE:
138             break;
139         default:
140             // Return null for other types.
141
return null;
142         }
143
144         // The return variable.
145
ColorModel JavaDoc colorModel = null;
146
147         // Get the sample size.
148
int[] sampleSize = sampleModel.getSampleSize();
149
150         // Create a Component ColorModel.
151
if(sampleModel instanceof ComponentSampleModel JavaDoc) {
152             // Get the number of bands.
153
int numBands = sampleModel.getNumBands();
154
155             // Determine the color space.
156
ColorSpace JavaDoc colorSpace = null;
157             if(numBands <= 2) {
158                 colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
159             } else if(numBands <= 4) {
160                 colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
161             } else {
162                 colorSpace = new BogusColorSpace(numBands);
163             }
164
165             boolean hasAlpha = (numBands == 2) || (numBands == 4);
166             boolean isAlphaPremultiplied = false;
167             int transparency = hasAlpha ?
168                 Transparency.TRANSLUCENT : Transparency.OPAQUE;
169
170             colorModel = new ComponentColorModel JavaDoc(colorSpace,
171                                                  sampleSize,
172                                                  hasAlpha,
173                                                  isAlphaPremultiplied,
174                                                  transparency,
175                                                  dataType);
176         } else if (sampleModel.getNumBands() <= 4 &&
177                    sampleModel instanceof SinglePixelPackedSampleModel JavaDoc) {
178             SinglePixelPackedSampleModel JavaDoc sppsm =
179                 (SinglePixelPackedSampleModel JavaDoc)sampleModel;
180
181             int[] bitMasks = sppsm.getBitMasks();
182             int rmask = 0;
183             int gmask = 0;
184             int bmask = 0;
185             int amask = 0;
186
187             int numBands = bitMasks.length;
188             if (numBands <= 2) {
189                 rmask = gmask = bmask = bitMasks[0];
190                 if (numBands == 2) {
191                     amask = bitMasks[1];
192                 }
193             } else {
194                 rmask = bitMasks[0];
195                 gmask = bitMasks[1];
196                 bmask = bitMasks[2];
197                 if (numBands == 4) {
198                     amask = bitMasks[3];
199                 }
200             }
201
202             int bits = 0;
203             for (int i = 0; i < sampleSize.length; i++) {
204                 bits += sampleSize[i];
205             }
206
207             return new DirectColorModel JavaDoc(bits, rmask, gmask, bmask, amask);
208
209         } else if(sampleModel instanceof MultiPixelPackedSampleModel JavaDoc) {
210             // Load the colormap with a ramp.
211
int bitsPerSample = sampleSize[0];
212             int numEntries = 1 << bitsPerSample;
213             byte[] map = new byte[numEntries];
214             for (int i = 0; i < numEntries; i++) {
215                 map[i] = (byte)(i*255/(numEntries - 1));
216             }
217
218             colorModel = new IndexColorModel JavaDoc(bitsPerSample, numEntries,
219                                              map, map, map);
220
221         }
222
223         return colorModel;
224     }
225
226     /**
227      * For the case of binary data (<code>isBinary()</code> returns
228      * <code>true</code>), return the binary data as a packed byte array.
229      * The data will be packed as eight bits per byte with no bit offset,
230      * i.e., the first bit in each image line will be the left-most of the
231      * first byte of the line. The line stride in bytes will be
232      * <code>(int)((getWidth()+7)/8)</code>. The length of the returned
233      * array will be the line stride multiplied by <code>getHeight()</code>
234      *
235      * @return the binary data as a packed array of bytes with zero offset
236      * of <code>null</code> if the data are not binary.
237      * @throws IllegalArgumentException if <code>isBinary()</code> returns
238      * <code>false</code> with the <code>SampleModel</code> of the
239      * supplied <code>Raster</code> as argument.
240      */

241     public static byte[] getPackedBinaryData(Raster JavaDoc raster,
242                                              Rectangle JavaDoc rect) {
243         SampleModel JavaDoc sm = raster.getSampleModel();
244         if(!isBinary(sm)) {
245             throw new IllegalArgumentException JavaDoc(I18N.getString("ImageUtil0"));
246         }
247
248         int rectX = rect.x;
249         int rectY = rect.y;
250         int rectWidth = rect.width;
251         int rectHeight = rect.height;
252
253         DataBuffer JavaDoc dataBuffer = raster.getDataBuffer();
254
255         int dx = rectX - raster.getSampleModelTranslateX();
256         int dy = rectY - raster.getSampleModelTranslateY();
257
258         MultiPixelPackedSampleModel JavaDoc mpp = (MultiPixelPackedSampleModel JavaDoc)sm;
259         int lineStride = mpp.getScanlineStride();
260         int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy);
261         int bitOffset = mpp.getBitOffset(dx);
262
263         int numBytesPerRow = (rectWidth + 7)/8;
264         if(dataBuffer instanceof DataBufferByte JavaDoc &&
265            eltOffset == 0 && bitOffset == 0 &&
266            numBytesPerRow == lineStride &&
267            ((DataBufferByte JavaDoc)dataBuffer).getData().length ==
268            numBytesPerRow*rectHeight) {
269             return ((DataBufferByte JavaDoc)dataBuffer).getData();
270         }
271
272         byte[] binaryDataArray = new byte[numBytesPerRow*rectHeight];
273
274         int b = 0;
275
276         if(bitOffset == 0) {
277             if(dataBuffer instanceof DataBufferByte JavaDoc) {
278                 byte[] data = ((DataBufferByte JavaDoc)dataBuffer).getData();
279                 int stride = numBytesPerRow;
280                 int offset = 0;
281                 for(int y = 0; y < rectHeight; y++) {
282                     System.arraycopy(data, eltOffset,
283                                      binaryDataArray, offset,
284                                      stride);
285                     offset += stride;
286                     eltOffset += lineStride;
287                 }
288             } else if(dataBuffer instanceof DataBufferShort JavaDoc ||
289                       dataBuffer instanceof DataBufferUShort JavaDoc) {
290                 short[] data = dataBuffer instanceof DataBufferShort JavaDoc ?
291                     ((DataBufferShort JavaDoc)dataBuffer).getData() :
292                     ((DataBufferUShort JavaDoc)dataBuffer).getData();
293
294                 for(int y = 0; y < rectHeight; y++) {
295                     int xRemaining = rectWidth;
296                     int i = eltOffset;
297                     while(xRemaining > 8) {
298                         short datum = data[i++];
299                         binaryDataArray[b++] = (byte)((datum >>> 8) & 0xFF);
300                         binaryDataArray[b++] = (byte)(datum & 0xFF);
301                         xRemaining -= 16;
302                     }
303                     if(xRemaining > 0) {
304                         binaryDataArray[b++] = (byte)((data[i] >>> 8) & 0XFF);
305                     }
306                     eltOffset += lineStride;
307                 }
308             } else if(dataBuffer instanceof DataBufferInt JavaDoc) {
309                 int[] data = ((DataBufferInt JavaDoc)dataBuffer).getData();
310
311                 for(int y = 0; y < rectHeight; y++) {
312                     int xRemaining = rectWidth;
313                     int i = eltOffset;
314                     while(xRemaining > 24) {
315                         int datum = data[i++];
316                         binaryDataArray[b++] = (byte)((datum >>> 24) & 0xFF);
317                         binaryDataArray[b++] = (byte)((datum >>> 16) & 0xFF);
318                         binaryDataArray[b++] = (byte)((datum >>> 8) & 0xFF);
319                         binaryDataArray[b++] = (byte)(datum & 0xFF);
320                         xRemaining -= 32;
321                     }
322                     int shift = 24;
323                     while(xRemaining > 0) {
324                         binaryDataArray[b++] =
325                             (byte)((data[i] >>> shift) & 0xFF);
326                         shift -= 8;
327                         xRemaining -= 8;
328                     }
329                     eltOffset += lineStride;
330                 }
331             }
332         } else { // bitOffset != 0
333
if(dataBuffer instanceof DataBufferByte JavaDoc) {
334                 byte[] data = ((DataBufferByte JavaDoc)dataBuffer).getData();
335
336                 if((bitOffset & 7) == 0) {
337                     int stride = numBytesPerRow;
338                     int offset = 0;
339                     for(int y = 0; y < rectHeight; y++) {
340                         System.arraycopy(data, eltOffset,
341                                          binaryDataArray, offset,
342                                          stride);
343                         offset += stride;
344                         eltOffset += lineStride;
345                     }
346                 } else { // bitOffset % 8 != 0
347
int leftShift = bitOffset & 7;
348                     int rightShift = 8 - leftShift;
349                     for(int y = 0; y < rectHeight; y++) {
350                         int i = eltOffset;
351                         int xRemaining = rectWidth;
352                         while(xRemaining > 0) {
353                             if(xRemaining > rightShift) {
354                                 binaryDataArray[b++] =
355                                     (byte)(((data[i++]&0xFF) << leftShift) |
356                                            ((data[i]&0xFF) >>> rightShift));
357                             } else {
358                                 binaryDataArray[b++] =
359                                     (byte)((data[i]&0xFF) << leftShift);
360                             }
361                             xRemaining -= 8;
362                         }
363                         eltOffset += lineStride;
364                     }
365                 }
366             } else if(dataBuffer instanceof DataBufferShort JavaDoc ||
367                       dataBuffer instanceof DataBufferUShort JavaDoc) {
368                 short[] data = dataBuffer instanceof DataBufferShort JavaDoc ?
369                     ((DataBufferShort JavaDoc)dataBuffer).getData() :
370                     ((DataBufferUShort JavaDoc)dataBuffer).getData();
371
372                 for(int y = 0; y < rectHeight; y++) {
373                     int bOffset = bitOffset;
374                     for(int x = 0; x < rectWidth; x += 8, bOffset += 8) {
375                         int i = eltOffset + bOffset/16;
376                         int mod = bOffset % 16;
377                         int left = data[i] & 0xFFFF;
378                         if(mod <= 8) {
379                             binaryDataArray[b++] = (byte)(left >>> (8 - mod));
380                         } else {
381                             int delta = mod - 8;
382                             int right = data[i+1] & 0xFFFF;
383                             binaryDataArray[b++] =
384                                 (byte)((left << delta) |
385                                        (right >>> (16 - delta)));
386                         }
387                     }
388                     eltOffset += lineStride;
389                 }
390             } else if(dataBuffer instanceof DataBufferInt JavaDoc) {
391                 int[] data = ((DataBufferInt JavaDoc)dataBuffer).getData();
392
393                 for(int y = 0; y < rectHeight; y++) {
394                     int bOffset = bitOffset;
395                     for(int x = 0; x < rectWidth; x += 8, bOffset += 8) {
396                         int i = eltOffset + bOffset/32;
397                         int mod = bOffset % 32;
398                         int left = data[i];
399                         if(mod <= 24) {
400                             binaryDataArray[b++] =
401                                 (byte)(left >>> (24 - mod));
402                         } else {
403                             int delta = mod - 24;
404                             int right = data[i+1];
405                             binaryDataArray[b++] =
406                                 (byte)((left << delta) |
407                                        (right >>> (32 - delta)));
408                         }
409                     }
410                     eltOffset += lineStride;
411                 }
412             }
413         }
414
415         return binaryDataArray;
416     }
417
418     /**
419      * Returns the binary data unpacked into an array of bytes.
420      * The line stride will be the width of the <code>Raster</code>.
421      *
422      * @throws IllegalArgumentException if <code>isBinary()</code> returns
423      * <code>false</code> with the <code>SampleModel</code> of the
424      * supplied <code>Raster</code> as argument.
425      */

426     public static byte[] getUnpackedBinaryData(Raster JavaDoc raster,
427                                                Rectangle JavaDoc rect) {
428         SampleModel JavaDoc sm = raster.getSampleModel();
429         if(!isBinary(sm)) {
430             throw new IllegalArgumentException JavaDoc(I18N.getString("ImageUtil0"));
431         }
432
433         int rectX = rect.x;
434         int rectY = rect.y;
435         int rectWidth = rect.width;
436         int rectHeight = rect.height;
437
438         DataBuffer JavaDoc dataBuffer = raster.getDataBuffer();
439
440         int dx = rectX - raster.getSampleModelTranslateX();
441         int dy = rectY - raster.getSampleModelTranslateY();
442
443         MultiPixelPackedSampleModel JavaDoc mpp = (MultiPixelPackedSampleModel JavaDoc)sm;
444         int lineStride = mpp.getScanlineStride();
445         int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy);
446         int bitOffset = mpp.getBitOffset(dx);
447
448         byte[] bdata = new byte[rectWidth*rectHeight];
449         int maxY = rectY + rectHeight;
450         int maxX = rectX + rectWidth;
451         int k = 0;
452
453         if(dataBuffer instanceof DataBufferByte JavaDoc) {
454             byte[] data = ((DataBufferByte JavaDoc)dataBuffer).getData();
455             for(int y = rectY; y < maxY; y++) {
456                 int bOffset = eltOffset*8 + bitOffset;
457                 for(int x = rectX; x < maxX; x++) {
458                     byte b = data[bOffset/8];
459                     bdata[k++] =
460                         (byte)((b >>> (7 - bOffset & 7)) & 0x0000001);
461                     bOffset++;
462                 }
463                 eltOffset += lineStride;
464             }
465         } else if(dataBuffer instanceof DataBufferShort JavaDoc ||
466                   dataBuffer instanceof DataBufferUShort JavaDoc) {
467             short[] data = dataBuffer instanceof DataBufferShort JavaDoc ?
468                 ((DataBufferShort JavaDoc)dataBuffer).getData() :
469                 ((DataBufferUShort JavaDoc)dataBuffer).getData();
470             for(int y = rectY; y < maxY; y++) {
471                 int bOffset = eltOffset*16 + bitOffset;
472                 for(int x = rectX; x < maxX; x++) {
473                     short s = data[bOffset/16];
474                     bdata[k++] =
475                         (byte)((s >>> (15 - bOffset % 16)) &
476                                0x0000001);
477                     bOffset++;
478                 }
479                 eltOffset += lineStride;
480             }
481         } else if(dataBuffer instanceof DataBufferInt JavaDoc) {
482             int[] data = ((DataBufferInt JavaDoc)dataBuffer).getData();
483             for(int y = rectY; y < maxY; y++) {
484                 int bOffset = eltOffset*32 + bitOffset;
485                 for(int x = rectX; x < maxX; x++) {
486                     int i = data[bOffset/32];
487                     bdata[k++] =
488                         (byte)((i >>> (31 - bOffset % 32)) &
489                                0x0000001);
490                     bOffset++;
491                 }
492                 eltOffset += lineStride;
493             }
494         }
495
496         return bdata;
497     }
498
499     /**
500      * Sets the supplied <code>Raster</code>'s data from an array
501      * of packed binary data of the form returned by
502      * <code>getPackedBinaryData()</code>.
503      *
504      * @throws IllegalArgumentException if <code>isBinary()</code> returns
505      * <code>false</code> with the <code>SampleModel</code> of the
506      * supplied <code>Raster</code> as argument.
507      */

508     public static void setPackedBinaryData(byte[] binaryDataArray,
509                                            WritableRaster JavaDoc raster,
510                                            Rectangle JavaDoc rect) {
511         SampleModel JavaDoc sm = raster.getSampleModel();
512         if(!isBinary(sm)) {
513             throw new IllegalArgumentException JavaDoc(I18N.getString("ImageUtil0"));
514         }
515
516         int rectX = rect.x;
517         int rectY = rect.y;
518         int rectWidth = rect.width;
519         int rectHeight = rect.height;
520
521         DataBuffer JavaDoc dataBuffer = raster.getDataBuffer();
522
523         int dx = rectX - raster.getSampleModelTranslateX();
524         int dy = rectY - raster.getSampleModelTranslateY();
525
526         MultiPixelPackedSampleModel JavaDoc mpp = (MultiPixelPackedSampleModel JavaDoc)sm;
527         int lineStride = mpp.getScanlineStride();
528         int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy);
529         int bitOffset = mpp.getBitOffset(dx);
530
531         int b = 0;
532
533         if(bitOffset == 0) {
534             if(dataBuffer instanceof DataBufferByte JavaDoc) {
535                 byte[] data = ((DataBufferByte JavaDoc)dataBuffer).getData();
536                 if(data == binaryDataArray) {
537                     // Optimal case: simply return.
538
return;
539                 }
540                 int stride = (rectWidth + 7)/8;
541                 int offset = 0;
542                 for(int y = 0; y < rectHeight; y++) {
543                     System.arraycopy(binaryDataArray, offset,
544                                      data, eltOffset,
545                                      stride);
546                     offset += stride;
547                     eltOffset += lineStride;
548                 }
549             } else if(dataBuffer instanceof DataBufferShort JavaDoc ||
550                       dataBuffer instanceof DataBufferUShort JavaDoc) {
551                 short[] data = dataBuffer instanceof DataBufferShort JavaDoc ?
552                     ((DataBufferShort JavaDoc)dataBuffer).getData() :
553                     ((DataBufferUShort JavaDoc)dataBuffer).getData();
554
555                 for(int y = 0; y < rectHeight; y++) {
556                     int xRemaining = rectWidth;
557                     int i = eltOffset;
558                     while(xRemaining > 8) {
559                         data[i++] =
560                             (short)(((binaryDataArray[b++] & 0xFF) << 8) |
561                                     (binaryDataArray[b++] & 0xFF));
562                         xRemaining -= 16;
563                     }
564                     if(xRemaining > 0) {
565                         data[i++] =
566                             (short)((binaryDataArray[b++] & 0xFF) << 8);
567                     }
568                     eltOffset += lineStride;
569                 }
570             } else if(dataBuffer instanceof DataBufferInt JavaDoc) {
571                 int[] data = ((DataBufferInt JavaDoc)dataBuffer).getData();
572
573                 for(int y = 0; y < rectHeight; y++) {
574                     int xRemaining = rectWidth;
575                     int i = eltOffset;
576                     while(xRemaining > 24) {
577                         data[i++] =
578                             (int)(((binaryDataArray[b++] & 0xFF) << 24) |
579                                   ((binaryDataArray[b++] & 0xFF) << 16) |
580                                   ((binaryDataArray[b++] & 0xFF) << 8) |
581                                   (binaryDataArray[b++] & 0xFF));
582                         xRemaining -= 32;
583                     }
584                     int shift = 24;
585                     while(xRemaining > 0) {
586                         data[i] |=
587                             (int)((binaryDataArray[b++] & 0xFF) << shift);
588                         shift -= 8;
589                         xRemaining -= 8;
590                     }
591                     eltOffset += lineStride;
592                 }
593             }
594         } else { // bitOffset != 0
595
int stride = (rectWidth + 7)/8;
596             int offset = 0;
597             if(dataBuffer instanceof DataBufferByte JavaDoc) {
598                 byte[] data = ((DataBufferByte JavaDoc)dataBuffer).getData();
599
600                 if((bitOffset & 7) == 0) {
601                     for(int y = 0; y < rectHeight; y++) {
602                         System.arraycopy(binaryDataArray, offset,
603                                          data, eltOffset,
604                                          stride);
605                         offset += stride;
606                         eltOffset += lineStride;
607                     }
608                 } else { // bitOffset % 8 != 0
609
int rightShift = bitOffset & 7;
610                     int leftShift = 8 - rightShift;
611                     int leftShift8 = 8 + leftShift;
612             int mask = (byte)(255<<leftShift);
613             int mask1 = (byte)~mask;
614
615                     for(int y = 0; y < rectHeight; y++) {
616                         int i = eltOffset;
617                         int xRemaining = rectWidth;
618                         while(xRemaining > 0) {
619                             byte datum = binaryDataArray[b++];
620
621                             if (xRemaining > leftShift8) {
622                 // when all the bits in this BYTE will be set
623
// into the data buffer.
624
data[i] = (byte)((data[i] & mask ) |
625                                     ((datum&0xFF) >>> rightShift));
626                                 data[++i] = (byte)((datum & 0xFF) << leftShift);
627                             } else if (xRemaining > leftShift) {
628                 // All the "leftShift" high bits will be set
629
// into the data buffer. But not all the
630
// "rightShift" low bits will be set.
631
data[i] = (byte)((data[i] & mask ) |
632                     ((datum&0xFF) >>> rightShift));
633                 i++;
634                 data[i] =
635                     (byte)((data[i] & mask1) | ((datum & 0xFF) << leftShift));
636                 }
637                 else {
638                 // Less than "leftShift" high bits will be set.
639
int remainMask = (1 << leftShift - xRemaining) - 1;
640                                 data[i] =
641                                     (byte)((data[i] & (mask | remainMask)) |
642                     (datum&0xFF) >>> rightShift & ~remainMask);
643                             }
644                             xRemaining -= 8;
645                         }
646                         eltOffset += lineStride;
647                     }
648                 }
649             } else if(dataBuffer instanceof DataBufferShort JavaDoc ||
650                       dataBuffer instanceof DataBufferUShort JavaDoc) {
651                 short[] data = dataBuffer instanceof DataBufferShort JavaDoc ?
652                     ((DataBufferShort JavaDoc)dataBuffer).getData() :
653                     ((DataBufferUShort JavaDoc)dataBuffer).getData();
654
655         int rightShift = bitOffset & 7;
656         int leftShift = 8 - rightShift;
657                 int leftShift16 = 16 + leftShift;
658         int mask = (short)(~(255 << leftShift));
659         int mask1 = (short)(65535 << leftShift);
660         int mask2 = (short)~mask1;
661
662                 for(int y = 0; y < rectHeight; y++) {
663                     int bOffset = bitOffset;
664             int xRemaining = rectWidth;
665                     for(int x = 0; x < rectWidth;
666             x += 8, bOffset += 8, xRemaining -= 8) {
667                         int i = eltOffset + (bOffset >> 4);
668                         int mod = bOffset & 15;
669                         int datum = binaryDataArray[b++] & 0xFF;
670                         if(mod <= 8) {
671                 // This BYTE is set into one SHORT
672
if (xRemaining < 8) {
673                 // Mask the bits to be set.
674
datum &= 255 << 8 - xRemaining;
675                 }
676                             data[i] = (short)((data[i] & mask) | (datum << leftShift));
677                         } else if (xRemaining > leftShift16) {
678                 // This BYTE will be set into two SHORTs
679
data[i] = (short)((data[i] & mask1) | ((datum >>> rightShift)&0xFFFF));
680                             data[++i] =
681                                 (short)((datum << leftShift)&0xFFFF);
682                         } else if (xRemaining > leftShift) {
683                 // This BYTE will be set into two SHORTs;
684
// But not all the low bits will be set into SHORT
685
data[i] = (short)((data[i] & mask1) | ((datum >>> rightShift)&0xFFFF));
686                 i++;
687                 data[i] =
688                     (short)((data[i] & mask2) | ((datum << leftShift)&0xFFFF));
689             } else {
690                 // Only some of the high bits will be set into
691
// SHORTs
692
int remainMask = (1 << leftShift - xRemaining) - 1;
693                 data[i] = (short)((data[i] & (mask1 | remainMask)) |
694                       ((datum >>> rightShift)&0xFFFF & ~remainMask));
695             }
696                     }
697                     eltOffset += lineStride;
698                 }
699             } else if(dataBuffer instanceof DataBufferInt JavaDoc) {
700                 int[] data = ((DataBufferInt JavaDoc)dataBuffer).getData();
701                 int rightShift = bitOffset & 7;
702         int leftShift = 8 - rightShift;
703         int leftShift32 = 32 + leftShift;
704         int mask = 0xFFFFFFFF << leftShift;
705         int mask1 = ~mask;
706
707                 for(int y = 0; y < rectHeight; y++) {
708                     int bOffset = bitOffset;
709             int xRemaining = rectWidth;
710                     for(int x = 0; x < rectWidth;
711             x += 8, bOffset += 8, xRemaining -= 8) {
712                         int i = eltOffset + (bOffset >> 5);
713                         int mod = bOffset & 31;
714                         int datum = binaryDataArray[b++] & 0xFF;
715                         if(mod <= 24) {
716                 // This BYTE is set into one INT
717
int shift = 24 - mod;
718                 if (xRemaining < 8) {
719                 // Mask the bits to be set.
720
datum &= 255 << 8 - xRemaining;
721                 }
722                             data[i] = (data[i] & (~(255 << shift))) | (datum << shift);
723                         } else if (xRemaining > leftShift32) {
724                 // All the bits of this BYTE will be set into two INTs
725
data[i] = (data[i] & mask) | (datum >>> rightShift);
726                             data[++i] = datum << leftShift;
727                         } else if (xRemaining > leftShift) {
728                 // This BYTE will be set into two INTs;
729
// But not all the low bits will be set into INT
730
data[i] = (data[i] & mask) | (datum >>> rightShift);
731                 i++;
732                             data[i] = (data[i] & mask1) | (datum << leftShift);
733                         } else {
734                 // Only some of the high bits will be set into INT
735
int remainMask = (1 << leftShift - xRemaining) - 1;
736                 data[i] = (data[i] & (mask | remainMask)) |
737                       (datum >>> rightShift & ~remainMask);
738             }
739                     }
740                     eltOffset += lineStride;
741                 }
742             }
743         }
744     }
745
746     /**
747      * Copies data into the packed array of the <code>Raster</code>
748      * from an array of unpacked data of the form returned by
749      * <code>getUnpackedBinaryData()</code>.
750      *
751      * <p> If the data are binary, then the target bit will be set if
752      * and only if the corresponding byte is non-zero.
753      *
754      * @throws IllegalArgumentException if <code>isBinary()</code> returns
755      * <code>false</code> with the <code>SampleModel</code> of the
756      * supplied <code>Raster</code> as argument.
757      */

758     public static void setUnpackedBinaryData(byte[] bdata,
759                                              WritableRaster JavaDoc raster,
760                                              Rectangle JavaDoc rect) {
761         SampleModel JavaDoc sm = raster.getSampleModel();
762         if(!isBinary(sm)) {
763             throw new IllegalArgumentException JavaDoc(I18N.getString("ImageUtil0"));
764         }
765
766         int rectX = rect.x;
767         int rectY = rect.y;
768         int rectWidth = rect.width;
769         int rectHeight = rect.height;
770
771         DataBuffer JavaDoc dataBuffer = raster.getDataBuffer();
772
773         int dx = rectX - raster.getSampleModelTranslateX();
774         int dy = rectY - raster.getSampleModelTranslateY();
775
776         MultiPixelPackedSampleModel JavaDoc mpp = (MultiPixelPackedSampleModel JavaDoc)sm;
777         int lineStride = mpp.getScanlineStride();
778         int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy);
779         int bitOffset = mpp.getBitOffset(dx);
780
781         int k = 0;
782
783         if(dataBuffer instanceof DataBufferByte JavaDoc) {
784             byte[] data = ((DataBufferByte JavaDoc)dataBuffer).getData();
785             for(int y = 0; y < rectHeight; y++) {
786                 int bOffset = eltOffset*8 + bitOffset;
787                 for(int x = 0; x < rectWidth; x++) {
788                     if(bdata[k++] != (byte)0) {
789                         data[bOffset/8] |=
790                             (byte)(0x00000001 << (7 - bOffset & 7));
791                     }
792                     bOffset++;
793                 }
794                 eltOffset += lineStride;
795             }
796         } else if(dataBuffer instanceof DataBufferShort JavaDoc ||
797                   dataBuffer instanceof DataBufferUShort JavaDoc) {
798             short[] data = dataBuffer instanceof DataBufferShort JavaDoc ?
799                 ((DataBufferShort JavaDoc)dataBuffer).getData() :
800                 ((DataBufferUShort JavaDoc)dataBuffer).getData();
801             for(int y = 0; y < rectHeight; y++) {
802                 int bOffset = eltOffset*16 + bitOffset;
803                 for(int x = 0; x < rectWidth; x++) {
804                     if(bdata[k++] != (byte)0) {
805                         data[bOffset/16] |=
806                             (short)(0x00000001 <<
807                                     (15 - bOffset % 16));
808                     }
809                     bOffset++;
810                 }
811                 eltOffset += lineStride;
812             }
813         } else if(dataBuffer instanceof DataBufferInt JavaDoc) {
814             int[] data = ((DataBufferInt JavaDoc)dataBuffer).getData();
815             for(int y = 0; y < rectHeight; y++) {
816                 int bOffset = eltOffset*32 + bitOffset;
817                 for(int x = 0; x < rectWidth; x++) {
818                     if(bdata[k++] != (byte)0) {
819                         data[bOffset/32] |=
820                             (int)(0x00000001 <<
821                                   (31 - bOffset % 32));
822                     }
823                     bOffset++;
824                 }
825                 eltOffset += lineStride;
826             }
827         }
828     }
829
830     public static boolean isBinary(SampleModel JavaDoc sm) {
831         return sm instanceof MultiPixelPackedSampleModel JavaDoc &&
832             ((MultiPixelPackedSampleModel JavaDoc)sm).getPixelBitStride() == 1 &&
833             sm.getNumBands() == 1;
834     }
835
836     public static ColorModel JavaDoc createColorModel(ColorSpace JavaDoc colorSpace,
837                                               SampleModel JavaDoc sampleModel) {
838         ColorModel JavaDoc colorModel = null;
839
840         if(sampleModel == null) {
841             throw new IllegalArgumentException JavaDoc(I18N.getString("ImageUtil1"));
842         }
843
844         int numBands = sampleModel.getNumBands();
845         if (numBands < 1 || numBands > 4) {
846             return null;
847         }
848
849         int dataType = sampleModel.getDataType();
850         if (sampleModel instanceof ComponentSampleModel JavaDoc) {
851             if (dataType < DataBuffer.TYPE_BYTE ||
852                 //dataType == DataBuffer.TYPE_SHORT ||
853
dataType > DataBuffer.TYPE_DOUBLE) {
854                 return null;
855             }
856
857             if (colorSpace == null)
858                 colorSpace =
859                     numBands <= 2 ?
860                     ColorSpace.getInstance(ColorSpace.CS_GRAY) :
861                     ColorSpace.getInstance(ColorSpace.CS_sRGB);
862
863             boolean useAlpha = (numBands == 2) || (numBands == 4);
864             int transparency = useAlpha ?
865                                Transparency.TRANSLUCENT : Transparency.OPAQUE;
866
867             boolean premultiplied = false;
868
869             int dataTypeSize = DataBuffer.getDataTypeSize(dataType);
870             int[] bits = new int[numBands];
871             for (int i = 0; i < numBands; i++) {
872                 bits[i] = dataTypeSize;
873             }
874
875             colorModel = new ComponentColorModel JavaDoc(colorSpace,
876                                                  bits,
877                                                  useAlpha,
878                                                  premultiplied,
879                                                  transparency,
880                                                  dataType);
881         } else if (sampleModel instanceof SinglePixelPackedSampleModel JavaDoc) {
882             SinglePixelPackedSampleModel JavaDoc sppsm =
883                 (SinglePixelPackedSampleModel JavaDoc)sampleModel;
884
885             int[] bitMasks = sppsm.getBitMasks();
886             int rmask = 0;
887             int gmask = 0;
888             int bmask = 0;
889             int amask = 0;
890
891             numBands = bitMasks.length;
892             if (numBands <= 2) {
893                 rmask = gmask = bmask = bitMasks[0];
894                 if (numBands == 2) {
895                     amask = bitMasks[1];
896                 }
897             } else {
898                 rmask = bitMasks[0];
899                 gmask = bitMasks[1];
900                 bmask = bitMasks[2];
901                 if (numBands == 4) {
902                     amask = bitMasks[3];
903                 }
904             }
905
906             int[] sampleSize = sppsm.getSampleSize();
907             int bits = 0;
908             for (int i = 0; i < sampleSize.length; i++) {
909                 bits += sampleSize[i];
910             }
911
912             if (colorSpace == null)
913                 colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
914
915             colorModel =
916                 new DirectColorModel JavaDoc(colorSpace,
917                                      bits, rmask, gmask, bmask, amask,
918                                      false,
919                                      sampleModel.getDataType());
920         } else if (sampleModel instanceof MultiPixelPackedSampleModel JavaDoc) {
921             int bits =
922                 ((MultiPixelPackedSampleModel JavaDoc)sampleModel).getPixelBitStride();
923             int size = 1 << bits;
924             byte[] comp = new byte[size];
925
926             for (int i = 0; i < size; i++)
927                 comp[i] = (byte)(255 * i / (size - 1));
928
929             colorModel = new IndexColorModel JavaDoc(bits, size, comp, comp, comp);
930         }
931
932         return colorModel;
933     }
934
935     public static int getElementSize(SampleModel JavaDoc sm) {
936         int elementSize = DataBuffer.getDataTypeSize(sm.getDataType());
937         
938         if (sm instanceof MultiPixelPackedSampleModel JavaDoc) {
939             MultiPixelPackedSampleModel JavaDoc mppsm =
940                 (MultiPixelPackedSampleModel JavaDoc)sm;
941             return mppsm.getSampleSize(0) * mppsm.getNumBands();
942         } else if (sm instanceof ComponentSampleModel JavaDoc) {
943             return sm.getNumBands() * elementSize;
944         } else if (sm instanceof SinglePixelPackedSampleModel JavaDoc) {
945             return elementSize;
946         }
947         
948         return elementSize * sm.getNumBands();
949         
950     }
951     
952     public static long getTileSize(SampleModel JavaDoc sm) {
953         int elementSize = DataBuffer.getDataTypeSize(sm.getDataType());
954
955         if (sm instanceof MultiPixelPackedSampleModel JavaDoc) {
956             MultiPixelPackedSampleModel JavaDoc mppsm =
957                 (MultiPixelPackedSampleModel JavaDoc)sm;
958             return (mppsm.getScanlineStride() * mppsm.getHeight() +
959                    (mppsm.getDataBitOffset() + elementSize -1) / elementSize) *
960                    ((elementSize + 7) / 8);
961         } else if (sm instanceof ComponentSampleModel JavaDoc) {
962             ComponentSampleModel JavaDoc csm = (ComponentSampleModel JavaDoc)sm;
963             int[] bandOffsets = csm.getBandOffsets();
964             int maxBandOff = bandOffsets[0];
965             for (int i=1; i<bandOffsets.length; i++)
966                 maxBandOff = Math.max(maxBandOff, bandOffsets[i]);
967
968             long size = 0;
969             int pixelStride = csm.getPixelStride();
970             int scanlineStride = csm.getScanlineStride();
971             if (maxBandOff >= 0)
972                 size += maxBandOff + 1;
973             if (pixelStride > 0)
974                 size += pixelStride * (sm.getWidth() - 1);
975             if (scanlineStride > 0)
976                 size += scanlineStride * (sm.getHeight() - 1);
977
978             int[] bankIndices = csm.getBankIndices();
979             maxBandOff = bankIndices[0];
980             for (int i=1; i<bankIndices.length; i++)
981                 maxBandOff = Math.max(maxBandOff, bankIndices[i]);
982             return size * (maxBandOff + 1) * ((elementSize + 7) / 8);
983         } else if (sm instanceof SinglePixelPackedSampleModel JavaDoc) {
984             SinglePixelPackedSampleModel JavaDoc sppsm =
985                 (SinglePixelPackedSampleModel JavaDoc)sm;
986             long size = sppsm.getScanlineStride() * (sppsm.getHeight() - 1) +
987                         sppsm.getWidth();
988             return size * ((elementSize + 7) / 8);
989         }
990
991         return 0;
992     }
993
994     public static long getBandSize(SampleModel JavaDoc sm) {
995         int elementSize = DataBuffer.getDataTypeSize(sm.getDataType());
996
997         if (sm instanceof ComponentSampleModel JavaDoc) {
998             ComponentSampleModel JavaDoc csm = (ComponentSampleModel JavaDoc)sm;
999             int pixelStride = csm.getPixelStride();
1000            int scanlineStride = csm.getScanlineStride();
1001            long size = Math.min(pixelStride, scanlineStride);
1002
1003            if (pixelStride > 0)
1004                size += pixelStride * (sm.getWidth() - 1);
1005            if (scanlineStride > 0)
1006                size += scanlineStride * (sm.getHeight() - 1);
1007            return size * ((elementSize + 7) / 8);
1008        } else
1009            return getTileSize(sm);
1010    }
1011    /**
1012     * Tests whether the color indices represent a gray-scale image.
1013     *
1014     * @param r The red channel color indices.
1015     * @param g The green channel color indices.
1016     * @param b The blue channel color indices.
1017     * @return If all the indices have 256 entries, and are identical mappings,
1018     * return <code>true</code>; otherwise, return <code>false</code>.
1019     */

1020    public static boolean isIndicesForGrayscale(byte[] r, byte[] g, byte[] b) {
1021        if (r.length != g.length || r.length != b.length)
1022            return false;
1023
1024        int size = r.length;
1025
1026        if (size != 256)
1027            return false;
1028
1029        for (int i = 0; i < size; i++) {
1030            byte temp = (byte) i;
1031
1032            if (r[i] != temp || g[i] != temp || b[i] != temp)
1033                return false;
1034        }
1035
1036        return true;
1037    }
1038 
1039    /** Converts the provided object to <code>String</code> */
1040    public static String JavaDoc convertObjectToString(Object JavaDoc obj) {
1041        if (obj == null)
1042            return "";
1043        
1044        String JavaDoc s = "";
1045        if (obj instanceof byte[]) {
1046            byte[] bArray = (byte[])obj;
1047            for (int i = 0; i < bArray.length; i++)
1048                s += bArray[i] + " ";
1049            return s;
1050        }
1051        
1052        if (obj instanceof int[]) {
1053            int[] iArray = (int[])obj;
1054            for (int i = 0; i < iArray.length; i++)
1055                s += iArray[i] + " " ;
1056            return s;
1057        }
1058        
1059        if (obj instanceof short[]) {
1060            short[] sArray = (short[])obj;
1061            for (int i = 0; i < sArray.length; i++)
1062                s += sArray[i] + " " ;
1063            return s;
1064        }
1065        
1066        return obj.toString();
1067        
1068    }
1069    
1070    /** Checks that the provided <code>ImageWriter</code> can encode
1071     * the provided <code>ImageTypeSpecifier</code> or not. If not, an
1072     * <code>IIOException</code> will be thrown.
1073     * @param writer The provided <code>ImageWriter</code>.
1074     * @param type The image to be tested.
1075     * @throws IIOException If the writer cannot encoded the provided image.
1076     */

1077    public static final void canEncodeImage(ImageWriter JavaDoc writer,
1078                                            ImageTypeSpecifier JavaDoc type)
1079        throws IIOException JavaDoc {
1080    ImageWriterSpi JavaDoc spi = writer.getOriginatingProvider();
1081  
1082    if(type != null && spi != null && !spi.canEncodeImage(type)) {
1083        throw new IIOException JavaDoc(I18N.getString("ImageUtil2")+" "+
1084                                   writer.getClass().getName());
1085    }
1086    }
1087
1088    /** Checks that the provided <code>ImageWriter</code> can encode
1089     * the provided <code>ColorModel</code> and <code>SampleModel</code>.
1090     * If not, an <code>IIOException</code> will be thrown.
1091     * @param writer The provided <code>ImageWriter</code>.
1092     * @param colorModel The provided <code>ColorModel</code>.
1093     * @param sampleModel The provided <code>SampleModel</code>.
1094     * @throws IIOException If the writer cannot encoded the provided image.
1095     */

1096    public static final void canEncodeImage(ImageWriter JavaDoc writer,
1097                                            ColorModel JavaDoc colorModel,
1098                                            SampleModel JavaDoc sampleModel)
1099        throws IIOException JavaDoc {
1100    ImageTypeSpecifier JavaDoc type = null;
1101    if (colorModel != null && sampleModel != null)
1102        type = new ImageTypeSpecifier JavaDoc(colorModel, sampleModel);
1103    canEncodeImage(writer, type);
1104    }
1105
1106    /**
1107     * Returns whether the image has contiguous data across rows.
1108     */

1109    public static final boolean imageIsContiguous(RenderedImage JavaDoc image) {
1110        SampleModel JavaDoc sm;
1111        if(image instanceof BufferedImage JavaDoc) {
1112            WritableRaster JavaDoc ras = ((BufferedImage JavaDoc)image).getRaster();
1113            sm = ras.getSampleModel();
1114        } else {
1115            sm = image.getSampleModel();
1116        }
1117        
1118        if (sm instanceof ComponentSampleModel JavaDoc) {
1119            // Ensure image rows samples are stored contiguously
1120
// in a single bank.
1121
ComponentSampleModel JavaDoc csm = (ComponentSampleModel JavaDoc)sm;
1122
1123            if (csm.getPixelStride() != csm.getNumBands()) {
1124                return false;
1125            }
1126
1127            int[] bandOffsets = csm.getBandOffsets();
1128            for (int i = 0; i < bandOffsets.length; i++) {
1129                if (bandOffsets[i] != i) {
1130                    return false;
1131                }
1132            }
1133
1134            int[] bankIndices = csm.getBankIndices();
1135            for (int i = 0; i < bandOffsets.length; i++) {
1136                if (bankIndices[i] != 0) {
1137                    return false;
1138                }
1139            }
1140
1141            return true;
1142        }
1143
1144        // Otherwise true if and only if it's a bilevel image with
1145
// a MultiPixelPackedSampleModel, 1 bit per pixel, and 1 bit
1146
// pixel stride.
1147
return ImageUtil.isBinary(sm);
1148    }
1149}
1150
1151  
1152
1153
1154
Popular Tags