1/* $Id: tif_jbig.c,v 1.2.2.3 2010-06-08 18:50:42 bfriesen Exp $ */ 2 3/* 4 * Copyright (c) 1988-1997 Sam Leffler 5 * Copyright (c) 1991-1997 Silicon Graphics, Inc. 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 * 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 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 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/* 28 * TIFF Library. 29 * 30 * JBIG Compression Algorithm Support. 31 * Contributed by Lee Howard <faxguy@deanox.com> 32 * 33 */ 34 35#include "tiffiop.h" 36 37#ifdef JBIG_SUPPORT 38#include "jbig.h" 39 40typedef struct 41{ 42 uint32 recvparams; /* encoded Class 2 session params */ 43 char* subaddress; /* subaddress string */ 44 uint32 recvtime; /* time spend receiving in seconds */ 45 char* faxdcs; /* encoded fax parameters (DCS, Table 2/T.30) */ 46 47 TIFFVGetMethod vgetparent; 48 TIFFVSetMethod vsetparent; 49} JBIGState; 50 51#define GetJBIGState(tif) ((JBIGState*)(tif)->tif_data) 52 53#define FIELD_RECVPARAMS (FIELD_CODEC+0) 54#define FIELD_SUBADDRESS (FIELD_CODEC+1) 55#define FIELD_RECVTIME (FIELD_CODEC+2) 56#define FIELD_FAXDCS (FIELD_CODEC+3) 57 58static const TIFFFieldInfo jbigFieldInfo[] = 59{ 60 {TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, FIELD_RECVPARAMS, TRUE, FALSE, "FaxRecvParams"}, 61 {TIFFTAG_FAXSUBADDRESS, -1, -1, TIFF_ASCII, FIELD_SUBADDRESS, TRUE, FALSE, "FaxSubAddress"}, 62 {TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, FIELD_RECVTIME, TRUE, FALSE, "FaxRecvTime"}, 63 {TIFFTAG_FAXDCS, -1, -1, TIFF_ASCII, FIELD_FAXDCS, TRUE, FALSE, "FaxDcs"}, 64}; 65 66static int JBIGSetupDecode(TIFF* tif) 67{ 68 if (TIFFNumberOfStrips(tif) != 1) 69 { 70 TIFFError("JBIG", "Multistrip images not supported in decoder"); 71 return 0; 72 } 73 74 return 1; 75} 76 77static int JBIGDecode(TIFF* tif, tidata_t buffer, tsize_t size, tsample_t s) 78{ 79 struct jbg_dec_state decoder; 80 int decodeStatus = 0; 81 unsigned char* pImage = NULL; 82 (void) size, (void) s; 83 84 if (isFillOrder(tif, tif->tif_dir.td_fillorder)) 85 { 86 TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdatasize); 87 } 88 89 jbg_dec_init(&decoder); 90 91#if defined(HAVE_JBG_NEWLEN) 92 jbg_newlen(tif->tif_rawdata, tif->tif_rawdatasize); 93 /* 94 * I do not check the return status of jbg_newlen because even if this 95 * function fails it does not necessarily mean that decoding the image 96 * will fail. It is generally only needed for received fax images 97 * that do not contain the actual length of the image in the BIE 98 * header. I do not log when an error occurs because that will cause 99 * problems when converting JBIG encoded TIFF's to 100 * PostScript. As long as the actual image length is contained in the 101 * BIE header jbg_dec_in should succeed. 102 */ 103#endif /* HAVE_JBG_NEWLEN */ 104 105 decodeStatus = jbg_dec_in(&decoder, tif->tif_rawdata, 106 tif->tif_rawdatasize, NULL); 107 if (JBG_EOK != decodeStatus) 108 { 109 /* 110 * XXX: JBG_EN constant was defined in pre-2.0 releases of the 111 * JBIG-KIT. Since the 2.0 the error reporting functions were 112 * changed. We will handle both cases here. 113 */ 114 TIFFError("JBIG", "Error (%d) decoding: %s", decodeStatus, 115#if defined(JBG_EN) 116 jbg_strerror(decodeStatus, JBG_EN) 117#else 118 jbg_strerror(decodeStatus) 119#endif 120 ); 121 return 0; 122 } 123 124 pImage = jbg_dec_getimage(&decoder, 0); 125 _TIFFmemcpy(buffer, pImage, jbg_dec_getsize(&decoder)); 126 jbg_dec_free(&decoder); 127 return 1; 128} 129 130static int JBIGSetupEncode(TIFF* tif) 131{ 132 if (TIFFNumberOfStrips(tif) != 1) 133 { 134 TIFFError("JBIG", "Multistrip images not supported in encoder"); 135 return 0; 136 } 137 138 return 1; 139} 140 141static int JBIGCopyEncodedData(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) 142{ 143 (void) s; 144 while (cc > 0) 145 { 146 tsize_t n = cc; 147 148 if (tif->tif_rawcc + n > tif->tif_rawdatasize) 149 { 150 n = tif->tif_rawdatasize - tif->tif_rawcc; 151 } 152 153 assert(n > 0); 154 _TIFFmemcpy(tif->tif_rawcp, pp, n); 155 tif->tif_rawcp += n; 156 tif->tif_rawcc += n; 157 pp += n; 158 cc -= n; 159 if (tif->tif_rawcc >= tif->tif_rawdatasize && 160 !TIFFFlushData1(tif)) 161 { 162 return (-1); 163 } 164 } 165 166 return (1); 167} 168 169static void JBIGOutputBie(unsigned char* buffer, size_t len, void *userData) 170{ 171 TIFF* tif = (TIFF*)userData; 172 173 if (isFillOrder(tif, tif->tif_dir.td_fillorder)) 174 { 175 TIFFReverseBits(buffer, len); 176 } 177 178 JBIGCopyEncodedData(tif, buffer, len, 0); 179} 180 181static int JBIGEncode(TIFF* tif, tidata_t buffer, tsize_t size, tsample_t s) 182{ 183 TIFFDirectory* dir = &tif->tif_dir; 184 struct jbg_enc_state encoder; 185 186 (void) size, (void) s; 187 188 jbg_enc_init(&encoder, 189 dir->td_imagewidth, 190 dir->td_imagelength, 191 1, 192 &buffer, 193 JBIGOutputBie, 194 tif); 195 /* 196 * jbg_enc_out does the "real" encoding. As data is encoded, 197 * JBIGOutputBie is called, which writes the data to the directory. 198 */ 199 jbg_enc_out(&encoder); 200 jbg_enc_free(&encoder); 201 202 return 1; 203} 204 205static void JBIGCleanup(TIFF* tif) 206{ 207 JBIGState *sp = GetJBIGState(tif); 208 209 assert(sp != 0); 210 211 tif->tif_tagmethods.vgetfield = sp->vgetparent; 212 tif->tif_tagmethods.vsetfield = sp->vsetparent; 213 214 _TIFFfree(tif->tif_data); 215 tif->tif_data = NULL; 216 217 _TIFFSetDefaultCompressionState(tif); 218} 219 220static void JBIGPrintDir(TIFF* tif, FILE* fd, long flags) 221{ 222 JBIGState* codec = GetJBIGState(tif); 223 (void)flags; 224 225 if (TIFFFieldSet(tif, FIELD_RECVPARAMS)) 226 { 227 fprintf(fd, 228 " Fax Receive Parameters: %08lx\n", 229 (unsigned long)codec->recvparams); 230 } 231 232 if (TIFFFieldSet(tif, FIELD_SUBADDRESS)) 233 { 234 fprintf(fd, 235 " Fax SubAddress: %s\n", 236 codec->subaddress); 237 } 238 239 if (TIFFFieldSet(tif, FIELD_RECVTIME)) 240 { 241 fprintf(fd, 242 " Fax Receive Time: %lu secs\n", 243 (unsigned long)codec->recvtime); 244 } 245 246 if (TIFFFieldSet(tif, FIELD_FAXDCS)) 247 { 248 fprintf(fd, 249 " Fax DCS: %s\n", 250 codec->faxdcs); 251 } 252} 253 254static int JBIGVGetField(TIFF* tif, ttag_t tag, va_list ap) 255{ 256 JBIGState* codec = GetJBIGState(tif); 257 258 switch (tag) 259 { 260 case TIFFTAG_FAXRECVPARAMS: 261 *va_arg(ap, uint32*) = codec->recvparams; 262 break; 263 264 case TIFFTAG_FAXSUBADDRESS: 265 *va_arg(ap, char**) = codec->subaddress; 266 break; 267 268 case TIFFTAG_FAXRECVTIME: 269 *va_arg(ap, uint32*) = codec->recvtime; 270 break; 271 272 case TIFFTAG_FAXDCS: 273 *va_arg(ap, char**) = codec->faxdcs; 274 break; 275 276 default: 277 return (*codec->vgetparent)(tif, tag, ap); 278 } 279 280 return 1; 281} 282 283static int JBIGVSetField(TIFF* tif, ttag_t tag, va_list ap) 284{ 285 JBIGState* codec = GetJBIGState(tif); 286 287 switch (tag) 288 { 289 case TIFFTAG_FAXRECVPARAMS: 290 codec->recvparams = va_arg(ap, uint32); 291 break; 292 293 case TIFFTAG_FAXSUBADDRESS: 294 _TIFFsetString(&codec->subaddress, va_arg(ap, char*)); 295 break; 296 297 case TIFFTAG_FAXRECVTIME: 298 codec->recvtime = va_arg(ap, uint32); 299 break; 300 301 case TIFFTAG_FAXDCS: 302 _TIFFsetString(&codec->faxdcs, va_arg(ap, char*)); 303 break; 304 305 default: 306 return (*codec->vsetparent)(tif, tag, ap); 307 } 308 309 TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit); 310 tif->tif_flags |= TIFF_DIRTYDIRECT; 311 return 1; 312} 313 314int TIFFInitJBIG(TIFF* tif, int scheme) 315{ 316 JBIGState* codec = NULL; 317 318 assert(scheme == COMPRESSION_JBIG); 319 320 /* 321 * Merge codec-specific tag information. 322 */ 323 if (!_TIFFMergeFieldInfo(tif, jbigFieldInfo, 324 TIFFArrayCount(jbigFieldInfo))) { 325 TIFFErrorExt(tif->tif_clientdata, "TIFFInitJBIG", 326 "Merging JBIG codec-specific tags failed"); 327 return 0; 328 } 329 330 /* Allocate memory for the JBIGState structure.*/ 331 tif->tif_data = (tdata_t)_TIFFmalloc(sizeof(JBIGState)); 332 if (tif->tif_data == NULL) 333 { 334 TIFFError("TIFFInitJBIG", "Not enough memory for JBIGState"); 335 return 0; 336 } 337 _TIFFmemset(tif->tif_data, 0, sizeof(JBIGState)); 338 codec = GetJBIGState(tif); 339 340 /* Initialize codec private fields */ 341 codec->recvparams = 0; 342 codec->subaddress = NULL; 343 codec->faxdcs = NULL; 344 codec->recvtime = 0; 345 346 /* 347 * Override parent get/set field methods. 348 */ 349 codec->vgetparent = tif->tif_tagmethods.vgetfield; 350 codec->vsetparent = tif->tif_tagmethods.vsetfield; 351 tif->tif_tagmethods.vgetfield = JBIGVGetField; 352 tif->tif_tagmethods.vsetfield = JBIGVSetField; 353 tif->tif_tagmethods.printdir = JBIGPrintDir; 354 355 /* 356 * These flags are set so the JBIG Codec can control when to reverse 357 * bits and when not to and to allow the jbig decoder and bit reverser 358 * to write to memory when necessary. 359 */ 360 tif->tif_flags |= TIFF_NOBITREV; 361 tif->tif_flags &= ~TIFF_MAPPED; 362 363 /* Setup the function pointers for encode, decode, and cleanup. */ 364 tif->tif_setupdecode = JBIGSetupDecode; 365 tif->tif_decodestrip = JBIGDecode; 366 367 tif->tif_setupencode = JBIGSetupEncode; 368 tif->tif_encodestrip = JBIGEncode; 369 370 tif->tif_cleanup = JBIGCleanup; 371 372 return 1; 373} 374 375#endif /* JBIG_SUPPORT */ 376 377/* vim: set ts=8 sts=8 sw=8 noet: */ 378 379/* 380 * Local Variables: 381 * mode: c 382 * c-basic-offset: 8 383 * fill-column: 78 384 * End: 385 */ 386