• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**********************************************************************
2  * File:        imgtiff.c  (Formerly tiff.c)
3  * Description: Max format image reader/writer.
4  * Author:      Ray Smith
5  * Created:     Mon Jun 11 14:00:21 BST 1990
6  *
7  * (C) Copyright 1990, Hewlett-Packard Ltd.
8  ** Licensed under the Apache License, Version 2.0 (the "License");
9  ** you may not use this file except in compliance with the License.
10  ** You may obtain a copy of the License at
11  ** http://www.apache.org/licenses/LICENSE-2.0
12  ** Unless required by applicable law or agreed to in writing, software
13  ** distributed under the License is distributed on an "AS IS" BASIS,
14  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  ** See the License for the specific language governing permissions and
16  ** limitations under the License.
17  *
18  **********************************************************************/
19 
20 #include          "mfcpch.h"     //precompiled headers
21 #ifdef __MSW32__
22 #include          <io.h>
23 #else
24 #include          <unistd.h>
25 #endif
26 
27 /*
28 ** Include automatically generated configuration file if running autoconf
29 */
30 #ifdef HAVE_CONFIG_H
31 #include "config_auto.h"
32 #if defined(MOTOROLA_BYTE_ORDER) || defined(WORDS_BIGENDIAN)
33 #define __MOTO__  // Big-endian.
34 #endif
35 #endif
36 
37 #include          "fileerr.h"
38 #include          "imgerrs.h"
39 #include          "img.h"
40 #include          "bitstrm.h"
41 #include          "tprintf.h"
42 #include          "serialis.h"
43 #include          "imgtiff.h"
44 
45 #define INTEL       0x4949
46 #define MOTO        0x4d4d
47 
48 /*************************************************************************
49  * NOTE ON BIG-ENDIAN vs LITTLE-ENDIAN
50  *
51  * Intel machines store numbers with LSByte in the left position.
52  * Motorola	(and PA_RISC) machines use the opposite byte ordering.
53  *
54  * This code is written so that:
55  *   a) it will compile and run on EITHER machine type   AND
56  *   b) the program (on either machine) will process tiff file written in either
57  *      Motorola or Intel format.
58  *
59  * The code is compiled with a __NATIVE__ define which is either MOTO or INTEL.
60  * MOTO and INTEL are defined (above) to be the value of the first two bytes of
61  * a tiff file in either format. (This identifies the filetype).
62  *
63  * Subsequent reads and writes normally just reverse the byte order if the
64  * machine type (__NATIVE__) is not equal to the filetype determined from the
65  * first two bytes of the tiff file.
66  *
67  * A special case is the "value" field of the tag structure. This can contain
68  * EITHER a 16bit or a 32bit value. According to the "type" field. The 4 cases
69  * of machine type / file type combinations need to be treated differently in
70  * the case of 16 bit values
71  *************************************************************************/
72 
73 #define ENTRIES       19         /*no of entries */
74 #define START       8            /*start of tag table */
75 
76 typedef struct
77 {
78   uinT16 tag;                    //entry tag
79   uinT16 type;
80   uinT32 length;
81   inT32 value;
82 } TIFFENTRY;                     //tiff tag entry
83 
84 typedef struct myrational
85 {
86   inT32 top;
87   inT32 bottom;
88 } MYRATIONAL;                    //type 5
89 
90 //statics for the run length codes
91 #define EOL_CODE      0x800
92 #define EOL_MASK      0xfff
93 #define EOL_LENGTH      12       //12 bits
94 #define SHORT_CODE_SIZE   64     //no of short codes
95 #define LONG_CODE_SIZE    40     //no of long codes
96 
97 static uinT16 short_white_codes[SHORT_CODE_SIZE] = {
98   0xac, 0x38, 0xe, 0x1, 0xd, 0x3, 0x7, 0xf,
99   0x19, 0x5, 0x1c, 0x2, 0x4, 0x30, 0xb, 0x2b,
100   0x15, 0x35, 0x72, 0x18, 0x8, 0x74, 0x60, 0x10,
101   0xa, 0x6a, 0x64, 0x12, 0xc, 0x40, 0xc0, 0x58,
102   0xd8, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x14,
103   0x94, 0x54, 0xd4, 0x34, 0xb4, 0x20, 0xa0, 0x50,
104   0xd0, 0x4a, 0xca, 0x2a, 0xaa, 0x24, 0xa4, 0x1a,
105   0x9a, 0x5a, 0xda, 0x52, 0xd2, 0x4c, 0xcc, 0x2c
106 };
107 static uinT8 short_white_lengths[SHORT_CODE_SIZE] = {
108   8, 6, 4, 4, 4, 4, 4, 4,
109   5, 5, 5, 5, 6, 6, 6, 6,
110   6, 6, 7, 7, 7, 7, 7, 7,
111   7, 7, 7, 7, 7, 8, 8, 8,
112   8, 8, 8, 8, 8, 8, 8, 8,
113   8, 8, 8, 8, 8, 8, 8, 8,
114   8, 8, 8, 8, 8, 8, 8, 8,
115   8, 8, 8, 8, 8, 8, 8, 8
116 };
117 static uinT16 short_black_codes[SHORT_CODE_SIZE] = {
118   0x3b0, 0x2, 0x3, 0x1, 0x6, 0xc, 0x4, 0x18,
119   0x28, 0x8, 0x10, 0x50, 0x70, 0x20, 0xe0, 0x30,
120   0x3a0, 0x60, 0x40, 0x730, 0xb0, 0x1b0, 0x760, 0xa0,
121   0x740, 0xc0, 0x530, 0xd30,
122   0x330, 0xb30, 0x160, 0x960,
123   0x560, 0xd60, 0x4b0, 0xcb0,
124   0x2b0, 0xab0, 0x6b0, 0xeb0,
125   0x360, 0xb60, 0x5b0, 0xdb0,
126   0x2a0, 0xaa0, 0x6a0, 0xea0,
127   0x260, 0xa60, 0x4a0, 0xca0,
128   0x240, 0xec0, 0x1c0, 0xe40,
129   0x140, 0x1a0, 0x9a0, 0xd40,
130   0x340, 0x5a0, 0x660, 0xe60
131 };
132 static uinT8 short_black_lengths[SHORT_CODE_SIZE] = {
133   10, 3, 2, 2, 3, 4, 4, 5,
134   6, 6, 7, 7, 7, 8, 8, 9,
135   10, 10, 10, 11, 11, 11, 11, 11,
136   11, 11, 12, 12, 12, 12, 12, 12,
137   12, 12, 12, 12, 12, 12, 12, 12,
138   12, 12, 12, 12, 12, 12, 12, 12,
139   12, 12, 12, 12, 12, 12, 12, 12,
140   12, 12, 12, 12, 12, 12, 12, 12
141 };
142 static uinT16 long_white_codes[LONG_CODE_SIZE] = {
143   0x1b, 0x9, 0x3a, 0x76, 0x6c, 0xec, 0x26, 0xa6,
144   0x16, 0xe6, 0x66, 0x166, 0x96, 0x196, 0x56, 0x156,
145   0xd6, 0x1d6, 0x36, 0x136, 0xb6, 0x1b6, 0x32, 0x132,
146   0xb2, 0x6, 0x1b2,
147   0x80, 0x180, 0x580, 0x480, 0xc80,
148   0x280, 0xa80, 0x680, 0xe80, 0x380, 0xb80, 0x780, 0xf80
149 };
150 static uinT8 long_white_lengths[LONG_CODE_SIZE] = {
151   5, 5, 6, 7, 8, 8, 8, 8,
152   8, 8, 9, 9, 9, 9, 9, 9,
153   9, 9, 9, 9, 9, 9, 9, 9,
154   9, 6, 9, 11, 11, 11, 12, 12,
155   12, 12, 12, 12, 12, 12, 12, 12
156 };
157 static uinT16 long_black_codes[LONG_CODE_SIZE] = {
158   0x3c0, 0x130, 0x930, 0xda0,
159   0xcc0, 0x2c0, 0xac0, 0x6c0,
160   0x16c0, 0xa40, 0x1a40, 0x640,
161   0x1640, 0x9c0, 0x19c0, 0x5c0,
162   0x15c0, 0xdc0, 0x1dc0, 0x940,
163   0x1940, 0x540, 0x1540, 0xb40,
164   0x1b40, 0x4c0, 0x14c0,
165   0x80, 0x180, 0x580, 0x480, 0xc80,
166   0x280, 0xa80, 0x680, 0xe80, 0x380, 0xb80, 0x780, 0xf80
167 };
168 static uinT8 long_black_lengths[LONG_CODE_SIZE] = {
169   10, 12, 12, 12, 12, 12, 12, 13,
170   13, 13, 13, 13, 13, 13, 13, 13,
171   13, 13, 13, 13, 13, 13, 13, 13,
172   13, 13, 13, 11, 11, 11, 12, 12,
173   12, 12, 12, 12, 12, 12, 12, 12
174 };
175 
176 /**********************************************************************
177  * open_tif_image
178  *
179  * Read the header of a tif format image and prepare to read the rest.
180  **********************************************************************/
181 
open_tif_image(int fd,inT32 * xsize,inT32 * ysize,inT8 * bpp,inT8 * photo,inT32 * res)182 inT8 open_tif_image(               //read header
183                     int fd,        //file to read
184                     inT32 *xsize,  //size of image
185                     inT32 *ysize,
186                     inT8 *bpp,     //bits per pixel
187                     inT8 *photo,   //interpretation
188                     inT32 *res     //resolution
189                    ) {
190   inT16 filetype;
191   inT32 start;                   //start of tiff directory
192   inT16 entries;                 //no of tiff entries
193   inT32 imagestart;              //location of image in file
194   inT32 resoffset;               //location of res
195   TIFFENTRY tiffentry;           //tag table entry
196   BOOL8 compressed;              //compression control
197   MYRATIONAL resinfo;            //resolution
198   BOOL8 strips = false;          //if in strips
199 
200   *xsize = -1;                   //illegal values
201   *ysize = -1;
202   *bpp = -1;
203   *res = -1;
204   resoffset = -1;
205   if (read (fd, (char *) &filetype, sizeof filetype) != sizeof filetype
206   || (filetype != INTEL && filetype != MOTO)) {
207     BADIMAGEFORMAT.error ("read_tif_image", TESSLOG, "Filetype");
208     return -1;
209   }
210   lseek (fd, 4L, 0);
211   if (read (fd, (char *) &start, sizeof start) != sizeof start) {
212     READFAILED.error ("read_tif_image", TESSLOG, "Start of tag table");
213     return -1;
214   }
215 
216   if (filetype != __NATIVE__)
217     start = reverse32 (start);
218   if (start <= 0) {
219     BADIMAGEFORMAT.error ("read_tif_image", TESSLOG, "Start of tag table");
220     return -1;
221   }
222   lseek (fd, start, 0);
223   if (read (fd, (char *) &entries, sizeof (inT16)) != sizeof (inT16)) {
224     BADIMAGEFORMAT.error ("read_tif_image", TESSLOG, "Size of tag table");
225     return -1;
226   }
227   if (filetype != __NATIVE__)
228     entries = reverse16 (entries);
229   //      printf("No of tiff directory entries=%d\n",entries);
230   imagestart = 0;
231   compressed = FALSE;
232   int samples_per_pixel = 1;
233   int bits_per_sample = 1;
234   for (; entries-- > 0;) {
235     if (read (fd, (char *) &tiffentry, sizeof tiffentry) !=
236     sizeof tiffentry) {
237       BADIMAGEFORMAT.error ("read_tif_image", TESSLOG, "Tag table entry");
238       return -1;
239     }
240     if (filetype != __NATIVE__) {
241       tiffentry.type = reverse16 (tiffentry.type);
242       tiffentry.tag = reverse16 (tiffentry.tag);
243       tiffentry.length = reverse32 (tiffentry.length);
244     }
245     if (tiffentry.type != 3) {   //Full 32bit value
246       if (filetype != __NATIVE__)
247         tiffentry.value = reverse32 (tiffentry.value);
248     }
249     else {
250       /* A 16bit value in 4 bytes - handle with care. SEE NOTE at start of file */
251       if (__NATIVE__ == MOTO) {
252         if (filetype == MOTO)    //MOTO file on MOTO Machine
253           tiffentry.value = tiffentry.value >> 16;
254         else                     //INTEL file on MOTO Machine
255           tiffentry.value = reverse32 (tiffentry.value);
256       }
257       else {                     //INTEL Machine
258         if (filetype == MOTO)    //MOTO file on INTEL Machine
259           tiffentry.value = reverse16 ((uinT16) tiffentry.value);
260         //INTEL file on INTEL Machine NO ACTION NEEDED
261       }
262                                  //Clear top 2 MSBytes
263       tiffentry.value &= 0x0000ffff;
264     }
265 
266     //              printf("Tag=%x, Type=%x, Length=%x, value=%x\n",
267     //                      tiffentry.tag,tiffentry.type,tiffentry.length,tiffentry.value);
268     switch (tiffentry.tag) {
269       case 0x101:
270         *ysize = tiffentry.value;
271         break;
272       case 0x100:
273         *xsize = tiffentry.value;
274         break;
275       case 0x102:
276         if (tiffentry.length == 1)
277           bits_per_sample = (inT8) tiffentry.value;
278         else
279           bits_per_sample = 8;
280         break;
281       case 0x115:
282         samples_per_pixel = (inT8) tiffentry.value;
283         break;
284       case 0x111:
285         imagestart = tiffentry.value;
286         strips = tiffentry.length > 1;
287         break;
288       case 0x103:
289         if (tiffentry.value == 3) {
290           compressed = TRUE;
291         }
292         else if (tiffentry.value != 1) {
293           BADIMAGEFORMAT.error ("read_tif_image", TESSLOG, "Compression");
294           return -1;
295         }
296         break;
297       case 0x11a:
298       case 0x11b:
299                                  //resolution
300         resoffset = tiffentry.value;
301         break;
302       case 0x106:
303         *photo = (inT8) tiffentry.value;
304         break;
305     }                            //endswitch
306   }
307   if (*xsize <= 0 || *ysize <= 0 || imagestart <= 0) {
308     BADIMAGEFORMAT.error ("read_tif_image", TESSLOG, "Vital tag");
309     return -1;
310   }
311   tprintf("Image has %d * %d bit%c per pixel, and size (%d,%d)\n",
312           bits_per_sample, samples_per_pixel, bits_per_sample == 1 ? ' ' : 's',
313           *xsize, *ysize);
314   *bpp = bits_per_sample * samples_per_pixel;
315   if (resoffset >= 0) {
316     lseek (fd, resoffset, 0);
317     if (read (fd, (char *) &resinfo, sizeof (resinfo)) != sizeof (resinfo)) {
318       READFAILED.error ("read_tif_image", TESSLOG, "Resolution");
319       return -1;
320     }
321     if (filetype != __NATIVE__) {
322       resinfo.top = reverse32 (resinfo.top);
323       resinfo.bottom = reverse32 (resinfo.bottom);
324     }
325     *res = resinfo.top / resinfo.bottom;
326     tprintf ("Resolution=%d\n", *res);
327   }
328   lseek (fd, (long) imagestart, 0);
329   if (strips) {
330     if (read (fd, (char *) &imagestart, sizeof (imagestart)) !=
331     sizeof (imagestart)) {
332       READFAILED.error ("read_tif_image", TESSLOG, "Strip offset");
333       return -1;
334     }
335     if (filetype != __NATIVE__)
336       imagestart = reverse32 (imagestart);
337                                  //indirection
338     lseek (fd, (long) imagestart, 0);
339   }
340   return compressed ? -2 : 0;
341 }
342 
343 
344 /**********************************************************************
345  * read_tif_image
346  *
347  * Read a whole tif image into memory.
348  **********************************************************************/
349 
read_tif_image(int fd,uinT8 * pixels,inT32 xsize,inT32 ysize,inT8 bpp,inT32)350 inT8 read_tif_image(                //read whole image
351                     int fd,         //file to read
352                     uinT8 *pixels,  //pixels of image
353                     inT32 xsize,    //size of image
354                     inT32 ysize,
355                     inT8 bpp,       //bits per pixel
356                     inT32           //bytes per line
357                    ) {
358   inT32 xindex;                  //indices in image
359   inT32 yindex;
360   inT32 length;                  //short length
361   inT32 biglength;               //extender
362   uinT8 *lengths;                //current lengths
363   uinT16 *codes;                 //current codes
364   uinT16 codeword;               //current code word
365   IMAGELINE imageline;           //current line
366   IMAGE image;                   //dummy image
367   R_BITSTREAM bits;              //read bitstream
368   uinT8 colour;                  //current colour
369 
370   image.capture (pixels, xsize, ysize, bpp);
371   codeword = bits.open (fd);     //open bitstream
372   read_eol(&bits, codeword);  //find end of line
373   for (yindex = ysize - 1; yindex >= 0; yindex--) {
374     imageline.init ();
375     colour = TRUE;
376     for (xindex = 0; xindex < xsize;) {
377       if (colour) {
378         lengths = long_white_lengths;
379         codes = long_white_codes;
380       }
381       else {
382         lengths = long_black_lengths;
383         codes = long_black_codes;
384       }
385       for (biglength = 0; biglength < LONG_CODE_SIZE
386         && (codeword & bits.masks (*lengths))
387         != *codes; codes++, lengths++, biglength++);
388       if (biglength < LONG_CODE_SIZE) {
389         codeword = bits.read_code (*lengths);
390         biglength++;
391         biglength *= SHORT_CODE_SIZE;
392       }
393       else
394         biglength = 0;
395       if (colour) {
396         lengths = short_white_lengths;
397         codes = short_white_codes;
398       }
399       else {
400         lengths = short_black_lengths;
401         codes = short_black_codes;
402       }
403       for (length = 0; length < SHORT_CODE_SIZE
404         && (codeword & bits.masks (*lengths))
405         != *codes; codes++, lengths++, length++);
406       if (length < SHORT_CODE_SIZE) {
407         codeword = bits.read_code (*lengths);
408         for (length += biglength; length > 0; length--, xindex++)
409           imageline.pixels[xindex] = colour;
410         colour = !colour;
411       }
412       else
413         break;
414     }
415     if (xindex < xsize) {
416       tprintf ("%d pixels short on line %d", xsize - xindex, yindex);
417       tprintf (", unknown code=%x\n", codeword);
418     }
419     xindex = read_eol (&bits, codeword);
420     if (xindex > 0)
421       tprintf ("Discarding %d bits on line %d\n", xindex, yindex);
422     image.put_line (0, yindex, xsize, &imageline, 0);
423   }
424   return 0;
425 }
426 
427 
428 /**********************************************************************
429  * read_eol
430  *
431  * Take bits out of the stream until and end-of-line code is hit.
432  **********************************************************************/
433 
read_eol(R_BITSTREAM * bits,uinT16 & code)434 inT32 read_eol(                    //read end of line
435                R_BITSTREAM *bits,  //bitstream to read
436                uinT16 &code        //current code
437               ) {
438   BOOL8 anyones;                 //any 1 bits skipped
439   inT32 bitcount;                //total bits skipped
440 
441   anyones = FALSE;
442   bitcount = 0;
443   while ((code & EOL_MASK) != EOL_CODE) {
444     if (code & 1)
445       anyones = TRUE;            //discarded one bit
446     bitcount++;                  //total discarded bits
447     code = bits->read_code (1);  //take single bits
448   }
449                                  //extract EOL code
450   code = bits->read_code (EOL_LENGTH);
451 
452   if (!anyones)
453     bitcount = 0;                //ignore filler bits
454   return bitcount;
455 }
456 
457 
458 /**********************************************************************
459  * write_moto_tif
460  *
461  * Write a whole tif format image and close the file.
462  **********************************************************************/
463 
write_moto_tif(int fd,uinT8 * pixels,inT32 xsize,inT32 ysize,inT8 bpp,inT8 photo,inT32 res)464 inT8 write_moto_tif(                //write whole image
465                     int fd,         //file to write on
466                     uinT8 *pixels,  //image pixels
467                     inT32 xsize,    //size of image
468                     inT32 ysize,
469                     inT8 bpp,       //bits per pixel
470                     inT8 photo,
471                     inT32 res       //resolution
472                    ) {
473   return write_tif_image (fd, pixels, xsize, ysize, bpp, res, MOTO, photo);
474   //use moto format
475 }
476 
477 
478 /**********************************************************************
479  * write_intel_tif
480  *
481  * Write a whole tif format image and close the file.
482  **********************************************************************/
483 
write_intel_tif(int fd,uinT8 * pixels,inT32 xsize,inT32 ysize,inT8 bpp,inT8 photo,inT32 res)484 inT8 write_intel_tif(                //write whole image
485                      int fd,         //file to write on
486                      uinT8 *pixels,  //image pixels
487                      inT32 xsize,    //size of image
488                      inT32 ysize,
489                      inT8 bpp,       //bits per pixel
490                      inT8 photo,
491                      inT32 res       //resolution
492                     ) {
493   return write_tif_image (fd, pixels, xsize, ysize, bpp, res, INTEL, photo);
494   //use intel format
495 }
496 
497 
498 /**********************************************************************
499  * write_inverse_tif
500  *
501  * Write a whole tif format image and close the file.
502  **********************************************************************/
503 
write_inverse_tif(int fd,uinT8 * pixels,inT32 xsize,inT32 ysize,inT8 bpp,inT8 photo,inT32 res)504 inT8 write_inverse_tif(                //write whole image
505                        int fd,         //file to write on
506                        uinT8 *pixels,  //image pixels
507                        inT32 xsize,    //size of image
508                        inT32 ysize,
509                        inT8 bpp,       //bits per pixel
510                        inT8 photo,
511                        inT32 res       //resolution
512                       ) {
513   return write_tif_image (fd, pixels, xsize, ysize, bpp, res, INTEL,
514     1 - photo);
515   //use intel format
516 }
517 
518 
519 /**********************************************************************
520  * write_tif_image
521  *
522  * Write a whole tif format image and close the file.
523  **********************************************************************/
524 
write_tif_image(int fd,uinT8 * pixels,inT32 xsize,inT32 ysize,inT8 bpp,inT32 res,inT16 type,inT16 photo)525 inT8 write_tif_image(                //write whole image
526                      int fd,         //file to write on
527                      uinT8 *pixels,  //image pixels
528                      inT32 xsize,    //size of image
529                      inT32 ysize,
530                      inT8 bpp,       //bits per pixel
531                      inT32 res,      //resolution
532                      inT16 type,     //format type
533                      inT16 photo     //metric interp
534                     ) {
535   inT32 size;                    //line/image size
536   inT16 entries;                 //no of tiff entries
537   inT32 start;                   //start of tag table
538   inT32 zero = 0;
539   MYRATIONAL resolution;         //resolution
540   TIFFENTRY entry;               //current entry
541 
542   static TIFFENTRY tags[ENTRIES] = {
543     {0xfe, 4, 1, 0},
544     {0x100, 3, 1, 0},
545     {0x101, 3, 1, 0},
546     {0x102, 3, 1, 0},
547     {0x103, 3, 1, 1},
548     {0x106, 3, 1, 1},
549     {                            /*line art */
550       0x107, 3, 1, 1
551     },
552     {0x10a, 3, 1, 1},
553     {
554       0x111, 4, 1, START + ENTRIES * sizeof (TIFFENTRY)
555       + sizeof (inT32) + sizeof (short) + sizeof (MYRATIONAL) * 2
556     }
557     ,
558     {0x112, 3, 1, 1}
559     ,
560     {0x115, 3, 1, 1}
561     ,
562     {0x116, 4, 1, 0}
563     ,
564     {0x117, 4, 1, 0}
565     ,
566     {0x118, 3, 1, 0}
567     ,
568     {0x119, 3, 1, 1}
569     ,
570     {
571       0x11a, 5, 1, START + ENTRIES * sizeof (TIFFENTRY)
572       + sizeof (inT32) + sizeof (short)
573     },
574     {
575       0x11b, 5, 1, START + ENTRIES * sizeof (TIFFENTRY)
576       + sizeof (inT32) + sizeof (short) + sizeof (MYRATIONAL)
577     }
578     ,
579     {0x11c, 3, 1, 1}
580     ,
581     {0x128, 3, 1, 2}
582   };
583 
584   resolution.top = res;
585   resolution.bottom = 1;
586   if (write (fd, (char *) &type, sizeof type) != sizeof type
587   || (type != INTEL && type != MOTO)) {
588     WRITEFAILED.error ("write_tif_image", TESSLOG, "Filetype");
589     return -1;
590   }
591   start = START;
592   entries = 0x002a;
593   if (type != __NATIVE__)
594     entries = reverse16 (entries);
595   if (write (fd, (char *) &entries, sizeof entries) != sizeof entries) {
596     WRITEFAILED.error ("write_tif_image", TESSLOG, "Version");
597     return -1;
598   }
599   if (type != __NATIVE__)
600     start = reverse32 (start);
601   if (write (fd, (char *) &start, sizeof start) != sizeof start) {
602     WRITEFAILED.error ("write_tif_image", TESSLOG, "Start");
603     return -1;
604   }
605   lseek (fd, (long) START, 0);
606   entries = ENTRIES;
607   if (type != __NATIVE__)
608     entries = reverse16 (entries);
609   if (write (fd, (char *) &entries, sizeof entries) != sizeof entries) {
610     WRITEFAILED.error ("write_tif_image", TESSLOG, "Entries");
611     return -1;
612   }
613                                  //line length
614   size = COMPUTE_IMAGE_XDIM (xsize, bpp);
615   size *= ysize;                 //total image size
616   //      if (photo==0)
617   //      {
618   //              tags[0].tag=0xfe;
619   //              tags[0].type=4;
620   //              tags[0].value=0;
621   //      }
622   //      else
623   //      {
624   //              tags[0].tag=0xff;
625   //              tags[0].type=3;
626   //              tags[0].value=1;
627   //      }
628   tags[1].value = xsize;
629   tags[2].value = ysize;
630   if (bpp == 24) {
631     tags[3].value = 8;
632     tags[10].value = 3;
633     tags[5].value = 2;
634   }
635   else {
636     tags[3].value = bpp;
637     tags[5].value = photo;
638   }
639   tags[11].value = ysize;
640   tags[14].value = (1 << bpp) - 1;
641   tags[12].value = size;
642   for (entries = 0; entries < ENTRIES; entries++) {
643     entry = tags[entries];       //get an entry
644     /* NB Convert entry.value BEFORE converting entry.type!!! */
645     if (entry.type != 3) {       //Full 32bit value
646       if (type != __NATIVE__)
647         entry.value = reverse32 (entry.value);
648     }
649     else {
650       /* A 16bit value in 4 bytes - handle with care. SEE NOTE at start of file */
651       entry.value &= 0x0000ffff; //Ensure top 2 MSBytes clear
652       if (__NATIVE__ == MOTO) {
653         if (type == MOTO)        //MOTO file on MOTO Machine
654           entry.value = entry.value << 16;
655         else                     //INTEL file on MOTO Machine
656           entry.value = reverse32 (entry.value);
657       }
658       else {                     //INTEL Machine
659         if (type == MOTO)        //MOTO file on INTEL Machine
660           entry.value = reverse16 ((uinT16) entry.value);
661         //INTEL file on INTEL Machine NO ACTION NEEDED
662       }
663     }
664     if (type != __NATIVE__) {
665       entry.tag = reverse16 (entry.tag);
666       entry.type = reverse16 (entry.type);
667       entry.length = reverse32 (entry.length);
668     }
669     if (write (fd, (char *) &entry, sizeof (TIFFENTRY)) !=
670     sizeof (TIFFENTRY)) {
671       WRITEFAILED.error ("write_tif_image", TESSLOG, "Tag Table");
672       return -1;
673     }
674   }
675   if (write (fd, (char *) &zero, sizeof zero) != sizeof zero) {
676     WRITEFAILED.error ("write_tif_image", TESSLOG, "Tag table Terminator");
677     return -1;
678   }
679   if (type != __NATIVE__) {
680     resolution.top = reverse32 (resolution.top);
681     resolution.bottom = reverse32 (resolution.bottom);
682   }
683   if (write (fd, (char *) &resolution, sizeof resolution) != sizeof resolution
684     || write (fd, (char *) &resolution,
685   sizeof resolution) != sizeof resolution) {
686     WRITEFAILED.error ("write_tif_image", TESSLOG, "Resolution");
687     return -1;
688   }
689   if (write (fd, (char *) pixels, (size_t) size) != size) {
690     WRITEFAILED.error ("write_tif_image", TESSLOG, "Image");
691     return -1;
692   }
693   close(fd);
694   return 0;
695 }
696 
697 
698 /**********************************************************************
699  * reverse32
700  *
701  * Byte swap the 32 bit number between Motorola & Intel format.
702  **********************************************************************/
703 
704 //inT32                                                         reverse32(                                                      //reverse 32 bit int
705 //uinT32                                                        value                                                                   //value to reverse
706 //)
707 //{
708 //      return (value>>24) | (value>>8) & 0xff00
709 //      | (value<<8) & 0xff0000 | (value<<24);
710 //}
711 
712 /**********************************************************************
713  * reverse16
714  *
715  * Byte swap the 16 bit number between Motorola & Intel format.
716  **********************************************************************/
717 
718 //inT16                                                         reverse16(                                                      //reverse 16 bit int
719 //uinT16                                                        value                                                                   //value to reverse
720 //)
721 //{
722 //      return (value>>8) | (value<<8);
723 //}
724