Leptonica 1.82.0
Image processing and image analysis suite
pdfio2.c
Go to the documentation of this file.
1/*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
94#ifdef HAVE_CONFIG_H
95#include <config_auto.h>
96#endif /* HAVE_CONFIG_H */
97
98#include <string.h>
99#include <math.h>
100#include "allheaders.h"
101
102/* --------------------------------------------*/
103#if USE_PDFIO /* defined in environ.h */
104 /* --------------------------------------------*/
105
106 /* Typical scan resolution in ppi (pixels/inch) */
107static const l_int32 DefaultInputRes = 300;
108
109 /* Static helpers */
110static L_COMP_DATA *l_generateJp2kData(const char *fname);
111static L_COMP_DATA *pixGenerateFlateData(PIX *pixs, l_int32 ascii85flag);
112static L_COMP_DATA *pixGenerateJpegData(PIX *pixs, l_int32 ascii85flag,
113 l_int32 quality);
114static L_COMP_DATA *pixGenerateJp2kData(PIX *pixs, l_int32 quality);
115static L_COMP_DATA *pixGenerateG4Data(PIX *pixs, l_int32 ascii85flag);
116
117static l_int32 l_generatePdf(l_uint8 **pdata, size_t *pnbytes,
118 L_PDF_DATA *lpd);
119static void generateFixedStringsPdf(L_PDF_DATA *lpd);
120static char *generateEscapeString(const char *str);
121static void generateMediaboxPdf(L_PDF_DATA *lpd);
122static l_int32 generatePageStringPdf(L_PDF_DATA *lpd);
123static l_int32 generateContentStringPdf(L_PDF_DATA *lpd);
124static l_int32 generatePreXStringsPdf(L_PDF_DATA *lpd);
125static l_int32 generateColormapStringsPdf(L_PDF_DATA *lpd);
126static void generateTrailerPdf(L_PDF_DATA *lpd);
127static char *makeTrailerStringPdf(L_DNA *daloc);
128static l_int32 generateOutputDataPdf(l_uint8 **pdata, size_t *pnbytes,
129 L_PDF_DATA *lpd);
130
131static l_int32 parseTrailerPdf(L_BYTEA *bas, L_DNA **pda);
132static char *generatePagesObjStringPdf(NUMA *napage);
133static L_BYTEA *substituteObjectNumbers(L_BYTEA *bas, NUMA *na_objs);
134
135static L_PDF_DATA *pdfdataCreate(const char *title);
136static void pdfdataDestroy(L_PDF_DATA **plpd);
137static L_COMP_DATA *pdfdataGetCid(L_PDF_DATA *lpd, l_int32 index);
138
139
140/* ---------------- Defaults for rendering options ----------------- */
141 /* Output G4 as writing through image mask; this is the default */
142static l_int32 var_WRITE_G4_IMAGE_MASK = 1;
143 /* Write date/time and lib version into pdf; this is the default */
144static l_int32 var_WRITE_DATE_AND_VERSION = 1;
145
146#define L_SMALLBUF 256
147#define L_BIGBUF 2048 /* must be able to hold hex colormap */
148
149
150#ifndef NO_CONSOLE_IO
151#define DEBUG_MULTIPAGE 0
152#endif /* ~NO_CONSOLE_IO */
153
154
155/*---------------------------------------------------------------------*
156 * Intermediate function for generating multipage pdf output *
157 *---------------------------------------------------------------------*/
189l_ok
191 l_int32 type,
192 l_int32 quality,
193 l_uint8 **pdata,
194 size_t *pnbytes,
195 l_int32 x,
196 l_int32 y,
197 l_int32 res,
198 const char *title,
199 L_PDF_DATA **plpd,
200 l_int32 position)
201{
202l_int32 pixres, w, h, ret;
203l_float32 xpt, ypt, wpt, hpt;
204L_COMP_DATA *cid = NULL;
205L_PDF_DATA *lpd = NULL;
206
207 PROCNAME("pixConvertToPdfData");
208
209 if (!pdata)
210 return ERROR_INT("&data not defined", procName, 1);
211 *pdata = NULL;
212 if (!pnbytes)
213 return ERROR_INT("&nbytes not defined", procName, 1);
214 *pnbytes = 0;
215 if (!pix)
216 return ERROR_INT("pix not defined", procName, 1);
217 if (type != L_JPEG_ENCODE && type != L_G4_ENCODE &&
218 type != L_FLATE_ENCODE && type != L_JP2K_ENCODE) {
219 selectDefaultPdfEncoding(pix, &type);
220 }
221 if (plpd) { /* part of multi-page invocation */
222 if (position == L_FIRST_IMAGE)
223 *plpd = NULL;
224 }
225
226 /* Generate the compressed image data. It must NOT
227 * be ascii85 encoded. */
228 pixGenerateCIData(pix, type, quality, 0, &cid);
229 if (!cid)
230 return ERROR_INT("cid not made", procName, 1);
231
232 /* Get media box in pts. Guess the input image resolution
233 * based on the input parameter %res, the resolution data in
234 * the pix, and the size of the image. */
235 pixres = cid->res;
236 w = cid->w;
237 h = cid->h;
238 if (res <= 0.0) {
239 if (pixres > 0)
240 res = pixres;
241 else
242 res = DefaultInputRes;
243 }
244 xpt = x * 72. / res;
245 ypt = y * 72. / res;
246 wpt = w * 72. / res;
247 hpt = h * 72. / res;
248
249 /* Set up lpd */
250 if (!plpd) { /* single image */
251 if ((lpd = pdfdataCreate(title)) == NULL)
252 return ERROR_INT("lpd not made", procName, 1);
253 } else if (position == L_FIRST_IMAGE) { /* first of multiple images */
254 if ((lpd = pdfdataCreate(title)) == NULL)
255 return ERROR_INT("lpd not made", procName, 1);
256 *plpd = lpd;
257 } else { /* not the first of multiple images */
258 lpd = *plpd;
259 }
260
261 /* Add the data to the lpd */
262 ptraAdd(lpd->cida, cid);
263 lpd->n++;
264 ptaAddPt(lpd->xy, xpt, ypt);
265 ptaAddPt(lpd->wh, wpt, hpt);
266
267 /* If a single image or the last of multiple images,
268 * generate the pdf and destroy the lpd */
269 if (!plpd || (position == L_LAST_IMAGE)) {
270 ret = l_generatePdf(pdata, pnbytes, lpd);
271 pdfdataDestroy(&lpd);
272 if (plpd) *plpd = NULL;
273 if (ret)
274 return ERROR_INT("pdf output not made", procName, 1);
275 }
276
277 return 0;
278}
279
280
281/*---------------------------------------------------------------------*
282 * Intermediate function for generating multipage pdf output *
283 *---------------------------------------------------------------------*/
320l_ok
322 SARRAY *sa,
323 l_uint8 **pdata,
324 size_t *pnbytes)
325{
326char *fname, *str_pages, *str_trailer;
327l_uint8 *pdfdata, *data;
328l_int32 i, j, index, nobj, npages;
329l_int32 *sizes, *locs;
330size_t size;
331L_BYTEA *bas, *bad, *bat1, *bat2;
332L_DNA *da_locs, *da_sizes, *da_outlocs, *da;
333L_DNAA *daa_locs; /* object locations on each page */
334NUMA *na_objs, *napage;
335NUMAA *naa_objs; /* object mapping numbers to new values */
336
337 PROCNAME("ptraConcatenatePdfToData");
338
339 if (!pdata)
340 return ERROR_INT("&data not defined", procName, 1);
341 *pdata = NULL;
342 if (!pnbytes)
343 return ERROR_INT("&nbytes not defined", procName, 1);
344 *pnbytes = 0;
345 if (!pa_data)
346 return ERROR_INT("pa_data not defined", procName, 1);
347
348 /* Parse the files and find the object locations.
349 * Remove file data that cannot be parsed. */
350 ptraGetActualCount(pa_data, &npages);
351 daa_locs = l_dnaaCreate(npages);
352 for (i = 0; i < npages; i++) {
353 bas = (L_BYTEA *)ptraGetPtrToItem(pa_data, i);
354 if (parseTrailerPdf(bas, &da_locs) != 0) {
355 bas = (L_BYTEA *)ptraRemove(pa_data, i, L_NO_COMPACTION);
356 l_byteaDestroy(&bas);
357 if (sa) {
358 fname = sarrayGetString(sa, i, L_NOCOPY);
359 L_ERROR("can't parse file %s; skipping\n", procName, fname);
360 } else {
361 L_ERROR("can't parse file %d; skipping\n", procName, i);
362 }
363 } else {
364 l_dnaaAddDna(daa_locs, da_locs, L_INSERT);
365 }
366 }
367
368 /* Recompute npages in case some of the files were not pdf */
369 ptraCompactArray(pa_data);
370 ptraGetActualCount(pa_data, &npages);
371 if (npages == 0) {
372 l_dnaaDestroy(&daa_locs);
373 return ERROR_INT("no parsable pdf files found", procName, 1);
374 }
375
376 /* Find the mapping from initial to final object numbers */
377 naa_objs = numaaCreate(npages); /* stores final object numbers */
378 napage = numaCreate(npages); /* stores "Page" object numbers */
379 index = 0;
380 for (i = 0; i < npages; i++) {
381 da = l_dnaaGetDna(daa_locs, i, L_CLONE);
382 nobj = l_dnaGetCount(da);
383 if (i == 0) {
384 numaAddNumber(napage, 4); /* object 4 on first page */
385 na_objs = numaMakeSequence(0.0, 1.0, nobj - 1);
386 index = nobj - 1;
387 } else { /* skip the first 3 objects in each file */
388 numaAddNumber(napage, index); /* Page object is first we add */
389 na_objs = numaMakeConstant(0.0, nobj - 1);
390 numaReplaceNumber(na_objs, 3, 3); /* refers to parent of all */
391 for (j = 4; j < nobj - 1; j++)
392 numaSetValue(na_objs, j, index++);
393 }
394 numaaAddNuma(naa_objs, na_objs, L_INSERT);
395 l_dnaDestroy(&da);
396 }
397
398 /* Make the Pages object (#3) */
399 str_pages = generatePagesObjStringPdf(napage);
400
401 /* Build the output */
402 bad = l_byteaCreate(5000);
403 da_outlocs = l_dnaCreate(0); /* locations of all output objects */
404 for (i = 0; i < npages; i++) {
405 bas = (L_BYTEA *)ptraGetPtrToItem(pa_data, i);
406 pdfdata = l_byteaGetData(bas, &size);
407 da_locs = l_dnaaGetDna(daa_locs, i, L_CLONE); /* locs on this page */
408 na_objs = numaaGetNuma(naa_objs, i, L_CLONE); /* obj # on this page */
409 nobj = l_dnaGetCount(da_locs) - 1;
410 da_sizes = l_dnaDiffAdjValues(da_locs); /* object sizes on this page */
411 sizes = l_dnaGetIArray(da_sizes);
412 locs = l_dnaGetIArray(da_locs);
413 if (i == 0) {
414 l_byteaAppendData(bad, pdfdata, sizes[0]);
415 l_byteaAppendData(bad, pdfdata + locs[1], sizes[1]);
416 l_byteaAppendData(bad, pdfdata + locs[2], sizes[2]);
417 l_byteaAppendString(bad, str_pages);
418 for (j = 0; j < 4; j++)
419 l_dnaAddNumber(da_outlocs, locs[j]);
420 }
421 for (j = 4; j < nobj; j++) {
422 l_dnaAddNumber(da_outlocs, l_byteaGetSize(bad));
423 bat1 = l_byteaInitFromMem(pdfdata + locs[j], sizes[j]);
424 bat2 = substituteObjectNumbers(bat1, na_objs);
425 data = l_byteaGetData(bat2, &size);
426 l_byteaAppendData(bad, data, size);
427 l_byteaDestroy(&bat1);
428 l_byteaDestroy(&bat2);
429 }
430 if (i == npages - 1) /* last one */
431 l_dnaAddNumber(da_outlocs, l_byteaGetSize(bad));
432 LEPT_FREE(sizes);
433 LEPT_FREE(locs);
434 l_dnaDestroy(&da_locs);
435 numaDestroy(&na_objs);
436 l_dnaDestroy(&da_sizes);
437 }
438
439 /* Add the trailer */
440 str_trailer = makeTrailerStringPdf(da_outlocs);
441 l_byteaAppendString(bad, str_trailer);
442
443 /* Transfer the output data */
444 *pdata = l_byteaCopyData(bad, pnbytes);
445 l_byteaDestroy(&bad);
446
447#if DEBUG_MULTIPAGE
448 lept_stderr("******** object mapper **********");
449 numaaWriteStream(stderr, naa_objs);
450
451 lept_stderr("******** Page object numbers ***********");
452 numaWriteStderr(napage);
453
454 lept_stderr("******** Pages object ***********\n");
455 lept_stderr("%s\n", str_pages);
456#endif /* DEBUG_MULTIPAGE */
457
458 numaDestroy(&napage);
459 numaaDestroy(&naa_objs);
460 l_dnaDestroy(&da_outlocs);
461 l_dnaaDestroy(&daa_locs);
462 LEPT_FREE(str_pages);
463 LEPT_FREE(str_trailer);
464 return 0;
465}
466
467
468/*---------------------------------------------------------------------*
469 * Convert tiff multipage to pdf file *
470 *---------------------------------------------------------------------*/
484l_ok
485convertTiffMultipageToPdf(const char *filein,
486 const char *fileout)
487{
488l_int32 istiff;
489PIXA *pixa;
490FILE *fp;
491
492 PROCNAME("convertTiffMultipageToPdf");
493
494 if ((fp = fopenReadStream(filein)) == NULL)
495 return ERROR_INT("file not found", procName, 1);
496 istiff = fileFormatIsTiff(fp);
497 fclose(fp);
498 if (!istiff)
499 return ERROR_INT("file not tiff format", procName, 1);
500
501 pixa = pixaReadMultipageTiff(filein);
502 pixaConvertToPdf(pixa, 0, 1.0, 0, 0, "weasel2", fileout);
503 pixaDestroy(&pixa);
504 return 0;
505}
506
507
508/*---------------------------------------------------------------------*
509 * CID-based operations *
510 *---------------------------------------------------------------------*/
538l_ok
539l_generateCIDataForPdf(const char *fname,
540 PIX *pix,
541 l_int32 quality,
542 L_COMP_DATA **pcid)
543{
544l_int32 format, type;
545L_COMP_DATA *cid;
546PIX *pixt;
547
548 PROCNAME("l_generateCIDataForPdf");
549
550 if (!pcid)
551 return ERROR_INT("&cid not defined", procName, 1);
552 *pcid = cid = NULL;
553 if (!fname && !pix)
554 return ERROR_INT("neither fname nor pix are defined", procName, 1);
555
556 /* If a compressed file is given that is not 'stdin', see if we
557 * can generate the pdf output without transcoding. */
558 if (fname && strcmp(fname, "-") != 0 && strcmp(fname, "stdin") != 0) {
559 findFileFormat(fname, &format);
560 if (format == IFF_UNKNOWN)
561 L_WARNING("file %s format is unknown\n", procName, fname);
562 if (format == IFF_PS || format == IFF_LPDF) {
563 L_ERROR("file %s is unsupported format %d\n",
564 procName, fname, format);
565 return 1;
566 }
567 if (format == IFF_JFIF_JPEG) {
568 cid = l_generateJpegData(fname, 0);
569 } else if (format == IFF_JP2) {
570 cid = l_generateJp2kData(fname);
571 } else if (format == IFF_PNG) {
572 cid = l_generateFlateDataPdf(fname, pix);
573 }
574
575 }
576
577 /* Otherwise, use the pix to generate the pdf output */
578 if (!cid) {
579 if (!pix)
580 pixt = pixRead(fname);
581 else
582 pixt = pixClone(pix);
583 if (!pixt)
584 return ERROR_INT("pixt not made", procName, 1);
585 if (selectDefaultPdfEncoding(pixt, &type)) {
586 pixDestroy(&pixt);
587 return 1;
588 }
589 pixGenerateCIData(pixt, type, quality, 0, &cid);
590 pixDestroy(&pixt);
591 }
592 if (!cid) {
593 L_ERROR("totally kerflummoxed\n", procName);
594 return 1;
595 }
596 *pcid = cid;
597 return 0;
598}
599
600
625l_ok
626l_generateCIData(const char *fname,
627 l_int32 type,
628 l_int32 quality,
629 l_int32 ascii85,
630 L_COMP_DATA **pcid)
631{
632l_int32 format, d, bps, spp, iscmap;
633L_COMP_DATA *cid;
634PIX *pix;
635
636 PROCNAME("l_generateCIData");
637
638 if (!pcid)
639 return ERROR_INT("&cid not defined", procName, 1);
640 *pcid = NULL;
641 if (!fname)
642 return ERROR_INT("fname not defined", procName, 1);
643 if (type != L_G4_ENCODE && type != L_JPEG_ENCODE &&
644 type != L_FLATE_ENCODE && type != L_JP2K_ENCODE)
645 return ERROR_INT("invalid conversion type", procName, 1);
646 if (ascii85 != 0 && ascii85 != 1)
647 return ERROR_INT("invalid ascii85", procName, 1);
648
649 /* Sanity check on requested encoding */
650 pixReadHeader(fname, &format, NULL, NULL, &bps, &spp, &iscmap);
651 d = bps * spp;
652 if (d == 24) d = 32;
653 if (iscmap && type != L_FLATE_ENCODE) {
654 L_WARNING("pixs has cmap; using flate encoding\n", procName);
655 type = L_FLATE_ENCODE;
656 } else if (d < 8 && type == L_JPEG_ENCODE) {
657 L_WARNING("pixs has < 8 bpp; using flate encoding\n", procName);
658 type = L_FLATE_ENCODE;
659 } else if (d < 8 && type == L_JP2K_ENCODE) {
660 L_WARNING("pixs has < 8 bpp; using flate encoding\n", procName);
661 type = L_FLATE_ENCODE;
662 } else if (d > 1 && type == L_G4_ENCODE) {
663 L_WARNING("pixs has > 1 bpp; using flate encoding\n", procName);
664 type = L_FLATE_ENCODE;
665 }
666
667 if (type == L_JPEG_ENCODE) {
668 if (format == IFF_JFIF_JPEG) { /* do not transcode */
669 cid = l_generateJpegData(fname, ascii85);
670 } else {
671 if ((pix = pixRead(fname)) == NULL)
672 return ERROR_INT("pix not returned for JPEG", procName, 1);
673 cid = pixGenerateJpegData(pix, ascii85, quality);
674 pixDestroy(&pix);
675 }
676 if (!cid)
677 return ERROR_INT("jpeg data not made", procName, 1);
678 } else if (type == L_JP2K_ENCODE) {
679 if (format == IFF_JP2) { /* do not transcode */
680 cid = l_generateJp2kData(fname);
681 } else {
682 if ((pix = pixRead(fname)) == NULL)
683 return ERROR_INT("pix not returned for JP2K", procName, 1);
684 cid = pixGenerateJp2kData(pix, quality);
685 pixDestroy(&pix);
686 }
687 if (!cid)
688 return ERROR_INT("jp2k data not made", procName, 1);
689 } else if (type == L_G4_ENCODE) {
690 if ((pix = pixRead(fname)) == NULL)
691 return ERROR_INT("pix not returned for G4", procName, 1);
692 cid = pixGenerateG4Data(pix, ascii85);
693 pixDestroy(&pix);
694 if (!cid)
695 return ERROR_INT("g4 data not made", procName, 1);
696 } else if (type == L_FLATE_ENCODE) {
697 if ((cid = l_generateFlateData(fname, ascii85)) == NULL)
698 return ERROR_INT("flate data not made", procName, 1);
699 } else {
700 return ERROR_INT("invalid conversion type", procName, 1);
701 }
702 *pcid = cid;
703
704 return 0;
705}
706
707
708/*---------------------------------------------------------------------*
709 * Low-level CID-based operations *
710 *---------------------------------------------------------------------*/
730l_generateFlateDataPdf(const char *fname,
731 PIX *pixs)
732{
733l_uint8 *pngcomp = NULL; /* entire PNG compressed file */
734l_uint8 *datacomp = NULL; /* gzipped raster data */
735l_uint8 *cmapdata = NULL; /* uncompressed colormap */
736char *cmapdatahex = NULL; /* hex ascii uncompressed colormap */
737l_uint32 i, j, n;
738l_int32 format, interlaced;
739l_int32 ncolors; /* in colormap */
740l_int32 bps; /* bits/sample: usually 8 */
741l_int32 spp; /* samples/pixel: 1-grayscale/cmap); 3-rgb; 4-rgba */
742l_int32 w, h, cmapflag;
743l_int32 xres, yres;
744size_t nbytescomp = 0, nbytespng = 0;
745FILE *fp;
746L_COMP_DATA *cid;
747PIX *pix;
748PIXCMAP *cmap = NULL;
749
750 PROCNAME("l_generateFlateDataPdf");
751
752 if (!fname)
753 return (L_COMP_DATA *)ERROR_PTR("fname not defined", procName, NULL);
754
755 findFileFormat(fname, &format);
756 spp = 0; /* init to spp != 4 if not png */
757 interlaced = 0; /* initialize to no interlacing */
758 bps = 0; /* initialize to a nonsense value */
759 if (format == IFF_PNG) {
760 isPngInterlaced(fname, &interlaced);
761 if (readHeaderPng(fname, NULL, NULL, &bps, &spp, NULL))
762 return (L_COMP_DATA *)ERROR_PTR("bad png input", procName, NULL);
763 }
764
765 /* PDF is capable of inlining some types of PNG files, but not all
766 of them. We need to transcode anything with interlacing, an
767 alpha channel, or 1 bpp (which would otherwise be photo-inverted).
768
769 Note: any PNG image file with an alpha channel is converted on
770 reading to RGBA (spp == 4). This includes the (gray + alpha) format
771 with spp == 2. Because of the conversion, readHeaderPng() gives
772 spp = 2, whereas pixGetSpp() gives spp = 4 on the converted pix. */
773 if (format != IFF_PNG ||
774 (format == IFF_PNG && (interlaced || bps == 1 || spp == 4 || spp == 2)))
775 { /* lgtm+ analyzer needed the logic expanded */
776 if (!pixs)
777 pix = pixRead(fname);
778 else
779 pix = pixClone(pixs);
780 if (!pix)
781 return (L_COMP_DATA *)ERROR_PTR("pix not made", procName, NULL);
782 cid = pixGenerateFlateData(pix, 0);
783 pixDestroy(&pix);
784 return cid;
785 }
786
787 /* It's png. Generate the pdf data without transcoding.
788 * Implementation by Jeff Breidenbach.
789 * First, read the metadata */
790 if ((fp = fopenReadStream(fname)) == NULL)
791 return (L_COMP_DATA *)ERROR_PTR("stream not opened", procName, NULL);
792 freadHeaderPng(fp, &w, &h, &bps, &spp, &cmapflag);
793 fgetPngResolution(fp, &xres, &yres);
794 fclose(fp);
795
796 /* We get pdf corruption when inlining the data from 16 bpp png. */
797 if (bps == 16)
798 return l_generateFlateData(fname, 0);
799
800 /* Read the entire png file */
801 if ((pngcomp = l_binaryRead(fname, &nbytespng)) == NULL)
802 return (L_COMP_DATA *)ERROR_PTR("unable to read file",
803 procName, NULL);
804
805 /* Extract flate data, copying portions of it to memory, including
806 * the predictor information in a byte at the beginning of each
807 * raster line. The flate data makes up the vast majority of
808 * the png file, so after extraction we expect datacomp to
809 * be nearly full (i.e., nbytescomp will be only slightly less
810 * than nbytespng). Also extract the colormap if present. */
811 if ((datacomp = (l_uint8 *)LEPT_CALLOC(1, nbytespng)) == NULL) {
812 LEPT_FREE(pngcomp);
813 return (L_COMP_DATA *)ERROR_PTR("unable to allocate memory",
814 procName, NULL);
815 }
816
817 /* Parse the png file. Each chunk consists of:
818 * length: 4 bytes
819 * name: 4 bytes (e.g., "IDAT")
820 * data: n bytes
821 * CRC: 4 bytes
822 * Start at the beginning of the data section of the first chunk,
823 * byte 16, because the png file begins with 8 bytes of header,
824 * followed by the first 8 bytes of the first chunk
825 * (length and name). On each loop, increment by 12 bytes to
826 * skip over the CRC, length and name of the next chunk. */
827 for (i = 16; i < nbytespng; i += 12) { /* do each successive chunk */
828 /* Get the chunk length */
829 n = pngcomp[i - 8] << 24;
830 n += pngcomp[i - 7] << 16;
831 n += pngcomp[i - 6] << 8;
832 n += pngcomp[i - 5] << 0;
833 if (n >= nbytespng - i) { /* "n + i" can overflow */
834 LEPT_FREE(pngcomp);
835 LEPT_FREE(datacomp);
836 pixcmapDestroy(&cmap);
837 L_ERROR("invalid png: i = %d, n = %d, nbytes = %zu\n", procName,
838 i, n, nbytespng);
839 return NULL;
840 }
841
842 /* Is it a data chunk? */
843 if (memcmp(pngcomp + i - 4, "IDAT", 4) == 0) {
844 memcpy(datacomp + nbytescomp, pngcomp + i, n);
845 nbytescomp += n;
846 }
847
848 /* Is it a palette chunk? */
849 if (cmapflag && !cmap &&
850 memcmp(pngcomp + i - 4, "PLTE", 4) == 0) {
851 if ((n / 3) > (1 << bps)) {
852 LEPT_FREE(pngcomp);
853 LEPT_FREE(datacomp);
854 pixcmapDestroy(&cmap);
855 L_ERROR("invalid png: i = %d, n = %d, cmapsize = %d\n",
856 procName, i, n, (1 << bps));
857 return NULL;
858 }
859 cmap = pixcmapCreate(bps);
860 for (j = i; j < i + n; j += 3) {
861 pixcmapAddColor(cmap, pngcomp[j], pngcomp[j + 1],
862 pngcomp[j + 2]);
863 }
864 }
865 i += n; /* move to the end of the data chunk */
866 }
867 LEPT_FREE(pngcomp);
868
869 if (nbytescomp == 0) {
870 LEPT_FREE(datacomp);
871 pixcmapDestroy(&cmap);
872 return (L_COMP_DATA *)ERROR_PTR("invalid PNG file", procName, NULL);
873 }
874
875 /* Extract and encode the colormap data as hexascii */
876 ncolors = 0;
877 if (cmap) {
878 pixcmapSerializeToMemory(cmap, 3, &ncolors, &cmapdata);
879 pixcmapDestroy(&cmap);
880 if (!cmapdata) {
881 LEPT_FREE(datacomp);
882 return (L_COMP_DATA *)ERROR_PTR("cmapdata not made",
883 procName, NULL);
884 }
885 cmapdatahex = pixcmapConvertToHex(cmapdata, ncolors);
886 LEPT_FREE(cmapdata);
887 }
888
889 /* Note that this is the only situation where the predictor
890 * field of the CID is set to 1. Adobe's predictor values on
891 * p. 76 of pdf_reference_1-7.pdf give 1 for no predictor and
892 * 10-14 for inline predictors, the specifics of which are
893 * ignored by the pdf interpreter, which just needs to know that
894 * the first byte on each compressed scanline is some predictor
895 * whose type can be inferred from the byte itself. */
896 cid = (L_COMP_DATA *)LEPT_CALLOC(1, sizeof(L_COMP_DATA));
897 cid->datacomp = datacomp;
898 cid->type = L_FLATE_ENCODE;
899 cid->cmapdatahex = cmapdatahex;
900 cid->nbytescomp = nbytescomp;
901 cid->ncolors = ncolors;
902 cid->predictor = TRUE;
903 cid->w = w;
904 cid->h = h;
905 cid->bps = bps;
906 cid->spp = spp;
907 cid->res = xres;
908 return cid;
909}
910
911
929l_generateJpegData(const char *fname,
930 l_int32 ascii85flag)
931{
932char *data85 = NULL; /* ascii85 encoded jpeg compressed file */
933l_uint8 *data = NULL;
934l_int32 w, h, xres, yres, bps, spp;
935size_t nbytes, nbytes85;
936L_COMP_DATA *cid;
937FILE *fp;
938
939 PROCNAME("l_generateJpegData");
940
941 if (!fname)
942 return (L_COMP_DATA *)ERROR_PTR("fname not defined", procName, NULL);
943
944 /* Read the metadata */
945 if (readHeaderJpeg(fname, &w, &h, &spp, NULL, NULL))
946 return (L_COMP_DATA *)ERROR_PTR("bad jpeg metadata", procName, NULL);
947 bps = 8;
948 if ((fp = fopenReadStream(fname)) == NULL)
949 return (L_COMP_DATA *)ERROR_PTR("stream not opened", procName, NULL);
950 fgetJpegResolution(fp, &xres, &yres);
951 fclose(fp);
952
953 /* Read the entire jpeg file. The returned jpeg data in memory
954 * starts with ffd8 and ends with ffd9 */
955 if ((data = l_binaryRead(fname, &nbytes)) == NULL)
956 return (L_COMP_DATA *)ERROR_PTR("data not extracted", procName, NULL);
957
958 /* Optionally, encode the compressed data */
959 if (ascii85flag == 1) {
960 data85 = encodeAscii85(data, nbytes, &nbytes85);
961 LEPT_FREE(data);
962 if (!data85)
963 return (L_COMP_DATA *)ERROR_PTR("data85 not made", procName, NULL);
964 else
965 data85[nbytes85 - 1] = '\0'; /* remove the newline */
966 }
967
968 cid = (L_COMP_DATA *)LEPT_CALLOC(1, sizeof(L_COMP_DATA));
969 if (ascii85flag == 0) {
970 cid->datacomp = data;
971 } else { /* ascii85 */
972 cid->data85 = data85;
973 cid->nbytes85 = nbytes85;
974 }
975 cid->type = L_JPEG_ENCODE;
976 cid->nbytescomp = nbytes;
977 cid->w = w;
978 cid->h = h;
979 cid->bps = bps;
980 cid->spp = spp;
981 cid->res = xres;
982 return cid;
983}
984
985
1003 size_t nbytes,
1004 l_int32 ascii85flag)
1005{
1006char *data85 = NULL; /* ascii85 encoded jpeg compressed file */
1007l_int32 w, h, xres, yres, bps, spp;
1008size_t nbytes85;
1009L_COMP_DATA *cid;
1010
1011 PROCNAME("l_generateJpegDataMem");
1012
1013 if (!data)
1014 return (L_COMP_DATA *)ERROR_PTR("data not defined", procName, NULL);
1015
1016 /* Read the metadata */
1017 if (readHeaderMemJpeg(data, nbytes, &w, &h, &spp, NULL, NULL)) {
1018 LEPT_FREE(data);
1019 return (L_COMP_DATA *)ERROR_PTR("bad jpeg metadata", procName, NULL);
1020 }
1021 bps = 8;
1022 readResolutionMemJpeg(data, nbytes, &xres, &yres);
1023
1024 /* Optionally, encode the compressed data */
1025 if (ascii85flag == 1) {
1026 data85 = encodeAscii85(data, nbytes, &nbytes85);
1027 LEPT_FREE(data);
1028 if (!data85)
1029 return (L_COMP_DATA *)ERROR_PTR("data85 not made", procName, NULL);
1030 else
1031 data85[nbytes85 - 1] = '\0'; /* remove the newline */
1032 }
1033
1034 cid = (L_COMP_DATA *)LEPT_CALLOC(1, sizeof(L_COMP_DATA));
1035 if (ascii85flag == 0) {
1036 cid->datacomp = data;
1037 } else { /* ascii85 */
1038 cid->data85 = data85;
1039 cid->nbytes85 = nbytes85;
1040 }
1041 cid->type = L_JPEG_ENCODE;
1042 cid->nbytescomp = nbytes;
1043 cid->w = w;
1044 cid->h = h;
1045 cid->bps = bps;
1046 cid->spp = spp;
1047 cid->res = xres;
1048 return cid;
1049}
1050
1051
1063static L_COMP_DATA *
1064l_generateJp2kData(const char *fname)
1065{
1066l_int32 w, h, bps, spp, xres, yres;
1067size_t nbytes;
1068L_COMP_DATA *cid;
1069FILE *fp;
1070
1071 PROCNAME("l_generateJp2kData");
1072
1073 if (!fname)
1074 return (L_COMP_DATA *)ERROR_PTR("fname not defined", procName, NULL);
1075
1076 if (readHeaderJp2k(fname, &w, &h, &bps, &spp, NULL))
1077 return (L_COMP_DATA *)ERROR_PTR("bad jp2k metadata", procName, NULL);
1078
1079 /* The returned jp2k data in memory is the entire jp2k file */
1080 cid = (L_COMP_DATA *)LEPT_CALLOC(1, sizeof(L_COMP_DATA));
1081 if ((cid->datacomp = l_binaryRead(fname, &nbytes)) == NULL) {
1082 l_CIDataDestroy(&cid);
1083 return (L_COMP_DATA *)ERROR_PTR("data not extracted", procName, NULL);
1084 }
1085
1086 xres = yres = 0;
1087 if ((fp = fopenReadStream(fname)) != NULL) {
1088 fgetJp2kResolution(fp, &xres, &yres);
1089 fclose(fp);
1090 }
1091 cid->type = L_JP2K_ENCODE;
1092 cid->nbytescomp = nbytes;
1093 cid->w = w;
1094 cid->h = h;
1095 cid->bps = bps;
1096 cid->spp = spp;
1097 cid->res = xres;
1098 return cid;
1099}
1100
1101
1118l_generateG4Data(const char *fname,
1119 l_int32 ascii85flag)
1120{
1121l_uint8 *datacomp = NULL; /* g4 compressed raster data */
1122char *data85 = NULL; /* ascii85 encoded g4 compressed data */
1123l_int32 w, h, xres, yres, npages;
1124l_int32 minisblack; /* TRUE or FALSE */
1125size_t nbytes85, nbytescomp;
1126L_COMP_DATA *cid;
1127FILE *fp;
1128
1129 PROCNAME("l_generateG4Data");
1130
1131 if (!fname)
1132 return (L_COMP_DATA *)ERROR_PTR("fname not defined", procName, NULL);
1133
1134 /* Make sure this is a single page tiff file */
1135 if ((fp = fopenReadStream(fname)) == NULL)
1136 return (L_COMP_DATA *)ERROR_PTR("stream not opened", procName, NULL);
1137 tiffGetCount(fp, &npages);
1138 fclose(fp);
1139 if (npages != 1) {
1140 L_ERROR(" %d page tiff; only works with 1 page\n", procName, npages);
1141 return NULL;
1142 }
1143
1144 /* Read the resolution */
1145 fp = fopenReadStream(fname);
1146 getTiffResolution(fp, &xres, &yres);
1147 fclose(fp);
1148
1149 /* The returned ccitt g4 data in memory is the block of
1150 * bytes in the tiff file, starting after 8 bytes and
1151 * ending before the directory. */
1152 if (extractG4DataFromFile(fname, &datacomp, &nbytescomp,
1153 &w, &h, &minisblack)) {
1154 return (L_COMP_DATA *)ERROR_PTR("datacomp not extracted",
1155 procName, NULL);
1156 }
1157
1158 /* Optionally, encode the compressed data */
1159 if (ascii85flag == 1) {
1160 data85 = encodeAscii85(datacomp, nbytescomp, &nbytes85);
1161 LEPT_FREE(datacomp);
1162 if (!data85)
1163 return (L_COMP_DATA *)ERROR_PTR("data85 not made", procName, NULL);
1164 else
1165 data85[nbytes85 - 1] = '\0'; /* remove the newline */
1166 }
1167
1168 cid = (L_COMP_DATA *)LEPT_CALLOC(1, sizeof(L_COMP_DATA));
1169 if (ascii85flag == 0) {
1170 cid->datacomp = datacomp;
1171 } else { /* ascii85 */
1172 cid->data85 = data85;
1173 cid->nbytes85 = nbytes85;
1174 }
1175 cid->type = L_G4_ENCODE;
1176 cid->nbytescomp = nbytescomp;
1177 cid->w = w;
1178 cid->h = h;
1179 cid->bps = 1;
1180 cid->spp = 1;
1181 cid->minisblack = minisblack;
1182 cid->res = xres;
1183 return cid;
1184}
1185
1186
1206l_ok
1208 l_int32 type,
1209 l_int32 quality,
1210 l_int32 ascii85,
1211 L_COMP_DATA **pcid)
1212{
1213l_int32 d;
1214PIXCMAP *cmap;
1215
1216 PROCNAME("pixGenerateCIData");
1217
1218 if (!pcid)
1219 return ERROR_INT("&cid not defined", procName, 1);
1220 *pcid = NULL;
1221 if (!pixs)
1222 return ERROR_INT("pixs not defined", procName, 1);
1223 if (type != L_G4_ENCODE && type != L_JPEG_ENCODE &&
1224 type != L_FLATE_ENCODE && type != L_JP2K_ENCODE) {
1225 selectDefaultPdfEncoding(pixs, &type);
1226 }
1227 if (ascii85 != 0 && ascii85 != 1)
1228 return ERROR_INT("invalid ascii85", procName, 1);
1229
1230 /* Conditionally modify the encoding type if libz is
1231 * available and the requested library is missing. */
1232#if defined(HAVE_LIBZ)
1233# if !defined(HAVE_LIBJPEG)
1234 if (type == L_JPEG_ENCODE) {
1235 L_WARNING("no libjpeg; using flate encoding\n", procName);
1236 type = L_FLATE_ENCODE;
1237 }
1238# endif /* !defined(HAVE_LIBJPEG) */
1239# if !defined(HAVE_LIBJP2K)
1240 if (type == L_JP2K_ENCODE) {
1241 L_WARNING("no libjp2k; using flate encoding\n", procName);
1242 type = L_FLATE_ENCODE;
1243 }
1244# endif /* !defined(HAVE_LIBJP2K) */
1245# if !defined(HAVE_LIBTIFF)
1246 if (type == L_G4_ENCODE) {
1247 L_WARNING("no libtiff; using flate encoding\n", procName);
1248 type = L_FLATE_ENCODE;
1249 }
1250# endif /* !defined(HAVE_LIBTIFF) */
1251#endif /* defined(HAVE_LIBZ) */
1252
1253 /* Sanity check on requested encoding */
1254 d = pixGetDepth(pixs);
1255 cmap = pixGetColormap(pixs);
1256 if (cmap && type != L_FLATE_ENCODE) {
1257 L_WARNING("pixs has cmap; using flate encoding\n", procName);
1258 type = L_FLATE_ENCODE;
1259 } else if (d < 8 && (type == L_JPEG_ENCODE || type == L_JP2K_ENCODE)) {
1260 L_WARNING("pixs has < 8 bpp; using flate encoding\n", procName);
1261 type = L_FLATE_ENCODE;
1262 } else if (d > 1 && type == L_G4_ENCODE) {
1263 L_WARNING("pixs has > 1 bpp; using flate encoding\n", procName);
1264 type = L_FLATE_ENCODE;
1265 }
1266
1267 if (type == L_JPEG_ENCODE) {
1268 if ((*pcid = pixGenerateJpegData(pixs, ascii85, quality)) == NULL)
1269 return ERROR_INT("jpeg data not made", procName, 1);
1270 } else if (type == L_JP2K_ENCODE) {
1271 if ((*pcid = pixGenerateJp2kData(pixs, quality)) == NULL)
1272 return ERROR_INT("jp2k data not made", procName, 1);
1273 } else if (type == L_G4_ENCODE) {
1274 if ((*pcid = pixGenerateG4Data(pixs, ascii85)) == NULL)
1275 return ERROR_INT("g4 data not made", procName, 1);
1276 } else { /* type == L_FLATE_ENCODE */
1277 if ((*pcid = pixGenerateFlateData(pixs, ascii85)) == NULL)
1278 return ERROR_INT("flate data not made", procName, 1);
1279 }
1280 return 0;
1281}
1282
1283
1305l_generateFlateData(const char *fname,
1306 l_int32 ascii85flag)
1307{
1308L_COMP_DATA *cid;
1309PIX *pixs;
1310
1311 PROCNAME("l_generateFlateData");
1312
1313 if (!fname)
1314 return (L_COMP_DATA *)ERROR_PTR("fname not defined", procName, NULL);
1315
1316 if ((pixs = pixRead(fname)) == NULL)
1317 return (L_COMP_DATA *)ERROR_PTR("pixs not made", procName, NULL);
1318 cid = pixGenerateFlateData(pixs, ascii85flag);
1319 pixDestroy(&pixs);
1320 return cid;
1321}
1322
1323
1341static L_COMP_DATA *
1343 l_int32 ascii85flag)
1344{
1345l_uint8 *data = NULL; /* uncompressed raster data in required format */
1346l_uint8 *datacomp = NULL; /* gzipped raster data */
1347char *data85 = NULL; /* ascii85 encoded gzipped raster data */
1348l_uint8 *cmapdata = NULL; /* uncompressed colormap */
1349char *cmapdata85 = NULL; /* ascii85 encoded uncompressed colormap */
1350char *cmapdatahex = NULL; /* hex ascii uncompressed colormap */
1351l_int32 ncolors; /* in colormap; not used if cmapdata85 is null */
1352l_int32 bps; /* bits/sample: usually 8 */
1353l_int32 spp; /* samples/pixel: 1-grayscale/cmap); 3-rgb */
1354l_int32 w, h, d, cmapflag;
1355size_t ncmapbytes85 = 0;
1356size_t nbytes85 = 0;
1357size_t nbytes, nbytescomp;
1358L_COMP_DATA *cid;
1359PIX *pixt;
1360PIXCMAP *cmap;
1361
1362 PROCNAME("pixGenerateFlateData");
1363
1364 if (!pixs)
1365 return (L_COMP_DATA *)ERROR_PTR("pixs not defined", procName, NULL);
1366
1367 /* Convert the image to one of these 4 types:
1368 * 1 bpp
1369 * 8 bpp, no colormap
1370 * 8 bpp, colormap
1371 * 32 bpp rgb */
1372 pixGetDimensions(pixs, &w, &h, &d);
1373 cmap = pixGetColormap(pixs);
1374 cmapflag = (cmap) ? 1 : 0;
1375 if (d == 2 || d == 4 || d == 16) {
1376 pixt = pixConvertTo8(pixs, cmapflag);
1377 cmap = pixGetColormap(pixt);
1378 d = pixGetDepth(pixt);
1379 } else if (d == 32 && pixGetSpp(pixs) == 4) { /* remove alpha */
1380 pixt = pixAlphaBlendUniform(pixs, 0xffffff00);
1381 } else {
1382 pixt = pixClone(pixs);
1383 }
1384 spp = (d == 32) ? 3 : 1;
1385 bps = (d == 32) ? 8 : d;
1386
1387 /* Extract and encode the colormap data as both ascii85 and hexascii */
1388 ncolors = 0;
1389 if (cmap) {
1390 pixcmapSerializeToMemory(cmap, 3, &ncolors, &cmapdata);
1391 if (!cmapdata) {
1392 pixDestroy(&pixt);
1393 return (L_COMP_DATA *)ERROR_PTR("cmapdata not made",
1394 procName, NULL);
1395 }
1396
1397 cmapdata85 = encodeAscii85(cmapdata, 3 * ncolors, &ncmapbytes85);
1398 cmapdatahex = pixcmapConvertToHex(cmapdata, ncolors);
1399 LEPT_FREE(cmapdata);
1400 }
1401
1402 /* Extract and compress the raster data */
1403 pixGetRasterData(pixt, &data, &nbytes);
1404 pixDestroy(&pixt);
1405 datacomp = zlibCompress(data, nbytes, &nbytescomp);
1406 LEPT_FREE(data);
1407 if (!datacomp) {
1408 LEPT_FREE(cmapdata85);
1409 LEPT_FREE(cmapdatahex);
1410 return (L_COMP_DATA *)ERROR_PTR("datacomp not made", procName, NULL);
1411 }
1412
1413 /* Optionally, encode the compressed data */
1414 if (ascii85flag == 1) {
1415 data85 = encodeAscii85(datacomp, nbytescomp, &nbytes85);
1416 LEPT_FREE(datacomp);
1417 if (!data85) {
1418 LEPT_FREE(cmapdata85);
1419 LEPT_FREE(cmapdatahex);
1420 return (L_COMP_DATA *)ERROR_PTR("data85 not made", procName, NULL);
1421 } else {
1422 data85[nbytes85 - 1] = '\0'; /* remove the newline */
1423 }
1424 }
1425
1426 cid = (L_COMP_DATA *)LEPT_CALLOC(1, sizeof(L_COMP_DATA));
1427 if (ascii85flag == 0) {
1428 cid->datacomp = datacomp;
1429 } else { /* ascii85 */
1430 cid->data85 = data85;
1431 cid->nbytes85 = nbytes85;
1432 }
1433 cid->type = L_FLATE_ENCODE;
1434 cid->cmapdatahex = cmapdatahex;
1435 cid->cmapdata85 = cmapdata85;
1436 cid->nbytescomp = nbytescomp;
1437 cid->ncolors = ncolors;
1438 cid->w = w;
1439 cid->h = h;
1440 cid->bps = bps;
1441 cid->spp = spp;
1442 cid->res = pixGetXRes(pixs);
1443 cid->nbytes = nbytes; /* only for debugging */
1444 return cid;
1445}
1446
1447
1463static L_COMP_DATA *
1465 l_int32 ascii85flag,
1466 l_int32 quality)
1467{
1468l_int32 d;
1469char *fname;
1470L_COMP_DATA *cid;
1471
1472 PROCNAME("pixGenerateJpegData");
1473
1474 if (!pixs)
1475 return (L_COMP_DATA *)ERROR_PTR("pixs not defined", procName, NULL);
1476 if (pixGetColormap(pixs))
1477 return (L_COMP_DATA *)ERROR_PTR("pixs has colormap", procName, NULL);
1478 d = pixGetDepth(pixs);
1479 if (d != 8 && d != 32)
1480 return (L_COMP_DATA *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
1481
1482 /* Compress to a temp jpeg file */
1483 fname = l_makeTempFilename();
1484 if (pixWriteJpeg(fname, pixs, quality, 0)) {
1485 LEPT_FREE(fname);
1486 return NULL;
1487 }
1488
1489 /* Generate the data */
1490 cid = l_generateJpegData(fname, ascii85flag);
1491 if (lept_rmfile(fname) != 0)
1492 L_ERROR("temp file %s was not deleted\n", procName, fname);
1493 LEPT_FREE(fname);
1494 return cid;
1495}
1496
1497
1512static L_COMP_DATA *
1514 l_int32 quality)
1515{
1516l_int32 d;
1517char *fname;
1518L_COMP_DATA *cid;
1519
1520 PROCNAME("pixGenerateJp2kData");
1521
1522 if (!pixs)
1523 return (L_COMP_DATA *)ERROR_PTR("pixs not defined", procName, NULL);
1524 if (pixGetColormap(pixs))
1525 return (L_COMP_DATA *)ERROR_PTR("pixs has colormap", procName, NULL);
1526 d = pixGetDepth(pixs);
1527 if (d != 8 && d != 32)
1528 return (L_COMP_DATA *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
1529
1530 /* Compress to a temp jp2k file */
1531 fname = l_makeTempFilename();
1532 if (pixWriteJp2k(fname, pixs, quality, 5, 0, 0)) {
1533 LEPT_FREE(fname);
1534 return NULL;
1535 }
1536
1537 /* Generate the data */
1538 cid = l_generateJp2kData(fname);
1539 if (lept_rmfile(fname) != 0)
1540 L_ERROR("temp file %s was not deleted\n", procName, fname);
1541 LEPT_FREE(fname);
1542 return cid;
1543}
1544
1545
1560static L_COMP_DATA *
1562 l_int32 ascii85flag)
1563{
1564char *fname;
1565L_COMP_DATA *cid;
1566
1567 PROCNAME("pixGenerateG4Data");
1568
1569 if (!pixs)
1570 return (L_COMP_DATA *)ERROR_PTR("pixs not defined", procName, NULL);
1571 if (pixGetDepth(pixs) != 1)
1572 return (L_COMP_DATA *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
1573 if (pixGetColormap(pixs))
1574 return (L_COMP_DATA *)ERROR_PTR("pixs has colormap", procName, NULL);
1575
1576 /* Compress to a temp tiff g4 file */
1577 fname = l_makeTempFilename();
1578 if (pixWrite(fname, pixs, IFF_TIFF_G4)) {
1579 LEPT_FREE(fname);
1580 return NULL;
1581 }
1582
1583 cid = l_generateG4Data(fname, ascii85flag);
1584 if (lept_rmfile(fname) != 0)
1585 L_ERROR("temp file %s was not deleted\n", procName, fname);
1586 LEPT_FREE(fname);
1587 return cid;
1588}
1589
1590
1606l_ok
1608 const char *title,
1609 l_uint8 **pdata,
1610 size_t *pnbytes)
1611{
1612l_int32 res, ret;
1613l_float32 wpt, hpt;
1614L_PDF_DATA *lpd = NULL;
1615
1616 PROCNAME("cidConvertToPdfData");
1617
1618 if (!pdata || !pnbytes)
1619 return ERROR_INT("&data and &nbytes not both defined", procName, 1);
1620 *pdata = NULL;
1621 *pnbytes = 0;
1622 if (!cid)
1623 return ERROR_INT("cid not defined", procName, 1);
1624
1625 /* Get media box parameters, in pts */
1626 res = cid->res;
1627 if (res <= 0)
1628 res = DefaultInputRes;
1629 wpt = cid->w * 72. / res;
1630 hpt = cid->h * 72. / res;
1631
1632 /* Set up the pdf data struct (lpd) */
1633 if ((lpd = pdfdataCreate(title)) == NULL)
1634 return ERROR_INT("lpd not made", procName, 1);
1635 ptraAdd(lpd->cida, cid);
1636 lpd->n++;
1637 ptaAddPt(lpd->xy, 0, 0); /* xpt = ypt = 0 */
1638 ptaAddPt(lpd->wh, wpt, hpt);
1639
1640 /* Generate the pdf string and destroy the lpd */
1641 ret = l_generatePdf(pdata, pnbytes, lpd);
1642 pdfdataDestroy(&lpd);
1643 if (ret)
1644 return ERROR_INT("pdf output not made", procName, 1);
1645 return 0;
1646}
1647
1648
1655void
1657{
1658L_COMP_DATA *cid;
1659
1660 PROCNAME("l_CIDataDestroy");
1661
1662 if (pcid == NULL) {
1663 L_WARNING("ptr address is null!\n", procName);
1664 return;
1665 }
1666 if ((cid = *pcid) == NULL)
1667 return;
1668
1669 if (cid->datacomp) LEPT_FREE(cid->datacomp);
1670 if (cid->data85) LEPT_FREE(cid->data85);
1671 if (cid->cmapdata85) LEPT_FREE(cid->cmapdata85);
1672 if (cid->cmapdatahex) LEPT_FREE(cid->cmapdatahex);
1673 LEPT_FREE(cid);
1674 *pcid = NULL;
1675}
1676
1677
1678/*---------------------------------------------------------------------*
1679 * Helper functions for generating the output pdf string *
1680 *---------------------------------------------------------------------*/
1702static l_int32
1703l_generatePdf(l_uint8 **pdata,
1704 size_t *pnbytes,
1705 L_PDF_DATA *lpd)
1706{
1707 PROCNAME("l_generatePdf");
1708
1709 if (!pdata)
1710 return ERROR_INT("&data not defined", procName, 1);
1711 *pdata = NULL;
1712 if (!pnbytes)
1713 return ERROR_INT("&nbytes not defined", procName, 1);
1714 *pnbytes = 0;
1715 if (!lpd)
1716 return ERROR_INT("lpd not defined", procName, 1);
1717
1718 generateFixedStringsPdf(lpd);
1719 generateMediaboxPdf(lpd);
1720 generatePageStringPdf(lpd);
1721 generateContentStringPdf(lpd);
1722 generatePreXStringsPdf(lpd);
1723 generateColormapStringsPdf(lpd);
1724 generateTrailerPdf(lpd);
1725 return generateOutputDataPdf(pdata, pnbytes, lpd);
1726}
1727
1728
1729static void
1730generateFixedStringsPdf(L_PDF_DATA *lpd)
1731{
1732char buf[L_SMALLBUF];
1733char *version, *datestr;
1734SARRAY *sa;
1735
1736 PROCNAME("generateFixedStringsPdf");
1737
1738 /* Accumulate data for the header and objects 1-3 */
1739 lpd->id = stringNew("%PDF-1.5\n");
1740 l_dnaAddNumber(lpd->objsize, strlen(lpd->id));
1741
1742 lpd->obj1 = stringNew("1 0 obj\n"
1743 "<<\n"
1744 "/Type /Catalog\n"
1745 "/Pages 3 0 R\n"
1746 ">>\n"
1747 "endobj\n");
1748 l_dnaAddNumber(lpd->objsize, strlen(lpd->obj1));
1749
1750 sa = sarrayCreate(0);
1751 sarrayAddString(sa, "2 0 obj\n"
1752 "<<\n", L_COPY);
1753 if (var_WRITE_DATE_AND_VERSION) {
1754 datestr = l_getFormattedDate();
1755 snprintf(buf, sizeof(buf), "/CreationDate (D:%s)\n", datestr);
1756 sarrayAddString(sa, buf, L_COPY);
1757 LEPT_FREE(datestr);
1758 version = getLeptonicaVersion();
1759 snprintf(buf, sizeof(buf),
1760 "/Producer (leptonica: %s)\n", version);
1761 LEPT_FREE(version);
1762 } else {
1763 snprintf(buf, sizeof(buf), "/Producer (leptonica)\n");
1764 }
1765 sarrayAddString(sa, buf, L_COPY);
1766 if (lpd->title) {
1767 char *hexstr;
1768 if ((hexstr = generateEscapeString(lpd->title)) != NULL) {
1769 snprintf(buf, sizeof(buf), "/Title %s\n", hexstr);
1770 sarrayAddString(sa, buf, L_COPY);
1771 } else {
1772 L_ERROR("title string is not ascii\n", procName);
1773 }
1774 LEPT_FREE(hexstr);
1775 }
1776 sarrayAddString(sa, ">>\n"
1777 "endobj\n", L_COPY);
1778 lpd->obj2 = sarrayToString(sa, 0);
1779 l_dnaAddNumber(lpd->objsize, strlen(lpd->obj2));
1780 sarrayDestroy(&sa);
1781
1782 lpd->obj3 = stringNew("3 0 obj\n"
1783 "<<\n"
1784 "/Type /Pages\n"
1785 "/Kids [ 4 0 R ]\n"
1786 "/Count 1\n"
1787 ">>\n");
1788 l_dnaAddNumber(lpd->objsize, strlen(lpd->obj3));
1789
1790 /* Do the post-datastream string */
1791 lpd->poststream = stringNew("\n"
1792 "endstream\n"
1793 "endobj\n");
1794}
1795
1796
1814static char *
1815generateEscapeString(const char *str)
1816{
1817char smallbuf[8];
1818char *buffer;
1819l_int32 i, nchar, buflen;
1820
1821 PROCNAME("generateEscapeString");
1822
1823 if (!str)
1824 return (char *)ERROR_PTR("str not defined", procName, NULL);
1825 nchar = strlen(str);
1826 for (i = 0; i < nchar; i++) {
1827 if (str[i] < 0)
1828 return (char *)ERROR_PTR("str not all ascii", procName, NULL);
1829 }
1830
1831 buflen = 4 * nchar + 10;
1832 buffer = (char *)LEPT_CALLOC(buflen, sizeof(char));
1833 stringCat(buffer, buflen, "<feff");
1834 for (i = 0; i < nchar; i++) {
1835 snprintf(smallbuf, sizeof(smallbuf), "%04x", str[i]);
1836 stringCat(buffer, buflen, smallbuf);
1837 }
1838 stringCat(buffer, buflen, ">");
1839 return buffer;
1840}
1841
1842
1843static void
1844generateMediaboxPdf(L_PDF_DATA *lpd)
1845{
1846l_int32 i;
1847l_float32 xpt, ypt, wpt, hpt, maxx, maxy;
1848
1849 /* First get the full extent of all the images.
1850 * This is the mediabox, in pts. */
1851 maxx = maxy = 0;
1852 for (i = 0; i < lpd->n; i++) {
1853 ptaGetPt(lpd->xy, i, &xpt, &ypt);
1854 ptaGetPt(lpd->wh, i, &wpt, &hpt);
1855 maxx = L_MAX(maxx, xpt + wpt);
1856 maxy = L_MAX(maxy, ypt + hpt);
1857 }
1858
1859 lpd->mediabox = boxCreate(0, 0, (l_int32)(maxx + 0.5),
1860 (l_int32)(maxy + 0.5));
1861
1862 /* ypt is in standard image coordinates: the location of
1863 * the UL image corner with respect to the UL media box corner.
1864 * Rewrite each ypt for PostScript coordinates: the location of
1865 * the LL image corner with respect to the LL media box corner. */
1866 for (i = 0; i < lpd->n; i++) {
1867 ptaGetPt(lpd->xy, i, &xpt, &ypt);
1868 ptaGetPt(lpd->wh, i, &wpt, &hpt);
1869 ptaSetPt(lpd->xy, i, xpt, maxy - ypt - hpt);
1870 }
1871}
1872
1873
1874static l_int32
1875generatePageStringPdf(L_PDF_DATA *lpd)
1876{
1877char *buf;
1878char *xstr;
1879l_int32 bufsize, i, wpt, hpt;
1880SARRAY *sa;
1881
1882 PROCNAME("generatePageStringPdf");
1883
1884 /* Allocate 1000 bytes for the boilerplate text, and
1885 * 50 bytes for each reference to an image in the
1886 * ProcSet array. */
1887 bufsize = 1000 + 50 * lpd->n;
1888 if ((buf = (char *)LEPT_CALLOC(bufsize, sizeof(char))) == NULL)
1889 return ERROR_INT("calloc fail for buf", procName, 1);
1890
1891 boxGetGeometry(lpd->mediabox, NULL, NULL, &wpt, &hpt);
1892 sa = sarrayCreate(lpd->n);
1893 for (i = 0; i < lpd->n; i++) {
1894 snprintf(buf, bufsize, "/Im%d %d 0 R ", i + 1, 6 + i);
1895 sarrayAddString(sa, buf, L_COPY);
1896 }
1897 xstr = sarrayToString(sa, 0);
1898 sarrayDestroy(&sa);
1899 if (!xstr) {
1900 LEPT_FREE(buf);
1901 return ERROR_INT("xstr not made", procName, 1);
1902 }
1903
1904 snprintf(buf, bufsize, "4 0 obj\n"
1905 "<<\n"
1906 "/Type /Page\n"
1907 "/Parent 3 0 R\n"
1908 "/MediaBox [%d %d %d %d]\n"
1909 "/Contents 5 0 R\n"
1910 "/Resources\n"
1911 "<<\n"
1912 "/XObject << %s >>\n"
1913 "/ProcSet [ /ImageB /ImageI /ImageC ]\n"
1914 ">>\n"
1915 ">>\n"
1916 "endobj\n",
1917 0, 0, wpt, hpt, xstr);
1918
1919 lpd->obj4 = stringNew(buf);
1920 l_dnaAddNumber(lpd->objsize, strlen(lpd->obj4));
1921 sarrayDestroy(&sa);
1922 LEPT_FREE(buf);
1923 LEPT_FREE(xstr);
1924 return 0;
1925}
1926
1927
1928static l_int32
1929generateContentStringPdf(L_PDF_DATA *lpd)
1930{
1931char *buf;
1932char *cstr;
1933l_int32 i, bufsize;
1934l_float32 xpt, ypt, wpt, hpt;
1935SARRAY *sa;
1936
1937 PROCNAME("generateContentStringPdf");
1938
1939 bufsize = 1000 + 200 * lpd->n;
1940 if ((buf = (char *)LEPT_CALLOC(bufsize, sizeof(char))) == NULL)
1941 return ERROR_INT("calloc fail for buf", procName, 1);
1942
1943 sa = sarrayCreate(lpd->n);
1944 for (i = 0; i < lpd->n; i++) {
1945 ptaGetPt(lpd->xy, i, &xpt, &ypt);
1946 ptaGetPt(lpd->wh, i, &wpt, &hpt);
1947 snprintf(buf, bufsize,
1948 "q %.4f %.4f %.4f %.4f %.4f %.4f cm /Im%d Do Q\n",
1949 wpt, 0.0, 0.0, hpt, xpt, ypt, i + 1);
1950 sarrayAddString(sa, buf, L_COPY);
1951 }
1952 cstr = sarrayToString(sa, 0);
1953 sarrayDestroy(&sa);
1954 if (!cstr) {
1955 LEPT_FREE(buf);
1956 return ERROR_INT("cstr not made", procName, 1);
1957 }
1958
1959 snprintf(buf, bufsize, "5 0 obj\n"
1960 "<< /Length %d >>\n"
1961 "stream\n"
1962 "%s"
1963 "endstream\n"
1964 "endobj\n",
1965 (l_int32)strlen(cstr), cstr);
1966
1967 lpd->obj5 = stringNew(buf);
1968 l_dnaAddNumber(lpd->objsize, strlen(lpd->obj5));
1969 sarrayDestroy(&sa);
1970 LEPT_FREE(buf);
1971 LEPT_FREE(cstr);
1972 return 0;
1973}
1974
1975
1976static l_int32
1977generatePreXStringsPdf(L_PDF_DATA *lpd)
1978{
1979char buff[256];
1980char buf[L_BIGBUF];
1981char *cstr, *bstr, *fstr, *pstr, *xstr, *photometry;
1982l_int32 i, cmindex;
1983L_COMP_DATA *cid;
1984SARRAY *sa;
1985
1986 PROCNAME("generatePreXStringsPdf");
1987
1988 sa = lpd->saprex;
1989 cmindex = 6 + lpd->n; /* starting value */
1990 for (i = 0; i < lpd->n; i++) {
1991 pstr = cstr = NULL;
1992 if ((cid = pdfdataGetCid(lpd, i)) == NULL)
1993 return ERROR_INT("cid not found", procName, 1);
1994
1995 if (cid->type == L_G4_ENCODE) {
1996 if (var_WRITE_G4_IMAGE_MASK) {
1997 cstr = stringNew("/ImageMask true\n"
1998 "/ColorSpace /DeviceGray");
1999 } else {
2000 cstr = stringNew("/ColorSpace /DeviceGray");
2001 }
2002 bstr = stringNew("/BitsPerComponent 1\n"
2003 "/Interpolate true");
2004 /* Note: the reversal is deliberate */
2005 photometry = (cid->minisblack) ? stringNew("true")
2006 : stringNew("false");
2007 snprintf(buff, sizeof(buff),
2008 "/Filter /CCITTFaxDecode\n"
2009 "/DecodeParms\n"
2010 "<<\n"
2011 "/BlackIs1 %s\n"
2012 "/K -1\n"
2013 "/Columns %d\n"
2014 ">>", photometry, cid->w);
2015 fstr = stringNew(buff);
2016 LEPT_FREE(photometry);
2017 } else if (cid->type == L_JPEG_ENCODE) {
2018 if (cid->spp == 1)
2019 cstr = stringNew("/ColorSpace /DeviceGray");
2020 else if (cid->spp == 3)
2021 cstr = stringNew("/ColorSpace /DeviceRGB");
2022 else if (cid->spp == 4) /* pdf supports cmyk */
2023 cstr = stringNew("/ColorSpace /DeviceCMYK");
2024 else
2025 L_ERROR("in jpeg: spp != 1, 3 or 4\n", procName);
2026 bstr = stringNew("/BitsPerComponent 8");
2027 fstr = stringNew("/Filter /DCTDecode");
2028 } else if (cid->type == L_JP2K_ENCODE) {
2029 if (cid->spp == 1)
2030 cstr = stringNew("/ColorSpace /DeviceGray");
2031 else if (cid->spp == 3)
2032 cstr = stringNew("/ColorSpace /DeviceRGB");
2033 else
2034 L_ERROR("in jp2k: spp != 1 && spp != 3\n", procName);
2035 bstr = stringNew("/BitsPerComponent 8");
2036 fstr = stringNew("/Filter /JPXDecode");
2037 } else { /* type == L_FLATE_ENCODE */
2038 if (cid->ncolors > 0) { /* cmapped */
2039 snprintf(buff, sizeof(buff), "/ColorSpace %d 0 R", cmindex++);
2040 cstr = stringNew(buff);
2041 } else {
2042 if (cid->spp == 1 && cid->bps == 1)
2043 cstr = stringNew("/ColorSpace /DeviceGray\n"
2044 "/Decode [1 0]");
2045 else if (cid->spp == 1) /* 8 bpp */
2046 cstr = stringNew("/ColorSpace /DeviceGray");
2047 else if (cid->spp == 3)
2048 cstr = stringNew("/ColorSpace /DeviceRGB");
2049 else
2050 L_ERROR("unknown colorspace: spp = %d\n",
2051 procName, cid->spp);
2052 }
2053 snprintf(buff, sizeof(buff), "/BitsPerComponent %d", cid->bps);
2054 bstr = stringNew(buff);
2055 fstr = stringNew("/Filter /FlateDecode");
2056 if (cid->predictor == TRUE) {
2057 snprintf(buff, sizeof(buff),
2058 "/DecodeParms\n"
2059 "<<\n"
2060 " /Columns %d\n"
2061 " /Predictor 14\n"
2062 " /Colors %d\n"
2063 " /BitsPerComponent %d\n"
2064 ">>\n", cid->w, cid->spp, cid->bps);
2065 pstr = stringNew(buff);
2066 }
2067 }
2068 if (!pstr) /* no decode parameters */
2069 pstr = stringNew("");
2070
2071 snprintf(buf, sizeof(buf),
2072 "%d 0 obj\n"
2073 "<<\n"
2074 "/Length %zu\n"
2075 "/Subtype /Image\n"
2076 "%s\n" /* colorspace */
2077 "/Width %d\n"
2078 "/Height %d\n"
2079 "%s\n" /* bits/component */
2080 "%s\n" /* filter */
2081 "%s" /* decode parms; can be empty */
2082 ">>\n"
2083 "stream\n",
2084 6 + i, cid->nbytescomp, cstr,
2085 cid->w, cid->h, bstr, fstr, pstr);
2086 xstr = stringNew(buf);
2087 sarrayAddString(sa, xstr, L_INSERT);
2089 strlen(xstr) + cid->nbytescomp + strlen(lpd->poststream));
2090 LEPT_FREE(cstr);
2091 LEPT_FREE(bstr);
2092 LEPT_FREE(fstr);
2093 LEPT_FREE(pstr);
2094 }
2095
2096 return 0;
2097}
2098
2099
2100static l_int32
2101generateColormapStringsPdf(L_PDF_DATA *lpd)
2102{
2103char buf[L_BIGBUF];
2104char *cmstr;
2105l_int32 i, cmindex, ncmap;
2106L_COMP_DATA *cid;
2107SARRAY *sa;
2108
2109 PROCNAME("generateColormapStringsPdf");
2110
2111 /* In our canonical format, we have 5 objects, followed
2112 * by n XObjects, followed by m colormaps, so the index of
2113 * the first colormap object is 6 + n. */
2114 sa = lpd->sacmap;
2115 cmindex = 6 + lpd->n; /* starting value */
2116 ncmap = 0;
2117 for (i = 0; i < lpd->n; i++) {
2118 if ((cid = pdfdataGetCid(lpd, i)) == NULL)
2119 return ERROR_INT("cid not found", procName, 1);
2120 if (cid->ncolors == 0) continue;
2121
2122 ncmap++;
2123 snprintf(buf, sizeof(buf), "%d 0 obj\n"
2124 "[ /Indexed /DeviceRGB\n"
2125 "%d\n"
2126 "%s\n"
2127 "]\n"
2128 "endobj\n",
2129 cmindex, cid->ncolors - 1, cid->cmapdatahex);
2130 cmindex++;
2131 cmstr = stringNew(buf);
2132 l_dnaAddNumber(lpd->objsize, strlen(cmstr));
2133 sarrayAddString(sa, cmstr, L_INSERT);
2134 }
2135
2136 lpd->ncmap = ncmap;
2137 return 0;
2138}
2139
2140
2141static void
2142generateTrailerPdf(L_PDF_DATA *lpd)
2143{
2144l_int32 i, n, size, linestart;
2145L_DNA *daloc, *dasize;
2146
2147 /* Let nobj be the number of numbered objects. These numbered
2148 * objects are indexed by their pdf number in arrays naloc[]
2149 * and nasize[]. The 0th object is the 9 byte header. Then
2150 * the number of objects in nasize, which includes the header,
2151 * is n = nobj + 1. The array naloc[] has n + 1 elements,
2152 * because it includes as the last element the starting
2153 * location of xref. The indexing of these objects, their
2154 * starting locations and sizes are:
2155 *
2156 * Object number Starting location Size
2157 * ------------- ----------------- --------------
2158 * 0 daloc[0] = 0 dasize[0] = 9
2159 * 1 daloc[1] = 9 dasize[1] = 49
2160 * n daloc[n] dasize[n]
2161 * xref daloc[n+1]
2162 *
2163 * We first generate daloc.
2164 */
2165 dasize = lpd->objsize;
2166 daloc = lpd->objloc;
2167 linestart = 0;
2168 l_dnaAddNumber(daloc, linestart); /* header */
2169 n = l_dnaGetCount(dasize);
2170 for (i = 0; i < n; i++) {
2171 l_dnaGetIValue(dasize, i, &size);
2172 linestart += size;
2173 l_dnaAddNumber(daloc, linestart);
2174 }
2175 l_dnaGetIValue(daloc, n, &lpd->xrefloc); /* save it */
2176
2177 /* Now make the actual trailer string */
2178 lpd->trailer = makeTrailerStringPdf(daloc);
2179}
2180
2181
2182static char *
2183makeTrailerStringPdf(L_DNA *daloc)
2184{
2185char *outstr;
2186char buf[L_BIGBUF];
2187l_int32 i, n, linestart, xrefloc;
2188SARRAY *sa;
2189
2190 PROCNAME("makeTrailerStringPdf");
2191
2192 if (!daloc)
2193 return (char *)ERROR_PTR("daloc not defined", procName, NULL);
2194 n = l_dnaGetCount(daloc) - 1; /* numbered objects + 1 (yes, +1) */
2195
2196 sa = sarrayCreate(0);
2197 snprintf(buf, sizeof(buf), "xref\n"
2198 "0 %d\n"
2199 "0000000000 65535 f \n", n);
2200 sarrayAddString(sa, buf, L_COPY);
2201 for (i = 1; i < n; i++) {
2202 l_dnaGetIValue(daloc, i, &linestart);
2203 snprintf(buf, sizeof(buf), "%010d 00000 n \n", linestart);
2204 sarrayAddString(sa, buf, L_COPY);
2205 }
2206
2207 l_dnaGetIValue(daloc, n, &xrefloc);
2208 snprintf(buf, sizeof(buf), "trailer\n"
2209 "<<\n"
2210 "/Size %d\n"
2211 "/Root 1 0 R\n"
2212 "/Info 2 0 R\n"
2213 ">>\n"
2214 "startxref\n"
2215 "%d\n"
2216 "%%%%EOF\n", n, xrefloc);
2217 sarrayAddString(sa, buf, L_COPY);
2218 outstr = sarrayToString(sa, 0);
2219 sarrayDestroy(&sa);
2220 return outstr;
2221}
2222
2223
2237static l_int32
2239 size_t *pnbytes,
2240 L_PDF_DATA *lpd)
2241{
2242char *str;
2243l_uint8 *data;
2244l_int32 nimages, i, len;
2245l_int32 *sizes, *locs;
2246size_t nbytes;
2247L_COMP_DATA *cid;
2248
2249 PROCNAME("generateOutputDataPdf");
2250
2251 if (!pdata)
2252 return ERROR_INT("&data not defined", procName, 1);
2253 *pdata = NULL;
2254 if (!pnbytes)
2255 return ERROR_INT("&nbytes not defined", procName, 1);
2256 nbytes = lpd->xrefloc + strlen(lpd->trailer);
2257 *pnbytes = nbytes;
2258 if ((data = (l_uint8 *)LEPT_CALLOC(nbytes, sizeof(l_uint8))) == NULL)
2259 return ERROR_INT("calloc fail for data", procName, 1);
2260 *pdata = data;
2261
2262 sizes = l_dnaGetIArray(lpd->objsize);
2263 locs = l_dnaGetIArray(lpd->objloc);
2264 memcpy(data, lpd->id, sizes[0]);
2265 memcpy(data + locs[1], lpd->obj1, sizes[1]);
2266 memcpy(data + locs[2], lpd->obj2, sizes[2]);
2267 memcpy(data + locs[3], lpd->obj3, sizes[3]);
2268 memcpy(data + locs[4], lpd->obj4, sizes[4]);
2269 memcpy(data + locs[5], lpd->obj5, sizes[5]);
2270
2271 /* Each image has 3 parts: variable preamble, the compressed
2272 * data stream, and the fixed poststream. */
2273 nimages = lpd->n;
2274 for (i = 0; i < nimages; i++) {
2275 if ((cid = pdfdataGetCid(lpd, i)) == NULL) { /* should not happen */
2276 LEPT_FREE(sizes);
2277 LEPT_FREE(locs);
2278 return ERROR_INT("cid not found", procName, 1);
2279 }
2280 str = sarrayGetString(lpd->saprex, i, L_NOCOPY);
2281 len = strlen(str);
2282 memcpy(data + locs[6 + i], str, len);
2283 memcpy(data + locs[6 + i] + len,
2284 cid->datacomp, cid->nbytescomp);
2285 memcpy(data + locs[6 + i] + len + cid->nbytescomp,
2286 lpd->poststream, strlen(lpd->poststream));
2287 }
2288
2289 /* Each colormap is simply a stored string */
2290 for (i = 0; i < lpd->ncmap; i++) {
2291 str = sarrayGetString(lpd->sacmap, i, L_NOCOPY);
2292 memcpy(data + locs[6 + nimages + i], str, strlen(str));
2293 }
2294
2295 /* And finally the trailer */
2296 memcpy(data + lpd->xrefloc, lpd->trailer, strlen(lpd->trailer));
2297 LEPT_FREE(sizes);
2298 LEPT_FREE(locs);
2299 return 0;
2300}
2301
2302
2303/*---------------------------------------------------------------------*
2304 * Helper functions for generating multipage pdf output *
2305 *---------------------------------------------------------------------*/
2313static l_int32
2315 L_DNA **pda)
2316{
2317char *str;
2318l_uint8 nl = '\n';
2319l_uint8 *data;
2320l_int32 i, j, start, startloc, xrefloc, found, loc, nobj, objno, trailer_ok;
2321size_t size;
2322L_DNA *da, *daobj, *daxref;
2323SARRAY *sa;
2324
2325 PROCNAME("parseTrailerPdf");
2326
2327 if (!pda)
2328 return ERROR_INT("&da not defined", procName, 1);
2329 *pda = NULL;
2330 if (!bas)
2331 return ERROR_INT("bas not defined", procName, 1);
2332 data = l_byteaGetData(bas, &size);
2333 if (memcmp(data, "%PDF-1.", 7) != 0)
2334 return ERROR_INT("PDF header signature not found", procName, 1);
2335
2336 /* Search for "startxref" starting 50 bytes from the EOF */
2337 start = 0;
2338 if (size > 50)
2339 start = size - 50;
2340 arrayFindSequence(data + start, size - start,
2341 (l_uint8 *)"startxref\n", 10, &loc, &found);
2342 if (!found)
2343 return ERROR_INT("startxref not found!", procName, 1);
2344 if (sscanf((char *)(data + start + loc + 10), "%d\n", &xrefloc) != 1)
2345 return ERROR_INT("xrefloc not found!", procName, 1);
2346 if (xrefloc < 0 || xrefloc >= size)
2347 return ERROR_INT("invalid xrefloc!", procName, 1);
2348 sa = sarrayCreateLinesFromString((char *)(data + xrefloc), 0);
2349 str = sarrayGetString(sa, 1, L_NOCOPY);
2350 if ((sscanf(str, "0 %d", &nobj)) != 1) {
2351 sarrayDestroy(&sa);
2352 return ERROR_INT("nobj not found", procName, 1);
2353 }
2354
2355 /* Get starting locations. The numa index is the
2356 * object number. loc[0] is the ID; loc[nobj + 1] is xrefloc. */
2357 da = l_dnaCreate(nobj + 1);
2358 *pda = da;
2359 for (i = 0; i < nobj; i++) {
2360 str = sarrayGetString(sa, i + 2, L_NOCOPY);
2361 sscanf(str, "%d", &startloc);
2362 l_dnaAddNumber(da, startloc);
2363 }
2364 l_dnaAddNumber(da, xrefloc);
2365
2366#if DEBUG_MULTIPAGE
2367 lept_stderr("************** Trailer string ************\n");
2368 lept_stderr("xrefloc = %d", xrefloc);
2370
2371 lept_stderr("************** Object locations ************");
2372 l_dnaWriteStderr(da);
2373#endif /* DEBUG_MULTIPAGE */
2374 sarrayDestroy(&sa);
2375
2376 /* Verify correct parsing */
2377 trailer_ok = TRUE;
2378 for (i = 1; i < nobj; i++) {
2379 l_dnaGetIValue(da, i, &startloc);
2380 if ((sscanf((char *)(data + startloc), "%d 0 obj", &objno)) != 1) {
2381 L_ERROR("bad trailer for object %d\n", procName, i);
2382 trailer_ok = FALSE;
2383 break;
2384 }
2385 }
2386
2387 /* If the trailer is broken, reconstruct the correct obj locations */
2388 if (!trailer_ok) {
2389 L_INFO("rebuilding pdf trailer\n", procName);
2390 l_dnaEmpty(da);
2391 l_dnaAddNumber(da, 0);
2392 l_byteaFindEachSequence(bas, (l_uint8 *)" 0 obj\n", 7, &daobj);
2393 nobj = l_dnaGetCount(daobj);
2394 for (i = 0; i < nobj; i++) {
2395 l_dnaGetIValue(daobj, i, &loc);
2396 for (j = loc - 1; j > 0; j--) {
2397 if (data[j] == nl)
2398 break;
2399 }
2400 l_dnaAddNumber(da, j + 1);
2401 }
2402 l_byteaFindEachSequence(bas, (l_uint8 *)"xref", 4, &daxref);
2403 l_dnaGetIValue(daxref, 0, &loc);
2404 l_dnaAddNumber(da, loc);
2405 l_dnaDestroy(&daobj);
2406 l_dnaDestroy(&daxref);
2407 }
2408
2409 return 0;
2410}
2411
2412
2413static char *
2414generatePagesObjStringPdf(NUMA *napage)
2415{
2416char *str;
2417char *buf;
2418l_int32 i, n, index, bufsize;
2419SARRAY *sa;
2420
2421 PROCNAME("generatePagesObjStringPdf");
2422
2423 if (!napage)
2424 return (char *)ERROR_PTR("napage not defined", procName, NULL);
2425
2426 n = numaGetCount(napage);
2427 bufsize = 100 + 16 * n; /* large enough to hold the output string */
2428 buf = (char *)LEPT_CALLOC(bufsize, sizeof(char));
2429 sa = sarrayCreate(n);
2430 for (i = 0; i < n; i++) {
2431 numaGetIValue(napage, i, &index);
2432 snprintf(buf, bufsize, " %d 0 R ", index);
2433 sarrayAddString(sa, buf, L_COPY);
2434 }
2435
2436 str = sarrayToString(sa, 0);
2437 snprintf(buf, bufsize - 1, "3 0 obj\n"
2438 "<<\n"
2439 "/Type /Pages\n"
2440 "/Kids [%s]\n"
2441 "/Count %d\n"
2442 ">>\n", str, n);
2443 sarrayDestroy(&sa);
2444 LEPT_FREE(str);
2445 return buf;
2446}
2447
2448
2466static L_BYTEA *
2468 NUMA *na_objs)
2469{
2470l_uint8 space = ' ';
2471l_uint8 *datas;
2472l_uint8 buf[32]; /* only needs to hold one integer in ascii format */
2473l_int32 start, nrepl, i, j, nobjs, objin, objout, found;
2474l_int32 *objs, *matches;
2475size_t size;
2476L_BYTEA *bad;
2477L_DNA *da_match;
2478
2479 PROCNAME("substituteObjectNumbers");
2480 if (!bas)
2481 return (L_BYTEA *)ERROR_PTR("bas not defined", procName, NULL);
2482 if (!na_objs)
2483 return (L_BYTEA *)ERROR_PTR("na_objs not defined", procName, NULL);
2484
2485 datas = l_byteaGetData(bas, &size);
2486 bad = l_byteaCreate(100);
2487 objs = numaGetIArray(na_objs); /* object number mapper */
2488 nobjs = numaGetCount(na_objs); /* use for sanity checking */
2489
2490 /* Substitute the object number on the first line */
2491 sscanf((char *)datas, "%d", &objin);
2492 if (objin < 0 || objin >= nobjs) {
2493 L_ERROR("index %d into array of size %d\n", procName, objin, nobjs);
2494 LEPT_FREE(objs);
2495 return bad;
2496 }
2497 objout = objs[objin];
2498 snprintf((char *)buf, 32, "%d", objout);
2499 l_byteaAppendString(bad, (char *)buf);
2500
2501 /* Find the set of matching locations for object references */
2502 arrayFindSequence(datas, size, &space, 1, &start, &found);
2503 da_match = arrayFindEachSequence(datas, size, (l_uint8 *)" 0 R", 4);
2504 if (!da_match) {
2505 l_byteaAppendData(bad, datas + start, size - start);
2506 LEPT_FREE(objs);
2507 return bad;
2508 }
2509
2510 /* Substitute all the object reference numbers */
2511 nrepl = l_dnaGetCount(da_match);
2512 matches = l_dnaGetIArray(da_match);
2513 for (i = 0; i < nrepl; i++) {
2514 /* Find the first space before the object number */
2515 for (j = matches[i] - 1; j > 0; j--) {
2516 if (datas[j] == space)
2517 break;
2518 }
2519 /* Copy bytes from 'start' up to the object number */
2520 l_byteaAppendData(bad, datas + start, j - start + 1);
2521 sscanf((char *)(datas + j + 1), "%d", &objin);
2522 if (objin < 0 || objin >= nobjs) {
2523 L_ERROR("index %d into array of size %d\n", procName, objin, nobjs);
2524 LEPT_FREE(objs);
2525 LEPT_FREE(matches);
2526 l_dnaDestroy(&da_match);
2527 return bad;
2528 }
2529 objout = objs[objin];
2530 snprintf((char *)buf, 32, "%d", objout);
2531 l_byteaAppendString(bad, (char *)buf);
2532 start = matches[i];
2533 }
2534 l_byteaAppendData(bad, datas + start, size - start);
2535
2536 LEPT_FREE(objs);
2537 LEPT_FREE(matches);
2538 l_dnaDestroy(&da_match);
2539 return bad;
2540}
2541
2542
2543/*---------------------------------------------------------------------*
2544 * Create/destroy/access pdf data *
2545 *---------------------------------------------------------------------*/
2546static L_PDF_DATA *
2547pdfdataCreate(const char *title)
2548{
2549L_PDF_DATA *lpd;
2550
2551 lpd = (L_PDF_DATA *)LEPT_CALLOC(1, sizeof(L_PDF_DATA));
2552 if (title) lpd->title = stringNew(title);
2553 lpd->cida = ptraCreate(10);
2554 lpd->xy = ptaCreate(10);
2555 lpd->wh = ptaCreate(10);
2556 lpd->saprex = sarrayCreate(10);
2557 lpd->sacmap = sarrayCreate(10);
2558 lpd->objsize = l_dnaCreate(20);
2559 lpd->objloc = l_dnaCreate(20);
2560 return lpd;
2561}
2562
2563static void
2564pdfdataDestroy(L_PDF_DATA **plpd)
2565{
2566l_int32 i;
2567L_COMP_DATA *cid;
2568L_PDF_DATA *lpd;
2569
2570 PROCNAME("pdfdataDestroy");
2571
2572 if (plpd== NULL) {
2573 L_WARNING("ptr address is null!\n", procName);
2574 return;
2575 }
2576 if ((lpd = *plpd) == NULL)
2577 return;
2578
2579 if (lpd->title) LEPT_FREE(lpd->title);
2580 for (i = 0; i < lpd->n; i++) {
2581 cid = (L_COMP_DATA *)ptraRemove(lpd->cida, i, L_NO_COMPACTION);
2582 l_CIDataDestroy(&cid);
2583 }
2584
2585 ptraDestroy(&lpd->cida, 0, 0);
2586 if (lpd->id) LEPT_FREE(lpd->id);
2587 if (lpd->obj1) LEPT_FREE(lpd->obj1);
2588 if (lpd->obj2) LEPT_FREE(lpd->obj2);
2589 if (lpd->obj3) LEPT_FREE(lpd->obj3);
2590 if (lpd->obj4) LEPT_FREE(lpd->obj4);
2591 if (lpd->obj5) LEPT_FREE(lpd->obj5);
2592 if (lpd->poststream) LEPT_FREE(lpd->poststream);
2593 if (lpd->trailer) LEPT_FREE(lpd->trailer);
2594 if (lpd->xy) ptaDestroy(&lpd->xy);
2595 if (lpd->wh) ptaDestroy(&lpd->wh);
2596 if (lpd->mediabox) boxDestroy(&lpd->mediabox);
2597 if (lpd->saprex) sarrayDestroy(&lpd->saprex);
2598 if (lpd->sacmap) sarrayDestroy(&lpd->sacmap);
2599 if (lpd->objsize) l_dnaDestroy(&lpd->objsize);
2600 if (lpd->objloc) l_dnaDestroy(&lpd->objloc);
2601 LEPT_FREE(lpd);
2602 *plpd = NULL;
2603}
2604
2605
2606static L_COMP_DATA *
2607pdfdataGetCid(L_PDF_DATA *lpd,
2608 l_int32 index)
2609{
2610 PROCNAME("pdfdataGetCid");
2611
2612 if (!lpd)
2613 return (L_COMP_DATA *)ERROR_PTR("lpd not defined", procName, NULL);
2614 if (index < 0 || index >= lpd->n)
2615 return (L_COMP_DATA *)ERROR_PTR("invalid image index", procName, NULL);
2616
2617 return (L_COMP_DATA *)ptraGetPtrToItem(lpd->cida, index);
2618}
2619
2620
2621/*---------------------------------------------------------------------*
2622 * Set flags for special modes *
2623 *---------------------------------------------------------------------*/
2638void
2640{
2641 var_WRITE_G4_IMAGE_MASK = flag;
2642}
2643
2644
2658void
2660{
2661 var_WRITE_DATE_AND_VERSION = flag;
2662}
2663
2664/* --------------------------------------------*/
2665#endif /* USE_PDFIO */
2666/* --------------------------------------------*/
PIX * pixAlphaBlendUniform(PIX *pixs, l_uint32 color)
pixAlphaBlendUniform()
Definition: blend.c:2024
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:313
L_BYTEA * l_byteaInitFromMem(const l_uint8 *data, size_t size)
l_byteaInitFromMem()
Definition: bytearray.c:125
L_BYTEA * l_byteaCreate(size_t nbytes)
l_byteaCreate()
Definition: bytearray.c:97
size_t l_byteaGetSize(L_BYTEA *ba)
l_byteaGetSize()
Definition: bytearray.c:284
l_ok l_byteaFindEachSequence(L_BYTEA *ba, const l_uint8 *sequence, size_t seqlen, L_DNA **pda)
l_byteaFindEachSequence()
Definition: bytearray.c:558
l_uint8 * l_byteaCopyData(L_BYTEA *ba, size_t *psize)
l_byteaCopyData()
Definition: bytearray.c:336
void l_byteaDestroy(L_BYTEA **pba)
l_byteaDestroy()
Definition: bytearray.c:250
l_uint8 * l_byteaGetData(L_BYTEA *ba, size_t *psize)
l_byteaGetData()
Definition: bytearray.c:307
l_ok l_byteaAppendString(L_BYTEA *ba, const char *str)
l_byteaAppendString()
Definition: bytearray.c:401
l_ok l_byteaAppendData(L_BYTEA *ba, const l_uint8 *newdata, size_t newbytes)
l_byteaAppendData()
Definition: bytearray.c:366
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
Definition: colormap.c:279
l_ok pixcmapSerializeToMemory(PIXCMAP *cmap, l_int32 cpc, l_int32 *pncolors, l_uint8 **pdata)
pixcmapSerializeToMemory()
Definition: colormap.c:2164
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:125
char * pixcmapConvertToHex(l_uint8 *data, l_int32 ncolors)
pixcmapConvertToHex()
Definition: colormap.c:2272
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:414
l_ok l_dnaGetIValue(L_DNA *da, l_int32 index, l_int32 *pival)
l_dnaGetIValue()
Definition: dnabasic.c:727
l_ok l_dnaAddNumber(L_DNA *da, l_float64 val)
l_dnaAddNumber()
Definition: dnabasic.c:448
L_DNAA * l_dnaaCreate(l_int32 n)
l_dnaaCreate()
Definition: dnabasic.c:1285
l_ok l_dnaEmpty(L_DNA *da)
l_dnaEmpty()
Definition: dnabasic.c:424
L_DNA * l_dnaCreate(l_int32 n)
l_dnaCreate()
Definition: dnabasic.c:180
l_ok l_dnaaAddDna(L_DNAA *daa, L_DNA *da, l_int32 copyflag)
l_dnaaAddDna()
Definition: dnabasic.c:1421
l_int32 * l_dnaGetIArray(L_DNA *da)
l_dnaGetIArray()
Definition: dnabasic.c:820
l_ok l_dnaWriteStderr(L_DNA *da)
l_dnaWriteStrderr()
Definition: dnabasic.c:1191
void l_dnaDestroy(L_DNA **pda)
l_dnaDestroy()
Definition: dnabasic.c:332
l_int32 l_dnaGetCount(L_DNA *da)
l_dnaGetCount()
Definition: dnabasic.c:631
void l_dnaaDestroy(L_DNAA **pdaa)
l_dnaaDestroy()
Definition: dnabasic.c:1386
L_DNA * l_dnaaGetDna(L_DNAA *daa, l_int32 index, l_int32 accessflag)
l_dnaaGetDna()
Definition: dnabasic.c:1576
L_DNA * l_dnaDiffAdjValues(L_DNA *das)
l_dnaDiffAdjValues()
Definition: dnafunc1.c:785
@ L_FLATE_ENCODE
Definition: imageio.h:161
@ L_G4_ENCODE
Definition: imageio.h:160
@ L_JP2K_ENCODE
Definition: imageio.h:162
@ L_JPEG_ENCODE
Definition: imageio.h:159
@ L_FIRST_IMAGE
Definition: imageio.h:208
@ L_LAST_IMAGE
Definition: imageio.h:210
l_ok readHeaderJp2k(const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *pcodec)
readHeaderJp2k()
Definition: jp2kheader.c:80
l_ok readHeaderMemJpeg(const l_uint8 *data, size_t size, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk)
readHeaderMemJpeg()
Definition: jpegio.c:1048
l_ok readResolutionMemJpeg(const l_uint8 *data, size_t size, l_int32 *pxres, l_int32 *pyres)
readResolutionMemJpeg()
Definition: jpegio.c:1089
l_ok readHeaderJpeg(const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk)
readHeaderJpeg()
Definition: jpegio.c:509
l_ok pixWriteJpeg(const char *filename, PIX *pix, l_int32 quality, l_int32 progressive)
pixWriteJpeg()
Definition: jpegio.c:741
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
l_ok numaReplaceNumber(NUMA *na, l_int32 index, l_float32 val)
numaReplaceNumber()
Definition: numabasic.c:627
l_ok numaWriteStderr(NUMA *na)
numaWriteStderr()
Definition: numabasic.c:1313
NUMA * numaaGetNuma(NUMAA *naa, l_int32 index, l_int32 accessflag)
numaaGetNuma()
Definition: numabasic.c:1740
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:847
l_ok numaaWriteStream(FILE *fp, NUMAA *naa)
numaaWriteStream()
Definition: numabasic.c:2020
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_ok numaSetValue(NUMA *na, l_int32 index, l_float32 val)
numaSetValue()
Definition: numabasic.c:786
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:754
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
l_ok numaaAddNuma(NUMAA *naa, NUMA *na, l_int32 copyflag)
numaaAddNuma()
Definition: numabasic.c:1546
NUMAA * numaaCreate(l_int32 n)
numaaCreate()
Definition: numabasic.c:1407
void numaaDestroy(NUMAA **pnaa)
numaaDestroy()
Definition: numabasic.c:1510
NUMA * numaMakeSequence(l_float32 startval, l_float32 increment, l_int32 size)
numaMakeSequence()
Definition: numafunc1.c:821
NUMA * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
Definition: numafunc1.c:851
l_ok pixaConvertToPdf(PIXA *pixa, l_int32 res, l_float32 scalefactor, l_int32 type, l_int32 quality, const char *title, const char *fileout)
pixaConvertToPdf()
Definition: pdfio1.c:790
l_ok selectDefaultPdfEncoding(PIX *pix, l_int32 *ptype)
selectDefaultPdfEncoding()
Definition: pdfio1.c:477
void l_CIDataDestroy(L_COMP_DATA **pcid)
l_CIDataDestroy()
Definition: pdfio2.c:1656
L_COMP_DATA * l_generateJpegDataMem(l_uint8 *data, size_t nbytes, l_int32 ascii85flag)
l_generateJpegDataMem()
Definition: pdfio2.c:1002
l_ok pixGenerateCIData(PIX *pixs, l_int32 type, l_int32 quality, l_int32 ascii85, L_COMP_DATA **pcid)
pixGenerateCIData()
Definition: pdfio2.c:1207
static L_COMP_DATA * pixGenerateFlateData(PIX *pixs, l_int32 ascii85flag)
pixGenerateFlateData()
Definition: pdfio2.c:1342
L_COMP_DATA * l_generateFlateData(const char *fname, l_int32 ascii85flag)
l_generateFlateData()
Definition: pdfio2.c:1305
l_ok pixConvertToPdfData(PIX *pix, l_int32 type, l_int32 quality, l_uint8 **pdata, size_t *pnbytes, l_int32 x, l_int32 y, l_int32 res, const char *title, L_PDF_DATA **plpd, l_int32 position)
pixConvertToPdfData()
Definition: pdfio2.c:190
L_COMP_DATA * l_generateJpegData(const char *fname, l_int32 ascii85flag)
l_generateJpegData()
Definition: pdfio2.c:929
static char * generateEscapeString(const char *str)
generateEscapeString()
Definition: pdfio2.c:1815
L_COMP_DATA * l_generateG4Data(const char *fname, l_int32 ascii85flag)
l_generateG4Data()
Definition: pdfio2.c:1118
static L_COMP_DATA * pixGenerateJpegData(PIX *pixs, l_int32 ascii85flag, l_int32 quality)
pixGenerateJpegData()
Definition: pdfio2.c:1464
void l_pdfSetDateAndVersion(l_int32 flag)
l_pdfSetDateAndVersion()
Definition: pdfio2.c:2659
static L_BYTEA * substituteObjectNumbers(L_BYTEA *bas, NUMA *na_objs)
substituteObjectNumbers()
Definition: pdfio2.c:2467
l_ok convertTiffMultipageToPdf(const char *filein, const char *fileout)
convertTiffMultipageToPdf()
Definition: pdfio2.c:485
l_ok l_generateCIData(const char *fname, l_int32 type, l_int32 quality, l_int32 ascii85, L_COMP_DATA **pcid)
l_generateCIData()
Definition: pdfio2.c:626
l_ok ptraConcatenatePdfToData(L_PTRA *pa_data, SARRAY *sa, l_uint8 **pdata, size_t *pnbytes)
ptraConcatenatePdfToData()
Definition: pdfio2.c:321
static l_int32 parseTrailerPdf(L_BYTEA *bas, L_DNA **pda)
parseTrailerPdf()
Definition: pdfio2.c:2314
static L_COMP_DATA * pixGenerateG4Data(PIX *pixs, l_int32 ascii85flag)
pixGenerateG4Data()
Definition: pdfio2.c:1561
void l_pdfSetG4ImageMask(l_int32 flag)
l_pdfSetG4ImageMask()
Definition: pdfio2.c:2639
l_ok cidConvertToPdfData(L_COMP_DATA *cid, const char *title, l_uint8 **pdata, size_t *pnbytes)
cidConvertToPdfData()
Definition: pdfio2.c:1607
static L_COMP_DATA * l_generateJp2kData(const char *fname)
l_generateJp2kData()
Definition: pdfio2.c:1064
L_COMP_DATA * l_generateFlateDataPdf(const char *fname, PIX *pixs)
l_generateFlateDataPdf()
Definition: pdfio2.c:730
static l_int32 l_generatePdf(l_uint8 **pdata, size_t *pnbytes, L_PDF_DATA *lpd)
l_generatePdf()
Definition: pdfio2.c:1703
l_ok l_generateCIDataForPdf(const char *fname, PIX *pix, l_int32 quality, L_COMP_DATA **pcid)
l_generateCIDataForPdf()
Definition: pdfio2.c:539
static l_int32 generateOutputDataPdf(l_uint8 **pdata, size_t *pnbytes, L_PDF_DATA *lpd)
generateOutputDataPdf()
Definition: pdfio2.c:2238
static L_COMP_DATA * pixGenerateJp2kData(PIX *pixs, l_int32 quality)
pixGenerateJp2kData()
Definition: pdfio2.c:1513
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
l_ok pixGetRasterData(PIX *pixs, l_uint8 **pdata, size_t *pnbytes)
pixGetRasterData()
Definition: pix2.c:3293
@ L_COPY
Definition: pix.h:712
@ L_CLONE
Definition: pix.h:713
@ L_NOCOPY
Definition: pix.h:710
@ L_INSERT
Definition: pix.h:711
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:412
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3133
l_ok readHeaderPng(const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
readHeaderPng()
Definition: pngio.c:575
l_ok isPngInterlaced(const char *filename, l_int32 *pinterlaced)
isPngInterlaced()
Definition: pngio.c:827
l_ok freadHeaderPng(FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
freadHeaderPng()
Definition: pngio.c:619
l_ok ptaSetPt(PTA *pta, l_int32 index, l_float32 x, l_float32 y)
ptaSetPt()
Definition: ptabasic.c:607
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:343
l_ok ptaGetPt(PTA *pta, l_int32 index, l_float32 *px, l_float32 *py)
ptaGetPt()
Definition: ptabasic.c:548
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
l_ok ptraGetActualCount(L_PTRA *pa, l_int32 *pcount)
ptraGetActualCount()
Definition: ptra.c:735
l_ok ptraCompactArray(L_PTRA *pa)
ptraCompactArray()
Definition: ptra.c:598
l_ok ptraAdd(L_PTRA *pa, void *item)
ptraAdd()
Definition: ptra.c:250
void * ptraRemove(L_PTRA *pa, l_int32 index, l_int32 flag)
ptraRemove()
Definition: ptra.c:442
void ptraDestroy(L_PTRA **ppa, l_int32 freeflag, l_int32 warnflag)
ptraDestroy()
Definition: ptra.c:194
L_PTRA * ptraCreate(l_int32 n)
ptraCreate()
Definition: ptra.c:144
void * ptraGetPtrToItem(L_PTRA *pa, l_int32 index)
ptraGetPtrToItem()
Definition: ptra.c:767
@ L_NO_COMPACTION
Definition: ptra.h:79
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:193
l_ok pixReadHeader(const char *filename, l_int32 *pformat, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
pixReadHeader()
Definition: readfile.c:446
l_ok findFileFormat(const char *filename, l_int32 *pformat)
findFileFormat()
Definition: readfile.c:584
l_int32 fileFormatIsTiff(FILE *fp)
fileFormatIsTiff()
Definition: readfile.c:800
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:170
l_ok sarrayWriteStderr(SARRAY *sa)
sarrayWriteStderr()
Definition: sarray1.c:1646
char * sarrayToString(SARRAY *sa, l_int32 addnlflag)
sarrayToString()
Definition: sarray1.c:785
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:703
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:362
SARRAY * sarrayCreateLinesFromString(const char *string, l_int32 blankflag)
sarrayCreateLinesFromString()
Definition: sarray1.c:283
l_ok sarrayAddString(SARRAY *sa, const char *string, l_int32 copyflag)
sarrayAddString()
Definition: sarray1.c:451
Definition: array.h:137
l_int32 ncolors
Definition: imageio.h:190
l_int32 predictor
Definition: imageio.h:196
char * cmapdatahex
Definition: imageio.h:189
l_uint8 * datacomp
Definition: imageio.h:184
size_t nbytescomp
Definition: imageio.h:185
l_int32 minisblack
Definition: imageio.h:195
char * cmapdata85
Definition: imageio.h:188
l_int32 type
Definition: imageio.h:183
size_t nbytes85
Definition: imageio.h:187
Definition: array.h:95
Definition: array.h:107
l_int32 xrefloc
Definition: imageio.h:246
char * poststream
Definition: imageio.h:237
struct Sarray * saprex
Definition: imageio.h:242
struct L_Ptra * cida
Definition: imageio.h:230
struct Pta * xy
Definition: imageio.h:239
l_int32 ncmap
Definition: imageio.h:229
char * obj2
Definition: imageio.h:233
char * trailer
Definition: imageio.h:238
char * obj1
Definition: imageio.h:232
struct Sarray * sacmap
Definition: imageio.h:243
l_int32 n
Definition: imageio.h:228
struct L_Dna * objsize
Definition: imageio.h:244
struct L_Dna * objloc
Definition: imageio.h:245
char * title
Definition: imageio.h:227
char * id
Definition: imageio.h:231
struct Pta * wh
Definition: imageio.h:240
char * obj5
Definition: imageio.h:236
char * obj4
Definition: imageio.h:235
struct Box * mediabox
Definition: imageio.h:241
char * obj3
Definition: imageio.h:234
Definition: ptra.h:54
Definition: array.h:71
Definition: array.h:83
Definition: pix.h:139
Definition: pix.h:456
Definition: array.h:127
PIXA * pixaReadMultipageTiff(const char *filename)
pixaReadMultipageTiff()
Definition: tiffio.c:1401
l_ok getTiffResolution(FILE *fp, l_int32 *pxres, l_int32 *pyres)
getTiffResolution()
Definition: tiffio.c:1685
l_ok tiffGetCount(FILE *fp, l_int32 *pn)
tiffGetCount()
Definition: tiffio.c:1637
l_ok extractG4DataFromFile(const char *filein, l_uint8 **pdata, size_t *pnbytes, l_int32 *pw, l_int32 *ph, l_int32 *pminisblack)
extractG4DataFromFile()
Definition: tiffio.c:2132
char * l_getFormattedDate(void)
l_getFormattedDate()
Definition: utils1.c:1319
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
char * getLeptonicaVersion(void)
getLeptonicaVersion()
Definition: utils1.c:982
l_int32 lept_rmfile(const char *filepath)
lept_rmfile()
Definition: utils2.c:2517
char * l_makeTempFilename(void)
l_makeTempFilename()
Definition: utils2.c:3397
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1352
l_int32 stringCat(char *dest, size_t size, const char *src)
stringCat()
Definition: utils2.c:423
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1932
L_DNA * arrayFindEachSequence(const l_uint8 *data, size_t datalen, const l_uint8 *sequence, size_t seqlen)
arrayFindEachSequence()
Definition: utils2.c:1173
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:223
l_ok arrayFindSequence(const l_uint8 *data, size_t datalen, const l_uint8 *sequence, size_t seqlen, l_int32 *poffset, l_int32 *pfound)
arrayFindSequence()
Definition: utils2.c:1233
l_uint8 * zlibCompress(const l_uint8 *datain, size_t nin, size_t *pnout)
zlibCompress()
Definition: zlibmem.c:92