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