PageRenderTime 97ms CodeModel.GetById 11ms app.highlight 75ms RepoModel.GetById 2ms app.codeStats 0ms

/src/FreeImage/Source/LibTIFF/tif_pixarlog.c

https://bitbucket.org/cabalistic/ogredeps/
C | 1371 lines | 1074 code | 124 blank | 173 comment | 222 complexity | 1f38fddd16ac4780af495479bb4e9ea6 MD5 | raw file
   1/* $Id: tif_pixarlog.c,v 1.37 2011/04/10 17:14:09 drolon Exp $ */
   2
   3/*
   4 * Copyright (c) 1996-1997 Sam Leffler
   5 * Copyright (c) 1996 Pixar
   6 *
   7 * Permission to use, copy, modify, distribute, and sell this software and 
   8 * its documentation for any purpose is hereby granted without fee, provided
   9 * that (i) the above copyright notices and this permission notice appear in
  10 * all copies of the software and related documentation, and (ii) the names of
  11 * Pixar, Sam Leffler and Silicon Graphics may not be used in any advertising or
  12 * publicity relating to the software without the specific, prior written
  13 * permission of Pixar, Sam Leffler and Silicon Graphics.
  14 * 
  15 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18 * 
  19 * IN NO EVENT SHALL PIXAR, SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24 * OF THIS SOFTWARE.
  25 */
  26
  27#include "tiffiop.h"
  28#ifdef PIXARLOG_SUPPORT
  29
  30/*
  31 * TIFF Library.
  32 * PixarLog Compression Support
  33 *
  34 * Contributed by Dan McCoy.
  35 *
  36 * PixarLog film support uses the TIFF library to store companded
  37 * 11 bit values into a tiff file, which are compressed using the 
  38 * zip compressor.  
  39 *
  40 * The codec can take as input and produce as output 32-bit IEEE float values 
  41 * as well as 16-bit or 8-bit unsigned integer values.
  42 *
  43 * On writing any of the above are converted into the internal
  44 * 11-bit log format.   In the case of  8 and 16 bit values, the
  45 * input is assumed to be unsigned linear color values that represent
  46 * the range 0-1.  In the case of IEEE values, the 0-1 range is assumed to
  47 * be the normal linear color range, in addition over 1 values are
  48 * accepted up to a value of about 25.0 to encode "hot" hightlights and such.
  49 * The encoding is lossless for 8-bit values, slightly lossy for the
  50 * other bit depths.  The actual color precision should be better
  51 * than the human eye can perceive with extra room to allow for
  52 * error introduced by further image computation.  As with any quantized
  53 * color format, it is possible to perform image calculations which
  54 * expose the quantization error. This format should certainly be less 
  55 * susceptable to such errors than standard 8-bit encodings, but more
  56 * susceptable than straight 16-bit or 32-bit encodings.
  57 *
  58 * On reading the internal format is converted to the desired output format.
  59 * The program can request which format it desires by setting the internal
  60 * pseudo tag TIFFTAG_PIXARLOGDATAFMT to one of these possible values:
  61 *  PIXARLOGDATAFMT_FLOAT     = provide IEEE float values.
  62 *  PIXARLOGDATAFMT_16BIT     = provide unsigned 16-bit integer values
  63 *  PIXARLOGDATAFMT_8BIT      = provide unsigned 8-bit integer values
  64 *
  65 * alternately PIXARLOGDATAFMT_8BITABGR provides unsigned 8-bit integer
  66 * values with the difference that if there are exactly three or four channels
  67 * (rgb or rgba) it swaps the channel order (bgr or abgr).
  68 *
  69 * PIXARLOGDATAFMT_11BITLOG provides the internal encoding directly
  70 * packed in 16-bit values.   However no tools are supplied for interpreting
  71 * these values.
  72 *
  73 * "hot" (over 1.0) areas written in floating point get clamped to
  74 * 1.0 in the integer data types.
  75 *
  76 * When the file is closed after writing, the bit depth and sample format
  77 * are set always to appear as if 8-bit data has been written into it.
  78 * That way a naive program unaware of the particulars of the encoding
  79 * gets the format it is most likely able to handle.
  80 *
  81 * The codec does it's own horizontal differencing step on the coded
  82 * values so the libraries predictor stuff should be turned off.
  83 * The codec also handle byte swapping the encoded values as necessary
  84 * since the library does not have the information necessary
  85 * to know the bit depth of the raw unencoded buffer.
  86 * 
  87 */
  88
  89#include "tif_predict.h"
  90#include "../ZLib/zlib.h"
  91
  92#include <stdio.h>
  93#include <stdlib.h>
  94#include <math.h>
  95
  96/* Tables for converting to/from 11 bit coded values */
  97
  98#define  TSIZE	 2048		/* decode table size (11-bit tokens) */
  99#define  TSIZEP1 2049		/* Plus one for slop */
 100#define  ONE	 1250		/* token value of 1.0 exactly */
 101#define  RATIO	 1.004		/* nominal ratio for log part */
 102
 103#define CODE_MASK 0x7ff         /* 11 bits. */
 104
 105static float  Fltsize;
 106static float  LogK1, LogK2;
 107
 108#define REPEAT(n, op)   { int i; i=n; do { i--; op; } while (i>0); }
 109
 110static void
 111horizontalAccumulateF(uint16 *wp, int n, int stride, float *op, 
 112	float *ToLinearF)
 113{
 114    register unsigned int  cr, cg, cb, ca, mask;
 115    register float  t0, t1, t2, t3;
 116
 117    if (n >= stride) {
 118	mask = CODE_MASK;
 119	if (stride == 3) {
 120	    t0 = ToLinearF[cr = wp[0]];
 121	    t1 = ToLinearF[cg = wp[1]];
 122	    t2 = ToLinearF[cb = wp[2]];
 123	    op[0] = t0;
 124	    op[1] = t1;
 125	    op[2] = t2;
 126	    n -= 3;
 127	    while (n > 0) {
 128		wp += 3;
 129		op += 3;
 130		n -= 3;
 131		t0 = ToLinearF[(cr += wp[0]) & mask];
 132		t1 = ToLinearF[(cg += wp[1]) & mask];
 133		t2 = ToLinearF[(cb += wp[2]) & mask];
 134		op[0] = t0;
 135		op[1] = t1;
 136		op[2] = t2;
 137	    }
 138	} else if (stride == 4) {
 139	    t0 = ToLinearF[cr = wp[0]];
 140	    t1 = ToLinearF[cg = wp[1]];
 141	    t2 = ToLinearF[cb = wp[2]];
 142	    t3 = ToLinearF[ca = wp[3]];
 143	    op[0] = t0;
 144	    op[1] = t1;
 145	    op[2] = t2;
 146	    op[3] = t3;
 147	    n -= 4;
 148	    while (n > 0) {
 149		wp += 4;
 150		op += 4;
 151		n -= 4;
 152		t0 = ToLinearF[(cr += wp[0]) & mask];
 153		t1 = ToLinearF[(cg += wp[1]) & mask];
 154		t2 = ToLinearF[(cb += wp[2]) & mask];
 155		t3 = ToLinearF[(ca += wp[3]) & mask];
 156		op[0] = t0;
 157		op[1] = t1;
 158		op[2] = t2;
 159		op[3] = t3;
 160	    }
 161	} else {
 162	    REPEAT(stride, *op = ToLinearF[*wp&mask]; wp++; op++)
 163	    n -= stride;
 164	    while (n > 0) {
 165		REPEAT(stride,
 166		    wp[stride] += *wp; *op = ToLinearF[*wp&mask]; wp++; op++)
 167		n -= stride;
 168	    }
 169	}
 170    }
 171}
 172
 173static void
 174horizontalAccumulate12(uint16 *wp, int n, int stride, int16 *op,
 175	float *ToLinearF)
 176{
 177    register unsigned int  cr, cg, cb, ca, mask;
 178    register float  t0, t1, t2, t3;
 179
 180#define SCALE12 2048.0F
 181#define CLAMP12(t) (((t) < 3071) ? (uint16) (t) : 3071)
 182
 183    if (n >= stride) {
 184	mask = CODE_MASK;
 185	if (stride == 3) {
 186	    t0 = ToLinearF[cr = wp[0]] * SCALE12;
 187	    t1 = ToLinearF[cg = wp[1]] * SCALE12;
 188	    t2 = ToLinearF[cb = wp[2]] * SCALE12;
 189	    op[0] = CLAMP12(t0);
 190	    op[1] = CLAMP12(t1);
 191	    op[2] = CLAMP12(t2);
 192	    n -= 3;
 193	    while (n > 0) {
 194		wp += 3;
 195		op += 3;
 196		n -= 3;
 197		t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
 198		t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
 199		t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
 200		op[0] = CLAMP12(t0);
 201		op[1] = CLAMP12(t1);
 202		op[2] = CLAMP12(t2);
 203	    }
 204	} else if (stride == 4) {
 205	    t0 = ToLinearF[cr = wp[0]] * SCALE12;
 206	    t1 = ToLinearF[cg = wp[1]] * SCALE12;
 207	    t2 = ToLinearF[cb = wp[2]] * SCALE12;
 208	    t3 = ToLinearF[ca = wp[3]] * SCALE12;
 209	    op[0] = CLAMP12(t0);
 210	    op[1] = CLAMP12(t1);
 211	    op[2] = CLAMP12(t2);
 212	    op[3] = CLAMP12(t3);
 213	    n -= 4;
 214	    while (n > 0) {
 215		wp += 4;
 216		op += 4;
 217		n -= 4;
 218		t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
 219		t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
 220		t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
 221		t3 = ToLinearF[(ca += wp[3]) & mask] * SCALE12;
 222		op[0] = CLAMP12(t0);
 223		op[1] = CLAMP12(t1);
 224		op[2] = CLAMP12(t2);
 225		op[3] = CLAMP12(t3);
 226	    }
 227	} else {
 228	    REPEAT(stride, t0 = ToLinearF[*wp&mask] * SCALE12;
 229                           *op = CLAMP12(t0); wp++; op++)
 230	    n -= stride;
 231	    while (n > 0) {
 232		REPEAT(stride,
 233		    wp[stride] += *wp; t0 = ToLinearF[wp[stride]&mask]*SCALE12;
 234		    *op = CLAMP12(t0);  wp++; op++)
 235		n -= stride;
 236	    }
 237	}
 238    }
 239}
 240
 241static void
 242horizontalAccumulate16(uint16 *wp, int n, int stride, uint16 *op,
 243	uint16 *ToLinear16)
 244{
 245    register unsigned int  cr, cg, cb, ca, mask;
 246
 247    if (n >= stride) {
 248	mask = CODE_MASK;
 249	if (stride == 3) {
 250	    op[0] = ToLinear16[cr = wp[0]];
 251	    op[1] = ToLinear16[cg = wp[1]];
 252	    op[2] = ToLinear16[cb = wp[2]];
 253	    n -= 3;
 254	    while (n > 0) {
 255		wp += 3;
 256		op += 3;
 257		n -= 3;
 258		op[0] = ToLinear16[(cr += wp[0]) & mask];
 259		op[1] = ToLinear16[(cg += wp[1]) & mask];
 260		op[2] = ToLinear16[(cb += wp[2]) & mask];
 261	    }
 262	} else if (stride == 4) {
 263	    op[0] = ToLinear16[cr = wp[0]];
 264	    op[1] = ToLinear16[cg = wp[1]];
 265	    op[2] = ToLinear16[cb = wp[2]];
 266	    op[3] = ToLinear16[ca = wp[3]];
 267	    n -= 4;
 268	    while (n > 0) {
 269		wp += 4;
 270		op += 4;
 271		n -= 4;
 272		op[0] = ToLinear16[(cr += wp[0]) & mask];
 273		op[1] = ToLinear16[(cg += wp[1]) & mask];
 274		op[2] = ToLinear16[(cb += wp[2]) & mask];
 275		op[3] = ToLinear16[(ca += wp[3]) & mask];
 276	    }
 277	} else {
 278	    REPEAT(stride, *op = ToLinear16[*wp&mask]; wp++; op++)
 279	    n -= stride;
 280	    while (n > 0) {
 281		REPEAT(stride,
 282		    wp[stride] += *wp; *op = ToLinear16[*wp&mask]; wp++; op++)
 283		n -= stride;
 284	    }
 285	}
 286    }
 287}
 288
 289/* 
 290 * Returns the log encoded 11-bit values with the horizontal
 291 * differencing undone.
 292 */
 293static void
 294horizontalAccumulate11(uint16 *wp, int n, int stride, uint16 *op)
 295{
 296    register unsigned int  cr, cg, cb, ca, mask;
 297
 298    if (n >= stride) {
 299	mask = CODE_MASK;
 300	if (stride == 3) {
 301	    op[0] = cr = wp[0];  op[1] = cg = wp[1];  op[2] = cb = wp[2];
 302	    n -= 3;
 303	    while (n > 0) {
 304		wp += 3;
 305		op += 3;
 306		n -= 3;
 307		op[0] = (cr += wp[0]) & mask;
 308		op[1] = (cg += wp[1]) & mask;
 309		op[2] = (cb += wp[2]) & mask;
 310	    }
 311	} else if (stride == 4) {
 312	    op[0] = cr = wp[0];  op[1] = cg = wp[1];
 313	    op[2] = cb = wp[2];  op[3] = ca = wp[3];
 314	    n -= 4;
 315	    while (n > 0) {
 316		wp += 4;
 317		op += 4;
 318		n -= 4;
 319		op[0] = (cr += wp[0]) & mask;
 320		op[1] = (cg += wp[1]) & mask;
 321		op[2] = (cb += wp[2]) & mask;
 322		op[3] = (ca += wp[3]) & mask;
 323	    } 
 324	} else {
 325	    REPEAT(stride, *op = *wp&mask; wp++; op++)
 326	    n -= stride;
 327	    while (n > 0) {
 328		REPEAT(stride,
 329		    wp[stride] += *wp; *op = *wp&mask; wp++; op++)
 330		n -= stride;
 331	    }
 332	}
 333    }
 334}
 335
 336static void
 337horizontalAccumulate8(uint16 *wp, int n, int stride, unsigned char *op,
 338	unsigned char *ToLinear8)
 339{
 340    register unsigned int  cr, cg, cb, ca, mask;
 341
 342    if (n >= stride) {
 343	mask = CODE_MASK;
 344	if (stride == 3) {
 345	    op[0] = ToLinear8[cr = wp[0]];
 346	    op[1] = ToLinear8[cg = wp[1]];
 347	    op[2] = ToLinear8[cb = wp[2]];
 348	    n -= 3;
 349	    while (n > 0) {
 350		n -= 3;
 351		wp += 3;
 352		op += 3;
 353		op[0] = ToLinear8[(cr += wp[0]) & mask];
 354		op[1] = ToLinear8[(cg += wp[1]) & mask];
 355		op[2] = ToLinear8[(cb += wp[2]) & mask];
 356	    }
 357	} else if (stride == 4) {
 358	    op[0] = ToLinear8[cr = wp[0]];
 359	    op[1] = ToLinear8[cg = wp[1]];
 360	    op[2] = ToLinear8[cb = wp[2]];
 361	    op[3] = ToLinear8[ca = wp[3]];
 362	    n -= 4;
 363	    while (n > 0) {
 364		n -= 4;
 365		wp += 4;
 366		op += 4;
 367		op[0] = ToLinear8[(cr += wp[0]) & mask];
 368		op[1] = ToLinear8[(cg += wp[1]) & mask];
 369		op[2] = ToLinear8[(cb += wp[2]) & mask];
 370		op[3] = ToLinear8[(ca += wp[3]) & mask];
 371	    }
 372	} else {
 373	    REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++)
 374	    n -= stride;
 375	    while (n > 0) {
 376		REPEAT(stride,
 377		    wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++)
 378		n -= stride;
 379	    }
 380	}
 381    }
 382}
 383
 384
 385static void
 386horizontalAccumulate8abgr(uint16 *wp, int n, int stride, unsigned char *op,
 387	unsigned char *ToLinear8)
 388{
 389    register unsigned int  cr, cg, cb, ca, mask;
 390    register unsigned char  t0, t1, t2, t3;
 391
 392    if (n >= stride) {
 393	mask = CODE_MASK;
 394	if (stride == 3) {
 395	    op[0] = 0;
 396	    t1 = ToLinear8[cb = wp[2]];
 397	    t2 = ToLinear8[cg = wp[1]];
 398	    t3 = ToLinear8[cr = wp[0]];
 399	    op[1] = t1;
 400	    op[2] = t2;
 401	    op[3] = t3;
 402	    n -= 3;
 403	    while (n > 0) {
 404		n -= 3;
 405		wp += 3;
 406		op += 4;
 407		op[0] = 0;
 408		t1 = ToLinear8[(cb += wp[2]) & mask];
 409		t2 = ToLinear8[(cg += wp[1]) & mask];
 410		t3 = ToLinear8[(cr += wp[0]) & mask];
 411		op[1] = t1;
 412		op[2] = t2;
 413		op[3] = t3;
 414	    }
 415	} else if (stride == 4) {
 416	    t0 = ToLinear8[ca = wp[3]];
 417	    t1 = ToLinear8[cb = wp[2]];
 418	    t2 = ToLinear8[cg = wp[1]];
 419	    t3 = ToLinear8[cr = wp[0]];
 420	    op[0] = t0;
 421	    op[1] = t1;
 422	    op[2] = t2;
 423	    op[3] = t3;
 424	    n -= 4;
 425	    while (n > 0) {
 426		n -= 4;
 427		wp += 4;
 428		op += 4;
 429		t0 = ToLinear8[(ca += wp[3]) & mask];
 430		t1 = ToLinear8[(cb += wp[2]) & mask];
 431		t2 = ToLinear8[(cg += wp[1]) & mask];
 432		t3 = ToLinear8[(cr += wp[0]) & mask];
 433		op[0] = t0;
 434		op[1] = t1;
 435		op[2] = t2;
 436		op[3] = t3;
 437	    }
 438	} else {
 439	    REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++)
 440	    n -= stride;
 441	    while (n > 0) {
 442		REPEAT(stride,
 443		    wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++)
 444		n -= stride;
 445	    }
 446	}
 447    }
 448}
 449
 450/*
 451 * State block for each open TIFF
 452 * file using PixarLog compression/decompression.
 453 */
 454typedef	struct {
 455	TIFFPredictorState	predict;
 456	z_stream		stream;
 457	uint16			*tbuf; 
 458	uint16			stride;
 459	int			state;
 460	int			user_datafmt;
 461	int			quality;
 462#define PLSTATE_INIT 1
 463
 464	TIFFVSetMethod		vgetparent;	/* super-class method */
 465	TIFFVSetMethod		vsetparent;	/* super-class method */
 466
 467	float *ToLinearF;
 468	uint16 *ToLinear16;
 469	unsigned char *ToLinear8;
 470	uint16  *FromLT2;
 471	uint16  *From14; /* Really for 16-bit data, but we shift down 2 */
 472	uint16  *From8;
 473	
 474} PixarLogState;
 475
 476static int
 477PixarLogMakeTables(PixarLogState *sp)
 478{
 479
 480/*
 481 *    We make several tables here to convert between various external
 482 *    representations (float, 16-bit, and 8-bit) and the internal
 483 *    11-bit companded representation.  The 11-bit representation has two
 484 *    distinct regions.  A linear bottom end up through .018316 in steps
 485 *    of about .000073, and a region of constant ratio up to about 25.
 486 *    These floating point numbers are stored in the main table ToLinearF. 
 487 *    All other tables are derived from this one.  The tables (and the
 488 *    ratios) are continuous at the internal seam.
 489 */
 490
 491    int  nlin, lt2size;
 492    int  i, j;
 493    double  b, c, linstep, v;
 494    float *ToLinearF;
 495    uint16 *ToLinear16;
 496    unsigned char *ToLinear8;
 497    uint16  *FromLT2;
 498    uint16  *From14; /* Really for 16-bit data, but we shift down 2 */
 499    uint16  *From8;
 500
 501    c = log(RATIO);	
 502    nlin = (int)(1./c);	/* nlin must be an integer */
 503    c = 1./nlin;
 504    b = exp(-c*ONE);	/* multiplicative scale factor [b*exp(c*ONE) = 1] */
 505    linstep = b*c*exp(1.);
 506
 507    LogK1 = (float)(1./c);	/* if (v >= 2)  token = k1*log(v*k2) */
 508    LogK2 = (float)(1./b);
 509    lt2size = (int)(2./linstep) + 1;
 510    FromLT2 = (uint16 *)_TIFFmalloc(lt2size*sizeof(uint16));
 511    From14 = (uint16 *)_TIFFmalloc(16384*sizeof(uint16));
 512    From8 = (uint16 *)_TIFFmalloc(256*sizeof(uint16));
 513    ToLinearF = (float *)_TIFFmalloc(TSIZEP1 * sizeof(float));
 514    ToLinear16 = (uint16 *)_TIFFmalloc(TSIZEP1 * sizeof(uint16));
 515    ToLinear8 = (unsigned char *)_TIFFmalloc(TSIZEP1 * sizeof(unsigned char));
 516    if (FromLT2 == NULL || From14  == NULL || From8   == NULL ||
 517	 ToLinearF == NULL || ToLinear16 == NULL || ToLinear8 == NULL) {
 518	if (FromLT2) _TIFFfree(FromLT2);
 519	if (From14) _TIFFfree(From14);
 520	if (From8) _TIFFfree(From8);
 521	if (ToLinearF) _TIFFfree(ToLinearF);
 522	if (ToLinear16) _TIFFfree(ToLinear16);
 523	if (ToLinear8) _TIFFfree(ToLinear8);
 524	sp->FromLT2 = NULL;
 525	sp->From14 = NULL;
 526	sp->From8 = NULL;
 527	sp->ToLinearF = NULL;
 528	sp->ToLinear16 = NULL;
 529	sp->ToLinear8 = NULL;
 530	return 0;
 531    }
 532
 533    j = 0;
 534
 535    for (i = 0; i < nlin; i++)  {
 536	v = i * linstep;
 537	ToLinearF[j++] = (float)v;
 538    }
 539
 540    for (i = nlin; i < TSIZE; i++)
 541	ToLinearF[j++] = (float)(b*exp(c*i));
 542
 543    ToLinearF[2048] = ToLinearF[2047];
 544
 545    for (i = 0; i < TSIZEP1; i++)  {
 546	v = ToLinearF[i]*65535.0 + 0.5;
 547	ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16)v;
 548	v = ToLinearF[i]*255.0  + 0.5;
 549	ToLinear8[i]  = (v > 255.0) ? 255 : (unsigned char)v;
 550    }
 551
 552    j = 0;
 553    for (i = 0; i < lt2size; i++)  {
 554	if ((i*linstep)*(i*linstep) > ToLinearF[j]*ToLinearF[j+1])
 555	    j++;
 556	FromLT2[i] = j;
 557    }
 558
 559    /*
 560     * Since we lose info anyway on 16-bit data, we set up a 14-bit
 561     * table and shift 16-bit values down two bits on input.
 562     * saves a little table space.
 563     */
 564    j = 0;
 565    for (i = 0; i < 16384; i++)  {
 566	while ((i/16383.)*(i/16383.) > ToLinearF[j]*ToLinearF[j+1])
 567	    j++;
 568	From14[i] = j;
 569    }
 570
 571    j = 0;
 572    for (i = 0; i < 256; i++)  {
 573	while ((i/255.)*(i/255.) > ToLinearF[j]*ToLinearF[j+1])
 574	    j++;
 575	From8[i] = j;
 576    }
 577
 578    Fltsize = (float)(lt2size/2);
 579
 580    sp->ToLinearF = ToLinearF;
 581    sp->ToLinear16 = ToLinear16;
 582    sp->ToLinear8 = ToLinear8;
 583    sp->FromLT2 = FromLT2;
 584    sp->From14 = From14;
 585    sp->From8 = From8;
 586
 587    return 1;
 588}
 589
 590#define	DecoderState(tif)	((PixarLogState*) (tif)->tif_data)
 591#define	EncoderState(tif)	((PixarLogState*) (tif)->tif_data)
 592
 593static	int PixarLogEncode(TIFF*, tidata_t, tsize_t, tsample_t);
 594static	int PixarLogDecode(TIFF*, tidata_t, tsize_t, tsample_t);
 595
 596#define PIXARLOGDATAFMT_UNKNOWN	-1
 597
 598static int
 599PixarLogGuessDataFmt(TIFFDirectory *td)
 600{
 601	int guess = PIXARLOGDATAFMT_UNKNOWN;
 602	int format = td->td_sampleformat;
 603
 604	/* If the user didn't tell us his datafmt,
 605	 * take our best guess from the bitspersample.
 606	 */
 607	switch (td->td_bitspersample) {
 608	 case 32:
 609		if (format == SAMPLEFORMAT_IEEEFP)
 610			guess = PIXARLOGDATAFMT_FLOAT;
 611		break;
 612	 case 16:
 613		if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
 614			guess = PIXARLOGDATAFMT_16BIT;
 615		break;
 616	 case 12:
 617		if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_INT)
 618			guess = PIXARLOGDATAFMT_12BITPICIO;
 619		break;
 620	 case 11:
 621		if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
 622			guess = PIXARLOGDATAFMT_11BITLOG;
 623		break;
 624	 case 8:
 625		if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
 626			guess = PIXARLOGDATAFMT_8BIT;
 627		break;
 628	}
 629
 630	return guess;
 631}
 632
 633static uint32
 634multiply(size_t m1, size_t m2)
 635{
 636	uint32	bytes = m1 * m2;
 637
 638	if (m1 && bytes / m1 != m2)
 639		bytes = 0;
 640
 641	return bytes;
 642}
 643
 644static int
 645PixarLogSetupDecode(TIFF* tif)
 646{
 647	TIFFDirectory *td = &tif->tif_dir;
 648	PixarLogState* sp = DecoderState(tif);
 649	tsize_t tbuf_size;
 650	static const char module[] = "PixarLogSetupDecode";
 651
 652	assert(sp != NULL);
 653
 654	/* Make sure no byte swapping happens on the data
 655	 * after decompression. */
 656	tif->tif_postdecode = _TIFFNoPostDecode;
 657
 658	/* for some reason, we can't do this in TIFFInitPixarLog */
 659
 660	sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
 661	    td->td_samplesperpixel : 1);
 662	tbuf_size = multiply(multiply(multiply(sp->stride, td->td_imagewidth),
 663				      td->td_rowsperstrip), sizeof(uint16));
 664	if (tbuf_size == 0)
 665		return (0);
 666	sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size);
 667	if (sp->tbuf == NULL)
 668		return (0);
 669	if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
 670		sp->user_datafmt = PixarLogGuessDataFmt(td);
 671	if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
 672		TIFFErrorExt(tif->tif_clientdata, module,
 673			"PixarLog compression can't handle bits depth/data format combination (depth: %d)", 
 674			td->td_bitspersample);
 675		return (0);
 676	}
 677
 678	if (inflateInit(&sp->stream) != Z_OK) {
 679		TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg);
 680		return (0);
 681	} else {
 682		sp->state |= PLSTATE_INIT;
 683		return (1);
 684	}
 685}
 686
 687/*
 688 * Setup state for decoding a strip.
 689 */
 690static int
 691PixarLogPreDecode(TIFF* tif, tsample_t s)
 692{
 693	PixarLogState* sp = DecoderState(tif);
 694
 695	(void) s;
 696	assert(sp != NULL);
 697	sp->stream.next_in = tif->tif_rawdata;
 698	sp->stream.avail_in = tif->tif_rawcc;
 699	return (inflateReset(&sp->stream) == Z_OK);
 700}
 701
 702static int
 703PixarLogDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
 704{
 705	TIFFDirectory *td = &tif->tif_dir;
 706	PixarLogState* sp = DecoderState(tif);
 707	static const char module[] = "PixarLogDecode";
 708	int i, nsamples, llen;
 709	uint16 *up;
 710
 711	switch (sp->user_datafmt) {
 712	case PIXARLOGDATAFMT_FLOAT:
 713		nsamples = occ / sizeof(float);	/* XXX float == 32 bits */
 714		break;
 715	case PIXARLOGDATAFMT_16BIT:
 716	case PIXARLOGDATAFMT_12BITPICIO:
 717	case PIXARLOGDATAFMT_11BITLOG:
 718		nsamples = occ / sizeof(uint16); /* XXX uint16 == 16 bits */
 719		break;
 720	case PIXARLOGDATAFMT_8BIT:
 721	case PIXARLOGDATAFMT_8BITABGR:
 722		nsamples = occ;
 723		break;
 724	default:
 725		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
 726			"%d bit input not supported in PixarLog",
 727			td->td_bitspersample);
 728		return 0;
 729	}
 730
 731	llen = sp->stride * td->td_imagewidth;
 732
 733	(void) s;
 734	assert(sp != NULL);
 735	sp->stream.next_out = (unsigned char *) sp->tbuf;
 736	sp->stream.avail_out = nsamples * sizeof(uint16);
 737	do {
 738		int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
 739		if (state == Z_STREAM_END) {
 740			break;			/* XXX */
 741		}
 742		if (state == Z_DATA_ERROR) {
 743			TIFFErrorExt(tif->tif_clientdata, module,
 744			    "%s: Decoding error at scanline %d, %s",
 745			    tif->tif_name, tif->tif_row, sp->stream.msg);
 746			if (inflateSync(&sp->stream) != Z_OK)
 747				return (0);
 748			continue;
 749		}
 750		if (state != Z_OK) {
 751			TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
 752			    tif->tif_name, sp->stream.msg);
 753			return (0);
 754		}
 755	} while (sp->stream.avail_out > 0);
 756
 757	/* hopefully, we got all the bytes we needed */
 758	if (sp->stream.avail_out != 0) {
 759		TIFFErrorExt(tif->tif_clientdata, module,
 760		    "%s: Not enough data at scanline %d (short %d bytes)",
 761		    tif->tif_name, tif->tif_row, sp->stream.avail_out);
 762		return (0);
 763	}
 764
 765	up = sp->tbuf;
 766	/* Swap bytes in the data if from a different endian machine. */
 767	if (tif->tif_flags & TIFF_SWAB)
 768		TIFFSwabArrayOfShort(up, nsamples);
 769
 770	/* 
 771	 * if llen is not an exact multiple of nsamples, the decode operation
 772	 * may overflow the output buffer, so truncate it enough to prevent
 773	 * that but still salvage as much data as possible.
 774	 */
 775	if (nsamples % llen) { 
 776		TIFFWarningExt(tif->tif_clientdata, module,
 777			"%s: stride %d is not a multiple of sample count, "
 778			"%d, data truncated.", tif->tif_name, llen, nsamples);
 779		nsamples -= nsamples % llen;
 780	}
 781
 782	for (i = 0; i < nsamples; i += llen, up += llen) {
 783		switch (sp->user_datafmt)  {
 784		case PIXARLOGDATAFMT_FLOAT:
 785			horizontalAccumulateF(up, llen, sp->stride,
 786					(float *)op, sp->ToLinearF);
 787			op += llen * sizeof(float);
 788			break;
 789		case PIXARLOGDATAFMT_16BIT:
 790			horizontalAccumulate16(up, llen, sp->stride,
 791					(uint16 *)op, sp->ToLinear16);
 792			op += llen * sizeof(uint16);
 793			break;
 794		case PIXARLOGDATAFMT_12BITPICIO:
 795			horizontalAccumulate12(up, llen, sp->stride,
 796					(int16 *)op, sp->ToLinearF);
 797			op += llen * sizeof(int16);
 798			break;
 799		case PIXARLOGDATAFMT_11BITLOG:
 800			horizontalAccumulate11(up, llen, sp->stride,
 801					(uint16 *)op);
 802			op += llen * sizeof(uint16);
 803			break;
 804		case PIXARLOGDATAFMT_8BIT:
 805			horizontalAccumulate8(up, llen, sp->stride,
 806					(unsigned char *)op, sp->ToLinear8);
 807			op += llen * sizeof(unsigned char);
 808			break;
 809		case PIXARLOGDATAFMT_8BITABGR:
 810			horizontalAccumulate8abgr(up, llen, sp->stride,
 811					(unsigned char *)op, sp->ToLinear8);
 812			op += llen * sizeof(unsigned char);
 813			break;
 814		default:
 815			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
 816				  "PixarLogDecode: unsupported bits/sample: %d", 
 817				  td->td_bitspersample);
 818			return (0);
 819		}
 820	}
 821
 822	return (1);
 823}
 824
 825static int
 826PixarLogSetupEncode(TIFF* tif)
 827{
 828	TIFFDirectory *td = &tif->tif_dir;
 829	PixarLogState* sp = EncoderState(tif);
 830	tsize_t tbuf_size;
 831	static const char module[] = "PixarLogSetupEncode";
 832
 833	assert(sp != NULL);
 834
 835	/* for some reason, we can't do this in TIFFInitPixarLog */
 836
 837	sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
 838	    td->td_samplesperpixel : 1);
 839	tbuf_size = multiply(multiply(multiply(sp->stride, td->td_imagewidth),
 840				      td->td_rowsperstrip), sizeof(uint16));
 841	if (tbuf_size == 0)
 842		return (0);
 843	sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size);
 844	if (sp->tbuf == NULL)
 845		return (0);
 846	if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
 847		sp->user_datafmt = PixarLogGuessDataFmt(td);
 848	if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
 849		TIFFErrorExt(tif->tif_clientdata, module, "PixarLog compression can't handle %d bit linear encodings", td->td_bitspersample);
 850		return (0);
 851	}
 852
 853	if (deflateInit(&sp->stream, sp->quality) != Z_OK) {
 854		TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg);
 855		return (0);
 856	} else {
 857		sp->state |= PLSTATE_INIT;
 858		return (1);
 859	}
 860}
 861
 862/*
 863 * Reset encoding state at the start of a strip.
 864 */
 865static int
 866PixarLogPreEncode(TIFF* tif, tsample_t s)
 867{
 868	PixarLogState *sp = EncoderState(tif);
 869
 870	(void) s;
 871	assert(sp != NULL);
 872	sp->stream.next_out = tif->tif_rawdata;
 873	sp->stream.avail_out = tif->tif_rawdatasize;
 874	return (deflateReset(&sp->stream) == Z_OK);
 875}
 876
 877static void
 878horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2)
 879{
 880
 881    int32 r1, g1, b1, a1, r2, g2, b2, a2, mask;
 882    float fltsize = Fltsize;
 883
 884#define  CLAMP(v) ( (v<(float)0.)   ? 0				\
 885		  : (v<(float)2.)   ? FromLT2[(int)(v*fltsize)]	\
 886		  : (v>(float)24.2) ? 2047			\
 887		  : LogK1*log(v*LogK2) + 0.5 )
 888
 889    mask = CODE_MASK;
 890    if (n >= stride) {
 891	if (stride == 3) {
 892	    r2 = wp[0] = (uint16) CLAMP(ip[0]);
 893	    g2 = wp[1] = (uint16) CLAMP(ip[1]);
 894	    b2 = wp[2] = (uint16) CLAMP(ip[2]);
 895	    n -= 3;
 896	    while (n > 0) {
 897		n -= 3;
 898		wp += 3;
 899		ip += 3;
 900		r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
 901		g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
 902		b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
 903	    }
 904	} else if (stride == 4) {
 905	    r2 = wp[0] = (uint16) CLAMP(ip[0]);
 906	    g2 = wp[1] = (uint16) CLAMP(ip[1]);
 907	    b2 = wp[2] = (uint16) CLAMP(ip[2]);
 908	    a2 = wp[3] = (uint16) CLAMP(ip[3]);
 909	    n -= 4;
 910	    while (n > 0) {
 911		n -= 4;
 912		wp += 4;
 913		ip += 4;
 914		r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
 915		g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
 916		b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
 917		a1 = (int32) CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
 918	    }
 919	} else {
 920	    ip += n - 1;	/* point to last one */
 921	    wp += n - 1;	/* point to last one */
 922	    n -= stride;
 923	    while (n > 0) {
 924		REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]);
 925				wp[stride] -= wp[0];
 926				wp[stride] &= mask;
 927				wp--; ip--)
 928		n -= stride;
 929	    }
 930	    REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp--; ip--)
 931	}
 932    }
 933}
 934
 935static void
 936horizontalDifference16(unsigned short *ip, int n, int stride, 
 937	unsigned short *wp, uint16 *From14)
 938{
 939    register int  r1, g1, b1, a1, r2, g2, b2, a2, mask;
 940
 941/* assumption is unsigned pixel values */
 942#undef   CLAMP
 943#define  CLAMP(v) From14[(v) >> 2]
 944
 945    mask = CODE_MASK;
 946    if (n >= stride) {
 947	if (stride == 3) {
 948	    r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
 949	    b2 = wp[2] = CLAMP(ip[2]);
 950	    n -= 3;
 951	    while (n > 0) {
 952		n -= 3;
 953		wp += 3;
 954		ip += 3;
 955		r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
 956		g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
 957		b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
 958	    }
 959	} else if (stride == 4) {
 960	    r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
 961	    b2 = wp[2] = CLAMP(ip[2]);  a2 = wp[3] = CLAMP(ip[3]);
 962	    n -= 4;
 963	    while (n > 0) {
 964		n -= 4;
 965		wp += 4;
 966		ip += 4;
 967		r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
 968		g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
 969		b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
 970		a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
 971	    }
 972	} else {
 973	    ip += n - 1;	/* point to last one */
 974	    wp += n - 1;	/* point to last one */
 975	    n -= stride;
 976	    while (n > 0) {
 977		REPEAT(stride, wp[0] = CLAMP(ip[0]);
 978				wp[stride] -= wp[0];
 979				wp[stride] &= mask;
 980				wp--; ip--)
 981		n -= stride;
 982	    }
 983	    REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
 984	}
 985    }
 986}
 987
 988
 989static void
 990horizontalDifference8(unsigned char *ip, int n, int stride, 
 991	unsigned short *wp, uint16 *From8)
 992{
 993    register int  r1, g1, b1, a1, r2, g2, b2, a2, mask;
 994
 995#undef	 CLAMP
 996#define  CLAMP(v) (From8[(v)])
 997
 998    mask = CODE_MASK;
 999    if (n >= stride) {
1000	if (stride == 3) {
1001	    r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
1002	    b2 = wp[2] = CLAMP(ip[2]);
1003	    n -= 3;
1004	    while (n > 0) {
1005		n -= 3;
1006		r1 = CLAMP(ip[3]); wp[3] = (r1-r2) & mask; r2 = r1;
1007		g1 = CLAMP(ip[4]); wp[4] = (g1-g2) & mask; g2 = g1;
1008		b1 = CLAMP(ip[5]); wp[5] = (b1-b2) & mask; b2 = b1;
1009		wp += 3;
1010		ip += 3;
1011	    }
1012	} else if (stride == 4) {
1013	    r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
1014	    b2 = wp[2] = CLAMP(ip[2]);  a2 = wp[3] = CLAMP(ip[3]);
1015	    n -= 4;
1016	    while (n > 0) {
1017		n -= 4;
1018		r1 = CLAMP(ip[4]); wp[4] = (r1-r2) & mask; r2 = r1;
1019		g1 = CLAMP(ip[5]); wp[5] = (g1-g2) & mask; g2 = g1;
1020		b1 = CLAMP(ip[6]); wp[6] = (b1-b2) & mask; b2 = b1;
1021		a1 = CLAMP(ip[7]); wp[7] = (a1-a2) & mask; a2 = a1;
1022		wp += 4;
1023		ip += 4;
1024	    }
1025	} else {
1026	    wp += n + stride - 1;	/* point to last one */
1027	    ip += n + stride - 1;	/* point to last one */
1028	    n -= stride;
1029	    while (n > 0) {
1030		REPEAT(stride, wp[0] = CLAMP(ip[0]);
1031				wp[stride] -= wp[0];
1032				wp[stride] &= mask;
1033				wp--; ip--)
1034		n -= stride;
1035	    }
1036	    REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
1037	}
1038    }
1039}
1040
1041/*
1042 * Encode a chunk of pixels.
1043 */
1044static int
1045PixarLogEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
1046{
1047	TIFFDirectory *td = &tif->tif_dir;
1048	PixarLogState *sp = EncoderState(tif);
1049	static const char module[] = "PixarLogEncode";
1050	int	i, n, llen;
1051	unsigned short * up;
1052
1053	(void) s;
1054
1055	switch (sp->user_datafmt) {
1056	case PIXARLOGDATAFMT_FLOAT:
1057		n = cc / sizeof(float);		/* XXX float == 32 bits */
1058		break;
1059	case PIXARLOGDATAFMT_16BIT:
1060	case PIXARLOGDATAFMT_12BITPICIO:
1061	case PIXARLOGDATAFMT_11BITLOG:
1062		n = cc / sizeof(uint16);	/* XXX uint16 == 16 bits */
1063		break;
1064	case PIXARLOGDATAFMT_8BIT:
1065	case PIXARLOGDATAFMT_8BITABGR:
1066		n = cc;
1067		break;
1068	default:
1069		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
1070			"%d bit input not supported in PixarLog",
1071			td->td_bitspersample);
1072		return 0;
1073	}
1074
1075	llen = sp->stride * td->td_imagewidth;
1076
1077	for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) {
1078		switch (sp->user_datafmt)  {
1079		case PIXARLOGDATAFMT_FLOAT:
1080			horizontalDifferenceF((float *)bp, llen, 
1081				sp->stride, up, sp->FromLT2);
1082			bp += llen * sizeof(float);
1083			break;
1084		case PIXARLOGDATAFMT_16BIT:
1085			horizontalDifference16((uint16 *)bp, llen, 
1086				sp->stride, up, sp->From14);
1087			bp += llen * sizeof(uint16);
1088			break;
1089		case PIXARLOGDATAFMT_8BIT:
1090			horizontalDifference8((unsigned char *)bp, llen, 
1091				sp->stride, up, sp->From8);
1092			bp += llen * sizeof(unsigned char);
1093			break;
1094		default:
1095			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
1096				"%d bit input not supported in PixarLog",
1097				td->td_bitspersample);
1098			return 0;
1099		}
1100	}
1101 
1102	sp->stream.next_in = (unsigned char *) sp->tbuf;
1103	sp->stream.avail_in = n * sizeof(uint16);
1104
1105	do {
1106		if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
1107			TIFFErrorExt(tif->tif_clientdata, module, "%s: Encoder error: %s",
1108			    tif->tif_name, sp->stream.msg);
1109			return (0);
1110		}
1111		if (sp->stream.avail_out == 0) {
1112			tif->tif_rawcc = tif->tif_rawdatasize;
1113			TIFFFlushData1(tif);
1114			sp->stream.next_out = tif->tif_rawdata;
1115			sp->stream.avail_out = tif->tif_rawdatasize;
1116		}
1117	} while (sp->stream.avail_in > 0);
1118	return (1);
1119}
1120
1121/*
1122 * Finish off an encoded strip by flushing the last
1123 * string and tacking on an End Of Information code.
1124 */
1125
1126static int
1127PixarLogPostEncode(TIFF* tif)
1128{
1129	PixarLogState *sp = EncoderState(tif);
1130	static const char module[] = "PixarLogPostEncode";
1131	int state;
1132
1133	sp->stream.avail_in = 0;
1134
1135	do {
1136		state = deflate(&sp->stream, Z_FINISH);
1137		switch (state) {
1138		case Z_STREAM_END:
1139		case Z_OK:
1140		    if (sp->stream.avail_out != (uint32)tif->tif_rawdatasize) {
1141			    tif->tif_rawcc =
1142				tif->tif_rawdatasize - sp->stream.avail_out;
1143			    TIFFFlushData1(tif);
1144			    sp->stream.next_out = tif->tif_rawdata;
1145			    sp->stream.avail_out = tif->tif_rawdatasize;
1146		    }
1147		    break;
1148		default:
1149			TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
1150			tif->tif_name, sp->stream.msg);
1151		    return (0);
1152		}
1153	} while (state != Z_STREAM_END);
1154	return (1);
1155}
1156
1157static void
1158PixarLogClose(TIFF* tif)
1159{
1160	TIFFDirectory *td = &tif->tif_dir;
1161
1162	/* In a really sneaky maneuver, on close, we covertly modify both
1163	 * bitspersample and sampleformat in the directory to indicate
1164	 * 8-bit linear.  This way, the decode "just works" even for
1165	 * readers that don't know about PixarLog, or how to set
1166	 * the PIXARLOGDATFMT pseudo-tag.
1167	 */
1168	td->td_bitspersample = 8;
1169	td->td_sampleformat = SAMPLEFORMAT_UINT;
1170}
1171
1172static void
1173PixarLogCleanup(TIFF* tif)
1174{
1175	PixarLogState* sp = (PixarLogState*) tif->tif_data;
1176
1177	assert(sp != 0);
1178
1179	(void)TIFFPredictorCleanup(tif);
1180
1181	tif->tif_tagmethods.vgetfield = sp->vgetparent;
1182	tif->tif_tagmethods.vsetfield = sp->vsetparent;
1183
1184	if (sp->FromLT2) _TIFFfree(sp->FromLT2);
1185	if (sp->From14) _TIFFfree(sp->From14);
1186	if (sp->From8) _TIFFfree(sp->From8);
1187	if (sp->ToLinearF) _TIFFfree(sp->ToLinearF);
1188	if (sp->ToLinear16) _TIFFfree(sp->ToLinear16);
1189	if (sp->ToLinear8) _TIFFfree(sp->ToLinear8);
1190	if (sp->state&PLSTATE_INIT) {
1191		if (tif->tif_mode == O_RDONLY)
1192			inflateEnd(&sp->stream);
1193		else
1194			deflateEnd(&sp->stream);
1195	}
1196	if (sp->tbuf)
1197		_TIFFfree(sp->tbuf);
1198	_TIFFfree(sp);
1199	tif->tif_data = NULL;
1200
1201	_TIFFSetDefaultCompressionState(tif);
1202}
1203
1204static int
1205PixarLogVSetField(TIFF* tif, ttag_t tag, va_list ap)
1206{
1207    PixarLogState *sp = (PixarLogState *)tif->tif_data;
1208    int result;
1209    static const char module[] = "PixarLogVSetField";
1210
1211    switch (tag) {
1212     case TIFFTAG_PIXARLOGQUALITY:
1213		sp->quality = va_arg(ap, int);
1214		if (tif->tif_mode != O_RDONLY && (sp->state&PLSTATE_INIT)) {
1215			if (deflateParams(&sp->stream,
1216			    sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) {
1217				TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
1218					tif->tif_name, sp->stream.msg);
1219				return (0);
1220			}
1221		}
1222		return (1);
1223     case TIFFTAG_PIXARLOGDATAFMT:
1224	sp->user_datafmt = va_arg(ap, int);
1225	/* Tweak the TIFF header so that the rest of libtiff knows what
1226	 * size of data will be passed between app and library, and
1227	 * assume that the app knows what it is doing and is not
1228	 * confused by these header manipulations...
1229	 */
1230	switch (sp->user_datafmt) {
1231	 case PIXARLOGDATAFMT_8BIT:
1232	 case PIXARLOGDATAFMT_8BITABGR:
1233	    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
1234	    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1235	    break;
1236	 case PIXARLOGDATAFMT_11BITLOG:
1237	    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1238	    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1239	    break;
1240	 case PIXARLOGDATAFMT_12BITPICIO:
1241	    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1242	    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
1243	    break;
1244	 case PIXARLOGDATAFMT_16BIT:
1245	    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1246	    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1247	    break;
1248	 case PIXARLOGDATAFMT_FLOAT:
1249	    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
1250	    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
1251	    break;
1252	}
1253	/*
1254	 * Must recalculate sizes should bits/sample change.
1255	 */
1256	tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
1257	tif->tif_scanlinesize = TIFFScanlineSize(tif);
1258	result = 1;		/* NB: pseudo tag */
1259	break;
1260     default:
1261	result = (*sp->vsetparent)(tif, tag, ap);
1262    }
1263    return (result);
1264}
1265
1266static int
1267PixarLogVGetField(TIFF* tif, ttag_t tag, va_list ap)
1268{
1269    PixarLogState *sp = (PixarLogState *)tif->tif_data;
1270
1271    switch (tag) {
1272     case TIFFTAG_PIXARLOGQUALITY:
1273	*va_arg(ap, int*) = sp->quality;
1274	break;
1275     case TIFFTAG_PIXARLOGDATAFMT:
1276	*va_arg(ap, int*) = sp->user_datafmt;
1277	break;
1278     default:
1279	return (*sp->vgetparent)(tif, tag, ap);
1280    }
1281    return (1);
1282}
1283
1284static const TIFFFieldInfo pixarlogFieldInfo[] = {
1285    {TIFFTAG_PIXARLOGDATAFMT,0,0,TIFF_ANY,  FIELD_PSEUDO,FALSE,FALSE,""},
1286    {TIFFTAG_PIXARLOGQUALITY,0,0,TIFF_ANY,  FIELD_PSEUDO,FALSE,FALSE,""}
1287};
1288
1289int
1290TIFFInitPixarLog(TIFF* tif, int scheme)
1291{
1292	static const char module[] = "TIFFInitPixarLog";
1293
1294	PixarLogState* sp;
1295
1296	assert(scheme == COMPRESSION_PIXARLOG);
1297
1298	/*
1299	 * Merge codec-specific tag information.
1300	 */
1301	if (!_TIFFMergeFieldInfo(tif, pixarlogFieldInfo,
1302				 TIFFArrayCount(pixarlogFieldInfo))) {
1303		TIFFErrorExt(tif->tif_clientdata, module,
1304			     "Merging PixarLog codec-specific tags failed");
1305		return 0;
1306	}
1307
1308	/*
1309	 * Allocate state block so tag methods have storage to record values.
1310	 */
1311	tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (PixarLogState));
1312	if (tif->tif_data == NULL)
1313		goto bad;
1314	sp = (PixarLogState*) tif->tif_data;
1315	_TIFFmemset(sp, 0, sizeof (*sp));
1316	sp->stream.data_type = Z_BINARY;
1317	sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN;
1318
1319	/*
1320	 * Install codec methods.
1321	 */
1322	tif->tif_setupdecode = PixarLogSetupDecode;
1323	tif->tif_predecode = PixarLogPreDecode;
1324	tif->tif_decoderow = PixarLogDecode;
1325	tif->tif_decodestrip = PixarLogDecode;
1326	tif->tif_decodetile = PixarLogDecode;
1327	tif->tif_setupencode = PixarLogSetupEncode;
1328	tif->tif_preencode = PixarLogPreEncode;
1329	tif->tif_postencode = PixarLogPostEncode;
1330	tif->tif_encoderow = PixarLogEncode;
1331	tif->tif_encodestrip = PixarLogEncode;
1332	tif->tif_encodetile = PixarLogEncode;
1333	tif->tif_close = PixarLogClose;
1334	tif->tif_cleanup = PixarLogCleanup;
1335
1336	/* Override SetField so we can handle our private pseudo-tag */
1337	sp->vgetparent = tif->tif_tagmethods.vgetfield;
1338	tif->tif_tagmethods.vgetfield = PixarLogVGetField;   /* hook for codec tags */
1339	sp->vsetparent = tif->tif_tagmethods.vsetfield;
1340	tif->tif_tagmethods.vsetfield = PixarLogVSetField;   /* hook for codec tags */
1341
1342	/* Default values for codec-specific fields */
1343	sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */
1344	sp->state = 0;
1345
1346	/* we don't wish to use the predictor, 
1347	 * the default is none, which predictor value 1
1348	 */
1349	(void) TIFFPredictorInit(tif);
1350
1351	/*
1352	 * build the companding tables 
1353	 */
1354	PixarLogMakeTables(sp);
1355
1356	return (1);
1357bad:
1358	TIFFErrorExt(tif->tif_clientdata, module,
1359		     "No space for PixarLog state block");
1360	return (0);
1361}
1362#endif /* PIXARLOG_SUPPORT */
1363
1364/* vim: set ts=8 sts=8 sw=8 noet: */
1365/*
1366 * Local Variables:
1367 * mode: c
1368 * c-basic-offset: 8
1369 * fill-column: 78
1370 * End:
1371 */