00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00032 #include "../Include/FlyLegacy.h"
00033 #include "../Include/Utility.h"
00034 #include "../Include/Globals.h"
00035 #include "../Include/Endian.h"
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 GLuint CImageTIFF::CreateTexture (bool mipmap)
00145 {
00146
00147 glGenTextures (1, &texid);
00148 glBindTexture (GL_TEXTURE_2D, texid);
00149 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
00150 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00151 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00152 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00153 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00154 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00155
00156 GLenum format = GL_RGBA;
00157 switch (depth) {
00158 case 4:
00159
00160 format = GL_RGBA;
00161 break;
00162 }
00163
00164 if (mipmap) {
00165
00166 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00167 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00168
00169 gluBuild2DMipmaps (GL_TEXTURE_2D, depth, width, height, format,
00170 GL_UNSIGNED_BYTE, image);
00171 } else {
00172
00173 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00174 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00175
00176 glTexImage2D (GL_TEXTURE_2D, 0, depth, width, height, 0,
00177 format, GL_UNSIGNED_BYTE, image);
00178 }
00179
00180 return texid;
00181 }
00182
00183 int CImageTIFF::GetWidth (void)
00184 {
00185 return width;
00186 }
00187
00188 int CImageTIFF::GetHeight (void)
00189 {
00190 return height;
00191 }
00192
00193
00194
00195
00196
00197
00198 static short tifRead16 (PODFILE *p, bool bigEndian)
00199 {
00200 short s;
00201 pread (&s, sizeof(short), 1, p);
00202 if (bigEndian) {
00203 s = BigEndian (s);
00204 } else {
00205 s = LittleEndian (s);
00206 }
00207 return s;
00208 }
00209
00210 static long tifRead32 (PODFILE *p, bool bigEndian)
00211 {
00212 long v;
00213 pread (&v, sizeof(long), 1, p);
00214 if (bigEndian) {
00215 v = BigEndian (v);
00216 } else {
00217 v = LittleEndian (v);
00218 }
00219 return v;
00220 }
00221
00222 typedef struct {
00223 unsigned short endian;
00224 unsigned short signature;
00225 long ifd;
00226 } TIFF_IFH;
00227
00228 typedef struct {
00229 unsigned short tag;
00230 unsigned short type;
00231 unsigned long count;
00232 unsigned long offset;
00233 } TIFF_IFD_ENTRY;
00234
00235
00236 #define TIFF_TYPE_BYTE (1)
00237 #define TIFF_TYPE_ASCII (2)
00238 #define TIFF_TYPE_SHORT (3)
00239 #define TIFF_TYPE_LONG (4)
00240 #define TIFF_TYPE_RATIONAL (5)
00241
00242 #define TIFF_LITTLE_ENDIAN (0x4949)
00243 #define TIFF_BIG_ENDIAN (0x4D4D)
00244 #define TIFF_SIGNATURE (42)
00245
00246 #define TIFF_TAG_IMAGEWIDTH (0x0100)
00247 #define TIFF_TAG_IMAGELENGTH (0x0101)
00248 #define TIFF_TAG_BITSPERSAMPLE (0x0102)
00249 #define TIFF_TAG_COMPRESSION (0x0103)
00250 #define TIFF_TAG_INTERPRETATION (0x0106)
00251 #define TIFF_TAG_STRIPOFFSETS (0x0111)
00252 #define TIFF_TAG_SAMPLESPERPIXEL (0x0115)
00253 #define TIFF_TAG_ROWSPERSTRIP (0x0116)
00254 #define TIFF_TAG_STRIPBYTECOUNTS (0x0117)
00255 #define TIFF_TAG_PLANARCONFIGURATION (0x011C)
00256 #define TIFF_TAG_COLORMAP (0x0140)
00257
00258
00259 typedef enum {
00260 TIFF_UNKNOWN,
00261 TIFF_RGB,
00262 TIFF_CMAP
00263 } ETiffImageType;
00264
00265
00266 CImageTIFF::CImageTIFF (const char* tifFilename)
00267 {
00268 int i, j, k;
00269
00270
00271 unsigned long bps = 0;
00272 unsigned long spp = 0;
00273 ETiffImageType type = TIFF_UNKNOWN;
00274 unsigned short num_strips = 0;
00275 unsigned long *strip_offsets = NULL;
00276 unsigned long rows_per_strip = 0;
00277 unsigned long *bytes_per_strip = NULL;
00278 unsigned long cmap_size = 0;
00279 unsigned long cmap_offset = 0;
00280
00281
00282 image = NULL;
00283 width = height = 0;
00284 texid = 0;
00285
00286
00287 PODFILE *p = popen (&globals->pfs, tifFilename);
00288 if (p == NULL) {
00289 gtfo ("CImageTIFF : Failed to open file %s", tifFilename);
00290 }
00291
00292
00293 TIFF_IFH ifh;
00294 pread (&ifh, sizeof(TIFF_IFH), 1, p);
00295 bool bigEndian = false;
00296 switch (ifh.endian) {
00297 case TIFF_LITTLE_ENDIAN:
00298 ifh.signature = LittleEndian (ifh.signature);
00299 ifh.ifd = LittleEndian (ifh.ifd);
00300 break;
00301
00302 case TIFF_BIG_ENDIAN:
00303 bigEndian = true;
00304 ifh.signature = BigEndian (ifh.signature);
00305 ifh.ifd = BigEndian (ifh.ifd);
00306 break;
00307
00308 default:
00309
00310 gtfo ("ssgLoadTIF : Invalid endian tag 0x%04X in image file header", ifh.endian);
00311 }
00312
00313
00314 if (ifh.signature != TIFF_SIGNATURE) {
00315
00316 gtfo ("ssgLoadTIF : Incorrect TIFF signature");
00317 }
00318
00319
00320 pseek (p, ifh.ifd, SEEK_SET);
00321 unsigned short nEntries = (unsigned short) tifRead16 (p, bigEndian);
00322
00323
00324 TIFF_IFD_ENTRY *entry = new TIFF_IFD_ENTRY[nEntries];
00325 for (i=0; i<nEntries; i++) {
00326 TIFF_IFD_ENTRY* ifd = &entry[i];
00327 ifd->tag = tifRead16 (p, bigEndian);
00328 ifd->type = tifRead16 (p, bigEndian);
00329 ifd->count = tifRead32 (p, bigEndian);
00330 ifd->offset = tifRead32 (p, bigEndian);
00331
00332
00333 switch (ifd->tag) {
00334 case TIFF_TAG_IMAGEWIDTH:
00335
00336 switch (ifd->type) {
00337 case TIFF_TYPE_SHORT:
00338 width = (short)ifd->offset;
00339 break;
00340 case TIFF_TYPE_LONG:
00341 width = (long)ifd->offset;
00342 break;
00343 }
00344 break;
00345
00346 case TIFF_TAG_IMAGELENGTH:
00347
00348 switch (ifd->type) {
00349 case TIFF_TYPE_SHORT:
00350 height = (unsigned short)ifd->offset;
00351 break;
00352 case TIFF_TYPE_LONG:
00353 height = (unsigned long)ifd->offset;
00354 break;
00355 }
00356 break;
00357
00358 case TIFF_TAG_BITSPERSAMPLE:
00359
00360
00361
00362 bps = ifd->offset;
00363 break;
00364
00365 case TIFF_TAG_COMPRESSION:
00366
00367 if (ifd->offset != 1) {
00368 gtfo ("ssgLoadTIF : Compressed images not supported");
00369 }
00370 break;
00371
00372 case TIFF_TAG_INTERPRETATION:
00373 switch (ifd->offset) {
00374 case 0:
00375
00376 gtfo ("ssgLoadTIF : Monochrome images not supported");
00377 break;
00378
00379 case 1:
00380
00381 gtfo ("ssgLoadTIF : Monochrome images not supported");
00382 break;
00383
00384 case 2:
00385
00386 type = TIFF_RGB;
00387 break;
00388
00389 case 3:
00390
00391 type = TIFF_CMAP;
00392 break;
00393
00394 case 4:
00395
00396 gtfo ("ssgLoadTIF : Transparency mask not supported");
00397 break;
00398 }
00399 break;
00400
00401 case TIFF_TAG_STRIPOFFSETS:
00402 {
00403
00404 num_strips = ifd->count;
00405 strip_offsets = new unsigned long[num_strips];
00406
00407 if (num_strips == 1) {
00408 strip_offsets[0] = ifd->offset;
00409 } else {
00410 long tell = ptell (p);
00411
00412 pseek (p, ifd->offset, SEEK_SET);
00413 switch (ifd->type) {
00414 case TIFF_TYPE_SHORT:
00415
00416 for (j=0; j<num_strips; j++) {
00417 short s = tifRead16 (p, bigEndian);
00418 strip_offsets[j] = (long)s;
00419 }
00420 break;
00421 case TIFF_TYPE_LONG:
00422
00423 for (j=0; j<num_strips; j++) {
00424 strip_offsets[j] = tifRead32 (p, bigEndian);
00425 }
00426 }
00427
00428 pseek (p, tell, SEEK_SET);
00429 }
00430 }
00431 break;
00432
00433 case TIFF_TAG_ROWSPERSTRIP:
00434
00435 rows_per_strip = ifd->offset;
00436 break;
00437
00438 case TIFF_TAG_STRIPBYTECOUNTS:
00439 {
00440
00441 num_strips = ifd->count;
00442 bytes_per_strip = new unsigned long[num_strips];
00443
00444 if (num_strips == 1) {
00445 bytes_per_strip[0] = ifd->offset;
00446 } else {
00447 long tell = ptell (p);
00448 pseek (p, ifd->offset, SEEK_SET);
00449 switch (ifd->type) {
00450 case TIFF_TYPE_SHORT:
00451 for (j=0; j<(int)ifd->count; j++) {
00452 short s = tifRead16 (p, bigEndian);
00453 bytes_per_strip[j] = (long)s;
00454 }
00455 break;
00456 case TIFF_TYPE_LONG:
00457 for (j=0; j<(int)ifd->count; j++) {
00458 bytes_per_strip[j] = tifRead32 (p, bigEndian);
00459 }
00460 break;
00461 }
00462
00463 pseek (p, tell, SEEK_SET);
00464 }
00465 }
00466 break;
00467
00468 case TIFF_TAG_SAMPLESPERPIXEL:
00469
00470 spp = ifd->offset;
00471 break;
00472
00473 case TIFF_TAG_PLANARCONFIGURATION:
00474
00475 switch (ifd->offset) {
00476 case 1:
00477
00478 break;
00479
00480 case 2:
00481
00482 gtfo ("ssgLoadTIF : Planar format not supported");
00483 break;
00484 }
00485 break;
00486
00487 case TIFF_TAG_COLORMAP:
00488
00489
00490 cmap_size = ifd->count;
00491 cmap_offset = ifd->offset;
00492 break;
00493 }
00494 }
00495
00496
00497 if (type == TIFF_UNKNOWN) {
00498 gtfo ("ssgLoadTIF : No photometric interpretation type");
00499 }
00500
00501
00502 depth = 4;
00503 image = new GLubyte[width*height*depth];
00504 memset (image, 0, width*height*depth);
00505
00506
00507 typedef struct {
00508 GLubyte r, g, b;
00509 } RGB;
00510 RGB *pal = new RGB[0x100];
00511
00512
00513 switch (type) {
00514 case TIFF_CMAP:
00515 {
00516
00517 pseek (p, cmap_offset, SEEK_SET);
00518
00519
00520
00521 for (i=0; i<0x100; i++) {
00522 short s;
00523 pread (&s, sizeof(short), 1, p);
00524 pal[i].r = (GLubyte)s;
00525 }
00526
00527
00528 for (i=0; i<0x100; i++) {
00529 short s;
00530 pread (&s, sizeof(short), 1, p);
00531 pal[i].g = (GLubyte)s;
00532 }
00533
00534
00535 for (i=0; i<0x100; i++) {
00536 short s;
00537 pread (&s, sizeof(short), 1, p);
00538 pal[i].b = (GLubyte)s;
00539 }
00540
00541
00542 for (i=0; i<num_strips; i++) {
00543 GLubyte *strip_data = new GLubyte[bytes_per_strip[i]];
00544 pseek (p, strip_offsets[i], SEEK_SET);
00545 pread (strip_data, sizeof(GLubyte), bytes_per_strip[i], p);
00546
00547
00548
00549 int iData = 0;
00550 for (j=0; j<(int)rows_per_strip; j++) {
00551 for (k=0; k<width; k++) {
00552 unsigned long imageRow = (i * rows_per_strip) + j;
00553 unsigned long imageCol = k;
00554 unsigned long iImage = ((imageRow * width) + imageCol) * depth;
00555
00556
00557 GLubyte pi = strip_data[iData++];
00558 image [iImage + 0] = pal[pi].r;
00559 image [iImage + 1] = pal[pi].g;
00560 image [iImage + 2] = pal[pi].b;
00561
00562
00563 if (spp == 2) {
00564 GLubyte a = strip_data[iData++];
00565 image [iImage + 3] = a;
00566 } else {
00567
00568 image [iImage + 3] = 0;
00569 }
00570 }
00571 }
00572 delete strip_data;
00573 }
00574 }
00575
00576 break;
00577
00578 case TIFF_RGB:
00579
00580 break;
00581
00582 default:
00583
00584 gtfo ("CImageTIFF : Unsupported TIF image type %d in %s", type, tifFilename);
00585 }
00586
00587
00588 delete entry;
00589 delete pal;
00590 delete strip_offsets;
00591 delete bytes_per_strip;
00592
00593 pclose (p);
00594 }
00595
00596 CImageTIFF::~CImageTIFF (void)
00597 {
00598 if (image != NULL) delete image;
00599 }
00600