comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/TIFFDirectory.d @ 0:6dd524f61e62

add dwt win and basic java stuff
author Frank Benoit <benoit@tionex.de>
date Mon, 02 Mar 2009 14:44:16 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:6dd524f61e62
1 /*******************************************************************************
2 * Copyright (c) 2000, 2005 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module org.eclipse.swt.internal.image.TIFFDirectory;
14
15 import org.eclipse.swt.internal.image.TIFFRandomFileAccess;
16 import org.eclipse.swt.internal.image.TIFFModifiedHuffmanCodec;
17 import org.eclipse.swt.internal.image.LEDataOutputStream;
18 import org.eclipse.swt.graphics.ImageData;
19 import org.eclipse.swt.graphics.ImageLoaderEvent;
20 import org.eclipse.swt.graphics.ImageLoader;
21 import org.eclipse.swt.graphics.PaletteData;
22 import org.eclipse.swt.graphics.RGB;
23 import org.eclipse.swt.SWT;
24 import java.lang.all;
25
26 final class TIFFDirectory {
27
28 TIFFRandomFileAccess file;
29 bool isLittleEndian;
30 ImageLoader loader;
31 int depth;
32
33 /* Directory fields */
34 int imageWidth;
35 int imageLength;
36 int[] bitsPerSample;
37 int compression;
38 int photometricInterpretation;
39 int[] stripOffsets;
40 int samplesPerPixel;
41 int rowsPerStrip;
42 int[] stripByteCounts;
43 int t4Options;
44 int colorMapOffset;
45
46 /* Encoder fields */
47 ImageData image;
48 LEDataOutputStream ostr;
49
50 static const int NO_VALUE = -1;
51
52 static const short TAG_ImageWidth = 256;
53 static const short TAG_ImageLength = 257;
54 static const short TAG_BitsPerSample = 258;
55 static const short TAG_Compression = 259;
56 static const short TAG_PhotometricInterpretation = 262;
57 static const short TAG_StripOffsets = 273;
58 static const short TAG_SamplesPerPixel = 277;
59 static const short TAG_RowsPerStrip = 278;
60 static const short TAG_StripByteCounts = 279;
61 static const short TAG_XResolution = 282;
62 static const short TAG_YResolution = 283;
63 static const short TAG_T4Options = 292;
64 static const short TAG_ResolutionUnit = 296;
65 static const short TAG_ColorMap = 320;
66
67 static const int TYPE_BYTE = 1;
68 static const int TYPE_ASCII = 2;
69 static const int TYPE_SHORT = 3;
70 static const int TYPE_LONG = 4;
71 static const int TYPE_RATIONAL = 5;
72
73 /* Different compression schemes */
74 static const int COMPRESSION_NONE = 1;
75 static const int COMPRESSION_CCITT_3_1 = 2;
76 static const int COMPRESSION_PACKBITS = 32773;
77
78 static const int IFD_ENTRY_SIZE = 12;
79
80 public this(TIFFRandomFileAccess file, bool isLittleEndian, ImageLoader loader) {
81 this.file = file;
82 this.isLittleEndian = isLittleEndian;
83 this.loader = loader;
84 }
85
86 public this(ImageData image) {
87 this.image = image;
88 }
89
90 /* PackBits decoder */
91 int decodePackBits(byte[] src, byte[] dest, int offsetDest) {
92 int destIndex = offsetDest;
93 int srcIndex = 0;
94 while (srcIndex < src.length) {
95 byte n = src[srcIndex];
96 if (0 <= n && n <= 127) {
97 /* Copy next n+1 bytes literally */
98 System.arraycopy(src, ++srcIndex, dest, destIndex, n + 1);
99 srcIndex += n + 1;
100 destIndex += n + 1;
101 } else if (-127 <= n && n <= -1) {
102 /* Copy next byte -n+1 times */
103 byte value = src[++srcIndex];
104 for (int j = 0; j < -n + 1; j++) {
105 dest[destIndex++] = value;
106 }
107 srcIndex++;
108 } else {
109 /* Noop when n is -128 */
110 srcIndex++;
111 }
112 }
113 /* Number of bytes copied */
114 return destIndex - offsetDest;
115 }
116
117 int getEntryValue(int type, byte[] buffer, int index) {
118 return toInt(buffer, index + 8, type);
119 }
120
121 void getEntryValue(int type, byte[] buffer, int index, int[] values) {
122 int start = index + 8;
123 int size;
124 int offset = toInt(buffer, start, TYPE_LONG);
125 switch (type) {
126 case TYPE_SHORT: size = 2; break;
127 case TYPE_LONG: size = 4; break;
128 case TYPE_RATIONAL: size = 8; break;
129 case TYPE_ASCII:
130 case TYPE_BYTE: size = 1; break;
131 default: SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT); return;
132 }
133 if (values.length * size > 4) {
134 buffer = new byte[values.length * size];
135 file.seek(offset);
136 file.read(buffer);
137 start = 0;
138 }
139 for (int i = 0; i < values.length; i++) {
140 values[i] = toInt(buffer, start + i * size, type);
141 }
142 }
143
144 void decodePixels(ImageData image) {
145 /* Each row is byte aligned */
146 byte[] imageData = new byte[(imageWidth * depth + 7) / 8 * imageLength];
147 image.data = imageData;
148 int destIndex = 0;
149 int length = stripOffsets.length;
150 for (int i = 0; i < length; i++) {
151 /* Read a strip */
152 byte[] data = new byte[](stripByteCounts[i]);
153 file.seek(stripOffsets[i]);
154 file.read(data);
155 if (compression is COMPRESSION_NONE) {
156 System.arraycopy(data, 0, imageData, destIndex, data.length);
157 destIndex += data.length;
158 } else if (compression is COMPRESSION_PACKBITS) {
159 destIndex += decodePackBits(data, imageData, destIndex);
160 } else if (compression is COMPRESSION_CCITT_3_1 || compression is 3) {
161 TIFFModifiedHuffmanCodec codec = new TIFFModifiedHuffmanCodec();
162 int nRows = rowsPerStrip;
163 if (i is length -1) {
164 int n = imageLength % rowsPerStrip;
165 if (n !is 0) nRows = n;
166 }
167 destIndex += codec.decode(data, imageData, destIndex, imageWidth, nRows);
168 }
169 if (loader.hasListeners()) {
170 loader.notifyListeners(new ImageLoaderEvent(loader, image, i, i is length - 1));
171 }
172 }
173 }
174
175 PaletteData getColorMap() {
176 int numColors = 1 << bitsPerSample[0];
177 /* R, G, B entries are 16 bit wide (2 bytes) */
178 int numBytes = 3 * 2 * numColors;
179 byte[] buffer = new byte[numBytes];
180 file.seek(colorMapOffset);
181 file.read(buffer);
182 RGB[] colors = new RGB[numColors];
183 /**
184 * SWT does not support 16-bit depth color formats.
185 * Convert the 16-bit data to 8-bit data.
186 * The correct way to do this is to multiply each
187 * 16 bit value by the value:
188 * (2^8 - 1) / (2^16 - 1).
189 * The fast way to do this is just to drop the low
190 * byte of the 16-bit value.
191 */
192 int offset = isLittleEndian ? 1 : 0;
193 int startG = 2 * numColors;
194 int startB = startG + 2 * numColors;
195 for (int i = 0; i < numColors; i++) {
196 int r = buffer[offset] & 0xFF;
197 int g = buffer[startG + offset] & 0xFF;
198 int b = buffer[startB + offset] & 0xFF;
199 colors[i] = new RGB(r, g, b);
200 offset += 2;
201 }
202 return new PaletteData(colors);
203 }
204
205 PaletteData getGrayPalette() {
206 int numColors = 1 << bitsPerSample[0];
207 RGB[] rgbs = new RGB[numColors];
208 for (int i = 0; i < numColors; i++) {
209 int value = i * 0xFF / (numColors - 1);
210 if (photometricInterpretation is 0) value = 0xFF - value;
211 rgbs[i] = new RGB(value, value, value);
212 }
213 return new PaletteData(rgbs);
214 }
215
216 PaletteData getRGBPalette(int bitsR, int bitsG, int bitsB) {
217 int blueMask = 0;
218 for (int i = 0; i < bitsB; i++) {
219 blueMask |= 1 << i;
220 }
221 int greenMask = 0;
222 for (int i = bitsB; i < bitsB + bitsG; i++) {
223 greenMask |= 1 << i;
224 }
225 int redMask = 0;
226 for (int i = bitsB + bitsG; i < bitsB + bitsG + bitsR; i++) {
227 redMask |= 1 << i;
228 }
229 return new PaletteData(redMask, greenMask, blueMask);
230 }
231
232 int formatStrips(int rowByteSize, int nbrRows, byte[] data, int maxStripByteSize, int offsetPostIFD, int extraBytes, int[][] strips) {
233 /*
234 * Calculate the nbr of required strips given the following requirements:
235 * - each strip should, if possible, not be greater than maxStripByteSize
236 * - each strip should contain 1 or more entire rows
237 *
238 * Format the strip fields arrays so that the image data is stored in one
239 * contiguous block. This block is stored after the IFD and after any tag
240 * info described in the IFD.
241 */
242 int n, nbrRowsPerStrip;
243 if (rowByteSize > maxStripByteSize) {
244 /* Each strip contains 1 row */
245 n = data.length / rowByteSize;
246 nbrRowsPerStrip = 1;
247 } else {
248 int nbr = (data.length + maxStripByteSize - 1) / maxStripByteSize;
249 nbrRowsPerStrip = nbrRows / nbr;
250 n = (nbrRows + nbrRowsPerStrip - 1) / nbrRowsPerStrip;
251 }
252 int stripByteSize = rowByteSize * nbrRowsPerStrip;
253
254 int[] offsets = new int[n];
255 int[] counts = new int[n];
256 /*
257 * Nbr of bytes between the end of the IFD directory and the start of
258 * the image data. Keep space for at least the offsets and counts
259 * data, each field being TYPE_LONG (4 bytes). If other tags require
260 * space between the IFD and the image block, use the extraBytes
261 * parameter.
262 * If there is only one strip, the offsets and counts data is stored
263 * directly in the IFD and we need not reserve space for it.
264 */
265 int postIFDData = n is 1 ? 0 : n * 2 * 4;
266 int startOffset = offsetPostIFD + extraBytes + postIFDData; /* offset of image data */
267
268 int offset = startOffset;
269 for (int i = 0; i < n; i++) {
270 /*
271 * Store all strips sequentially to allow us
272 * to copy all pixels in one contiguous area.
273 */
274 offsets[i] = offset;
275 counts[i] = stripByteSize;
276 offset += stripByteSize;
277 }
278 /* The last strip may contain fewer rows */
279 int mod = data.length % stripByteSize;
280 if (mod !is 0) counts[counts.length - 1] = mod;
281
282 strips[0] = offsets;
283 strips[1] = counts;
284 return nbrRowsPerStrip;
285 }
286
287 int[] formatColorMap(RGB[] rgbs) {
288 /*
289 * In a TIFF ColorMap, all red come first, followed by
290 * green and blue. All values must be converted from
291 * 8 bit to 16 bit.
292 */
293 int[] colorMap = new int[rgbs.length * 3];
294 int offsetGreen = rgbs.length;
295 int offsetBlue = rgbs.length * 2;
296 for (int i = 0; i < rgbs.length; i++) {
297 colorMap[i] = rgbs[i].red << 8 | rgbs[i].red;
298 colorMap[i + offsetGreen] = rgbs[i].green << 8 | rgbs[i].green;
299 colorMap[i + offsetBlue] = rgbs[i].blue << 8 | rgbs[i].blue;
300 }
301 return colorMap;
302 }
303
304 void parseEntries(byte[] buffer) {
305 for (int offset = 0; offset < buffer.length; offset += IFD_ENTRY_SIZE) {
306 int tag = toInt(buffer, offset, TYPE_SHORT);
307 int type = toInt(buffer, offset + 2, TYPE_SHORT);
308 int count = toInt(buffer, offset + 4, TYPE_LONG);
309 switch (tag) {
310 case TAG_ImageWidth: {
311 imageWidth = getEntryValue(type, buffer, offset);
312 break;
313 }
314 case TAG_ImageLength: {
315 imageLength = getEntryValue(type, buffer, offset);
316 break;
317 }
318 case TAG_BitsPerSample: {
319 if (type !is TYPE_SHORT) SWT.error(SWT.ERROR_INVALID_IMAGE);
320 bitsPerSample = new int[count];
321 getEntryValue(type, buffer, offset, bitsPerSample);
322 break;
323 }
324 case TAG_Compression: {
325 compression = getEntryValue(type, buffer, offset);
326 break;
327 }
328 case TAG_PhotometricInterpretation: {
329 photometricInterpretation = getEntryValue(type, buffer, offset);
330 break;
331 }
332 case TAG_StripOffsets: {
333 if (type !is TYPE_LONG && type !is TYPE_SHORT) SWT.error(SWT.ERROR_INVALID_IMAGE);
334 stripOffsets = new int[count];
335 getEntryValue(type, buffer, offset, stripOffsets);
336 break;
337 }
338 case TAG_SamplesPerPixel: {
339 if (type !is TYPE_SHORT) SWT.error(SWT.ERROR_INVALID_IMAGE);
340 samplesPerPixel = getEntryValue(type, buffer, offset);
341 /* Only the basic 1 and 3 values are supported */
342 if (samplesPerPixel !is 1 && samplesPerPixel !is 3) SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
343 break;
344 }
345 case TAG_RowsPerStrip: {
346 rowsPerStrip = getEntryValue(type, buffer, offset);
347 break;
348 }
349 case TAG_StripByteCounts: {
350 stripByteCounts = new int[count];
351 getEntryValue(type, buffer, offset, stripByteCounts);
352 break;
353 }
354 case TAG_XResolution: {
355 /* Ignored */
356 break;
357 }
358 case TAG_YResolution: {
359 /* Ignored */
360 break;
361 }
362 case TAG_T4Options: {
363 if (type !is TYPE_LONG) SWT.error(SWT.ERROR_INVALID_IMAGE);
364 t4Options = getEntryValue(type, buffer, offset);
365 if ((t4Options & 0x1) is 1) {
366 /* 2-dimensional coding is not supported */
367 SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
368 }
369 break;
370 }
371 case TAG_ResolutionUnit: {
372 /* Ignored */
373 break;
374 }
375 case TAG_ColorMap: {
376 if (type !is TYPE_SHORT) SWT.error(SWT.ERROR_INVALID_IMAGE);
377 /* Get the offset of the colorMap (use TYPE_LONG) */
378 colorMapOffset = getEntryValue(TYPE_LONG, buffer, offset);
379 break;
380 }
381 default:
382 }
383 }
384 }
385
386 public ImageData read() {
387 /* Set TIFF default values */
388 bitsPerSample = [1];
389 colorMapOffset = NO_VALUE;
390 compression = 1;
391 imageLength = NO_VALUE;
392 imageWidth = NO_VALUE;
393 photometricInterpretation = NO_VALUE;
394 rowsPerStrip = Integer.MAX_VALUE;
395 samplesPerPixel = 1;
396 stripByteCounts = null;
397 stripOffsets = null;
398
399 byte[] buffer = new byte[2];
400 file.read(buffer);
401 int numberEntries = toInt(buffer, 0, TYPE_SHORT);
402 buffer = new byte[IFD_ENTRY_SIZE * numberEntries];
403 file.read(buffer);
404 parseEntries(buffer);
405
406 PaletteData palette = null;
407 depth = 0;
408 switch (photometricInterpretation) {
409 case 0:
410 case 1: {
411 /* Bilevel or Grayscale image */
412 palette = getGrayPalette();
413 depth = bitsPerSample[0];
414 break;
415 }
416 case 2: {
417 /* RGB image */
418 if (colorMapOffset !is NO_VALUE) SWT.error(SWT.ERROR_INVALID_IMAGE);
419 /* SamplesPerPixel 3 is the only value supported */
420 palette = getRGBPalette(bitsPerSample[0], bitsPerSample[1], bitsPerSample[2]);
421 depth = bitsPerSample[0] + bitsPerSample[1] + bitsPerSample[2];
422 break;
423 }
424 case 3: {
425 /* Palette Color image */
426 if (colorMapOffset is NO_VALUE) SWT.error(SWT.ERROR_INVALID_IMAGE);
427 palette = getColorMap();
428 depth = bitsPerSample[0];
429 break;
430 }
431 default: {
432 SWT.error(SWT.ERROR_INVALID_IMAGE);
433 }
434 }
435
436 ImageData image = ImageData.internal_new(
437 imageWidth,
438 imageLength,
439 depth,
440 palette,
441 1,
442 null,
443 0,
444 null,
445 null,
446 -1,
447 -1,
448 SWT.IMAGE_TIFF,
449 0,
450 0,
451 0,
452 0);
453 decodePixels(image);
454 return image;
455 }
456
457 int toInt(byte[] buffer, int i, int type) {
458 if (type is TYPE_LONG) {
459 return isLittleEndian ?
460 (buffer[i] & 0xFF) | ((buffer[i + 1] & 0xFF) << 8) | ((buffer[i + 2] & 0xFF) << 16) | ((buffer[i + 3] & 0xFF) << 24) :
461 (buffer[i + 3] & 0xFF) | ((buffer[i + 2] & 0xFF) << 8) | ((buffer[i + 1] & 0xFF) << 16) | ((buffer[i] & 0xFF) << 24);
462 }
463 if (type is TYPE_SHORT) {
464 return isLittleEndian ?
465 (buffer[i] & 0xFF) | ((buffer[i + 1] & 0xFF) << 8) :
466 (buffer[i + 1] & 0xFF) | ((buffer[i] & 0xFF) << 8);
467 }
468 /* Invalid type */
469 SWT.error(SWT.ERROR_INVALID_IMAGE);
470 return -1;
471 }
472
473 void write(int photometricInterpretation) {
474 bool isRGB = photometricInterpretation is 2;
475 bool isColorMap = photometricInterpretation is 3;
476 bool isBiLevel = photometricInterpretation is 0 || photometricInterpretation is 1;
477
478 int imageWidth = image.width;
479 int imageLength = image.height;
480 int rowByteSize = image.bytesPerLine;
481
482 int numberEntries = isBiLevel ? 9 : 11;
483 int lengthDirectory = 2 + 12 * numberEntries + 4;
484 /* Offset following the header and the directory */
485 int nextOffset = 8 + lengthDirectory;
486
487 /* Extra space used by XResolution and YResolution values */
488 int extraBytes = 16;
489
490 int[] colorMap = null;
491 if (isColorMap) {
492 PaletteData palette = image.palette;
493 RGB[] rgbs = palette.getRGBs();
494 colorMap = formatColorMap(rgbs);
495 /* The number of entries of the Color Map must match the bitsPerSample field */
496 if (colorMap.length !is 3 * 1 << image.depth) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
497 /* Extra space used by ColorMap values */
498 extraBytes += colorMap.length * 2;
499 }
500 if (isRGB) {
501 /* Extra space used by BitsPerSample values */
502 extraBytes += 6;
503 }
504 /* TIFF recommends storing the data in strips of no more than 8 Ko */
505 byte[] data = image.data;
506 int[][] strips = new int[][](2);
507 int nbrRowsPerStrip = formatStrips(rowByteSize, imageLength, data, 8192, nextOffset, extraBytes, strips);
508 int[] stripOffsets = strips[0];
509 int[] stripByteCounts = strips[1];
510
511 int bitsPerSampleOffset = NO_VALUE;
512 if (isRGB) {
513 bitsPerSampleOffset = nextOffset;
514 nextOffset += 6;
515 }
516 int stripOffsetsOffset = NO_VALUE, stripByteCountsOffset = NO_VALUE;
517 int xResolutionOffset, yResolutionOffset, colorMapOffset = NO_VALUE;
518 int cnt = stripOffsets.length;
519 if (cnt > 1) {
520 stripOffsetsOffset = nextOffset;
521 nextOffset += 4 * cnt;
522 stripByteCountsOffset = nextOffset;
523 nextOffset += 4 * cnt;
524 }
525 xResolutionOffset = nextOffset;
526 nextOffset += 8;
527 yResolutionOffset = nextOffset;
528 nextOffset += 8;
529 if (isColorMap) {
530 colorMapOffset = nextOffset;
531 nextOffset += colorMap.length * 2;
532 }
533 /* TIFF header */
534 writeHeader();
535
536 /* Image File Directory */
537 ostr.writeShort(numberEntries);
538 writeEntry(TAG_ImageWidth, TYPE_LONG, 1, imageWidth);
539 writeEntry(TAG_ImageLength, TYPE_LONG, 1, imageLength);
540 if (isColorMap) writeEntry(TAG_BitsPerSample, TYPE_SHORT, 1, image.depth);
541 if (isRGB) writeEntry(TAG_BitsPerSample, TYPE_SHORT, 3, bitsPerSampleOffset);
542 writeEntry(TAG_Compression, TYPE_SHORT, 1, COMPRESSION_NONE);
543 writeEntry(TAG_PhotometricInterpretation, TYPE_SHORT, 1, photometricInterpretation);
544 writeEntry(TAG_StripOffsets, TYPE_LONG, cnt, cnt > 1 ? stripOffsetsOffset : stripOffsets[0]);
545 if (isRGB) writeEntry(TAG_SamplesPerPixel, TYPE_SHORT, 1, 3);
546 writeEntry(TAG_RowsPerStrip, TYPE_LONG, 1, nbrRowsPerStrip);
547 writeEntry(TAG_StripByteCounts, TYPE_LONG, cnt, cnt > 1 ? stripByteCountsOffset : stripByteCounts[0]);
548 writeEntry(TAG_XResolution, TYPE_RATIONAL, 1, xResolutionOffset);
549 writeEntry(TAG_YResolution, TYPE_RATIONAL, 1, yResolutionOffset);
550 if (isColorMap) writeEntry(TAG_ColorMap, TYPE_SHORT, colorMap.length, colorMapOffset);
551 /* Offset of next IFD (0 for last IFD) */
552 ostr.writeInt(0);
553
554 /* Values longer than 4 bytes Section */
555
556 /* BitsPerSample 8,8,8 */
557 if (isRGB) for (int i = 0; i < 3; i++) ostr.writeShort(8);
558 if (cnt > 1) {
559 for (int i = 0; i < cnt; i++) ostr.writeInt(stripOffsets[i]);
560 for (int i = 0; i < cnt; i++) ostr.writeInt(stripByteCounts[i]);
561 }
562 /* XResolution and YResolution set to 300 dpi */
563 for (int i = 0; i < 2; i++) {
564 ostr.writeInt(300);
565 ostr.writeInt(1);
566 }
567 /* ColorMap */
568 if (isColorMap) for (int i = 0; i < colorMap.length; i++) ostr.writeShort(colorMap[i]);
569
570 /* Image Data */
571 ostr.write(data);
572 }
573
574 void writeEntry(short tag, int type, int count, int value) {
575 ostr.writeShort(tag);
576 ostr.writeShort(type);
577 ostr.writeInt(count);
578 ostr.writeInt(value);
579 }
580
581 void writeHeader() {
582 /* little endian */
583 ostr.write(0x49);
584 ostr.write(0x49);
585
586 /* TIFF identifier */
587 ostr.writeShort(42);
588 /*
589 * Offset of the first IFD is chosen to be 8.
590 * It is word aligned and immediately after this header.
591 */
592 ostr.writeInt(8);
593 }
594
595 void writeToStream(LEDataOutputStream byteStream) {
596 ostr = byteStream;
597 int photometricInterpretation = -1;
598
599 /* Scanline pad must be 1 */
600 if (image.scanlinePad !is 1) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
601 switch (image.depth) {
602 case 1: {
603 /* Palette must be black and white or white and black */
604 PaletteData palette = image.palette;
605 RGB[] rgbs = palette.colors;
606 if (palette.isDirect || rgbs is null || rgbs.length !is 2) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
607 RGB rgb0 = rgbs[0];
608 RGB rgb1 = rgbs[1];
609 if (!(rgb0.red is rgb0.green && rgb0.green is rgb0.blue &&
610 rgb1.red is rgb1.green && rgb1.green is rgb1.blue &&
611 ((rgb0.red is 0x0 && rgb1.red is 0xFF) || (rgb0.red is 0xFF && rgb1.red is 0x0)))) {
612 SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
613 }
614 /* 0 means a color index of 0 is imaged as white */
615 photometricInterpretation = image.palette.colors[0].red is 0xFF ? 0 : 1;
616 break;
617 }
618 case 4:
619 case 8: {
620 photometricInterpretation = 3;
621 break;
622 }
623 case 24: {
624 photometricInterpretation = 2;
625 break;
626 }
627 default: {
628 SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
629 }
630 }
631 write(photometricInterpretation);
632 }
633
634 }