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) */
107 static const l_int32 DefaultInputRes = 300;
108 
109  /* Static helpers */
110 static L_COMP_DATA *l_generateJp2kData(const char *fname);
111 static L_COMP_DATA *pixGenerateFlateData(PIX *pixs, l_int32 ascii85flag);
112 static L_COMP_DATA *pixGenerateJpegData(PIX *pixs, l_int32 ascii85flag,
113  l_int32 quality);
114 static L_COMP_DATA *pixGenerateJp2kData(PIX *pixs, l_int32 quality);
115 static L_COMP_DATA *pixGenerateG4Data(PIX *pixs, l_int32 ascii85flag);
116 
117 static l_int32 l_generatePdf(l_uint8 **pdata, size_t *pnbytes,
118  L_PDF_DATA *lpd);
119 static void generateFixedStringsPdf(L_PDF_DATA *lpd);
120 static char *generateEscapeString(const char *str);
121 static void generateMediaboxPdf(L_PDF_DATA *lpd);
122 static l_int32 generatePageStringPdf(L_PDF_DATA *lpd);
123 static l_int32 generateContentStringPdf(L_PDF_DATA *lpd);
124 static l_int32 generatePreXStringsPdf(L_PDF_DATA *lpd);
125 static l_int32 generateColormapStringsPdf(L_PDF_DATA *lpd);
126 static void generateTrailerPdf(L_PDF_DATA *lpd);
127 static char *makeTrailerStringPdf(L_DNA *daloc);
128 static l_int32 generateOutputDataPdf(l_uint8 **pdata, size_t *pnbytes,
129  L_PDF_DATA *lpd);
130 
131 static l_int32 parseTrailerPdf(L_BYTEA *bas, L_DNA **pda);
132 static char *generatePagesObjStringPdf(NUMA *napage);
133 static L_BYTEA *substituteObjectNumbers(L_BYTEA *bas, NUMA *na_objs);
134 
135 static L_PDF_DATA *pdfdataCreate(const char *title);
136 static void pdfdataDestroy(L_PDF_DATA **plpd);
137 static 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 */
142 static l_int32 var_WRITE_G4_IMAGE_MASK = 1;
143  /* Write date/time and lib version into pdf; this is the default */
144 static 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  *---------------------------------------------------------------------*/
189 l_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 {
202 l_int32 pixres, w, h, ret;
203 l_float32 xpt, ypt, wpt, hpt;
204 L_COMP_DATA *cid = NULL;
205 L_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  *---------------------------------------------------------------------*/
320 l_ok
322  SARRAY *sa,
323  l_uint8 **pdata,
324  size_t *pnbytes)
325 {
326 char *fname, *str_pages, *str_trailer;
327 l_uint8 *pdfdata, *data;
328 l_int32 i, j, index, nobj, npages;
329 l_int32 *sizes, *locs;
330 size_t size;
331 L_BYTEA *bas, *bad, *bat1, *bat2;
332 L_DNA *da_locs, *da_sizes, *da_outlocs, *da;
333 L_DNAA *daa_locs; /* object locations on each page */
334 NUMA *na_objs, *napage;
335 NUMAA *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  *---------------------------------------------------------------------*/
484 l_ok
485 convertTiffMultipageToPdf(const char *filein,
486  const char *fileout)
487 {
488 l_int32 istiff;
489 PIXA *pixa;
490 FILE *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  *---------------------------------------------------------------------*/
538 l_ok
539 l_generateCIDataForPdf(const char *fname,
540  PIX *pix,
541  l_int32 quality,
542  L_COMP_DATA **pcid)
543 {
544 l_int32 format, type;
545 L_COMP_DATA *cid;
546 PIX *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 
625 l_ok
626 l_generateCIData(const char *fname,
627  l_int32 type,
628  l_int32 quality,
629  l_int32 ascii85,
630  L_COMP_DATA **pcid)
631 {
632 l_int32 format, d, bps, spp, iscmap;
633 L_COMP_DATA *cid;
634 PIX *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  *---------------------------------------------------------------------*/
729 L_COMP_DATA *
730 l_generateFlateDataPdf(const char *fname,
731  PIX *pixs)
732 {
733 l_uint8 *pngcomp = NULL; /* entire PNG compressed file */
734 l_uint8 *datacomp = NULL; /* gzipped raster data */
735 l_uint8 *cmapdata = NULL; /* uncompressed colormap */
736 char *cmapdatahex = NULL; /* hex ascii uncompressed colormap */
737 l_uint32 i, j, n;
738 l_int32 format, interlaced;
739 l_int32 ncolors; /* in colormap */
740 l_int32 bps; /* bits/sample: usually 8 */
741 l_int32 spp; /* samples/pixel: 1-grayscale/cmap); 3-rgb; 4-rgba */
742 l_int32 w, h, cmapflag;
743 l_int32 xres, yres;
744 size_t nbytescomp = 0, nbytespng = 0;
745 FILE *fp;
746 L_COMP_DATA *cid;
747 PIX *pix;
748 PIXCMAP *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 
928 L_COMP_DATA *
929 l_generateJpegData(const char *fname,
930  l_int32 ascii85flag)
931 {
932 char *data85 = NULL; /* ascii85 encoded jpeg compressed file */
933 l_uint8 *data = NULL;
934 l_int32 w, h, xres, yres, bps, spp;
935 size_t nbytes, nbytes85;
936 L_COMP_DATA *cid;
937 FILE *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 
1001 L_COMP_DATA *
1003  size_t nbytes,
1004  l_int32 ascii85flag)
1005 {
1006 char *data85 = NULL; /* ascii85 encoded jpeg compressed file */
1007 l_int32 w, h, xres, yres, bps, spp;
1008 size_t nbytes85;
1009 L_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 
1063 static L_COMP_DATA *
1064 l_generateJp2kData(const char *fname)
1065 {
1066 l_int32 w, h, bps, spp, xres, yres;
1067 size_t nbytes;
1068 L_COMP_DATA *cid;
1069 FILE *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 
1117 L_COMP_DATA *
1118 l_generateG4Data(const char *fname,
1119  l_int32 ascii85flag)
1120 {
1121 l_uint8 *datacomp = NULL; /* g4 compressed raster data */
1122 char *data85 = NULL; /* ascii85 encoded g4 compressed data */
1123 l_int32 w, h, xres, yres, npages;
1124 l_int32 minisblack; /* TRUE or FALSE */
1125 size_t nbytes85, nbytescomp;
1126 L_COMP_DATA *cid;
1127 FILE *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 
1206 l_ok
1208  l_int32 type,
1209  l_int32 quality,
1210  l_int32 ascii85,
1211  L_COMP_DATA **pcid)
1212 {
1213 l_int32 d;
1214 PIXCMAP *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 
1304 L_COMP_DATA *
1305 l_generateFlateData(const char *fname,
1306  l_int32 ascii85flag)
1307 {
1308 L_COMP_DATA *cid;
1309 PIX *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 
1341 static L_COMP_DATA *
1343  l_int32 ascii85flag)
1344 {
1345 l_uint8 *data = NULL; /* uncompressed raster data in required format */
1346 l_uint8 *datacomp = NULL; /* gzipped raster data */
1347 char *data85 = NULL; /* ascii85 encoded gzipped raster data */
1348 l_uint8 *cmapdata = NULL; /* uncompressed colormap */
1349 char *cmapdata85 = NULL; /* ascii85 encoded uncompressed colormap */
1350 char *cmapdatahex = NULL; /* hex ascii uncompressed colormap */
1351 l_int32 ncolors; /* in colormap; not used if cmapdata85 is null */
1352 l_int32 bps; /* bits/sample: usually 8 */
1353 l_int32 spp; /* samples/pixel: 1-grayscale/cmap); 3-rgb */
1354 l_int32 w, h, d, cmapflag;
1355 size_t ncmapbytes85 = 0;
1356 size_t nbytes85 = 0;
1357 size_t nbytes, nbytescomp;
1358 L_COMP_DATA *cid;
1359 PIX *pixt;
1360 PIXCMAP *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 
1463 static L_COMP_DATA *
1465  l_int32 ascii85flag,
1466  l_int32 quality)
1467 {
1468 l_int32 d;
1469 char *fname;
1470 L_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 
1512 static L_COMP_DATA *
1514  l_int32 quality)
1515 {
1516 l_int32 d;
1517 char *fname;
1518 L_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 
1560 static L_COMP_DATA *
1562  l_int32 ascii85flag)
1563 {
1564 char *fname;
1565 L_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 
1606 l_ok
1608  const char *title,
1609  l_uint8 **pdata,
1610  size_t *pnbytes)
1611 {
1612 l_int32 res, ret;
1613 l_float32 wpt, hpt;
1614 L_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 
1655 void
1657 {
1658 L_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  *---------------------------------------------------------------------*/
1702 static l_int32
1703 l_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 
1729 static void
1730 generateFixedStringsPdf(L_PDF_DATA *lpd)
1731 {
1732 char buf[L_SMALLBUF];
1733 char *version, *datestr;
1734 SARRAY *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 
1814 static char *
1815 generateEscapeString(const char *str)
1816 {
1817 char smallbuf[8];
1818 char *buffer;
1819 l_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 
1843 static void
1844 generateMediaboxPdf(L_PDF_DATA *lpd)
1845 {
1846 l_int32 i;
1847 l_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 
1874 static l_int32
1875 generatePageStringPdf(L_PDF_DATA *lpd)
1876 {
1877 char *buf;
1878 char *xstr;
1879 l_int32 bufsize, i, wpt, hpt;
1880 SARRAY *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 
1928 static l_int32
1929 generateContentStringPdf(L_PDF_DATA *lpd)
1930 {
1931 char *buf;
1932 char *cstr;
1933 l_int32 i, bufsize;
1934 l_float32 xpt, ypt, wpt, hpt;
1935 SARRAY *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 
1976 static l_int32
1977 generatePreXStringsPdf(L_PDF_DATA *lpd)
1978 {
1979 char buff[256];
1980 char buf[L_BIGBUF];
1981 char *cstr, *bstr, *fstr, *pstr, *xstr, *photometry;
1982 l_int32 i, cmindex;
1983 L_COMP_DATA *cid;
1984 SARRAY *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);
2088  l_dnaAddNumber(lpd->objsize,
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 
2100 static l_int32
2101 generateColormapStringsPdf(L_PDF_DATA *lpd)
2102 {
2103 char buf[L_BIGBUF];
2104 char *cmstr;
2105 l_int32 i, cmindex, ncmap;
2106 L_COMP_DATA *cid;
2107 SARRAY *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 
2141 static void
2142 generateTrailerPdf(L_PDF_DATA *lpd)
2143 {
2144 l_int32 i, n, size, linestart;
2145 L_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 
2182 static char *
2183 makeTrailerStringPdf(L_DNA *daloc)
2184 {
2185 char *outstr;
2186 char buf[L_BIGBUF];
2187 l_int32 i, n, linestart, xrefloc;
2188 SARRAY *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 
2237 static l_int32
2238 generateOutputDataPdf(l_uint8 **pdata,
2239  size_t *pnbytes,
2240  L_PDF_DATA *lpd)
2241 {
2242 char *str;
2243 l_uint8 *data;
2244 l_int32 nimages, i, len;
2245 l_int32 *sizes, *locs;
2246 size_t nbytes;
2247 L_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  *---------------------------------------------------------------------*/
2313 static l_int32
2315  L_DNA **pda)
2316 {
2317 char *str;
2318 l_uint8 nl = '\n';
2319 l_uint8 *data;
2320 l_int32 i, j, start, startloc, xrefloc, found, loc, nobj, objno, trailer_ok;
2321 size_t size;
2322 L_DNA *da, *daobj, *daxref;
2323 SARRAY *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);
2369  sarrayWriteStderr(sa);
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 
2413 static char *
2414 generatePagesObjStringPdf(NUMA *napage)
2415 {
2416 char *str;
2417 char *buf;
2418 l_int32 i, n, index, bufsize;
2419 SARRAY *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 
2466 static L_BYTEA *
2468  NUMA *na_objs)
2469 {
2470 l_uint8 space = ' ';
2471 l_uint8 *datas;
2472 l_uint8 buf[32]; /* only needs to hold one integer in ascii format */
2473 l_int32 start, nrepl, i, j, nobjs, objin, objout, found;
2474 l_int32 *objs, *matches;
2475 size_t size;
2476 L_BYTEA *bad;
2477 L_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  *---------------------------------------------------------------------*/
2546 static L_PDF_DATA *
2547 pdfdataCreate(const char *title)
2548 {
2549 L_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 
2563 static void
2564 pdfdataDestroy(L_PDF_DATA **plpd)
2565 {
2566 l_int32 i;
2567 L_COMP_DATA *cid;
2568 L_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 
2606 static L_COMP_DATA *
2607 pdfdataGetCid(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  *---------------------------------------------------------------------*/
2638 void
2639 l_pdfSetG4ImageMask(l_int32 flag)
2640 {
2641  var_WRITE_G4_IMAGE_MASK = flag;
2642 }
2643 
2644 
2658 void
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
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:313
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
l_uint8 * l_byteaCopyData(L_BYTEA *ba, size_t *psize)
l_byteaCopyData()
Definition: bytearray.c:336
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_byteaGetData(L_BYTEA *ba, size_t *psize)
l_byteaGetData()
Definition: bytearray.c:307
L_BYTEA * l_byteaCreate(size_t nbytes)
l_byteaCreate()
Definition: bytearray.c:97
void l_byteaDestroy(L_BYTEA **pba)
l_byteaDestroy()
Definition: bytearray.c:250
L_BYTEA * l_byteaInitFromMem(const l_uint8 *data, size_t size)
l_byteaInitFromMem()
Definition: bytearray.c:125
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
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:125
l_ok pixcmapSerializeToMemory(PIXCMAP *cmap, l_int32 cpc, l_int32 *pncolors, l_uint8 **pdata)
pixcmapSerializeToMemory()
Definition: colormap.c:2164
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_DNA * l_dnaCreate(l_int32 n)
l_dnaCreate()
Definition: dnabasic.c:180
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_DNA * l_dnaaGetDna(L_DNAA *daa, l_int32 index, l_int32 accessflag)
l_dnaaGetDna()
Definition: dnabasic.c:1576
l_ok l_dnaEmpty(L_DNA *da)
l_dnaEmpty()
Definition: dnabasic.c:424
L_DNAA * l_dnaaCreate(l_int32 n)
l_dnaaCreate()
Definition: dnabasic.c:1285
l_ok l_dnaaAddDna(L_DNAA *daa, L_DNA *da, l_int32 copyflag)
l_dnaaAddDna()
Definition: dnabasic.c:1421
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_dnaGetIArray(L_DNA *da)
l_dnaGetIArray()
Definition: dnabasic.c:820
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_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 * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
NUMA * numaaGetNuma(NUMAA *naa, l_int32 index, l_int32 accessflag)
numaaGetNuma()
Definition: numabasic.c:1740
l_ok numaaWriteStream(FILE *fp, NUMAA *naa)
numaaWriteStream()
Definition: numabasic.c:2020
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
NUMAA * numaaCreate(l_int32 n)
numaaCreate()
Definition: numabasic.c:1407
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
l_ok numaaAddNuma(NUMAA *naa, NUMA *na, l_int32 copyflag)
numaaAddNuma()
Definition: numabasic.c:1546
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:847
void numaaDestroy(NUMAA **pnaa)
numaaDestroy()
Definition: numabasic.c:1510
NUMA * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
Definition: numafunc1.c:851
NUMA * numaMakeSequence(l_float32 startval, l_float32 increment, l_int32 size)
numaMakeSequence()
Definition: numafunc1.c:821
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
L_COMP_DATA * l_generateG4Data(const char *fname, l_int32 ascii85flag)
l_generateG4Data()
Definition: pdfio2.c:1118
L_COMP_DATA * l_generateJpegDataMem(l_uint8 *data, size_t nbytes, l_int32 ascii85flag)
l_generateJpegDataMem()
Definition: pdfio2.c:1002
L_COMP_DATA * l_generateJpegData(const char *fname, l_int32 ascii85flag)
l_generateJpegData()
Definition: pdfio2.c:929
void l_CIDataDestroy(L_COMP_DATA **pcid)
l_CIDataDestroy()
Definition: pdfio2.c:1656
l_ok pixGenerateCIData(PIX *pixs, l_int32 type, l_int32 quality, l_int32 ascii85, L_COMP_DATA **pcid)
pixGenerateCIData()
Definition: pdfio2.c:1207
L_COMP_DATA * l_generateFlateData(const char *fname, l_int32 ascii85flag)
l_generateFlateData()
Definition: pdfio2.c:1305
static L_COMP_DATA * pixGenerateFlateData(PIX *pixs, l_int32 ascii85flag)
pixGenerateFlateData()
Definition: pdfio2.c:1342
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_generateFlateDataPdf(const char *fname, PIX *pixs)
l_generateFlateDataPdf()
Definition: pdfio2.c:730
static char * generateEscapeString(const char *str)
generateEscapeString()
Definition: pdfio2.c:1815
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
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
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
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
L_PTRA * ptraCreate(l_int32 n)
ptraCreate()
Definition: ptra.c:144
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 ptraDestroy(L_PTRA **ppa, l_int32 freeflag, l_int32 warnflag)
ptraDestroy()
Definition: ptra.c:194
void * ptraRemove(L_PTRA *pa, l_int32 index, l_int32 flag)
ptraRemove()
Definition: ptra.c:442
void * ptraGetPtrToItem(L_PTRA *pa, l_int32 index)
ptraGetPtrToItem()
Definition: ptra.c:767
@ L_NO_COMPACTION
Definition: ptra.h:79
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
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:193
l_int32 fileFormatIsTiff(FILE *fp)
fileFormatIsTiff()
Definition: readfile.c:800
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:170
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:703
l_ok sarrayWriteStderr(SARRAY *sa)
sarrayWriteStderr()
Definition: sarray1.c:1646
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
char * sarrayToString(SARRAY *sa, l_int32 addnlflag)
sarrayToString()
Definition: sarray1.c:785
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
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
PIXA * pixaReadMultipageTiff(const char *filename)
pixaReadMultipageTiff()
Definition: tiffio.c:1401
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
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
char * l_getFormattedDate(void)
l_getFormattedDate()
Definition: utils1.c:1319
char * getLeptonicaVersion(void)
getLeptonicaVersion()
Definition: utils1.c:982
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:223
l_int32 lept_rmfile(const char *filepath)
lept_rmfile()
Definition: utils2.c:2517
char * l_makeTempFilename(void)
l_makeTempFilename()
Definition: utils2.c:3397
l_int32 stringCat(char *dest, size_t size, const char *src)
stringCat()
Definition: utils2.c:423
L_DNA * arrayFindEachSequence(const l_uint8 *data, size_t datalen, const l_uint8 *sequence, size_t seqlen)
arrayFindEachSequence()
Definition: utils2.c:1173
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1932
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1352
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