00001
00020 #include "mfcpch.h"
00021 #ifdef __MSW32__
00022 #include <io.h>
00023 #else
00024 #include <unistd.h>
00025 #endif
00026 #include "fileerr.h"
00027 #include "imgerrs.h"
00028 #include "img.h"
00029 #include "bitstrm.h"
00030 #include "tprintf.h"
00031 #include "serialis.h"
00032 #include "imgtiff.h"
00033
00034 #define INTEL 0x4949
00035 #define MOTO 0x4d4d
00036
00067 #define ENTRIES 19
00068 #define START 8
00069
00074 typedef struct
00075 {
00076 UINT16 tag;
00077 UINT16 type;
00078 UINT32 length;
00079 INT32 value;
00080 } TIFFENTRY;
00081
00087 typedef struct myrational
00088 {
00089 INT32 top;
00090 INT32 bottom;
00091 } MYRATIONAL;
00092
00094 #define EOL_CODE 0x800
00095 #define EOL_MASK 0xfff
00096 #define EOL_LENGTH 12 //12 bits
00097 #define SHORT_CODE_SIZE 64 //no of short codes
00098 #define LONG_CODE_SIZE 40 //no of long codes
00099
00101 static UINT16 short_white_codes[SHORT_CODE_SIZE] = {
00102 0xac, 0x38, 0xe, 0x1, 0xd, 0x3, 0x7, 0xf,
00103 0x19, 0x5, 0x1c, 0x2, 0x4, 0x30, 0xb, 0x2b,
00104 0x15, 0x35, 0x72, 0x18, 0x8, 0x74, 0x60, 0x10,
00105 0xa, 0x6a, 0x64, 0x12, 0xc, 0x40, 0xc0, 0x58,
00106 0xd8, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x14,
00107 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x20, 0xa0, 0x50,
00108 0xd0, 0x4a, 0xca, 0x2a, 0xaa, 0x24, 0xa4, 0x1a,
00109 0x9a, 0x5a, 0xda, 0x52, 0xd2, 0x4c, 0xcc, 0x2c
00110 };
00111
00113 static UINT8 short_white_lengths[SHORT_CODE_SIZE] = {
00114 8, 6, 4, 4, 4, 4, 4, 4,
00115 5, 5, 5, 5, 6, 6, 6, 6,
00116 6, 6, 7, 7, 7, 7, 7, 7,
00117 7, 7, 7, 7, 7, 8, 8, 8,
00118 8, 8, 8, 8, 8, 8, 8, 8,
00119 8, 8, 8, 8, 8, 8, 8, 8,
00120 8, 8, 8, 8, 8, 8, 8, 8,
00121 8, 8, 8, 8, 8, 8, 8, 8
00122 };
00123
00125 static UINT16 short_black_codes[SHORT_CODE_SIZE] = {
00126 0x3b0, 0x2, 0x3, 0x1, 0x6, 0xc, 0x4, 0x18,
00127 0x28, 0x8, 0x10, 0x50, 0x70, 0x20, 0xe0, 0x30,
00128 0x3a0, 0x60, 0x40, 0x730, 0xb0, 0x1b0, 0x760, 0xa0,
00129 0x740, 0xc0, 0x530, 0xd30,
00130 0x330, 0xb30, 0x160, 0x960,
00131 0x560, 0xd60, 0x4b0, 0xcb0,
00132 0x2b0, 0xab0, 0x6b0, 0xeb0,
00133 0x360, 0xb60, 0x5b0, 0xdb0,
00134 0x2a0, 0xaa0, 0x6a0, 0xea0,
00135 0x260, 0xa60, 0x4a0, 0xca0,
00136 0x240, 0xec0, 0x1c0, 0xe40,
00137 0x140, 0x1a0, 0x9a0, 0xd40,
00138 0x340, 0x5a0, 0x660, 0xe60
00139 };
00140
00142 static UINT8 short_black_lengths[SHORT_CODE_SIZE] = {
00143 10, 3, 2, 2, 3, 4, 4, 5,
00144 6, 6, 7, 7, 7, 8, 8, 9,
00145 10, 10, 10, 11, 11, 11, 11, 11,
00146 11, 11, 12, 12, 12, 12, 12, 12,
00147 12, 12, 12, 12, 12, 12, 12, 12,
00148 12, 12, 12, 12, 12, 12, 12, 12,
00149 12, 12, 12, 12, 12, 12, 12, 12,
00150 12, 12, 12, 12, 12, 12, 12, 12
00151 };
00152
00154 static UINT16 long_white_codes[LONG_CODE_SIZE] = {
00155 0x1b, 0x9, 0x3a, 0x76, 0x6c, 0xec, 0x26, 0xa6,
00156 0x16, 0xe6, 0x66, 0x166, 0x96, 0x196, 0x56, 0x156,
00157 0xd6, 0x1d6, 0x36, 0x136, 0xb6, 0x1b6, 0x32, 0x132,
00158 0xb2, 0x6, 0x1b2,
00159 0x80, 0x180, 0x580, 0x480, 0xc80,
00160 0x280, 0xa80, 0x680, 0xe80, 0x380, 0xb80, 0x780, 0xf80
00161 };
00162
00164 static UINT8 long_white_lengths[LONG_CODE_SIZE] = {
00165 5, 5, 6, 7, 8, 8, 8, 8,
00166 8, 8, 9, 9, 9, 9, 9, 9,
00167 9, 9, 9, 9, 9, 9, 9, 9,
00168 9, 6, 9, 11, 11, 11, 12, 12,
00169 12, 12, 12, 12, 12, 12, 12, 12
00170 };
00171
00173 static UINT16 long_black_codes[LONG_CODE_SIZE] = {
00174 0x3c0, 0x130, 0x930, 0xda0,
00175 0xcc0, 0x2c0, 0xac0, 0x6c0,
00176 0x16c0, 0xa40, 0x1a40, 0x640,
00177 0x1640, 0x9c0, 0x19c0, 0x5c0,
00178 0x15c0, 0xdc0, 0x1dc0, 0x940,
00179 0x1940, 0x540, 0x1540, 0xb40,
00180 0x1b40, 0x4c0, 0x14c0,
00181 0x80, 0x180, 0x580, 0x480, 0xc80,
00182 0x280, 0xa80, 0x680, 0xe80, 0x380, 0xb80, 0x780, 0xf80
00183 };
00184
00186 static UINT8 long_black_lengths[LONG_CODE_SIZE] = {
00187 10, 12, 12, 12, 12, 12, 12, 13,
00188 13, 13, 13, 13, 13, 13, 13, 13,
00189 13, 13, 13, 13, 13, 13, 13, 13,
00190 13, 13, 13, 11, 11, 11, 12, 12,
00191 12, 12, 12, 12, 12, 12, 12, 12
00192 };
00193
00197 INT8 open_tif_image(
00198 int fd,
00199 INT32 *xsize,
00200 INT32 *ysize,
00201 INT8 *bpp,
00202 INT8 *photo,
00203 INT32 *res
00204 ) {
00205 INT16 filetype;
00206 INT32 start;
00207 INT16 entries;
00208 INT32 imagestart;
00209 INT32 resoffset;
00210 TIFFENTRY tiffentry;
00211 BOOL8 compressed;
00212 MYRATIONAL resinfo;
00213 BOOL8 strips = false;
00214
00215 *xsize = -1;
00216 *ysize = -1;
00217 *bpp = -1;
00218 *res = -1;
00219 resoffset = -1;
00220 if (read (fd, (char *) &filetype, sizeof filetype) != sizeof filetype
00221 || filetype != INTEL && filetype != MOTO) {
00222 BADIMAGEFORMAT.error ("read_tif_image", LOG, "Filetype");
00223 return -1;
00224 }
00225 lseek (fd, 4L, 0);
00226 if (read (fd, (char *) &start, sizeof start) != sizeof start) {
00227 READFAILED.error ("read_tif_image", LOG, "Start of tag table");
00228 return -1;
00229 }
00230
00231 if (filetype != __NATIVE__)
00232 start = reverse32 (start);
00233 if (start <= 0) {
00234 BADIMAGEFORMAT.error ("read_tif_image", LOG, "Start of tag table");
00235 return -1;
00236 }
00237 lseek (fd, start, 0);
00238 if (read (fd, (char *) &entries, sizeof (INT16)) != sizeof (INT16)) {
00239 BADIMAGEFORMAT.error ("read_tif_image", LOG, "Size of tag table");
00240 return -1;
00241 }
00242 if (filetype != __NATIVE__)
00243 entries = reverse16 (entries);
00244
00245 imagestart = 0;
00246 compressed = FALSE;
00247 for (; entries-- > 0;) {
00248 if (read (fd, (char *) &tiffentry, sizeof tiffentry) !=
00249 sizeof tiffentry) {
00250 BADIMAGEFORMAT.error ("read_tif_image", LOG, "Tag table entry");
00251 return -1;
00252 }
00253 if (filetype != __NATIVE__) {
00254 tiffentry.type = reverse16 (tiffentry.type);
00255 tiffentry.tag = reverse16 (tiffentry.tag);
00256 tiffentry.length = reverse32 (tiffentry.length);
00257 }
00258 if (tiffentry.type != 3) {
00259 if (filetype != __NATIVE__)
00260 tiffentry.value = reverse32 (tiffentry.value);
00261 }
00262 else {
00263
00264 if (__NATIVE__ == MOTO) {
00265 if (filetype == MOTO)
00266 tiffentry.value = tiffentry.value >> 16;
00267 else
00268 tiffentry.value = reverse32 (tiffentry.value);
00269 }
00270 else {
00271 if (filetype == MOTO)
00272 tiffentry.value = reverse16 ((UINT16) tiffentry.value);
00273
00274 }
00275
00276 tiffentry.value &= 0x0000ffff;
00277 }
00278
00279
00280
00281 switch (tiffentry.tag) {
00282 case 0x101:
00283 *ysize = tiffentry.value;
00284 break;
00285 case 0x100:
00286 *xsize = tiffentry.value;
00287 break;
00288 case 0x102:
00289 if (tiffentry.length == 1)
00290 *bpp = (INT8) tiffentry.value;
00291 else
00292 *bpp = 24;
00293 break;
00294 case 0x111:
00295 imagestart = tiffentry.value;
00296 strips = tiffentry.length > 1;
00297 break;
00298 case 0x103:
00299 if (tiffentry.value == 3) {
00300 compressed = TRUE;
00301 }
00302 else if (tiffentry.value != 1) {
00303 BADIMAGEFORMAT.error ("read_tif_image", LOG, "Compression");
00304 return -1;
00305 }
00306 break;
00307 case 0x11a:
00308 case 0x11b:
00309
00310 resoffset = tiffentry.value;
00311 break;
00312 case 0x106:
00313 *photo = (INT8) tiffentry.value;
00314 break;
00315 }
00316 }
00317 if (*xsize <= 0 || *ysize <= 0 || *bpp > 24 || imagestart <= 0) {
00318 BADIMAGEFORMAT.error ("read_tif_image", LOG, "Vital tag");
00319 return -1;
00320 }
00321 tprintf ("Image has %d bit%c per pixel and size (%d,%d)\n",
00322 *bpp, *bpp == 1 ? ' ' : 's', *xsize, *ysize);
00323 if (resoffset >= 0) {
00324 lseek (fd, resoffset, 0);
00325 if (read (fd, (char *) &resinfo, sizeof (resinfo)) != sizeof (resinfo)) {
00326 READFAILED.error ("read_tif_image", LOG, "Resolution");
00327 return -1;
00328 }
00329 if (filetype != __NATIVE__) {
00330 resinfo.top = reverse32 (resinfo.top);
00331 resinfo.bottom = reverse32 (resinfo.bottom);
00332 }
00333 *res = resinfo.top / resinfo.bottom;
00334 tprintf ("Resolution=%d\n", *res);
00335 }
00336 lseek (fd, (long) imagestart, 0);
00337 if (strips) {
00338 if (read (fd, (char *) &imagestart, sizeof (imagestart)) !=
00339 sizeof (imagestart)) {
00340 READFAILED.error ("read_tif_image", LOG, "Strip offset");
00341 return -1;
00342 }
00343 if (filetype != __NATIVE__)
00344 imagestart = reverse32 (imagestart);
00345
00346 lseek (fd, (long) imagestart, 0);
00347 }
00348 return compressed ? -2 : 0;
00349 }
00350
00351
00355 INT8 read_tif_image(
00356 int fd,
00357 UINT8 *pixels,
00358 INT32 xsize,
00359 INT32 ysize,
00360 INT8 bpp,
00361 INT32
00362 ) {
00363 INT32 xindex;
00364 INT32 yindex;
00365 INT32 length;
00366 INT32 biglength;
00367 UINT8 *lengths;
00368 UINT16 *codes;
00369 UINT16 codeword;
00370 IMAGELINE imageline;
00371 IMAGE image;
00372 R_BITSTREAM bits;
00373 UINT8 colour;
00374
00375 image.capture (pixels, xsize, ysize, bpp);
00376 codeword = bits.open (fd);
00377 read_eol(&bits, codeword);
00378 for (yindex = ysize - 1; yindex >= 0; yindex--) {
00379 imageline.init ();
00380 colour = TRUE;
00381 for (xindex = 0; xindex < xsize;) {
00382 if (colour) {
00383 lengths = long_white_lengths;
00384 codes = long_white_codes;
00385 }
00386 else {
00387 lengths = long_black_lengths;
00388 codes = long_black_codes;
00389 }
00390 for (biglength = 0; biglength < LONG_CODE_SIZE
00391 && (codeword & bits.masks (*lengths))
00392 != *codes; codes++, lengths++, biglength++);
00393 if (biglength < LONG_CODE_SIZE) {
00394 codeword = bits.read_code (*lengths);
00395 biglength++;
00396 biglength *= SHORT_CODE_SIZE;
00397 }
00398 else
00399 biglength = 0;
00400 if (colour) {
00401 lengths = short_white_lengths;
00402 codes = short_white_codes;
00403 }
00404 else {
00405 lengths = short_black_lengths;
00406 codes = short_black_codes;
00407 }
00408 for (length = 0; length < SHORT_CODE_SIZE
00409 && (codeword & bits.masks (*lengths))
00410 != *codes; codes++, lengths++, length++);
00411 if (length < SHORT_CODE_SIZE) {
00412 codeword = bits.read_code (*lengths);
00413 for (length += biglength; length > 0; length--, xindex++)
00414 imageline.pixels[xindex] = colour;
00415 colour = !colour;
00416 }
00417 else
00418 break;
00419 }
00420 if (xindex < xsize) {
00421 tprintf ("%d pixels short on line %d", xsize - xindex, yindex);
00422 tprintf (", unknown code=%x\n", codeword);
00423 }
00424 xindex = read_eol (&bits, codeword);
00425 if (xindex > 0)
00426 tprintf ("Discarding %d bits on line %d\n", xindex, yindex);
00427 image.put_line (0, yindex, xsize, &imageline, 0);
00428 }
00429 return 0;
00430 }
00431
00432
00436 INT32 read_eol(
00437 R_BITSTREAM *bits,
00438 UINT16 &code
00439 ) {
00440 BOOL8 anyones;
00441 INT32 bitcount;
00442
00443 anyones = FALSE;
00444 bitcount = 0;
00445 while ((code & EOL_MASK) != EOL_CODE) {
00446 if (code & 1)
00447 anyones = TRUE;
00448 bitcount++;
00449 code = bits->read_code (1);
00450 }
00451
00452 code = bits->read_code (EOL_LENGTH);
00453
00454 if (!anyones)
00455 bitcount = 0;
00456 return bitcount;
00457 }
00458
00459
00463 INT8 write_moto_tif(
00464 int fd,
00465 UINT8 *pixels,
00466 INT32 xsize,
00467 INT32 ysize,
00468 INT8 bpp,
00469 INT8 photo,
00470 INT32 res
00471 ) {
00472 return write_tif_image (fd, pixels, xsize, ysize, bpp, res, MOTO, photo);
00473
00474 }
00475
00476
00480 INT8 write_intel_tif(
00481 int fd,
00482 UINT8 *pixels,
00483 INT32 xsize,
00484 INT32 ysize,
00485 INT8 bpp,
00486 INT8 photo,
00487 INT32 res
00488 ) {
00489 return write_tif_image (fd, pixels, xsize, ysize, bpp, res, INTEL, photo);
00490
00491 }
00492
00493
00497 INT8 write_inverse_tif(
00498 int fd,
00499 UINT8 *pixels,
00500 INT32 xsize,
00501 INT32 ysize,
00502 INT8 bpp,
00503 INT8 photo,
00504 INT32 res
00505 ) {
00506 return write_tif_image (fd, pixels, xsize, ysize, bpp, res, INTEL,
00507 1 - photo);
00508
00509 }
00510
00511
00515 INT8 write_tif_image(
00516 int fd,
00517 UINT8 *pixels,
00518 INT32 xsize,
00519 INT32 ysize,
00520 INT8 bpp,
00521 INT32 res,
00522 INT16 type,
00523 INT16 photo
00524 ) {
00525 INT32 size;
00526 INT16 entries;
00527 INT32 start;
00528 INT32 zero = 0;
00529 MYRATIONAL resolution;
00530 TIFFENTRY entry;
00531
00532 static TIFFENTRY tags[ENTRIES] = {
00533 {0xfe, 4, 1, 0},
00534 {0x100, 3, 1, 0},
00535 {0x101, 3, 1, 0},
00536 {0x102, 3, 1, 0},
00537 {0x103, 3, 1, 1},
00538 {0x106, 3, 1, 1},
00539 {
00540 0x107, 3, 1, 1
00541 },
00542 {0x10a, 3, 1, 1},
00543 {
00544 0x111, 4, 1, START + ENTRIES * sizeof (TIFFENTRY)
00545 + sizeof (INT32) + sizeof (short) + sizeof (MYRATIONAL) * 2
00546 }
00547 ,
00548 {0x112, 3, 1, 1}
00549 ,
00550 {0x115, 3, 1, 1}
00551 ,
00552 {0x116, 4, 1, 0}
00553 ,
00554 {0x117, 4, 1, 0}
00555 ,
00556 {0x118, 3, 1, 0}
00557 ,
00558 {0x119, 3, 1, 1}
00559 ,
00560 {
00561 0x11a, 5, 1, START + ENTRIES * sizeof (TIFFENTRY)
00562 + sizeof (INT32) + sizeof (short)
00563 },
00564 {
00565 0x11b, 5, 1, START + ENTRIES * sizeof (TIFFENTRY)
00566 + sizeof (INT32) + sizeof (short) + sizeof (MYRATIONAL)
00567 }
00568 ,
00569 {0x11c, 3, 1, 1}
00570 ,
00571 {0x128, 3, 1, 2}
00572 };
00573
00574 resolution.top = res;
00575 resolution.bottom = 1;
00576 if (write (fd, (char *) &type, sizeof type) != sizeof type
00577 || type != INTEL && type != MOTO) {
00578 WRITEFAILED.error ("write_tif_image", LOG, "Filetype");
00579 return -1;
00580 }
00581 start = START;
00582 entries = 0x002a;
00583 if (type != __NATIVE__)
00584 entries = reverse16 (entries);
00585 if (write (fd, (char *) &entries, sizeof entries) != sizeof entries) {
00586 WRITEFAILED.error ("write_tif_image", LOG, "Version");
00587 return -1;
00588 }
00589 if (type != __NATIVE__)
00590 start = reverse32 (start);
00591 if (write (fd, (char *) &start, sizeof start) != sizeof start) {
00592 WRITEFAILED.error ("write_tif_image", LOG, "Start");
00593 return -1;
00594 }
00595 lseek (fd, (long) START, 0);
00596 entries = ENTRIES;
00597 if (type != __NATIVE__)
00598 entries = reverse16 (entries);
00599 if (write (fd, (char *) &entries, sizeof entries) != sizeof entries) {
00600 WRITEFAILED.error ("write_tif_image", LOG, "Entries");
00601 return -1;
00602 }
00603
00604 size = COMPUTE_IMAGE_XDIM (xsize, bpp);
00605 size *= ysize;
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618 tags[1].value = xsize;
00619 tags[2].value = ysize;
00620 if (bpp == 24) {
00621 tags[3].value = 8;
00622 tags[10].value = 3;
00623 tags[5].value = 2;
00624 }
00625 else {
00626 tags[3].value = bpp;
00627 tags[5].value = photo;
00628 }
00629 tags[11].value = ysize;
00630 tags[14].value = (1 << bpp) - 1;
00631 tags[12].value = size;
00632 for (entries = 0; entries < ENTRIES; entries++) {
00633 entry = tags[entries];
00634
00635 if (entry.type != 3) {
00636 if (type != __NATIVE__)
00637 entry.value = reverse32 (entry.value);
00638 }
00639 else {
00640
00641
00642 entry.value &= 0x0000ffff;
00643 if (__NATIVE__ == MOTO) {
00644 if (type == MOTO)
00645 entry.value = entry.value << 16;
00646 else
00647 entry.value = reverse32 (entry.value);
00648 }
00649 else {
00650 if (type == MOTO)
00651 entry.value = reverse16 ((UINT16) entry.value);
00652
00653 }
00654 }
00655 if (type != __NATIVE__) {
00656 entry.tag = reverse16 (entry.tag);
00657 entry.type = reverse16 (entry.type);
00658 entry.length = reverse32 (entry.length);
00659 }
00660 if (write (fd, (char *) &entry, sizeof (TIFFENTRY)) !=
00661 sizeof (TIFFENTRY)) {
00662 WRITEFAILED.error ("write_tif_image", LOG, "Tag Table");
00663 return -1;
00664 }
00665 }
00666 if (write (fd, (char *) &zero, sizeof zero) != sizeof zero) {
00667 WRITEFAILED.error ("write_tif_image", LOG, "Tag table Terminator");
00668 return -1;
00669 }
00670 if (type != __NATIVE__) {
00671 resolution.top = reverse32 (resolution.top);
00672 resolution.bottom = reverse32 (resolution.bottom);
00673 }
00674 if (write (fd, (char *) &resolution, sizeof resolution) != sizeof resolution
00675 || write (fd, (char *) &resolution,
00676 sizeof resolution) != sizeof resolution) {
00677 WRITEFAILED.error ("write_tif_image", LOG, "Resolution");
00678 return -1;
00679 }
00680 if (write (fd, (char *) pixels, (size_t) size) != size) {
00681 WRITEFAILED.error ("write_tif_image", LOG, "Image");
00682 return -1;
00683 }
00684 close(fd);
00685 return 0;
00686 }
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714