1/*
2 * << Haru Free PDF Library >> -- hpdf_image.c
3 *
4 * URL: http://libharu.org
5 *
6 * Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
7 * Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
8 *
9 * Permission to use, copy, modify, distribute and sell this software
10 * and its documentation for any purpose is hereby granted without fee,
11 * provided that the above copyright notice appear in all copies and
12 * that both that copyright notice and this permission notice appear
13 * in supporting documentation.
14 * It is provided "as is" without express or implied warranty.
15 *
16 */
17
18#include "hpdf_conf.h"
19#include "hpdf_utils.h"
20#include "hpdf.h"
21#include <memory.h>
22#include <assert.h>
23
24#define G3CODES
25#include "t4.h"
26
27typedef unsigned int uint32;
28typedef int int32;
29typedef unsigned short uint16;
30typedef int32 tsize_t; /* i/o size in bytes */
31/*
32 * Typedefs for ``method pointers'' used internally.
33 */
34typedef unsigned char tidataval_t; /* internal image data value type */
35typedef tidataval_t* tidata_t; /* reference to internal image data */
36
37/*
38 * Compression+decompression state blocks are
39 * derived from this ``base state'' block.
40 */
41typedef struct {
42 /* int rw_mode; */ /* O_RDONLY for decode, else encode */
43 int mode; /* operating mode */
44 uint32 rowbytes; /* bytes in a decoded scanline */
45 uint32 rowpixels; /* pixels in a scanline */
46
47 uint16 cleanfaxdata; /* CleanFaxData tag */
48 uint32 badfaxrun; /* BadFaxRun tag */
49 uint32 badfaxlines; /* BadFaxLines tag */
50 uint32 groupoptions; /* Group 3/4 options tag */
51 uint32 recvparams; /* encoded Class 2 session params */
52 char* subaddress; /* subaddress string */
53 uint32 recvtime; /* time spent receiving (secs) */
54 char* faxdcs; /* Table 2/T.30 encoded session params */
55} HPDF_Fax3BaseState;
56
57typedef struct {
58 HPDF_Fax3BaseState b;
59
60 /* Decoder state info */
61 const unsigned char* bitmap; /* bit reversal table */
62 uint32 data; /* current i/o byte/word */
63 int bit; /* current i/o bit in byte */
64 int EOLcnt; /* count of EOL codes recognized */
65 /* TIFFFaxFillFunc fill;*/ /* fill routine */
66 uint32* runs; /* b&w runs for current/previous row */
67 uint32* refruns; /* runs for reference line */
68 uint32* curruns; /* runs for current line */
69
70 /* Encoder state info */
71 /* Ttag tag; */ /* encoding state */
72 unsigned char* refline; /* reference line for 2d decoding */
73 int k; /* #rows left that can be 2d encoded */
74 int maxk; /* max #rows that can be 2d encoded */
75
76 int line;
77} HPDF_Fax3CodecState;
78
79#define Fax3State(tif) (&(tif)->tif_data->b)
80#define EncoderState(tif) ((tif)->tif_data)
81#define isAligned(p,t) ((((unsigned long)(p)) & (sizeof (t)-1)) == 0)
82
83/* NB: the uint32 casts are to silence certain ANSI-C compilers */
84#define TIFFhowmany(x, y) ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y)))
85#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3)
86#define TIFFroundup(x, y) (TIFFhowmany(x,y)*(y))
87
88
89/*
90struct _HPDF_CCITT_Encoder {
91} HPDF_CCITT_Encoder;
92*/
93
94struct _HPDF_CCITT_Data {
95 HPDF_Fax3CodecState *tif_data;
96
97 HPDF_Stream dst;
98
99 tsize_t tif_rawdatasize;/* # of bytes in raw data buffer */
100 tsize_t tif_rawcc; /* bytes unread from raw buffer */
101 tidata_t tif_rawcp; /* current spot in raw buffer */
102 tidata_t tif_rawdata; /* raw data buffer */
103
104} HPDF_CCITT_Data;
105
106static HPDF_STATUS HPDF_InitCCITTFax3(struct _HPDF_CCITT_Data *pData)
107{
108 HPDF_Fax3BaseState* sp;
109 HPDF_Fax3CodecState* esp;
110
111 /*
112 * Allocate state block so tag methods have storage to record values.
113 */
114 pData->tif_data = (HPDF_Fax3CodecState *)
115 malloc(sizeof (HPDF_Fax3CodecState));
116
117 if (pData->tif_data == NULL) {
118 return 1;
119 }
120
121 sp = Fax3State(pData);
122 /* sp->rw_mode = pData->tif_mode; */
123
124 /*
125 * Override parent get/set field methods.
126 */
127 sp->groupoptions = 0;
128 sp->recvparams = 0;
129 sp->subaddress = NULL;
130 sp->faxdcs = NULL;
131
132 esp = EncoderState(pData);
133 esp->refline = NULL;
134 esp->runs = NULL;
135
136 return HPDF_OK;
137}
138
139static HPDF_STATUS HPDF_FreeCCITTFax3(struct _HPDF_CCITT_Data *pData)
140{
141 if(pData->tif_data!=NULL) {
142 HPDF_Fax3CodecState* esp=pData->tif_data;
143 if(esp->refline!=NULL) {
144 free(esp->refline);
145 esp->refline=NULL;
146 }
147 if(esp->runs!=NULL) {
148 free(esp->runs);
149 esp->runs=NULL;
150 }
151 free(pData->tif_data);
152 pData->tif_data=NULL;
153 }
154 if(pData->tif_rawdata!=NULL) {
155 free(pData->tif_rawdata);
156 pData->tif_rawdata=NULL;
157 }
158 return HPDF_OK;
159}
160
161
162/*
163 * Setup G3/G4-related compression/decompression state
164 * before data is processed. This routine is called once
165 * per image -- it sets up different state based on whether
166 * or not decoding or encoding is being done and whether
167 * 1D- or 2D-encoded data is involved.
168 */
169static int
170HPDF_Fax3SetupState(struct _HPDF_CCITT_Data *pData, HPDF_UINT width,
171 HPDF_UINT height,
172 HPDF_UINT line_width)
173{
174 HPDF_Fax3BaseState* sp = Fax3State(pData);
175 HPDF_Fax3CodecState* esp = EncoderState(pData);
176 uint32 rowbytes, rowpixels, nruns;
177
178 HPDF_UNUSED (height);
179
180 rowbytes = line_width;
181 rowpixels = width;
182
183 sp->rowbytes = (uint32) rowbytes;
184 sp->rowpixels = (uint32) rowpixels;
185
186 nruns = 2*TIFFroundup(rowpixels,32);
187 nruns += 3;
188 esp->runs = (uint32*) malloc(2*nruns * sizeof (uint32));
189 if (esp->runs == NULL)
190 return 1;
191 esp->curruns = esp->runs;
192 esp->refruns = esp->runs + nruns;
193
194 /*
195 * 2d encoding requires a scanline
196 * buffer for the ``reference line''; the
197 * scanline against which delta encoding
198 * is referenced. The reference line must
199 * be initialized to be ``white'' (done elsewhere).
200 */
201 esp->refline = (unsigned char*) malloc(rowbytes);
202 if (esp->refline == NULL) {
203 return 1;
204 }
205
206 return HPDF_OK;
207}
208
209/*
210 * Reset encoding state at the start of a strip.
211 */
212static HPDF_STATUS
213HPDF_Fax3PreEncode(struct _HPDF_CCITT_Data *pData/*, tsample_t s*/)
214{
215 HPDF_Fax3CodecState* sp = EncoderState(pData);
216
217 /* assert(sp != NULL); */
218 sp->bit = 8;
219 sp->data = 0;
220 /* sp->tag = G3_1D; */
221 /*
222 * This is necessary for Group 4; otherwise it isn't
223 * needed because the first scanline of each strip ends
224 * up being copied into the refline.
225 */
226 if (sp->refline)
227 memset(sp->refline, 0x00, sp->b.rowbytes);
228 sp->k = sp->maxk = 0;
229 sp->line = 0;
230 return HPDF_OK;
231}
232
233static HPDF_STATUS
234HPDF_CCITT_AppendToStream(HPDF_Stream dst,
235 tidata_t tif_rawdata,
236 tsize_t tif_rawcc)
237{
238 if(HPDF_Stream_Write(dst, tif_rawdata, tif_rawcc)!=HPDF_OK)
239 return 1;
240 return HPDF_OK;
241}
242
243/*
244 * Internal version of TIFFFlushData that can be
245 * called by ``encodestrip routines'' w/o concern
246 * for infinite recursion.
247 */
248static HPDF_STATUS
249HPDF_CCITT_FlushData(struct _HPDF_CCITT_Data *pData)
250{
251 if (pData->tif_rawcc > 0) {
252 /*if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
253 (tif->tif_flags & TIFF_NOBITREV) == 0)
254 TIFFReverseBits((unsigned char *pData->tif_rawdata,
255 pData->tif_rawcc);*/
256 if (HPDF_CCITT_AppendToStream(pData->dst,
257 pData->tif_rawdata, pData->tif_rawcc)!=HPDF_OK)
258 return 1;
259 pData->tif_rawcc = 0;
260 pData->tif_rawcp = pData->tif_rawdata;
261 }
262 return HPDF_OK;
263}
264
265#define HPDF_Fax3FlushBits(tif, sp) { \
266 if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \
267 (void) HPDF_CCITT_FlushData(tif); \
268 *(tif)->tif_rawcp++ = (tidataval_t) (sp)->data; \
269 (tif)->tif_rawcc++; \
270 (sp)->data = 0, (sp)->bit = 8; \
271}
272#define _FlushBits(tif) { \
273 if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \
274 (void) HPDF_CCITT_FlushData(tif); \
275 *(tif)->tif_rawcp++ = (tidataval_t) data; \
276 (tif)->tif_rawcc++; \
277 data = 0, bit = 8; \
278}
279static const int _msbmask[9] =
280 { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
281#define _PutBits(tif, bits, length) { \
282 while (length > bit) { \
283 data |= bits >> (length - bit); \
284 length -= bit; \
285 _FlushBits(tif); \
286 } \
287 data |= (bits & _msbmask[length]) << (bit - length); \
288 bit -= length; \
289 if (bit == 0) \
290 _FlushBits(tif); \
291}
292
293/*
294 * Write a variable-length bit-value to
295 * the output stream. Values are
296 * assumed to be at most 16 bits.
297 */
298static void
299HPDF_Fax3PutBits(struct _HPDF_CCITT_Data *pData, unsigned int bits, unsigned int length)
300{
301 HPDF_Fax3CodecState* sp = EncoderState(pData);
302 unsigned int bit = sp->bit;
303 int data = sp->data;
304
305 _PutBits(pData, bits, length);
306
307 sp->data = data;
308 sp->bit = bit;
309}
310
311/*
312 * Write a code to the output stream.
313 */
314#define putcode(tif, te) HPDF_Fax3PutBits(tif, (te)->code, (te)->length)
315
316
317/*
318 * Write the sequence of codes that describes
319 * the specified span of zero's or one's. The
320 * appropriate table that holds the make-up and
321 * terminating codes is supplied.
322 */
323static void
324putspan(struct _HPDF_CCITT_Data *pData, int32 span, const tableentry* tab)
325{
326 HPDF_Fax3CodecState* sp = EncoderState(pData);
327 unsigned int bit = sp->bit;
328 int data = sp->data;
329 unsigned int code, length;
330
331 while (span >= 2624) {
332 const tableentry* te = &tab[63 + (2560>>6)];
333 code = te->code, length = te->length;
334#ifdef FAX3_DEBUG
335 DEBUG_PRINT("MakeUp", te->runlen);
336#endif
337 _PutBits(pData, code, length);
338 span -= te->runlen;
339 }
340 if (span >= 64) {
341 const tableentry* te = &tab[63 + (span>>6)];
342 assert(te->runlen == 64*(span>>6));
343 code = te->code, length = te->length;
344#ifdef FAX3_DEBUG
345 DEBUG_PRINT("MakeUp", te->runlen);
346#endif
347 _PutBits(pData, code, length);
348 span -= te->runlen;
349 }
350 code = tab[span].code, length = tab[span].length;
351#ifdef FAX3_DEBUG
352 DEBUG_PRINT(" Term", tab[span].runlen);
353#endif
354 _PutBits(pData, code, length);
355
356 sp->data = data;
357 sp->bit = bit;
358}
359
360static const unsigned char zeroruns[256] = {
361 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */
362 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */
363 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */
364 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */
365 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */
366 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */
367 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */
368 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */
369 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
370 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
371 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
372 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
373 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
374 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
375 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
376 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */
377};
378static const unsigned char oneruns[256] = {
379 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */
380 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
381 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
382 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
383 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
384 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
385 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */
386 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
387 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */
388 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */
389 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */
390 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */
391 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */
392 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */
393 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */
394 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */
395};
396
397/*
398 * Find a span of ones or zeros using the supplied
399 * table. The ``base'' of the bit string is supplied
400 * along with the start+end bit indices.
401 */
402static /*inline*/ int32 find0span(unsigned char* bp, int32 bs, int32 be)
403{
404 int32 bits = be - bs;
405 int32 n, span;
406
407 bp += bs>>3;
408 /*
409 * Check partial byte on lhs.
410 */
411 if (bits > 0 && (n = (bs & 7))) {
412 span = zeroruns[(*bp << n) & 0xff];
413 if (span > 8-n) /* table value too generous */
414 span = 8-n;
415 if (span > bits) /* constrain span to bit range */
416 span = bits;
417 if (n+span < 8) /* doesn't extend to edge of byte */
418 return (span);
419 bits -= span;
420 bp++;
421 } else
422 span = 0;
423 if (bits >= (int32)(2 * 8 * sizeof(long))) {
424 long* lp;
425 /*
426 * Align to longword boundary and check longwords.
427 */
428 while (!isAligned(bp, long)) {
429 if (*bp != 0x00)
430 return (span + zeroruns[*bp]);
431 span += 8, bits -= 8;
432 bp++;
433 }
434 lp = (long*) bp;
435 while ((bits >= (int32)(8 * sizeof(long))) && (0 == *lp)) {
436 span += 8*sizeof (long), bits -= 8*sizeof (long);
437 lp++;
438 }
439 bp = (unsigned char*) lp;
440 }
441 /*
442 * Scan full bytes for all 0's.
443 */
444 while (bits >= 8) {
445 if (*bp != 0x00) /* end of run */
446 return (span + zeroruns[*bp]);
447 span += 8, bits -= 8;
448 bp++;
449 }
450 /*
451 * Check partial byte on rhs.
452 */
453 if (bits > 0) {
454 n = zeroruns[*bp];
455 span += (n > bits ? bits : n);
456 }
457 return (span);
458}
459
460static /*inline*/ int32
461find1span(unsigned char* bp, int32 bs, int32 be)
462{
463 int32 bits = be - bs;
464 int32 n, span;
465
466 bp += bs>>3;
467 /*
468 * Check partial byte on lhs.
469 */
470 if (bits > 0 && (n = (bs & 7))) {
471 span = oneruns[(*bp << n) & 0xff];
472 if (span > 8-n) /* table value too generous */
473 span = 8-n;
474 if (span > bits) /* constrain span to bit range */
475 span = bits;
476 if (n+span < 8) /* doesn't extend to edge of byte */
477 return (span);
478 bits -= span;
479 bp++;
480 } else
481 span = 0;
482 if (bits >= (int32)(2 * 8 * sizeof(long))) {
483 long* lp;
484 /*
485 * Align to longword boundary and check longwords.
486 */
487 while (!isAligned(bp, long)) {
488 if (*bp != 0xff)
489 return (span + oneruns[*bp]);
490 span += 8, bits -= 8;
491 bp++;
492 }
493 lp = (long*) bp;
494 while ((bits >= (int32)(8 * sizeof(long))) && (~0 == *lp)) {
495 span += 8*sizeof (long), bits -= 8*sizeof (long);
496 lp++;
497 }
498 bp = (unsigned char*) lp;
499 }
500 /*
501 * Scan full bytes for all 1's.
502 */
503 while (bits >= 8) {
504 if (*bp != 0xff) /* end of run */
505 return (span + oneruns[*bp]);
506 span += 8, bits -= 8;
507 bp++;
508 }
509 /*
510 * Check partial byte on rhs.
511 */
512 if (bits > 0) {
513 n = oneruns[*bp];
514 span += (n > bits ? bits : n);
515 }
516 return (span);
517}
518
519/*
520 * Return the offset of the next bit in the range
521 * [bs..be] that is different from the specified
522 * color. The end, be, is returned if no such bit
523 * exists.
524 */
525#define finddiff(_cp, _bs, _be, _color) \
526 (_bs + (_color ? find1span(_cp,_bs,_be) : find0span(_cp,_bs,_be)))
527/*
528 * Like finddiff, but also check the starting bit
529 * against the end in case start > end.
530 */
531#define finddiff2(_cp, _bs, _be, _color) \
532 (_bs < _be ? finddiff(_cp,_bs,_be,_color) : _be)
533
534
535/*
536void
537HPDF_Fax3PostEncode(struct _HPDF_CCITT_Data *pData)
538{
539 HPDF_Fax3CodecState* sp = EncoderState(pData);
540
541 if (sp->bit != 8)
542 HPDF_Fax3FlushBits(pData, sp);
543}
544*/
545
546static const tableentry horizcode =
547 { 3, 0x1, 0 }; /* 001 */
548static const tableentry passcode =
549 { 4, 0x1, 0 }; /* 0001 */
550static const tableentry vcodes[7] = {
551 { 7, 0x03, 0 }, /* 0000 011 */
552 { 6, 0x03, 0 }, /* 0000 11 */
553 { 3, 0x03, 0 }, /* 011 */
554 { 1, 0x1, 0 }, /* 1 */
555 { 3, 0x2, 0 }, /* 010 */
556 { 6, 0x02, 0 }, /* 0000 10 */
557 { 7, 0x02, 0 } /* 0000 010 */
558};
559
560/*
561 * 2d-encode a row of pixels. Consult the CCITT
562 * documentation for the algorithm.
563 */
564static HPDF_STATUS
565HPDF_Fax3Encode2DRow(struct _HPDF_CCITT_Data *pData, unsigned char* bp, unsigned char* rp, uint32 bits)
566{
567#define PIXEL(buf,ix) ((((buf)[(ix)>>3]) >> (7-((ix)&7))) & 1)
568 uint32 a0 = 0;
569 uint32 a1 = (PIXEL(bp, 0) != 0 ? 0 : finddiff(bp, 0, bits, 0));
570 uint32 b1 = (PIXEL(rp, 0) != 0 ? 0 : finddiff(rp, 0, bits, 0));
571 uint32 a2, b2;
572
573 for (;;) {
574 b2 = finddiff2(rp, b1, bits, PIXEL(rp,b1));
575 if (b2 >= a1) {
576 int32 d = b1 - a1;
577 if (!(-3 <= d && d <= 3)) { /* horizontal mode */
578 a2 = finddiff2(bp, a1, bits, PIXEL(bp,a1));
579 putcode(pData, &horizcode);
580 if (a0+a1 == 0 || PIXEL(bp, a0) == 0) {
581 putspan(pData, a1-a0, TIFFFaxWhiteCodes);
582 putspan(pData, a2-a1, TIFFFaxBlackCodes);
583 } else {
584 putspan(pData, a1-a0, TIFFFaxBlackCodes);
585 putspan(pData, a2-a1, TIFFFaxWhiteCodes);
586 }
587 a0 = a2;
588 } else { /* vertical mode */
589 putcode(pData, &vcodes[d+3]);
590 a0 = a1;
591 }
592 } else { /* pass mode */
593 putcode(pData, &passcode);
594 a0 = b2;
595 }
596 if (a0 >= bits)
597 break;
598 a1 = finddiff(bp, a0, bits, PIXEL(bp,a0));
599 b1 = finddiff(rp, a0, bits, !PIXEL(bp,a0));
600 b1 = finddiff(rp, b1, bits, PIXEL(bp,a0));
601 }
602 return HPDF_OK;
603#undef PIXEL
604}
605
606/*
607 * Encode the requested amount of data.
608 */
609static HPDF_STATUS
610HPDF_Fax4Encode(struct _HPDF_CCITT_Data *pData, tidata_t bp, tsize_t cc/*, tsample_t s*/)
611{
612 HPDF_Fax3CodecState *sp = EncoderState(pData);
613
614 /* (void) s; */
615 while ((long)cc > 0) {
616 if (HPDF_Fax3Encode2DRow(pData, bp, sp->refline, sp->b.rowpixels)!=HPDF_OK)
617 return 1;
618 memcpy(sp->refline, bp, sp->b.rowbytes);
619 bp += sp->b.rowbytes;
620 cc -= sp->b.rowbytes;
621 }
622 return HPDF_OK;
623}
624
625static void
626HPDF_Fax4PostEncode(struct _HPDF_CCITT_Data *pData)
627{
628 /* HPDF_Fax3CodecState *sp = EncoderState(pData); */
629
630 /* terminate strip w/ EOFB */
631 HPDF_Fax3PutBits(pData, EOL, 12);
632 HPDF_Fax3PutBits(pData, EOL, 12);
633 /*if (sp->bit != 8)
634 HPDF_Fax3FlushBits(pData, sp);
635 */
636 HPDF_CCITT_FlushData(pData);
637}
638
639
640
641HPDF_STATUS
642HPDF_Stream_CcittToStream( const HPDF_BYTE *buf,
643 HPDF_Stream dst,
644 HPDF_Encrypt e,
645 HPDF_UINT width,
646 HPDF_UINT height,
647 HPDF_UINT line_width,
648 HPDF_BOOL top_is_first)
649{
650 const HPDF_BYTE *pBufPos;
651 const HPDF_BYTE *pBufEnd; /* end marker */
652 int lineIncrement;
653 struct _HPDF_CCITT_Data data;
654
655 HPDF_UNUSED (e);
656
657 if(height==0) return 1;
658 if(top_is_first) {
659 pBufPos = buf;
660 pBufEnd=buf+(line_width*height);
661 lineIncrement = line_width;
662 } else {
663 pBufPos = buf+(line_width*(height-1));
664 pBufEnd= buf-line_width;
665 lineIncrement = -((int)line_width);
666 }
667
668 memset(&data, 0, sizeof(struct _HPDF_CCITT_Data));
669 data.dst = dst;
670 data.tif_rawdata = (tidata_t) malloc( 16384 ); /* 16 kb buffer */
671 data.tif_rawdatasize = 16384;
672 data.tif_rawcc = 0;
673 data.tif_rawcp = data.tif_rawdata;
674
675 if(HPDF_InitCCITTFax3(&data)!=HPDF_OK)
676 return 1;
677
678 if(HPDF_Fax3SetupState(&data, width, height, line_width)!=HPDF_OK)
679 {
680 HPDF_FreeCCITTFax3(&data);
681 return 1;
682 }
683
684 if(HPDF_Fax3PreEncode(&data)!=HPDF_OK)
685 {
686 HPDF_FreeCCITTFax3(&data);
687 return 1;
688 }
689
690 /* encode data */
691 while(pBufEnd!=pBufPos)
692 {
693 HPDF_Fax4Encode(&data, (tidata_t)pBufPos, line_width);
694 pBufPos+=lineIncrement;
695 }
696
697 HPDF_Fax4PostEncode(&data);
698
699 HPDF_FreeCCITTFax3(&data);
700
701 return HPDF_OK;
702}
703
704HPDF_Image
705HPDF_Image_Load1BitImageFromMem (HPDF_MMgr mmgr,
706 const HPDF_BYTE *buf,
707 HPDF_Xref xref,
708 HPDF_UINT width,
709 HPDF_UINT height,
710 HPDF_UINT line_width,
711 HPDF_BOOL top_is_first
712 )
713{
714 HPDF_Dict image;
715 HPDF_STATUS ret = HPDF_OK;
716 /* HPDF_UINT size; */
717
718 HPDF_PTRACE ((" HPDF_Image_Load1BitImage\n"));
719
720 image = HPDF_DictStream_New (mmgr, xref);
721 if (!image)
722 return NULL;
723
724 image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
725 ret += HPDF_Dict_AddName (image, "Type", "XObject");
726 ret += HPDF_Dict_AddName (image, "Subtype", "Image");
727 if (ret != HPDF_OK)
728 return NULL;
729
730 /* size = width * height; */
731 ret = HPDF_Dict_AddName (image, "ColorSpace", "DeviceGray");
732 if (ret != HPDF_OK)
733 return NULL;
734
735 if (HPDF_Dict_AddNumber (image, "Width", width) != HPDF_OK)
736 return NULL;
737
738 if (HPDF_Dict_AddNumber (image, "Height", height) != HPDF_OK)
739 return NULL;
740
741 if (HPDF_Dict_AddNumber (image, "BitsPerComponent", 1) != HPDF_OK)
742 return NULL;
743
744 if (HPDF_Stream_CcittToStream (buf, image->stream, NULL, width, height, line_width, top_is_first) != HPDF_OK)
745 return NULL;
746
747 return image;
748}
749
750/*
751 * Load image from buffer
752 * line_width - width of the line in bytes
753 * top_is_first - image orientation:
754 * TRUE if image is oriented TOP-BOTTOM;
755 * FALSE if image is oriented BOTTOM-TOP
756 */
757HPDF_EXPORT(HPDF_Image)
758HPDF_Image_LoadRaw1BitImageFromMem (HPDF_Doc pdf,
759 const HPDF_BYTE *buf,
760 HPDF_UINT width,
761 HPDF_UINT height,
762 HPDF_UINT line_width,
763 HPDF_BOOL black_is1,
764 HPDF_BOOL top_is_first)
765{
766 HPDF_Image image;
767
768 HPDF_PTRACE ((" HPDF_Image_Load1BitImageFromMem\n"));
769
770 if (!HPDF_HasDoc (pdf))
771 return NULL;
772
773 image = HPDF_Image_Load1BitImageFromMem(pdf->mmgr, buf, pdf->xref, width,
774 height, line_width, top_is_first);
775
776 if (!image)
777 HPDF_CheckError (&pdf->error);
778
779 if (pdf->compression_mode & HPDF_COMP_IMAGE)
780 {
781 image->filter = HPDF_STREAM_FILTER_CCITT_DECODE;
782 image->filterParams = HPDF_Dict_New(pdf->mmgr);
783 if(image->filterParams==NULL) {
784 return NULL;
785 }
786
787 /* pure 2D encoding, default is 0 */
788 HPDF_Dict_AddNumber (image->filterParams, "K", -1);
789 /* default is 1728 */
790 HPDF_Dict_AddNumber (image->filterParams, "Columns", width);
791 /* default is 0 */
792 HPDF_Dict_AddNumber (image->filterParams, "Rows", height);
793 HPDF_Dict_AddBoolean (image->filterParams, "BlackIs1", black_is1);
794 }
795
796 return image;
797}
798