source: trunk/third/tiff/libtiff/tif_luv.c @ 18174

Revision 18174, 38.6 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18173, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 1997 Greg Ward Larson
3 * Copyright (c) 1997 Silicon Graphics, Inc.
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that (i) the above copyright notices and this permission notice appear in
8 * all copies of the software and related documentation, and (ii) the names of
9 * Sam Leffler, Greg Larson and Silicon Graphics may not be used in any
10 * advertising or publicity relating to the software without the specific,
11 * prior written permission of Sam Leffler, Greg Larson and Silicon Graphics.
12 *
13 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 
16 *
17 * IN NO EVENT SHALL SAM LEFFLER, GREG LARSON OR SILICON GRAPHICS BE LIABLE
18 * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 */
24
25#include "tiffiop.h"
26#ifdef LOGLUV_SUPPORT
27
28/*
29 * TIFF Library.
30 * LogLuv compression support for high dynamic range images.
31 *
32 * Contributed by Greg Larson.
33 *
34 * LogLuv image support uses the TIFF library to store 16 or 10-bit
35 * log luminance values with 8 bits each of u and v or a 14-bit index.
36 *
37 * The codec can take as input and produce as output 32-bit IEEE float values
38 * as well as 16-bit integer values.  A 16-bit luminance is interpreted
39 * as a sign bit followed by a 15-bit integer that is converted
40 * to and from a linear magnitude using the transformation:
41 *
42 *      L = 2^( (Le+.5)/256 - 64 )              # real from 15-bit
43 *
44 *      Le = floor( 256*(log2(L) + 64) )        # 15-bit from real
45 *
46 * The actual conversion to world luminance units in candelas per sq. meter
47 * requires an additional multiplier, which is stored in the TIFFTAG_STONITS.
48 * This value is usually set such that a reasonable exposure comes from
49 * clamping decoded luminances above 1 to 1 in the displayed image.
50 *
51 * The 16-bit values for u and v may be converted to real values by dividing
52 * each by 32768.  (This allows for negative values, which aren't useful as
53 * far as we know, but are left in case of future improvements in human
54 * color vision.)
55 *
56 * Conversion from (u,v), which is actually the CIE (u',v') system for
57 * you color scientists, is accomplished by the following transformation:
58 *
59 *      u = 4*x / (-2*x + 12*y + 3)
60 *      v = 9*y / (-2*x + 12*y + 3)
61 *
62 *      x = 9*u / (6*u - 16*v + 12)
63 *      y = 4*v / (6*u - 16*v + 12)
64 *
65 * This process is greatly simplified by passing 32-bit IEEE floats
66 * for each of three CIE XYZ coordinates.  The codec then takes care
67 * of conversion to and from LogLuv, though the application is still
68 * responsible for interpreting the TIFFTAG_STONITS calibration factor.
69 *
70 * By definition, a CIE XYZ vector of [1 1 1] corresponds to a neutral white
71 * point of (x,y)=(1/3,1/3).  However, most color systems assume some other
72 * white point, such as D65, and an absolute color conversion to XYZ then
73 * to another color space with a different white point may introduce an
74 * unwanted color cast to the image.  It is often desirable, therefore, to
75 * perform a white point conversion that maps the input white to [1 1 1]
76 * in XYZ, then record the original white point using the TIFFTAG_WHITEPOINT
77 * tag value.  A decoder that demands absolute color calibration may use
78 * this white point tag to get back the original colors, but usually it
79 * will be ignored and the new white point will be used instead that
80 * matches the output color space.
81 *
82 * Pixel information is compressed into one of two basic encodings, depending
83 * on the setting of the compression tag, which is one of COMPRESSION_SGILOG
84 * or COMPRESSION_SGILOG24.  For COMPRESSION_SGILOG, greyscale data is
85 * stored as:
86 *
87 *       1       15
88 *      |-+---------------|
89 *
90 * COMPRESSION_SGILOG color data is stored as:
91 *
92 *       1       15           8        8
93 *      |-+---------------|--------+--------|
94 *       S       Le           ue       ve
95 *
96 * For the 24-bit COMPRESSION_SGILOG24 color format, the data is stored as:
97 *
98 *           10           14
99 *      |----------|--------------|
100 *           Le'          Ce
101 *
102 * There is no sign bit in the 24-bit case, and the (u,v) chromaticity is
103 * encoded as an index for optimal color resolution.  The 10 log bits are
104 * defined by the following conversions:
105 *
106 *      L = 2^((Le'+.5)/64 - 12)                # real from 10-bit
107 *
108 *      Le' = floor( 64*(log2(L) + 12) )        # 10-bit from real
109 *
110 * The 10 bits of the smaller format may be converted into the 15 bits of
111 * the larger format by multiplying by 4 and adding 13314.  Obviously,
112 * a smaller range of magnitudes is covered (about 5 orders of magnitude
113 * instead of 38), and the lack of a sign bit means that negative luminances
114 * are not allowed.  (Well, they aren't allowed in the real world, either,
115 * but they are useful for certain types of image processing.)
116 *
117 * The desired user format is controlled by the setting the internal
118 * pseudo tag TIFFTAG_SGILOGDATAFMT to one of:
119 *  SGILOGDATAFMT_FLOAT       = IEEE 32-bit float XYZ values
120 *  SGILOGDATAFMT_16BIT       = 16-bit integer encodings of logL, u and v
121 * Raw data i/o is also possible using:
122 *  SGILOGDATAFMT_RAW         = 32-bit unsigned integer with encoded pixel
123 * In addition, the following decoding is provided for ease of display:
124 *  SGILOGDATAFMT_8BIT        = 8-bit default RGB gamma-corrected values
125 *
126 * For grayscale images, we provide the following data formats:
127 *  SGILOGDATAFMT_FLOAT       = IEEE 32-bit float Y values
128 *  SGILOGDATAFMT_16BIT       = 16-bit integer w/ encoded luminance
129 *  SGILOGDATAFMT_8BIT        = 8-bit gray monitor values
130 *
131 * Note that the COMPRESSION_SGILOG applies a simple run-length encoding
132 * scheme by separating the logL, u and v bytes for each row and applying
133 * a PackBits type of compression.  Since the 24-bit encoding is not
134 * adaptive, the 32-bit color format takes less space in many cases.
135 *
136 * Further control is provided over the conversion from higher-resolution
137 * formats to final encoded values through the pseudo tag
138 * TIFFTAG_SGILOGENCODE:
139 *  SGILOGENCODE_NODITHER     = do not dither encoded values
140 *  SGILOGENCODE_RANDITHER    = apply random dithering during encoding
141 *
142 * The default value of this tag is SGILOGENCODE_NODITHER for
143 * COMPRESSION_SGILOG to maximize run-length encoding and
144 * SGILOGENCODE_RANDITHER for COMPRESSION_SGILOG24 to turn
145 * quantization errors into noise.
146 */
147
148#include <stdio.h>
149#include <assert.h>
150#include <stdlib.h>
151#include <math.h>
152
153/*
154 * State block for each open TIFF
155 * file using LogLuv compression/decompression.
156 */
157typedef struct logLuvState LogLuvState;
158
159struct logLuvState {
160        int                     user_datafmt;   /* user data format */
161        int                     encode_meth;    /* encoding method */
162        int                     pixel_size;     /* bytes per pixel */
163
164        tidata_t*               tbuf;           /* translation buffer */
165        int                     tbuflen;        /* buffer length */
166        void (*tfunc)(LogLuvState*, tidata_t, int);
167
168        TIFFVSetMethod          vgetparent;     /* super-class method */
169        TIFFVSetMethod          vsetparent;     /* super-class method */
170};
171
172#define DecoderState(tif)       ((LogLuvState*) (tif)->tif_data)
173#define EncoderState(tif)       ((LogLuvState*) (tif)->tif_data)
174
175#define N(a)   (sizeof(a)/sizeof(a[0]))
176#define SGILOGDATAFMT_UNKNOWN   -1
177
178#define MINRUN          4       /* minimum run length */
179
180/*
181 * Decode a string of 16-bit gray pixels.
182 */
183static int
184LogL16Decode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
185{
186        LogLuvState* sp = DecoderState(tif);
187        int shft, i, npixels;
188        u_char* bp;
189        int16* tp;
190        int16 b;
191        int cc, rc;
192
193        assert(s == 0);
194        assert(sp != NULL);
195
196        npixels = occ / sp->pixel_size;
197
198        if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
199                tp = (int16*) op;
200        else {
201                assert(sp->tbuflen >= npixels);
202                tp = (int16*) sp->tbuf;
203        }
204        _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0]));
205
206        bp = (u_char*) tif->tif_rawcp;
207        cc = tif->tif_rawcc;
208                                        /* get each byte string */
209        for (shft = 2*8; (shft -= 8) >= 0; ) {
210                for (i = 0; i < npixels && cc > 0; )
211                        if (*bp >= 128) {               /* run */
212                                rc = *bp++ + (2-128);
213                                b = (int16)*bp++ << shft;
214                                cc -= 2;
215                                while (rc--)
216                                        tp[i++] |= b;
217                        } else {                        /* non-run */
218                                rc = *bp++;             /* nul is noop */
219                                while (--cc && rc--)
220                                        tp[i++] |= (int16)*bp++ << shft;
221                        }
222                if (i != npixels) {
223                        TIFFError(tif->tif_name,
224                "LogL16Decode: Not enough data at row %d (short %d pixels)",
225                            tif->tif_row, npixels - i);
226                        tif->tif_rawcp = (tidata_t) bp;
227                        tif->tif_rawcc = cc;
228                        return (0);
229                }
230        }
231        (*sp->tfunc)(sp, op, npixels);
232        tif->tif_rawcp = (tidata_t) bp;
233        tif->tif_rawcc = cc;
234        return (1);
235}
236
237/*
238 * Decode a string of 24-bit pixels.
239 */
240static int
241LogLuvDecode24(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
242{
243        LogLuvState* sp = DecoderState(tif);
244        int cc, i, npixels;
245        u_char* bp;
246        uint32* tp;
247
248        assert(s == 0);
249        assert(sp != NULL);
250
251        npixels = occ / sp->pixel_size;
252
253        if (sp->user_datafmt == SGILOGDATAFMT_RAW)
254                tp = (uint32 *)op;
255        else {
256                assert(sp->tbuflen >= npixels);
257                tp = (uint32 *) sp->tbuf;
258        }
259                                        /* copy to array of uint32 */
260        bp = (u_char*) tif->tif_rawcp;
261        cc = tif->tif_rawcc;
262        for (i = 0; i < npixels && cc > 0; i++) {
263                tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2];
264                bp += 3;
265                cc -= 3;
266        }
267        tif->tif_rawcp = (tidata_t) bp;
268        tif->tif_rawcc = cc;
269        if (i != npixels) {
270                TIFFError(tif->tif_name,
271            "LogLuvDecode24: Not enough data at row %d (short %d pixels)",
272                    tif->tif_row, npixels - i);
273                return (0);
274        }
275        (*sp->tfunc)(sp, op, npixels);
276        return (1);
277}
278
279/*
280 * Decode a string of 32-bit pixels.
281 */
282static int
283LogLuvDecode32(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
284{
285        LogLuvState* sp;
286        int shft, i, npixels;
287        u_char* bp;
288        uint32* tp;
289        uint32 b;
290        int cc, rc;
291
292        assert(s == 0);
293        sp = DecoderState(tif);
294        assert(sp != NULL);
295
296        npixels = occ / sp->pixel_size;
297
298        if (sp->user_datafmt == SGILOGDATAFMT_RAW)
299                tp = (uint32*) op;
300        else {
301                assert(sp->tbuflen >= npixels);
302                tp = (uint32*) sp->tbuf;
303        }
304        _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0]));
305
306        bp = (u_char*) tif->tif_rawcp;
307        cc = tif->tif_rawcc;
308                                        /* get each byte string */
309        for (shft = 4*8; (shft -= 8) >= 0; ) {
310                for (i = 0; i < npixels && cc > 0; )
311                        if (*bp >= 128) {               /* run */
312                                rc = *bp++ + (2-128);
313                                b = (uint32)*bp++ << shft;
314                                cc -= 2;
315                                while (rc--)
316                                        tp[i++] |= b;
317                        } else {                        /* non-run */
318                                rc = *bp++;             /* nul is noop */
319                                while (--cc && rc--)
320                                        tp[i++] |= (uint32)*bp++ << shft;
321                        }
322                if (i != npixels) {
323                        TIFFError(tif->tif_name,
324                "LogLuvDecode32: Not enough data at row %d (short %d pixels)",
325                            tif->tif_row, npixels - i);
326                        tif->tif_rawcp = (tidata_t) bp;
327                        tif->tif_rawcc = cc;
328                        return (0);
329                }
330        }
331        (*sp->tfunc)(sp, op, npixels);
332        tif->tif_rawcp = (tidata_t) bp;
333        tif->tif_rawcc = cc;
334        return (1);
335}
336
337/*
338 * Decode a strip of pixels.  We break it into rows to
339 * maintain synchrony with the encode algorithm, which
340 * is row by row.
341 */
342static int
343LogLuvDecodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
344{
345        tsize_t rowlen = TIFFScanlineSize(tif);
346
347        assert(cc%rowlen == 0);
348        while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
349                bp += rowlen, cc -= rowlen;
350        return (cc == 0);
351}
352
353/*
354 * Decode a tile of pixels.  We break it into rows to
355 * maintain synchrony with the encode algorithm, which
356 * is row by row.
357 */
358static int
359LogLuvDecodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
360{
361        tsize_t rowlen = TIFFTileRowSize(tif);
362
363        assert(cc%rowlen == 0);
364        while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
365                bp += rowlen, cc -= rowlen;
366        return (cc == 0);
367}
368
369/*
370 * Encode a row of 16-bit pixels.
371 */
372static int
373LogL16Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
374{
375        LogLuvState* sp = EncoderState(tif);
376        int shft, i, j, npixels;
377        tidata_t op;
378        int16* tp;
379        int16 b;
380        int occ, rc=0, mask, beg;
381
382        assert(s == 0);
383        assert(sp != NULL);
384        npixels = cc / sp->pixel_size;
385
386        if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
387                tp = (int16*) bp;
388        else {
389                tp = (int16*) sp->tbuf;
390                assert(sp->tbuflen >= npixels);
391                (*sp->tfunc)(sp, bp, npixels);
392        }
393                                        /* compress each byte string */
394        op = tif->tif_rawcp;
395        occ = tif->tif_rawdatasize - tif->tif_rawcc;
396        for (shft = 2*8; (shft -= 8) >= 0; )
397                for (i = 0; i < npixels; i += rc) {
398                        if (occ < 4) {
399                                tif->tif_rawcp = op;
400                                tif->tif_rawcc = tif->tif_rawdatasize - occ;
401                                if (!TIFFFlushData1(tif))
402                                        return (-1);
403                                op = tif->tif_rawcp;
404                                occ = tif->tif_rawdatasize - tif->tif_rawcc;
405                        }
406                        mask = 0xff << shft;            /* find next run */
407                        for (beg = i; beg < npixels; beg += rc) {
408                                b = tp[beg] & mask;
409                                rc = 1;
410                                while (rc < 127+2 && beg+rc < npixels &&
411                                                (tp[beg+rc] & mask) == b)
412                                        rc++;
413                                if (rc >= MINRUN)
414                                        break;          /* long enough */
415                        }
416                        if (beg-i > 1 && beg-i < MINRUN) {
417                                b = tp[i] & mask;       /* check short run */
418                                j = i+1;
419                                while ((tp[j++] & mask) == b)
420                                        if (j == beg) {
421                                                *op++ = 128-2+j-i;
422                                                *op++ = b >> shft;
423                                                occ -= 2;
424                                                i = beg;
425                                                break;
426                                        }
427                        }
428                        while (i < beg) {               /* write out non-run */
429                                if ((j = beg-i) > 127) j = 127;
430                                if (occ < j+3) {
431                                        tif->tif_rawcp = op;
432                                        tif->tif_rawcc = tif->tif_rawdatasize - occ;
433                                        if (!TIFFFlushData1(tif))
434                                                return (-1);
435                                        op = tif->tif_rawcp;
436                                        occ = tif->tif_rawdatasize - tif->tif_rawcc;
437                                }
438                                *op++ = j; occ--;
439                                while (j--) {
440                                        *op++ = tp[i++] >> shft & 0xff;
441                                        occ--;
442                                }
443                        }
444                        if (rc >= MINRUN) {             /* write out run */
445                                *op++ = 128-2+rc;
446                                *op++ = tp[beg] >> shft & 0xff;
447                                occ -= 2;
448                        } else
449                                rc = 0;
450                }
451        tif->tif_rawcp = op;
452        tif->tif_rawcc = tif->tif_rawdatasize - occ;
453
454        return (0);
455}
456
457/*
458 * Encode a row of 24-bit pixels.
459 */
460static int
461LogLuvEncode24(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
462{
463        LogLuvState* sp = EncoderState(tif);
464        int i, npixels, occ;
465        tidata_t op;
466        uint32* tp;
467
468        assert(s == 0);
469        assert(sp != NULL);
470        npixels = cc / sp->pixel_size;
471
472        if (sp->user_datafmt == SGILOGDATAFMT_RAW)
473                tp = (uint32*) bp;
474        else {
475                tp = (uint32*) sp->tbuf;
476                assert(sp->tbuflen >= npixels);
477                (*sp->tfunc)(sp, bp, npixels);
478        }
479                                        /* write out encoded pixels */
480        op = tif->tif_rawcp;
481        occ = tif->tif_rawdatasize - tif->tif_rawcc;
482        for (i = npixels; i--; ) {
483                if (occ < 3) {
484                        tif->tif_rawcp = op;
485                        tif->tif_rawcc = tif->tif_rawdatasize - occ;
486                        if (!TIFFFlushData1(tif))
487                                return (-1);
488                        op = tif->tif_rawcp;
489                        occ = tif->tif_rawdatasize - tif->tif_rawcc;
490                }
491                *op++ = (tidataval_t)(*tp >> 16);
492                *op++ = (tidataval_t)(*tp >> 8 & 0xff);
493                *op++ = (tidataval_t)(*tp++ & 0xff);
494                occ -= 3;
495        }
496        tif->tif_rawcp = op;
497        tif->tif_rawcc = tif->tif_rawdatasize - occ;
498
499        return (0);
500}
501
502/*
503 * Encode a row of 32-bit pixels.
504 */
505static int
506LogLuvEncode32(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
507{
508        LogLuvState* sp = EncoderState(tif);
509        int shft, i, j, npixels;
510        tidata_t op;
511        uint32* tp;
512        uint32 b;
513        int occ, rc=0, mask, beg;
514
515        assert(s == 0);
516        assert(sp != NULL);
517
518        npixels = cc / sp->pixel_size;
519
520        if (sp->user_datafmt == SGILOGDATAFMT_RAW)
521                tp = (uint32*) bp;
522        else {
523                tp = (uint32*) sp->tbuf;
524                assert(sp->tbuflen >= npixels);
525                (*sp->tfunc)(sp, bp, npixels);
526        }
527                                        /* compress each byte string */
528        op = tif->tif_rawcp;
529        occ = tif->tif_rawdatasize - tif->tif_rawcc;
530        for (shft = 4*8; (shft -= 8) >= 0; )
531                for (i = 0; i < npixels; i += rc) {
532                        if (occ < 4) {
533                                tif->tif_rawcp = op;
534                                tif->tif_rawcc = tif->tif_rawdatasize - occ;
535                                if (!TIFFFlushData1(tif))
536                                        return (-1);
537                                op = tif->tif_rawcp;
538                                occ = tif->tif_rawdatasize - tif->tif_rawcc;
539                        }
540                        mask = 0xff << shft;            /* find next run */
541                        for (beg = i; beg < npixels; beg += rc) {
542                                b = tp[beg] & mask;
543                                rc = 1;
544                                while (rc < 127+2 && beg+rc < npixels &&
545                                                (tp[beg+rc] & mask) == b)
546                                        rc++;
547                                if (rc >= MINRUN)
548                                        break;          /* long enough */
549                        }
550                        if (beg-i > 1 && beg-i < MINRUN) {
551                                b = tp[i] & mask;       /* check short run */
552                                j = i+1;
553                                while ((tp[j++] & mask) == b)
554                                        if (j == beg) {
555                                                *op++ = (tidataval_t)(128-2+j-i);
556                                                *op++ = (tidataval_t)(b >> shft);
557                                                occ -= 2;
558                                                i = beg;
559                                                break;
560                                        }
561                        }
562                        while (i < beg) {               /* write out non-run */
563                                if ((j = beg-i) > 127) j = 127;
564                                if (occ < j+3) {
565                                        tif->tif_rawcp = op;
566                                        tif->tif_rawcc = tif->tif_rawdatasize - occ;
567                                        if (!TIFFFlushData1(tif))
568                                                return (-1);
569                                        op = tif->tif_rawcp;
570                                        occ = tif->tif_rawdatasize - tif->tif_rawcc;
571                                }
572                                *op++ = j; occ--;
573                                while (j--) {
574                                        *op++ = (tidataval_t)(tp[i++] >> shft & 0xff);
575                                        occ--;
576                                }
577                        }
578                        if (rc >= MINRUN) {             /* write out run */
579                                *op++ = 128-2+rc;
580                                *op++ = (tidataval_t)(tp[beg] >> shft & 0xff);
581                                occ -= 2;
582                        } else
583                                rc = 0;
584                }
585        tif->tif_rawcp = op;
586        tif->tif_rawcc = tif->tif_rawdatasize - occ;
587
588        return (0);
589}
590
591/*
592 * Encode a strip of pixels.  We break it into rows to
593 * avoid encoding runs across row boundaries.
594 */
595static int
596LogLuvEncodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
597{
598        tsize_t rowlen = TIFFScanlineSize(tif);
599
600        assert(cc%rowlen == 0);
601        while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 0)
602                bp += rowlen, cc -= rowlen;
603        return (cc == 0);
604}
605
606/*
607 * Encode a tile of pixels.  We break it into rows to
608 * avoid encoding runs across row boundaries.
609 */
610static int
611LogLuvEncodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
612{
613        tsize_t rowlen = TIFFTileRowSize(tif);
614
615        assert(cc%rowlen == 0);
616        while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 0)
617                bp += rowlen, cc -= rowlen;
618        return (cc == 0);
619}
620
621/*
622 * Encode/Decode functions for converting to and from user formats.
623 */
624
625#include "uvcode.h"
626
627#ifndef UVSCALE
628#define U_NEU           0.210526316
629#define V_NEU           0.473684211
630#define UVSCALE         410.
631#endif
632
633#ifndef M_LN2
634#define M_LN2           0.69314718055994530942
635#endif
636#ifndef M_PI
637#define M_PI            3.14159265358979323846
638#endif
639#define log2(x)         ((1./M_LN2)*log(x))
640#define exp2(x)         exp(M_LN2*(x))
641
642#define itrunc(x,m)     ((m)==SGILOGENCODE_NODITHER ? \
643                                (int)(x) : \
644                                (int)((x) + rand()*(1./RAND_MAX) - .5))
645
646#if !LOGLUV_PUBLIC
647static
648#endif
649double
650LogL16toY(int p16)              /* compute luminance from 16-bit LogL */
651{
652        int     Le = p16 & 0x7fff;
653        double  Y;
654
655        if (!Le)
656                return (0.);
657        Y = exp(M_LN2/256.*(Le+.5) - M_LN2*64.);
658        return (!(p16 & 0x8000) ? Y : -Y);
659}
660
661#if !LOGLUV_PUBLIC
662static
663#endif
664int
665LogL16fromY(double Y, int em)   /* get 16-bit LogL from Y */
666{
667        if (Y >= 1.8371976e19)
668                return (0x7fff);
669        if (Y <= -1.8371976e19)
670                return (0xffff);
671        if (Y > 5.4136769e-20)
672                return itrunc(256.*(log2(Y) + 64.), em);
673        if (Y < -5.4136769e-20)
674                return (~0x7fff | itrunc(256.*(log2(-Y) + 64.), em));
675        return (0);
676}
677
678static void
679L16toY(LogLuvState* sp, tidata_t op, int n)
680{
681        int16* l16 = (int16*) sp->tbuf;
682        float* yp = (float*) op;
683
684        while (n-- > 0)
685                *yp++ = (float)LogL16toY(*l16++);
686}
687
688static void
689L16toGry(LogLuvState* sp, tidata_t op, int n)
690{
691        int16* l16 = (int16*) sp->tbuf;
692        uint8* gp = (uint8*) op;
693
694        while (n-- > 0) {
695                double Y = LogL16toY(*l16++);
696                *gp++ = (Y <= 0.) ? 0 : (Y >= 1.) ? 255 : (int)(256.*sqrt(Y));
697        }
698}
699
700static void
701L16fromY(LogLuvState* sp, tidata_t op, int n)
702{
703        int16* l16 = (int16*) sp->tbuf;
704        float* yp = (float*) op;
705
706        while (n-- > 0)
707                *l16++ = LogL16fromY(*yp++, sp->encode_meth);
708}
709
710#if !LOGLUV_PUBLIC
711static
712#endif
713void
714XYZtoRGB24(float xyz[3], uint8 rgb[3])
715{
716        double  r, g, b;
717                                        /* assume CCIR-709 primaries */
718        r =  2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2];
719        g = -1.022*xyz[0] +  1.978*xyz[1] +  0.044*xyz[2];
720        b =  0.061*xyz[0] + -0.224*xyz[1] +  1.163*xyz[2];
721                                        /* assume 2.0 gamma for speed */
722        /* could use integer sqrt approx., but this is probably faster */
723        rgb[0] = (r <= 0.) ? 0 : (r >= 1.) ? 255 : (int)(256.*sqrt(r));
724        rgb[1] = (g <= 0.) ? 0 : (g >= 1.) ? 255 : (int)(256.*sqrt(g));
725        rgb[2] = (b <= 0.) ? 0 : (b >= 1.) ? 255 : (int)(256.*sqrt(b));
726}
727
728#if !LOGLUV_PUBLIC
729static
730#endif
731double
732LogL10toY(int p10)              /* compute luminance from 10-bit LogL */
733{
734        if (p10 == 0)
735                return (0.);
736        return (exp(M_LN2/64.*(p10+.5) - M_LN2*12.));
737}
738
739#if !LOGLUV_PUBLIC
740static
741#endif
742int
743LogL10fromY(double Y, int em)   /* get 10-bit LogL from Y */
744{
745        if (Y >= 15.742)
746                return (0x3ff);
747        else if (Y <= .00024283)
748                return (0);
749        else
750                return itrunc(64.*(log2(Y) + 12.), em);
751}
752
753#define NANGLES         100
754#define uv2ang(u, v)    ( (NANGLES*.499999999/M_PI) \
755                                * atan2((v)-V_NEU,(u)-U_NEU) + .5*NANGLES )
756
757static int
758oog_encode(double u, double v)          /* encode out-of-gamut chroma */
759{
760        static int      oog_table[NANGLES];
761        static int      initialized = 0;
762        register int    i;
763       
764        if (!initialized) {             /* set up perimeter table */
765                double  eps[NANGLES], ua, va, ang, epsa;
766                int     ui, vi, ustep;
767                for (i = NANGLES; i--; )
768                        eps[i] = 2.;
769                for (vi = UV_NVS; vi--; ) {
770                        va = UV_VSTART + (vi+.5)*UV_SQSIZ;
771                        ustep = uv_row[vi].nus-1;
772                        if (vi == UV_NVS-1 || vi == 0 || ustep <= 0)
773                                ustep = 1;
774                        for (ui = uv_row[vi].nus-1; ui >= 0; ui -= ustep) {
775                                ua = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
776                                ang = uv2ang(ua, va);
777                                i = (int) ang;
778                                epsa = fabs(ang - (i+.5));
779                                if (epsa < eps[i]) {
780                                        oog_table[i] = uv_row[vi].ncum + ui;
781                                        eps[i] = epsa;
782                                }
783                        }
784                }
785                for (i = NANGLES; i--; )        /* fill any holes */
786                        if (eps[i] > 1.5) {
787                                int     i1, i2;
788                                for (i1 = 1; i1 < NANGLES/2; i1++)
789                                        if (eps[(i+i1)%NANGLES] < 1.5)
790                                                break;
791                                for (i2 = 1; i2 < NANGLES/2; i2++)
792                                        if (eps[(i+NANGLES-i2)%NANGLES] < 1.5)
793                                                break;
794                                if (i1 < i2)
795                                        oog_table[i] =
796                                                oog_table[(i+i1)%NANGLES];
797                                else
798                                        oog_table[i] =
799                                                oog_table[(i+NANGLES-i2)%NANGLES];
800                        }
801                initialized = 1;
802        }
803        i = (int) uv2ang(u, v);         /* look up hue angle */
804        return (oog_table[i]);
805}
806
807#undef uv2ang
808#undef NANGLES
809
810#if !LOGLUV_PUBLIC
811static
812#endif
813int
814uv_encode(double u, double v, int em)   /* encode (u',v') coordinates */
815{
816        register int    vi, ui;
817
818        if (v < UV_VSTART)
819                return oog_encode(u, v);
820        vi = itrunc((v - UV_VSTART)*(1./UV_SQSIZ), em);
821        if (vi >= UV_NVS)
822                return oog_encode(u, v);
823        if (u < uv_row[vi].ustart)
824                return oog_encode(u, v);
825        ui = itrunc((u - uv_row[vi].ustart)*(1./UV_SQSIZ), em);
826        if (ui >= uv_row[vi].nus)
827                return oog_encode(u, v);
828
829        return (uv_row[vi].ncum + ui);
830}
831
832#if !LOGLUV_PUBLIC
833static
834#endif
835int
836uv_decode(double *up, double *vp, int c)        /* decode (u',v') index */
837{
838        int     upper, lower;
839        register int    ui, vi;
840
841        if (c < 0 || c >= UV_NDIVS)
842                return (-1);
843        lower = 0;                              /* binary search */
844        upper = UV_NVS;
845        while (upper - lower > 1) {
846                vi = (lower + upper) >> 1;
847                ui = c - uv_row[vi].ncum;
848                if (ui > 0)
849                        lower = vi;
850                else if (ui < 0)
851                        upper = vi;
852                else {
853                        lower = vi;
854                        break;
855                }
856        }
857        vi = lower;
858        ui = c - uv_row[vi].ncum;
859        *up = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
860        *vp = UV_VSTART + (vi+.5)*UV_SQSIZ;
861        return (0);
862}
863
864#if !LOGLUV_PUBLIC
865static
866#endif
867void
868LogLuv24toXYZ(uint32 p, float XYZ[3])
869{
870        int     Ce;
871        double  L, u, v, s, x, y;
872                                        /* decode luminance */
873        L = LogL10toY(p>>14 & 0x3ff);
874        if (L <= 0.) {
875                XYZ[0] = XYZ[1] = XYZ[2] = 0.;
876                return;
877        }
878                                        /* decode color */
879        Ce = p & 0x3fff;
880        if (uv_decode(&u, &v, Ce) < 0) {
881                u = U_NEU; v = V_NEU;
882        }
883        s = 1./(6.*u - 16.*v + 12.);
884        x = 9.*u * s;
885        y = 4.*v * s;
886                                        /* convert to XYZ */
887        XYZ[0] = (float)(x/y * L);
888        XYZ[1] = (float)L;
889        XYZ[2] = (float)((1.-x-y)/y * L);
890}
891
892#if !LOGLUV_PUBLIC
893static
894#endif
895uint32
896LogLuv24fromXYZ(float XYZ[3], int em)
897{
898        int     Le, Ce;
899        double  u, v, s;
900                                        /* encode luminance */
901        Le = LogL10fromY(XYZ[1], em);
902                                        /* encode color */
903        s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
904        if (!Le || s <= 0.) {
905                u = U_NEU;
906                v = V_NEU;
907        } else {
908                u = 4.*XYZ[0] / s;
909                v = 9.*XYZ[1] / s;
910        }
911        Ce = uv_encode(u, v, em);
912        if (Ce < 0)                     /* never happens */
913                Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
914                                        /* combine encodings */
915        return (Le << 14 | Ce);
916}
917
918static void
919Luv24toXYZ(LogLuvState* sp, tidata_t op, int n)
920{
921        uint32* luv = (uint32*) sp->tbuf;
922        float* xyz = (float*) op;
923
924        while (n-- > 0) {
925                LogLuv24toXYZ(*luv, xyz);
926                xyz += 3;
927                luv++;
928        }
929}
930
931static void
932Luv24toLuv48(LogLuvState* sp, tidata_t op, int n)
933{
934        uint32* luv = (uint32*) sp->tbuf;
935        int16* luv3 = (int16*) op;
936
937        while (n-- > 0) {
938                double u, v;
939
940                *luv3++ = (int16)((*luv >> 12 & 0xffd) + 13314);
941                if (uv_decode(&u, &v, *luv&0x3fff) < 0) {
942                        u = U_NEU;
943                        v = V_NEU;
944                }
945                *luv3++ = (int16)(u * (1L<<15));
946                *luv3++ = (int16)(v * (1L<<15));
947                luv++;
948        }
949}
950
951static void
952Luv24toRGB(LogLuvState* sp, tidata_t op, int n)
953{
954        uint32* luv = (uint32*) sp->tbuf;
955        uint8* rgb = (uint8*) op;
956
957        while (n-- > 0) {
958                float xyz[3];
959
960                LogLuv24toXYZ(*luv++, xyz);
961                XYZtoRGB24(xyz, rgb);
962                rgb += 3;
963        }
964}
965
966static void
967Luv24fromXYZ(LogLuvState* sp, tidata_t op, int n)
968{
969        uint32* luv = (uint32*) sp->tbuf;
970        float* xyz = (float*) op;
971
972        while (n-- > 0) {
973                *luv++ = LogLuv24fromXYZ(xyz, sp->encode_meth);
974                xyz += 3;
975        }
976}
977
978static void
979Luv24fromLuv48(LogLuvState* sp, tidata_t op, int n)
980{
981        uint32* luv = (uint32*) sp->tbuf;
982        int16* luv3 = (int16*) op;
983
984        while (n-- > 0) {
985                int Le, Ce;
986
987                if (luv3[0] <= 0)
988                        Le = 0;
989                else if (luv3[0] >= (1<<12)+3314)
990                        Le = (1<<10) - 1;
991                else if (sp->encode_meth == SGILOGENCODE_NODITHER)
992                        Le = (luv3[0]-3314) >> 2;
993                else
994                        Le = itrunc(.25*(luv3[0]-3314.), sp->encode_meth);
995
996                Ce = uv_encode((luv[1]+.5)/(1<<15), (luv[2]+.5)/(1<<15),
997                                        sp->encode_meth);
998                if (Ce < 0)     /* never happens */
999                        Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
1000                *luv++ = (uint32)Le << 14 | Ce;
1001                luv3 += 3;
1002        }
1003}
1004
1005#if !LOGLUV_PUBLIC
1006static
1007#endif
1008void
1009LogLuv32toXYZ(uint32 p, float XYZ[3])
1010{
1011        double  L, u, v, s, x, y;
1012                                        /* decode luminance */
1013        L = LogL16toY((int)p >> 16);
1014        if (L <= 0.) {
1015                XYZ[0] = XYZ[1] = XYZ[2] = 0.;
1016                return;
1017        }
1018                                        /* decode color */
1019        u = 1./UVSCALE * ((p>>8 & 0xff) + .5);
1020        v = 1./UVSCALE * ((p & 0xff) + .5);
1021        s = 1./(6.*u - 16.*v + 12.);
1022        x = 9.*u * s;
1023        y = 4.*v * s;
1024                                        /* convert to XYZ */
1025        XYZ[0] = (float)(x/y * L);
1026        XYZ[1] = (float)L;
1027        XYZ[2] = (float)((1.-x-y)/y * L);
1028}
1029
1030#if !LOGLUV_PUBLIC
1031static
1032#endif
1033uint32
1034LogLuv32fromXYZ(float XYZ[3], int em)
1035{
1036        unsigned int    Le, ue, ve;
1037        double  u, v, s;
1038                                        /* encode luminance */
1039        Le = (unsigned int)LogL16fromY(XYZ[1], em);
1040                                        /* encode color */
1041        s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
1042        if (!Le || s <= 0.) {
1043                u = U_NEU;
1044                v = V_NEU;
1045        } else {
1046                u = 4.*XYZ[0] / s;
1047                v = 9.*XYZ[1] / s;
1048        }
1049        if (u <= 0.) ue = 0;
1050        else ue = itrunc(UVSCALE*u, em);
1051        if (ue > 255) ue = 255;
1052        if (v <= 0.) ve = 0;
1053        else ve = itrunc(UVSCALE*v, em);
1054        if (ve > 255) ve = 255;
1055                                        /* combine encodings */
1056        return (Le << 16 | ue << 8 | ve);
1057}
1058
1059static void
1060Luv32toXYZ(LogLuvState* sp, tidata_t op, int n)
1061{
1062        uint32* luv = (uint32*) sp->tbuf;
1063        float* xyz = (float*) op;
1064
1065        while (n-- > 0) {
1066                LogLuv32toXYZ(*luv++, xyz);
1067                xyz += 3;
1068        }
1069}
1070
1071static void
1072Luv32toLuv48(LogLuvState* sp, tidata_t op, int n)
1073{
1074        uint32* luv = (uint32*) sp->tbuf;
1075        int16* luv3 = (int16*) op;
1076
1077        while (n-- > 0) {
1078                double u, v;
1079
1080                *luv3++ = (int16)(*luv >> 16);
1081                u = 1./UVSCALE * ((*luv>>8 & 0xff) + .5);
1082                v = 1./UVSCALE * ((*luv & 0xff) + .5);
1083                *luv3++ = (int16)(u * (1L<<15));
1084                *luv3++ = (int16)(v * (1L<<15));
1085                luv++;
1086        }
1087}
1088
1089static void
1090Luv32toRGB(LogLuvState* sp, tidata_t op, int n)
1091{
1092        uint32* luv = (uint32*) sp->tbuf;
1093        uint8* rgb = (uint8*) op;
1094
1095        while (n-- > 0) {
1096                float xyz[3];
1097
1098                LogLuv32toXYZ(*luv++, xyz);
1099                XYZtoRGB24(xyz, rgb);
1100                rgb += 3;
1101        }
1102}
1103
1104static void
1105Luv32fromXYZ(LogLuvState* sp, tidata_t op, int n)
1106{
1107        uint32* luv = (uint32*) sp->tbuf;
1108        float* xyz = (float*) op;
1109
1110        while (n-- > 0) {
1111                *luv++ = LogLuv32fromXYZ(xyz, sp->encode_meth);
1112                xyz += 3;
1113        }
1114}
1115
1116static void
1117Luv32fromLuv48(LogLuvState* sp, tidata_t op, int n)
1118{
1119        uint32* luv = (uint32*) sp->tbuf;
1120        int16* luv3 = (int16*) op;
1121
1122        if (sp->encode_meth == SGILOGENCODE_NODITHER) {
1123                while (n-- > 0) {
1124                        *luv++ = (uint32)luv3[0] << 16 |
1125                                (luv3[1]*(uint32)(UVSCALE+.5) >> 7 & 0xff00) |
1126                                (luv3[2]*(uint32)(UVSCALE+.5) >> 15 & 0xff);
1127                        luv3 += 3;
1128                }
1129                return;
1130        }
1131        while (n-- > 0) {
1132                *luv++ = (uint32)luv3[0] << 16 |
1133        (itrunc(luv3[1]*(UVSCALE/(1<<15)), sp->encode_meth) << 8 & 0xff00) |
1134                (itrunc(luv3[2]*(UVSCALE/(1<<15)), sp->encode_meth) & 0xff);
1135                luv3 += 3;
1136        }
1137}
1138
1139static void
1140_logLuvNop(LogLuvState* sp, tidata_t op, int n)
1141{
1142        (void) sp; (void) op; (void) n;
1143}
1144
1145static int
1146LogL16GuessDataFmt(TIFFDirectory *td)
1147{
1148#define PACK(s,b,f)     (((b)<<6)|((s)<<3)|(f))
1149        switch (PACK(td->td_samplesperpixel, td->td_bitspersample, td->td_sampleformat)) {
1150        case PACK(1, 32, SAMPLEFORMAT_IEEEFP):
1151                return (SGILOGDATAFMT_FLOAT);
1152        case PACK(1, 16, SAMPLEFORMAT_VOID):
1153        case PACK(1, 16, SAMPLEFORMAT_INT):
1154        case PACK(1, 16, SAMPLEFORMAT_UINT):
1155                return (SGILOGDATAFMT_16BIT);
1156        case PACK(1,  8, SAMPLEFORMAT_VOID):
1157        case PACK(1,  8, SAMPLEFORMAT_UINT):
1158                return (SGILOGDATAFMT_8BIT);
1159        }
1160#undef PACK
1161        return (SGILOGDATAFMT_UNKNOWN);
1162}
1163
1164static int
1165LogL16InitState(TIFF* tif)
1166{
1167        TIFFDirectory *td = &tif->tif_dir;
1168        LogLuvState* sp = DecoderState(tif);
1169        static const char module[] = "LogL16InitState";
1170
1171        assert(sp != NULL);
1172        assert(td->td_photometric == PHOTOMETRIC_LOGL);
1173
1174        /* for some reason, we can't do this in TIFFInitLogL16 */
1175        if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
1176                sp->user_datafmt = LogL16GuessDataFmt(td);
1177        switch (sp->user_datafmt) {
1178        case SGILOGDATAFMT_FLOAT:
1179                sp->pixel_size = sizeof (float);
1180                break;
1181        case SGILOGDATAFMT_16BIT:
1182                sp->pixel_size = sizeof (int16);
1183                break;
1184        case SGILOGDATAFMT_8BIT:
1185                sp->pixel_size = sizeof (uint8);
1186                break;
1187        default:
1188                TIFFError(tif->tif_name,
1189                    "No support for converting user data format to LogL");
1190                return (0);
1191        }
1192        sp->tbuflen = td->td_imagewidth * td->td_rowsperstrip;
1193        sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (int16));
1194        if (sp->tbuf == NULL) {
1195                TIFFError(module, "%s: No space for SGILog translation buffer",
1196                    tif->tif_name);
1197                return (0);
1198        }
1199        return (1);
1200}
1201
1202static int
1203LogLuvGuessDataFmt(TIFFDirectory *td)
1204{
1205        int guess;
1206
1207        /*
1208         * If the user didn't tell us their datafmt,
1209         * take our best guess from the bitspersample.
1210         */
1211#define PACK(a,b)       (((a)<<3)|(b))
1212        switch (PACK(td->td_bitspersample, td->td_sampleformat)) {
1213        case PACK(32, SAMPLEFORMAT_IEEEFP):
1214                guess = SGILOGDATAFMT_FLOAT;
1215                break;
1216        case PACK(32, SAMPLEFORMAT_VOID):
1217        case PACK(32, SAMPLEFORMAT_UINT):
1218        case PACK(32, SAMPLEFORMAT_INT):
1219                guess = SGILOGDATAFMT_RAW;
1220                break;
1221        case PACK(16, SAMPLEFORMAT_VOID):
1222        case PACK(16, SAMPLEFORMAT_INT):
1223        case PACK(16, SAMPLEFORMAT_UINT):
1224                guess = SGILOGDATAFMT_16BIT;
1225                break;
1226        case PACK( 8, SAMPLEFORMAT_VOID):
1227        case PACK( 8, SAMPLEFORMAT_UINT):
1228                guess = SGILOGDATAFMT_8BIT;
1229                break;
1230        default:
1231                guess = SGILOGDATAFMT_UNKNOWN;
1232                break;
1233#undef PACK
1234        }
1235        /*
1236         * Double-check samples per pixel.
1237         */
1238        switch (td->td_samplesperpixel) {
1239        case 1:
1240                if (guess != SGILOGDATAFMT_RAW)
1241                        guess = SGILOGDATAFMT_UNKNOWN;
1242                break;
1243        case 3:
1244                if (guess == SGILOGDATAFMT_RAW)
1245                        guess = SGILOGDATAFMT_UNKNOWN;
1246                break;
1247        default:
1248                guess = SGILOGDATAFMT_UNKNOWN;
1249                break;
1250        }
1251        return (guess);
1252}
1253
1254static int
1255LogLuvInitState(TIFF* tif)
1256{
1257        TIFFDirectory* td = &tif->tif_dir;
1258        LogLuvState* sp = DecoderState(tif);
1259        static const char module[] = "LogLuvInitState";
1260
1261        assert(sp != NULL);
1262        assert(td->td_photometric == PHOTOMETRIC_LOGLUV);
1263
1264        /* for some reason, we can't do this in TIFFInitLogLuv */
1265        if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
1266                TIFFError(module,
1267                    "SGILog compression cannot handle non-contiguous data");
1268                return (0);
1269        }
1270        if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
1271                sp->user_datafmt = LogLuvGuessDataFmt(td);
1272        switch (sp->user_datafmt) {
1273        case SGILOGDATAFMT_FLOAT:
1274                sp->pixel_size = 3*sizeof (float);
1275                break;
1276        case SGILOGDATAFMT_16BIT:
1277                sp->pixel_size = 3*sizeof (int16);
1278                break;
1279        case SGILOGDATAFMT_RAW:
1280                sp->pixel_size = sizeof (uint32);
1281                break;
1282        case SGILOGDATAFMT_8BIT:
1283                sp->pixel_size = 3*sizeof (uint8);
1284                break;
1285        default:
1286                TIFFError(tif->tif_name,
1287                    "No support for converting user data format to LogLuv");
1288                return (0);
1289        }
1290        sp->tbuflen = td->td_imagewidth * td->td_rowsperstrip;
1291        sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (uint32));
1292        if (sp->tbuf == NULL) {
1293                TIFFError(module, "%s: No space for SGILog translation buffer",
1294                    tif->tif_name);
1295                return (0);
1296        }
1297        return (1);
1298}
1299
1300static int
1301LogLuvSetupDecode(TIFF* tif)
1302{
1303        LogLuvState* sp = DecoderState(tif);
1304        TIFFDirectory* td = &tif->tif_dir;
1305
1306        tif->tif_postdecode = _TIFFNoPostDecode;
1307        switch (td->td_photometric) {
1308        case PHOTOMETRIC_LOGLUV:
1309                if (!LogLuvInitState(tif))
1310                        break;
1311                if (td->td_compression == COMPRESSION_SGILOG24) {
1312                        tif->tif_decoderow = LogLuvDecode24;
1313                        switch (sp->user_datafmt) {
1314                        case SGILOGDATAFMT_FLOAT:
1315                                sp->tfunc = Luv24toXYZ;
1316                                break;
1317                        case SGILOGDATAFMT_16BIT:
1318                                sp->tfunc = Luv24toLuv48;
1319                                break;
1320                        case SGILOGDATAFMT_8BIT:
1321                                sp->tfunc = Luv24toRGB;
1322                                break;
1323                        }
1324                } else {
1325                        tif->tif_decoderow = LogLuvDecode32;
1326                        switch (sp->user_datafmt) {
1327                        case SGILOGDATAFMT_FLOAT:
1328                                sp->tfunc = Luv32toXYZ;
1329                                break;
1330                        case SGILOGDATAFMT_16BIT:
1331                                sp->tfunc = Luv32toLuv48;
1332                                break;
1333                        case SGILOGDATAFMT_8BIT:
1334                                sp->tfunc = Luv32toRGB;
1335                                break;
1336                        }
1337                }
1338                return (1);
1339        case PHOTOMETRIC_LOGL:
1340                if (!LogL16InitState(tif))
1341                        break;
1342                tif->tif_decoderow = LogL16Decode;
1343                switch (sp->user_datafmt) {
1344                case SGILOGDATAFMT_FLOAT:
1345                        sp->tfunc = L16toY;
1346                        break;
1347                case SGILOGDATAFMT_8BIT:
1348                        sp->tfunc = L16toGry;
1349                        break;
1350                }
1351                return (1);
1352        default:
1353                TIFFError(tif->tif_name,
1354    "Inappropriate photometric interpretation %d for SGILog compression; %s",
1355                    td->td_photometric, "must be either LogLUV or LogL");
1356                break;
1357        }
1358        return (0);
1359}
1360
1361static int
1362LogLuvSetupEncode(TIFF* tif)
1363{
1364        LogLuvState* sp = EncoderState(tif);
1365        TIFFDirectory* td = &tif->tif_dir;
1366
1367        switch (td->td_photometric) {
1368        case PHOTOMETRIC_LOGLUV:
1369                if (!LogLuvInitState(tif))
1370                        break;
1371                if (td->td_compression == COMPRESSION_SGILOG24) {
1372                        tif->tif_encoderow = LogLuvEncode24;
1373                        switch (sp->user_datafmt) {
1374                        case SGILOGDATAFMT_FLOAT:
1375                                sp->tfunc = Luv24fromXYZ;
1376                                break;
1377                        case SGILOGDATAFMT_16BIT:
1378                                sp->tfunc = Luv24fromLuv48;
1379                                break;
1380                        case SGILOGDATAFMT_RAW:
1381                                break;
1382                        default:
1383                                goto notsupported;
1384                        }
1385                } else {
1386                        tif->tif_encoderow = LogLuvEncode32;
1387                        switch (sp->user_datafmt) {
1388                        case SGILOGDATAFMT_FLOAT:
1389                                sp->tfunc = Luv32fromXYZ;
1390                                break;
1391                        case SGILOGDATAFMT_16BIT:
1392                                sp->tfunc = Luv32fromLuv48;
1393                                break;
1394                        case SGILOGDATAFMT_RAW:
1395                                break;
1396                        default:
1397                                goto notsupported;
1398                        }
1399                }
1400                break;
1401        case PHOTOMETRIC_LOGL:
1402                if (!LogL16InitState(tif))
1403                        break;
1404                tif->tif_encoderow = LogL16Encode;
1405                switch (sp->user_datafmt) {
1406                case SGILOGDATAFMT_FLOAT:
1407                        sp->tfunc = L16fromY;
1408                        break;
1409                case SGILOGDATAFMT_16BIT:
1410                        break;
1411                default:
1412                        goto notsupported;
1413                }
1414                break;
1415        default:
1416                TIFFError(tif->tif_name,
1417    "Inappropriate photometric interpretation %d for SGILog compression; %s",
1418                    td->td_photometric, "must be either LogLUV or LogL");
1419                break;
1420        }
1421        return (1);
1422notsupported:
1423        TIFFError(tif->tif_name,
1424            "SGILog compression supported only for %s, or raw data",
1425            td->td_photometric == PHOTOMETRIC_LOGL ? "Y, L" : "XYZ, Luv");
1426        return (0);
1427}
1428
1429static void
1430LogLuvClose(TIFF* tif)
1431{
1432        TIFFDirectory *td = &tif->tif_dir;
1433
1434        /*
1435         * For consistency, we always want to write out the same
1436         * bitspersample and sampleformat for our TIFF file,
1437         * regardless of the data format being used by the application.
1438         * Since this routine is called after tags have been set but
1439         * before they have been recorded in the file, we reset them here.
1440         */
1441        td->td_samplesperpixel =
1442            (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3;
1443        td->td_bitspersample = 16;
1444        td->td_sampleformat = SAMPLEFORMAT_INT;
1445}
1446
1447static void
1448LogLuvCleanup(TIFF* tif)
1449{
1450        LogLuvState* sp = (LogLuvState *)tif->tif_data;
1451
1452        if (sp) {
1453                if (sp->tbuf)
1454                        _TIFFfree(sp->tbuf);
1455                _TIFFfree(sp);
1456                tif->tif_data = NULL;
1457        }
1458}
1459
1460static int
1461LogLuvVSetField(TIFF* tif, ttag_t tag, va_list ap)
1462{
1463        LogLuvState* sp = DecoderState(tif);
1464        int bps, fmt;
1465
1466        switch (tag) {
1467        case TIFFTAG_SGILOGDATAFMT:
1468                sp->user_datafmt = va_arg(ap, int);
1469                /*
1470                 * Tweak the TIFF header so that the rest of libtiff knows what
1471                 * size of data will be passed between app and library, and
1472                 * assume that the app knows what it is doing and is not
1473                 * confused by these header manipulations...
1474                 */
1475                switch (sp->user_datafmt) {
1476                case SGILOGDATAFMT_FLOAT:
1477                        bps = 32, fmt = SAMPLEFORMAT_IEEEFP;
1478                        break;
1479                case SGILOGDATAFMT_16BIT:
1480                        bps = 16, fmt = SAMPLEFORMAT_INT;
1481                        break;
1482                case SGILOGDATAFMT_RAW:
1483                        bps = 32, fmt = SAMPLEFORMAT_UINT;
1484                        TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
1485                        break;
1486                case SGILOGDATAFMT_8BIT:
1487                        bps = 8, fmt = SAMPLEFORMAT_UINT;
1488                        break;
1489                default:
1490                        TIFFError(tif->tif_name,
1491                            "Unknown data format %d for LogLuv compression",
1492                            sp->user_datafmt);
1493                        return (0);
1494                }
1495                TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
1496                TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt);
1497                /*
1498                 * Must recalculate sizes should bits/sample change.
1499                 */
1500                tif->tif_tilesize = TIFFTileSize(tif);
1501                tif->tif_scanlinesize = TIFFScanlineSize(tif);
1502                return (1);
1503        case TIFFTAG_SGILOGENCODE:
1504                sp->encode_meth = va_arg(ap, int);
1505                if (sp->encode_meth != SGILOGENCODE_NODITHER &&
1506                                sp->encode_meth != SGILOGENCODE_RANDITHER) {
1507                        TIFFError(tif->tif_name,
1508                                "Unknown encoding %d for LogLuv compression",
1509                                sp->encode_meth);
1510                        return (0);
1511                }
1512                return (1);
1513        default:
1514                return (*sp->vsetparent)(tif, tag, ap);
1515        }
1516}
1517
1518static int
1519LogLuvVGetField(TIFF* tif, ttag_t tag, va_list ap)
1520{
1521        LogLuvState *sp = (LogLuvState *)tif->tif_data;
1522
1523        switch (tag) {
1524        case TIFFTAG_SGILOGDATAFMT:
1525                *va_arg(ap, int*) = sp->user_datafmt;
1526                return (1);
1527        default:
1528                return (*sp->vgetparent)(tif, tag, ap);
1529        }
1530}
1531
1532static const TIFFFieldInfo LogLuvFieldInfo[] = {
1533    { TIFFTAG_SGILOGDATAFMT,      0, 0, TIFF_SHORT,     FIELD_PSEUDO,
1534      TRUE,     FALSE,  "SGILogDataFmt"},
1535    { TIFFTAG_SGILOGENCODE,       0, 0, TIFF_SHORT,     FIELD_PSEUDO,
1536      TRUE,     FALSE,  "SGILogEncode"}
1537};
1538
1539int
1540TIFFInitSGILog(TIFF* tif, int scheme)
1541{
1542        static const char module[] = "TIFFInitSGILog";
1543        LogLuvState* sp;
1544
1545        assert(scheme == COMPRESSION_SGILOG24 || scheme == COMPRESSION_SGILOG);
1546
1547        /*
1548         * Allocate state block so tag methods have storage to record values.
1549         */
1550        tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (LogLuvState));
1551        if (tif->tif_data == NULL)
1552                goto bad;
1553        sp = (LogLuvState*) tif->tif_data;
1554        _TIFFmemset((tdata_t)sp, 0, sizeof (*sp));
1555        sp->user_datafmt = SGILOGDATAFMT_UNKNOWN;
1556        sp->encode_meth = (scheme == COMPRESSION_SGILOG24) ?
1557                                SGILOGENCODE_RANDITHER : SGILOGENCODE_NODITHER;
1558        sp->tfunc = _logLuvNop;
1559
1560        /*
1561         * Install codec methods.
1562         * NB: tif_decoderow & tif_encoderow are filled
1563         *     in at setup time.
1564         */
1565        tif->tif_setupdecode = LogLuvSetupDecode;
1566        tif->tif_decodestrip = LogLuvDecodeStrip;
1567        tif->tif_decodetile = LogLuvDecodeTile;
1568        tif->tif_setupencode = LogLuvSetupEncode;
1569        tif->tif_encodestrip = LogLuvEncodeStrip;
1570        tif->tif_encodetile = LogLuvEncodeTile;
1571        tif->tif_close = LogLuvClose;
1572        tif->tif_cleanup = LogLuvCleanup;
1573
1574        /* override SetField so we can handle our private pseudo-tag */
1575        _TIFFMergeFieldInfo(tif, LogLuvFieldInfo, N(LogLuvFieldInfo));
1576        sp->vgetparent = tif->tif_vgetfield;
1577        tif->tif_vgetfield = LogLuvVGetField;   /* hook for codec tags */
1578        sp->vsetparent = tif->tif_vsetfield;
1579        tif->tif_vsetfield = LogLuvVSetField;   /* hook for codec tags */
1580
1581        return (1);
1582bad:
1583        TIFFError(module, "%s: No space for LogLuv state block", tif->tif_name);
1584        return (0);
1585}
1586#endif /* LOGLUV_SUPPORT */
Note: See TracBrowser for help on using the repository browser.