40package com.jogamp.opengl.util.texture.spi;
44import com.jogamp.opengl.*;
45import com.jogamp.opengl.util.texture.ImageType;
46import com.jogamp.common.util.IOUtil;
58 private final Header header;
62 private int[] rowStart;
63 private int[] rowSize;
65 private byte[] tmpData;
66 private byte[] tmpRead;
68 private static final int MAGIC = 474;
109 Header(
final DataInputStream in)
throws IOException {
110 magic = in.readShort();
111 storage = in.readByte();
113 dimension = in.readShort();
114 xsize = in.readShort();
115 ysize = in.readShort();
116 zsize = in.readShort();
117 pixmin = in.readInt();
118 pixmax = in.readInt();
119 dummy = in.readInt();
120 final byte[] tmpname =
new byte[80];
123 while (tmpname[numChars++] != 0);
124 imagename =
new String(tmpname, 0, numChars);
125 colormap = in.readInt();
126 final byte[] tmp =
new byte[404];
132 return (
"magic: " + magic +
133 " storage: " + (
int) storage +
134 " bpc: " + (
int) bpc +
135 " dimension: " + dimension +
139 " pixmin: " + pixmin +
140 " pixmax: " + pixmax +
141 " imagename: " + imagename +
142 " colormap: " + colormap);
146 private SGIImage(
final Header header) {
147 this.header = header;
151 public static SGIImage read(
final String filename)
throws IOException {
152 return read(
new FileInputStream(filename));
157 final DataInputStream dIn =
new DataInputStream(
new BufferedInputStream(in));
159 final Header header =
new Header(dIn);
161 res.decodeImage(dIn);
168 public void write(
final String filename,
final boolean flipVertically)
throws IOException {
169 write(
new File(filename), flipVertically);
175 public void write(
final File file,
final boolean flipVertically)
throws IOException {
176 writeImage(file, data, header.xsize, header.ysize, header.zsize, flipVertically);
183 final boolean hasAlpha,
185 final Header header =
new Header();
186 header.xsize = (short) width;
187 header.ysize = (short) height;
188 header.zsize = (short) (hasAlpha ? 4 : 3);
215 return header.toString();
222 private void decodeImage(
final DataInputStream in)
throws IOException {
223 if (header.storage == 1) {
225 final int x = header.ysize * header.zsize;
226 rowStart =
new int[x];
227 rowSize =
new int[x];
228 rleEnd = 4 * 2 * x + 512;
229 for (
int i = 0; i < x; i++) {
230 rowStart[i] = in.readInt();
232 for (
int i = 0; i < x; i++) {
233 rowSize[i] = in.readInt();
235 tmpRead =
new byte[header.xsize * 256];
237 tmpData = readAll(in);
239 final int xsize = header.xsize;
240 final int ysize = header.ysize;
241 final int zsize = header.zsize;
244 data =
new byte[xsize * ysize * 4];
245 final byte[] rbuf =
new byte[xsize];
246 final byte[] gbuf =
new byte[xsize];
247 final byte[] bbuf =
new byte[xsize];
248 final byte[] abuf =
new byte[xsize];
249 for (
int y = 0; y < ysize; y++) {
255 rgbatorgba(rbuf, gbuf, bbuf, abuf, data, lptr);
256 }
else if (zsize == 3) {
260 rgbtorgba(rbuf, gbuf, bbuf, data, lptr);
261 }
else if (zsize == 2) {
264 latorgba(rbuf, abuf, data, lptr);
267 bwtorgba(rbuf, data, lptr);
279 private void getRow(
final byte[] buf,
final int y,
final int z) {
280 if (header.storage == 1) {
281 final int offs = rowStart[y + z * header.ysize] - rleEnd;
282 System.arraycopy(tmpData, offs, tmpRead, 0, rowSize[y + z * header.ysize]);
286 byte pixel = tmpRead[iPtr++];
287 int count = pixel & 0x7F;
291 if ((pixel & 0x80) != 0) {
292 while ((count--) > 0) {
293 buf[oPtr++] = tmpRead[iPtr++];
296 pixel = tmpRead[iPtr++];
297 while ((count--) > 0) {
303 final int offs = (y * header.xsize) + (z * header.xsize * header.ysize);
304 System.arraycopy(tmpData, offs, buf, 0, header.xsize);
308 private void bwtorgba(
final byte[] b,
final byte[] dest,
final int lptr) {
309 for (
int i = 0; i < b.length; i++) {
310 dest[4 * i + lptr + 0] = b[i];
311 dest[4 * i + lptr + 1] = b[i];
312 dest[4 * i + lptr + 2] = b[i];
313 dest[4 * i + lptr + 3] = (byte) 0xFF;
317 private void latorgba(
final byte[] b,
final byte[] a,
final byte[] dest,
final int lptr) {
318 for (
int i = 0; i < b.length; i++) {
319 dest[4 * i + lptr + 0] = b[i];
320 dest[4 * i + lptr + 1] = b[i];
321 dest[4 * i + lptr + 2] = b[i];
322 dest[4 * i + lptr + 3] = a[i];
326 private void rgbtorgba(
final byte[] r,
final byte[] g,
final byte[] b,
final byte[] dest,
final int lptr) {
327 for (
int i = 0; i < b.length; i++) {
328 dest[4 * i + lptr + 0] = r[i];
329 dest[4 * i + lptr + 1] = g[i];
330 dest[4 * i + lptr + 2] = b[i];
331 dest[4 * i + lptr + 3] = (byte) 0xFF;
335 private void rgbatorgba(
final byte[] r,
final byte[] g,
final byte[] b,
final byte[] a,
final byte[] dest,
final int lptr) {
336 for (
int i = 0; i < b.length; i++) {
337 dest[4 * i + lptr + 0] = r[i];
338 dest[4 * i + lptr + 1] = g[i];
339 dest[4 * i + lptr + 2] = b[i];
340 dest[4 * i + lptr + 3] = a[i];
344 private static byte imgref(
final byte[] i,
351 return i[(xs*ys*z)+(xs*y)+x];
355 private void writeHeader(
final DataOutputStream stream,
356 final int xsize,
final int ysize,
final int zsize,
final boolean rle)
throws IOException {
370 stream.writeShort(474);
371 stream.write((rle ? 1 : 0));
375 stream.writeShort(3);
378 stream.writeShort(xsize);
379 stream.writeShort(ysize);
380 stream.writeShort(zsize);
384 stream.writeInt(255);
390 for (
int i = 0; i < 80; i++)
397 for (
int i = 0; i < 404; i++)
401 private void writeImage(
final File file,
406 final boolean yflip)
throws IOException {
408 final byte[] tmpData =
new byte[xsize * ysize * zsize];
410 for (
int i = 0; i < zsize; i++) {
411 for (
int j = i; j < (xsize * ysize * zsize); j += zsize) {
412 tmpData[dest++] = data[j];
433 final int[] starttab =
new int[ysize * zsize];
434 final int[] lengthtab =
new int[ysize * zsize];
445 final int lookahead = 3;
446 final byte[] rlebuf =
new byte[2 * xsize * ysize * zsize];
461 final boolean DEBUG =
false;
463 for (
int z = 0; z < zsize; z++) {
464 for (
int y = ystart; y != yend; y += yincr) {
469 boolean repeat_mode =
false;
470 boolean should_switch =
false;
471 final int start_ptr = ptr;
477 should_switch =
false;
479 if (imgref(data, x, y, z, xsize, ysize, zsize) != repeat_val) {
480 should_switch =
true;
485 if ((x + lookahead) < xsize) {
486 should_switch =
true;
487 for (
int i = 1; i <= lookahead; i++) {
489 System.err.println(
"left side was " + ((
int) imgref(data, x, y, z, xsize, ysize, zsize)) +
490 ", right side was " + (int)imgref(data, x+i, y, z, xsize, ysize, zsize));
492 if (imgref(data, x, y, z, xsize, ysize, zsize) !=
493 imgref(data, x+i, y, z, xsize, ysize, zsize))
494 should_switch =
false;
499 if (should_switch || (count == 127)) {
503 rlebuf[num_ptr] = count;
505 rlebuf[num_ptr] = (byte) (count | 0x80);
513 rlebuf[ptr++] = repeat_val;
517 repeat_val = imgref(data, x, y, z, xsize, ysize, zsize);
530 rlebuf[ptr++] = imgref(data, x, y, z, xsize, ysize, zsize);
534 if (x == xsize - 1) {
537 rlebuf[num_ptr] = count;
540 rlebuf[ptr++] = repeat_val;
543 rlebuf[num_ptr] = (byte) (count | 0x80);
552 final int rowlen = ptr - start_ptr;
554 lengthtab[ysize*z+(ysize-y-1)] = rowlen;
556 lengthtab[ysize*z+y] = rowlen;
559 starttab[ysize*z+(ysize-y-1)] = cur_loc;
561 starttab[ysize*z+y] = cur_loc;
571 System.err.println(
"total_size was " + total_size);
573 final DataOutputStream stream =
new DataOutputStream(
new BufferedOutputStream(IOUtil.getFileOutputStream(file,
true)));
575 writeHeader(stream, xsize, ysize, zsize,
true);
577 final int SIZEOF_INT = 4;
578 for (
int i = 0; i < (ysize * zsize); i++)
579 stream.writeInt(starttab[i] + 512 + (2 * ysize * zsize * SIZEOF_INT));
580 for (
int i = 0; i < (ysize * zsize); i++)
581 stream.writeInt(lengthtab[i]);
582 for (
int i = 0; i < total_size; i++)
583 stream.write(rlebuf[i]);
588 private byte[] readAll(
final DataInputStream in)
throws IOException {
589 byte[] dest =
new byte[16384];
593 boolean done =
false;
596 numRead = in.read(dest, pos, dest.length - pos);
597 if (pos == dest.length) {
599 final byte[] newDest =
new byte[2 * dest.length];
600 System.arraycopy(dest, 0, newDest, 0, pos);
607 done = ((numRead == -1) || (in.available() == 0));
611 if (pos != dest.length) {
612 final byte[] finalDest =
new byte[pos];
613 System.arraycopy(dest, 0, finalDest, 0, pos);
void write(final File file, final boolean flipVertically)
Writes this SGIImage to the specified file.
int getWidth()
Returns the width of the image.
static SGIImage read(final InputStream in)
Reads an SGI image from the specified InputStream.
byte[] getData()
Returns the raw data for this texture in the correct (bottom-to-top) order for calls to glTexImage2D.
static SGIImage createFromData(final int width, final int height, final boolean hasAlpha, final byte[] data)
Creates an SGIImage from the specified data in either RGB or RGBA format.
void write(final String filename, final boolean flipVertically)
Writes this SGIImage to the specified file name.
int getHeight()
Returns the height of the image.
int getFormat()
Returns the OpenGL format for this texture; e.g.
static SGIImage read(final String filename)
Reads an SGI image from the specified file.
static final int GL_RGBA
GL_ES_VERSION_2_0, GL_VERSION_1_1, GL_VERSION_1_0, GL_VERSION_ES_1_0 Define "GL_RGBA" with expression...