2 Copyright (C) 2001, 2006 United States Government
3 as represented by the Administrator of the
4 National Aeronautics and Space Administration.
7 package gov
.nasa
.worldwind
;
11 * @version $Id: DDSConverter.java 1614 2007-04-23 22:38:20Z garakl $
13 public class DDSConverter
15 static final int DDSD_CAPS
= 0x0001;
16 static final int DDSD_HEIGHT
= 0x0002;
17 static final int DDSD_WIDTH
= 0x0004;
18 static final int DDSD_PIXELFORMAT
= 0x1000;
19 static final int DDSD_MIPMAPCOUNT
= 0x20000;
20 static final int DDSD_LINEARSIZE
= 0x80000;
21 static final int DDPF_FOURCC
= 0x0004;
22 static final int DDSCAPS_TEXTURE
= 0x1000;
24 protected static class Color
30 this.r
= this.g
= this.b
= 0;
33 public Color(int r
, int g
, int b
)
40 public boolean equals(Object o
)
44 if (o
== null || getClass() != o
.getClass())
47 final gov
.nasa
.worldwind
.DDSConverter
.Color color
= (gov
.nasa
.worldwind
.DDSConverter
.Color
) o
;
53 //noinspection RedundantIfStatement
64 result
= 29 * result
+ g
;
65 result
= 29 * result
+ b
;
74 * @throws IllegalArgumentException if either <code>image</code> or <code>mimeType</code> is null or if
75 * <code>mimeType</code> does not yield a valid suffix
76 * @throws java.io.IOException
78 public static java
.nio
.ByteBuffer
convertToDxt1NoTransparency(java
.nio
.ByteBuffer image
, String mimeType
)
79 throws java
.io
.IOException
83 String message
= WorldWind
.retrieveErrMsg("nullValue.ByteBufferIsNull");
84 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
85 throw new IllegalArgumentException(message
);
90 String message
= WorldWind
.retrieveErrMsg("nullValue.MimeTypeIsNull");
91 gov
.nasa
.worldwind
.WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
92 throw new IllegalArgumentException(message
);
95 String suffix
= WWIO
.getSuffixForMimeType(mimeType
);
98 String message
= WorldWind
.retrieveErrMsg("DDSConverter.UnsupportedMimeType") + mimeType
;
99 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
100 throw new IllegalArgumentException(message
);
103 java
.io
.File tempFile
= WWIO
.saveBufferToTempFile(image
, suffix
);
105 return convertToDxt1NoTransparency(tempFile
);
111 * @throws IllegalArgumentException if either <code>file</code> is null, does not exist, or cannot be read
112 * @throws java.io.IOException
114 public static java
.nio
.ByteBuffer
convertToDxt1NoTransparency(java
.io
.File file
) throws java
.io
.IOException
118 String message
= WorldWind
.retrieveErrMsg("nullValue.FileIsNull");
119 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
120 throw new IllegalArgumentException(message
);
123 if (!file
.exists() || !file
.canRead())
125 String message
= WorldWind
.retrieveErrMsg("DDSConverter.NoFileOrNoPermission");
126 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
127 throw new IllegalArgumentException(message
);
130 java
.awt
.image
.BufferedImage image
= javax
.imageio
.ImageIO
.read(file
);
137 // // Change its orientation to that of OpenGL.
138 // java.awt.geom.AffineTransform xform = java.awt.geom.AffineTransform.getScaleInstance(1, -1);
139 // xform.translate(0, -image.getHeight(null));
140 // java.awt.image.AffineTransformOp op = new java.awt.image.AffineTransformOp(
141 // xform, java.awt.image.AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
142 // image = op.filter(image, null);
144 int[] pixels
= new int[16];
145 int bufferSize
= 128 + image
.getWidth() * image
.getHeight() / 2;
146 java
.nio
.ByteBuffer buffer
= java
.nio
.ByteBuffer
.allocate(bufferSize
);
147 buffer
.order(java
.nio
.ByteOrder
.LITTLE_ENDIAN
);
148 buildHeaderDxt1(buffer
, image
.getWidth(), image
.getHeight());
150 int numTilesWide
= image
.getWidth() / 4;
151 int numTilesHigh
= image
.getHeight() / 4;
152 for (int i
= 0; i
< numTilesHigh
; i
++)
154 for (int j
= 0; j
< numTilesWide
; j
++)
156 java
.awt
.image
.BufferedImage originalTile
= image
.getSubimage(j
* 4, i
* 4, 4, 4);
157 originalTile
.getRGB(0, 0, 4, 4, pixels
, 0, 4);
158 Color
[] colors
= getColors888(pixels
);
160 for (int k
= 0; k
< pixels
.length
; k
++)
162 pixels
[k
] = getPixel565(colors
[k
]);
163 colors
[k
] = getColor565(pixels
[k
]);
166 int[] extremaIndices
= determineExtremeColors(colors
);
167 if (pixels
[extremaIndices
[0]] < pixels
[extremaIndices
[1]])
169 int t
= extremaIndices
[0];
170 extremaIndices
[0] = extremaIndices
[1];
171 extremaIndices
[1] = t
;
174 buffer
.putShort((short) pixels
[extremaIndices
[0]]);
175 buffer
.putShort((short) pixels
[extremaIndices
[1]]);
177 long bitmask
= computeBitMask(colors
, extremaIndices
);
178 buffer
.putInt((int) bitmask
);
189 * @throws IllegalArgumentException if either <code>image</code> or <code>mimeType</code> is null, or if
190 * <code>mimeType</code> does not yield a valid suffix
191 * @throws java.io.IOException
193 public static java
.nio
.ByteBuffer
convertToDxt1WithTransparency(java
.nio
.ByteBuffer image
, String mimeType
)
194 throws java
.io
.IOException
198 String message
= WorldWind
.retrieveErrMsg("nullValue.ByteBufferIsNull");
199 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
200 throw new IllegalArgumentException(message
);
203 if (mimeType
== null)
205 String message
= WorldWind
.retrieveErrMsg("nullValue.MimeTypeIsNull");
206 gov
.nasa
.worldwind
.WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
207 throw new IllegalArgumentException(message
);
210 String suffix
= WWIO
.getSuffixForMimeType(mimeType
);
213 String message
= WorldWind
.retrieveErrMsg("DDSConverter.UnsupportedMimeType") + mimeType
;
214 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
215 throw new IllegalArgumentException(message
);
218 java
.io
.File tempFile
= WWIO
.saveBufferToTempFile(image
, suffix
);
220 return convertToDxt1WithTransparency(tempFile
);
227 * @throws IllegalArgumentException if either <code>image</code> or <code>mimeType</code> is null, or if
228 * <code>mimeType</code> does not yield a valid suffix
229 * @throws java.io.IOException
231 public static java
.nio
.ByteBuffer
convertToDxt3(java
.nio
.ByteBuffer image
, String mimeType
)
232 throws java
.io
.IOException
236 String message
= WorldWind
.retrieveErrMsg("nullValue.ByteBufferIsNull");
237 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
238 throw new IllegalArgumentException(message
);
241 if (mimeType
== null)
243 String message
= WorldWind
.retrieveErrMsg("nullValue.MimeTypeIsNull");
244 gov
.nasa
.worldwind
.WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
245 throw new IllegalArgumentException(message
);
248 String suffix
= WWIO
.getSuffixForMimeType(mimeType
);
251 String message
= WorldWind
.retrieveErrMsg("DDSConverter.UnsupportedMimeType") + mimeType
;
252 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
253 throw new IllegalArgumentException(message
);
256 java
.io
.File tempFile
= WWIO
.saveBufferToTempFile(image
, suffix
);
258 return convertToDxt3(tempFile
);
264 * @throws IllegalArgumentException if either <code>file</code> is null, does not exist, or cannot be read
265 * @throws java.io.IOException
267 public static java
.nio
.ByteBuffer
convertToDxt3(java
.io
.File file
) throws java
.io
.IOException
271 String message
= WorldWind
.retrieveErrMsg("nullValue.FileIsNull");
272 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
273 throw new IllegalArgumentException(message
);
276 if (!file
.exists() || !file
.canRead())
278 String message
= WorldWind
.retrieveErrMsg("DDSConverter.NoFileOrNoPermission");
279 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
280 throw new IllegalArgumentException(message
);
283 java
.awt
.image
.BufferedImage image
= javax
.imageio
.ImageIO
.read(file
);
289 // // Change its orientation to that of OpenGL.
290 // java.awt.geom.AffineTransform xform = java.awt.geom.AffineTransform.getScaleInstance(1, -1);
291 // xform.translate(0, -image.getHeight(null));
292 // java.awt.image.AffineTransformOp op = new java.awt.image.AffineTransformOp(
293 // xform, java.awt.image.AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
294 // image = op.filter(image, null);
296 int[] pixels
= new int[16];
297 int bufferSize
= 128 + image
.getWidth() * image
.getHeight() / 2;
299 java
.nio
.ByteBuffer buffer
= java
.nio
.ByteBuffer
.allocate(bufferSize
);
300 buffer
.order(java
.nio
.ByteOrder
.LITTLE_ENDIAN
);
301 buildHeaderDxt3(buffer
, image
.getWidth(), image
.getHeight());
303 int numTilesWide
= image
.getWidth() / 4;
304 int numTilesHigh
= image
.getHeight() / 4;
305 for (int i
= 0; i
< numTilesHigh
; i
++)
307 for (int j
= 0; j
< numTilesWide
; j
++)
309 long alphas
= makeAlphas(pixels
);
310 buffer
.putLong(alphas
);
312 java
.awt
.image
.BufferedImage originalTile
= image
.getSubimage(j
* 4, i
* 4, 4, 4);
313 originalTile
.getRGB(0, 0, 4, 4, pixels
, 0, 4);
314 Color
[] colors
= getColors888(pixels
);
316 for (int k
= 0; k
< pixels
.length
; k
++)
318 pixels
[k
] = getPixel565(colors
[k
]);
319 colors
[k
] = getColor565(pixels
[k
]);
322 int[] extremaIndices
= determineExtremeColors(colors
);
323 if (pixels
[extremaIndices
[0]] < pixels
[extremaIndices
[1]])
325 int t
= extremaIndices
[0];
326 extremaIndices
[0] = extremaIndices
[1];
327 extremaIndices
[1] = t
;
330 buffer
.putShort((short) pixels
[extremaIndices
[0]]);
331 buffer
.putShort((short) pixels
[extremaIndices
[1]]);
333 long bitmask
= computeBitMask(colors
, extremaIndices
);
334 buffer
.putInt((int) bitmask
);
341 private static long makeAlphas(int[] pixels
)
344 for (int i
= 0; i
< pixels
.length
; i
++)
346 sol
|= (pixels
[i
] & 0xC0000000) >> (i
* 2);
352 protected static void buildHeaderDxt1(java
.nio
.ByteBuffer buffer
, int width
, int height
)
355 buffer
.put((byte) 'D');
356 buffer
.put((byte) 'D');
357 buffer
.put((byte) 'S');
358 buffer
.put((byte) ' ');
360 int flag
= DDSD_CAPS
| DDSD_HEIGHT
| DDSD_WIDTH
| DDSD_PIXELFORMAT
| DDSD_MIPMAPCOUNT
| DDSD_LINEARSIZE
;
362 buffer
.putInt(height
);
363 buffer
.putInt(width
);
364 buffer
.putInt(width
* height
/ 2);
365 buffer
.putInt(0); // depth
366 buffer
.putInt(0); // mipmap count
367 buffer
.position(buffer
.position() + 44); // 11 unused double-words
368 buffer
.putInt(32); // pixel format size
369 buffer
.putInt(DDPF_FOURCC
);
370 buffer
.put((byte) 'D');
371 buffer
.put((byte) 'X');
372 buffer
.put((byte) 'T');
373 buffer
.put((byte) '1');
374 buffer
.putInt(0); // bits per pixel for RGB (non-compressed) formats
375 buffer
.putInt(0); // rgb bit masks for RGB formats
376 buffer
.putInt(0); // rgb bit masks for RGB formats
377 buffer
.putInt(0); // rgb bit masks for RGB formats
378 buffer
.putInt(0); // alpha mask for RGB formats
379 buffer
.putInt(DDSCAPS_TEXTURE
);
380 buffer
.putInt(0); // ddsCaps2
381 buffer
.position(buffer
.position() + 12); // 3 unused double-words
384 protected static void buildHeaderDxt3(java
.nio
.ByteBuffer buffer
, int width
, int height
)
387 buffer
.put((byte) 'D');
388 buffer
.put((byte) 'D');
389 buffer
.put((byte) 'S');
390 buffer
.put((byte) ' ');
392 int flag
= DDSD_CAPS
| DDSD_HEIGHT
| DDSD_WIDTH
| DDSD_PIXELFORMAT
| DDSD_MIPMAPCOUNT
| DDSD_LINEARSIZE
;
394 buffer
.putInt(height
);
395 buffer
.putInt(width
);
396 buffer
.putInt(width
* height
/ 2);
397 buffer
.putInt(0); // depth
398 buffer
.putInt(0); // mipmap count
399 buffer
.position(buffer
.position() + 44); // 11 unused double-words
400 buffer
.putInt(32); // pixel format size
401 buffer
.putInt(DDPF_FOURCC
);
402 buffer
.put((byte) 'D');
403 buffer
.put((byte) 'X');
404 buffer
.put((byte) 'T');
405 buffer
.put((byte) '3');
406 buffer
.putInt(0); // bits per pixel for RGB (non-compressed) formats
407 buffer
.putInt(0); // rgb bit masks for RGB formats
408 buffer
.putInt(0); // rgb bit masks for RGB formats
409 buffer
.putInt(0); // rgb bit masks for RGB formats
410 buffer
.putInt(0); // alpha mask for RGB formats
411 buffer
.putInt(DDSCAPS_TEXTURE
);
412 buffer
.putInt(0); // ddsCaps2
413 buffer
.position(buffer
.position() + 12); // 3 unused double-words
416 protected static int[] determineExtremeColors(Color
[] colors
)
418 int farthest
= Integer
.MIN_VALUE
;
419 int[] ex
= new int[2];
421 for (int i
= 0; i
< colors
.length
- 1; i
++)
423 for (int j
= i
+ 1; j
< colors
.length
; j
++)
425 int d
= distance(colors
[i
], colors
[j
]);
438 protected static long computeBitMask(Color
[] colors
, int[] extremaIndices
)
440 Color
[] colorPoints
= new Color
[] {null, null, new Color(), new Color()};
441 colorPoints
[0] = colors
[extremaIndices
[0]];
442 colorPoints
[1] = colors
[extremaIndices
[1]];
443 if (colorPoints
[0].equals(colorPoints
[1]))
446 // colorPoints[0].r = (colorPoints[0].r & 0xF8) | (colorPoints[0].r >> 5 );
447 // colorPoints[0].g = (colorPoints[0].g & 0xFC) | (colorPoints[0].g >> 6 );
448 // colorPoints[0].b = (colorPoints[0].b & 0xF8) | (colorPoints[0].b >> 5 );
450 // colorPoints[1].r = (colorPoints[1].r & 0xF8) | (colorPoints[1].r >> 5 );
451 // colorPoints[1].g = (colorPoints[1].g & 0xFC) | (colorPoints[1].g >> 6 );
452 // colorPoints[1].b = (colorPoints[1].b & 0xF8) | (colorPoints[1].b >> 5 );
454 colorPoints
[2].r
= (2 * colorPoints
[0].r
+ colorPoints
[1].r
+ 1) / 3;
455 colorPoints
[2].g
= (2 * colorPoints
[0].g
+ colorPoints
[1].g
+ 1) / 3;
456 colorPoints
[2].b
= (2 * colorPoints
[0].b
+ colorPoints
[1].b
+ 1) / 3;
457 colorPoints
[3].r
= (colorPoints
[0].r
+ 2 * colorPoints
[1].r
+ 1) / 3;
458 colorPoints
[3].g
= (colorPoints
[0].g
+ 2 * colorPoints
[1].g
+ 1) / 3;
459 colorPoints
[3].b
= (colorPoints
[0].b
+ 2 * colorPoints
[1].b
+ 1) / 3;
462 for (int i
= 0; i
< colors
.length
; i
++)
464 int closest
= Integer
.MAX_VALUE
;
466 for (int j
= 0; j
< colorPoints
.length
; j
++)
468 int d
= distance(colors
[i
], colorPoints
[j
]);
475 bitmask
|= mask
<< i
* 2;
484 protected static int getPixel565(Color color
)
486 int r
= color
.r
>> 3;
487 int g
= color
.g
>> 2;
488 int b
= color
.b
>> 3;
489 return r
<< 11 | g
<< 5 | b
;
492 protected static Color
getColor565(int pixel
)
494 Color color
= new Color();
496 color
.r
= (int) (((long) pixel
) & 0xf800) >> 11;
497 color
.g
= (int) (((long) pixel
) & 0x07e0) >> 5;
498 color
.b
= (int) (((long) pixel
) & 0x001f);
503 protected static Color
getColor888(int r8g8b8
)
506 (int) (((long) r8g8b8
) & 0xff0000) >> 16,
507 (int) (((long) r8g8b8
) & 0x00ff00) >> 8,
508 (int) (((long) r8g8b8
) & 0x0000ff)
513 protected static Color
[] getColors888(int[] pixels
)
515 Color
[] colors
= new Color
[pixels
.length
];
517 for (int i
= 0; i
< pixels
.length
; i
++)
519 colors
[i
] = new Color();
520 colors
[i
].r
= (int) (((long) pixels
[i
]) & 0xff0000) >> 16;
521 colors
[i
].g
= (int) (((long) pixels
[i
]) & 0x00ff00) >> 8;
522 colors
[i
].b
= (int) (((long) pixels
[i
]) & 0x0000ff);
528 protected static int distance(Color ca
, Color cb
)
530 return (cb
.r
- ca
.r
) * (cb
.r
- ca
.r
) + (cb
.g
- ca
.g
) * (cb
.g
- ca
.g
) + (cb
.b
- ca
.b
) * (cb
.b
- ca
.b
);
536 * @throws IllegalArgumentException if either <code>file</code> is null, does not exist, or cannot be read
537 * @throws java.io.IOException
539 public static java
.nio
.ByteBuffer
convertToDxt1WithTransparency(java
.io
.File file
) throws java
.io
.IOException
541 /*java.awt.image.BufferedImage image = javax.imageio.ImageIO.read(file);
543 int bufferSize = 128 + image.getWidth() * image.getHeight() / 2;
544 java.nio.ByteBuffer testBuffer = java.nio.ByteBuffer.allocate(bufferSize);
545 testBuffer.order(java.nio.ByteOrder.LITTLE_ENDIAN);
546 buildHeaderDxt1(testBuffer, image.getWidth(), image.getHeight());
548 int numTilesWide = image.getWidth() / 4;
549 int numTilesHigh = image.getHeight() / 4;
551 for (int i = 0; i < numTilesHigh; i++)
553 for (int j = 0; j < numTilesWide; j++)
558 testBuffer.putShort(min);
559 testBuffer.putShort(max);
561 int bitmask = 0x012345678;//0xffff43cf;
562 testBuffer.putInt(bitmask);
571 String message
= WorldWind
.retrieveErrMsg("nullValue.FileIsNull");
572 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
573 throw new IllegalArgumentException(message
);
576 if (!file
.exists() || !file
.canRead())
578 String message
= WorldWind
.retrieveErrMsg("DDSConverter.NoFileOrNoPermission");
579 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
580 throw new IllegalArgumentException(message
);
583 java
.awt
.image
.BufferedImage image
= javax
.imageio
.ImageIO
.read(file
);
588 int[] pixels
= new int[16];
589 int bufferSize
= 128 + image
.getWidth() * image
.getHeight() / 2;
590 java
.nio
.ByteBuffer buffer
= java
.nio
.ByteBuffer
.allocate(bufferSize
);
591 buffer
.order(java
.nio
.ByteOrder
.LITTLE_ENDIAN
);
592 buildHeaderDxt1(buffer
, image
.getWidth(), image
.getHeight());
594 int numTilesWide
= image
.getWidth() / 4;
595 int numTilesHigh
= image
.getHeight() / 4;
596 for (int i
= 0; i
< numTilesHigh
; i
++)
598 for (int j
= 0; j
< numTilesWide
; j
++)
600 java
.awt
.image
.BufferedImage originalTile
= image
.getSubimage(j
* 4, i
* 4, 4, 4);
601 originalTile
.getRGB(0, 0, 4, 4, pixels
, 0, 4); // these are in format "TYPE_INT_ARGB" 16,5,6,5
603 TransparentColor
[] colors
= getColors5551(pixels
);
605 int[] extremaIndices
= determineExtremeColors(colors
);
607 // we want extremaIndices[0] to be greater than extremaIndices[1]
608 short min
= getShort5551(colors
[extremaIndices
[0]]);
609 short max
= getShort5551(colors
[extremaIndices
[1]]);
612 // we want min to be less than max.
613 int t
= extremaIndices
[0];
614 extremaIndices
[0] = extremaIndices
[1];
615 extremaIndices
[1] = t
;
623 // because of this case, we don't get transparency.
624 equalTransparentCase(colors
, extremaIndices
, min
);
626 min
= getShort5551(colors
[extremaIndices
[0]]);
627 max
= getShort5551(colors
[extremaIndices
[1]]);
630 buffer
.putShort(min
);
631 buffer
.putShort(max
);
633 long bitmask
= computeBitMask(colors
, extremaIndices
);
634 buffer
.putInt((int) bitmask
);
641 protected static void equalTransparentCase(TransparentColor
[] colors
, int[] extremaIndices
, short value
)
643 // we want extremaIndices[0] to be greater than extremaIndices[1]
648 colors
[extremaIndices
[0]] = TransparentColor
.OFF_TRANSPARENT
;
652 // not transparent anywhere - it's all one colour, so we don't need to bother making changes
657 protected static int distance(TransparentColor ca
, TransparentColor cb
)
659 return (cb
.r
- ca
.r
) * (cb
.r
- ca
.r
) + (cb
.g
- ca
.g
) * (cb
.g
- ca
.g
) + (cb
.b
- ca
.b
) * (cb
.b
- ca
.b
)
660 + (cb
.a
- ca
.a
) * (cb
.a
- ca
.a
);
663 // public static void main(String[] args)
667 // String fileName = "testdata/0000_0001";
668 // java.nio.ByteBuffer buffer = convertToDxt1NoTransparency(new java.io.File(fileName + ".jpg"));
670 // java.io.FileOutputStream fos = new java.io.FileOutputStream(fileName + ".dds");
671 // java.nio.channels.FileChannel channel = fos.getChannel();
672 // channel.write(buffer);
674 // catch (java.io.IOException e)
676 // e.printStackTrace();
682 protected static long computeBitMask(TransparentColor
[] colors
, int[] extremaIndices
)
684 TransparentColor
[] colorPoints
= {null, null, new TransparentColor(), new TransparentColor()};
686 colorPoints
[0] = colors
[extremaIndices
[0]];
687 colorPoints
[1] = colors
[extremaIndices
[1]];
689 colorPoints
[2].r
= (byte) ((colorPoints
[0].r
+ colorPoints
[1].r
) / 2);
690 colorPoints
[2].g
= (byte) ((colorPoints
[0].g
+ colorPoints
[1].g
) / 2);
691 colorPoints
[2].b
= (byte) ((colorPoints
[0].b
+ colorPoints
[1].b
) / 2);
692 colorPoints
[2].a
= 1;
694 colorPoints
[3].r
= 0;
695 colorPoints
[3].g
= 0;
696 colorPoints
[3].b
= 0;
697 colorPoints
[3].a
= 0;
700 for (int i
= 0; i
< colors
.length
; i
++)
702 int closest
= Integer
.MAX_VALUE
;
704 if (colors
[i
].a
== 0)
710 for (int j
= 0; j
< colorPoints
.length
; j
++)
712 int d
= distance(colors
[i
], colorPoints
[j
]);
720 bitmask
|= mask
<< i
* 2;
726 protected static short getShort5551(TransparentColor color
)
729 s
|= ((color
.r
& 0x0f8) << 8) | ((color
.g
& 0x0f8) << 4) | ((color
.b
& 0x0f8) >> 3) | ((color
.a
& 0x0f8) >> 7);
730 // System.out.println(Integer.toBinaryString(s));
734 protected static int[] determineExtremeColors(TransparentColor
[] colors
)
736 int farthest
= Integer
.MIN_VALUE
;
739 for (int i
= 0; i
< colors
.length
- 1; i
++)
741 for (int j
= i
+ 1; j
< colors
.length
; j
++)
743 int d
= distance(colors
[i
], colors
[j
]);
756 protected static TransparentColor
[] getColors5551(int[] pixels
)
758 TransparentColor colors
[] = new TransparentColor
[pixels
.length
];
760 for (int i
= 0; i
< pixels
.length
; i
++)
762 colors
[i
] = generateColor5551(pixels
[i
]);
767 protected static TransparentColor
generateColor5551(int pixel
)
769 short alpha
= (short) (pixel
>> 24);
770 if ((alpha
& 0xf0) == 0)
772 return TransparentColor
.TRANSPARENT
;
775 // ok, it's not transparent - that's already been ruled out.
777 TransparentColor tc
= new TransparentColor();
778 tc
.a
= (byte) 0x000000ff;
779 tc
.r
= (byte) ((pixel
& 0x00ff0000) >> 16);
780 tc
.g
= (byte) ((pixel
& 0x0000ff00) >> 8);
781 tc
.b
= (byte) (pixel
& 0x000000ff);
786 protected static class TransparentColor
788 private static final TransparentColor TRANSPARENT
= new TransparentColor((byte) 0, (byte) 0, (byte) 0,
790 private static final TransparentColor OFF_TRANSPARENT
= new TransparentColor((byte) 0, (byte) 0, (byte) 1,
792 private byte r
, g
, b
, a
;
794 private TransparentColor()
798 private TransparentColor(byte r
, byte g
, byte b
, byte a
)
806 public boolean equals(Object o
)
810 if (o
== null || getClass() != o
.getClass())
813 final gov
.nasa
.worldwind
.DDSConverter
.TransparentColor that
=
814 (gov
.nasa
.worldwind
.DDSConverter
.TransparentColor
) o
;
822 //noinspection RedundantIfStatement
829 public int hashCode()
833 result
= 29 * result
+ g
;
834 result
= 29 * result
+ b
;
835 result
= 29 * result
+ a
;
839 public String
toString()
841 return "TransColor argb: " + this.a
+ ", " + this.r
+ ", " + this.g
+ ", " + this.b
;