Leptonica  1.73
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 
92 #include <string.h>
93 #include <math.h>
94 #include "allheaders.h"
95 
96 /* --------------------------------------------*/
97 #if USE_PDFIO /* defined in environ.h */
98  /* --------------------------------------------*/
99 
100  /* Typical scan resolution in ppi (pixels/inch) */
101 static const l_int32 DEFAULT_INPUT_RES = 300;
102 
103  /* Static helpers */
104 static L_COMP_DATA *l_generateJp2kData(const char *fname);
105 static L_COMP_DATA *pixGenerateFlateData(PIX *pixs, l_int32 ascii85flag);
106 static L_COMP_DATA *pixGenerateJpegData(PIX *pixs, l_int32 ascii85flag,
107  l_int32 quality);
108 static L_COMP_DATA *pixGenerateG4Data(PIX *pixs, l_int32 ascii85flag);
109 
110 static l_int32 l_generatePdf(l_uint8 **pdata, size_t *pnbytes,
111  L_PDF_DATA *lpd);
112 static void generateFixedStringsPdf(L_PDF_DATA *lpd);
113 static char *generateEscapeString(const char *str);
114 static void generateMediaboxPdf(L_PDF_DATA *lpd);
115 static l_int32 generatePageStringPdf(L_PDF_DATA *lpd);
116 static l_int32 generateContentStringPdf(L_PDF_DATA *lpd);
117 static l_int32 generatePreXStringsPdf(L_PDF_DATA *lpd);
118 static l_int32 generateColormapStringsPdf(L_PDF_DATA *lpd);
119 static void generateTrailerPdf(L_PDF_DATA *lpd);
120 static char *makeTrailerStringPdf(L_DNA *daloc);
121 static l_int32 generateOutputDataPdf(l_uint8 **pdata, size_t *pnbytes,
122  L_PDF_DATA *lpd);
123 
124 static l_int32 parseTrailerPdf(L_BYTEA *bas, L_DNA **pda);
125 static char *generatePagesObjStringPdf(NUMA *napage);
126 static L_BYTEA *substituteObjectNumbers(L_BYTEA *bas, NUMA *na_objs);
127 
128 static L_PDF_DATA *pdfdataCreate(const char *title);
129 static void pdfdataDestroy(L_PDF_DATA **plpd);
130 static L_COMP_DATA *pdfdataGetCid(L_PDF_DATA *lpd, l_int32 index);
131 
132 
133 /* ---------------- Defaults for rendering options ----------------- */
134  /* Output G4 as writing through image mask; this is the default */
135 static l_int32 var_WRITE_G4_IMAGE_MASK = 1;
136  /* Write date/time and lib version into pdf; this is the default */
137 static l_int32 var_WRITE_DATE_AND_VERSION = 1;
138 
139 #define L_SMALLBUF 256
140 #define L_BIGBUF 2048 /* must be able to hold hex colormap */
141 
142 
143 #ifndef NO_CONSOLE_IO
144 #define DEBUG_MULTIPAGE 0
145 #endif /* ~NO_CONSOLE_IO */
146 
147 
148 /*---------------------------------------------------------------------*
149  * Intermediate function for generating multipage pdf output *
150  *---------------------------------------------------------------------*/
180 l_int32
182  l_int32 type,
183  l_int32 quality,
184  l_uint8 **pdata,
185  size_t *pnbytes,
186  l_int32 x,
187  l_int32 y,
188  l_int32 res,
189  const char *title,
190  L_PDF_DATA **plpd,
191  l_int32 position)
192 {
193 l_int32 pixres, w, h, ret;
194 l_float32 xpt, ypt, wpt, hpt;
195 L_COMP_DATA *cid = NULL;
196 L_PDF_DATA *lpd = NULL;
197 
198  PROCNAME("pixConvertToPdfData");
199 
200  if (!pdata)
201  return ERROR_INT("&data not defined", procName, 1);
202  *pdata = NULL;
203  if (!pnbytes)
204  return ERROR_INT("&nbytes not defined", procName, 1);
205  *pnbytes = 0;
206  if (!pix)
207  return ERROR_INT("pix not defined", procName, 1);
208  if (plpd) { /* part of multi-page invocation */
209  if (position == L_FIRST_IMAGE)
210  *plpd = NULL;
211  }
212 
213  /* Generate the compressed image data. It must NOT
214  * be ascii85 encoded. */
215  pixGenerateCIData(pix, type, quality, 0, &cid);
216  if (!cid)
217  return ERROR_INT("cid not made", procName, 1);
218 
219  /* Get media box in pts. Guess the input image resolution
220  * based on the input parameter %res, the resolution data in
221  * the pix, and the size of the image. */
222  pixres = cid->res;
223  w = cid->w;
224  h = cid->h;
225  if (res <= 0.0) {
226  if (pixres > 0)
227  res = pixres;
228  else
229  res = DEFAULT_INPUT_RES;
230  }
231  xpt = x * 72. / res;
232  ypt = y * 72. / res;
233  wpt = w * 72. / res;
234  hpt = h * 72. / res;
235 
236  /* Set up lpd */
237  if (!plpd) { /* single image */
238  if ((lpd = pdfdataCreate(title)) == NULL)
239  return ERROR_INT("lpd not made", procName, 1);
240  } else if (position == L_FIRST_IMAGE) { /* first of multiple images */
241  if ((lpd = pdfdataCreate(title)) == NULL)
242  return ERROR_INT("lpd not made", procName, 1);
243  *plpd = lpd;
244  } else { /* not the first of multiple images */
245  lpd = *plpd;
246  }
247 
248  /* Add the data to the lpd */
249  ptraAdd(lpd->cida, cid);
250  lpd->n++;
251  ptaAddPt(lpd->xy, xpt, ypt);
252  ptaAddPt(lpd->wh, wpt, hpt);
253 
254  /* If a single image or the last of multiple images,
255  * generate the pdf and destroy the lpd */
256  if (!plpd || (position == L_LAST_IMAGE)) {
257  ret = l_generatePdf(pdata, pnbytes, lpd);
258  pdfdataDestroy(&lpd);
259  if (plpd) *plpd = NULL;
260  if (ret)
261  return ERROR_INT("pdf output not made", procName, 1);
262  }
263 
264  return 0;
265 }
266 
267 
268 /*---------------------------------------------------------------------*
269  * Intermediate function for generating multipage pdf output *
270  *---------------------------------------------------------------------*/
305 l_int32
307  SARRAY *sa,
308  l_uint8 **pdata,
309  size_t *pnbytes)
310 {
311 char *fname, *str_pages, *str_trailer;
312 l_uint8 *pdfdata, *data;
313 l_int32 i, j, index, nobj, npages;
314 l_int32 *sizes, *locs;
315 size_t size;
316 L_BYTEA *bas, *bad, *bat1, *bat2;
317 L_DNA *da_locs, *da_sizes, *da_outlocs, *da;
318 L_DNAA *daa_locs; /* object locations on each page */
319 NUMA *na_objs, *napage;
320 NUMAA *naa_objs; /* object mapping numbers to new values */
321 
322  PROCNAME("ptraConcatenatePdfToData");
323 
324  if (!pdata)
325  return ERROR_INT("&data not defined", procName, 1);
326  *pdata = NULL;
327  if (!pnbytes)
328  return ERROR_INT("&nbytes not defined", procName, 1);
329  *pnbytes = 0;
330  if (!pa_data)
331  return ERROR_INT("pa_data not defined", procName, 1);
332 
333  /* Parse the files and find the object locations.
334  * Remove file data that cannot be parsed. */
335  ptraGetActualCount(pa_data, &npages);
336  daa_locs = l_dnaaCreate(npages);
337  for (i = 0; i < npages; i++) {
338  bas = (L_BYTEA *)ptraGetPtrToItem(pa_data, i);
339  if (parseTrailerPdf(bas, &da_locs) != 0) {
340  bas = (L_BYTEA *)ptraRemove(pa_data, i, L_NO_COMPACTION);
341  l_byteaDestroy(&bas);
342  if (sa) {
343  fname = sarrayGetString(sa, i, L_NOCOPY);
344  L_ERROR("can't parse file %s; skipping\n", procName, fname);
345  } else {
346  L_ERROR("can't parse file %d; skipping\n", procName, i);
347  }
348  } else {
349  l_dnaaAddDna(daa_locs, da_locs, L_INSERT);
350  }
351  }
352 
353  /* Recompute npages in case some of the files were not pdf */
354  ptraCompactArray(pa_data);
355  ptraGetActualCount(pa_data, &npages);
356  if (npages == 0) {
357  l_dnaaDestroy(&daa_locs);
358  return ERROR_INT("no parsable pdf files found", procName, 1);
359  }
360 
361  /* Find the mapping from initial to final object numbers */
362  naa_objs = numaaCreate(npages); /* stores final object numbers */
363  napage = numaCreate(npages); /* stores "Page" object numbers */
364  index = 0;
365  for (i = 0; i < npages; i++) {
366  da = l_dnaaGetDna(daa_locs, i, L_CLONE);
367  nobj = l_dnaGetCount(da);
368  if (i == 0) {
369  numaAddNumber(napage, 4); /* object 4 on first page */
370  na_objs = numaMakeSequence(0.0, 1.0, nobj - 1);
371  index = nobj - 1;
372  } else { /* skip the first 3 objects in each file */
373  numaAddNumber(napage, index); /* Page object is first we add */
374  na_objs = numaMakeConstant(0.0, nobj - 1);
375  numaReplaceNumber(na_objs, 3, 3); /* refers to parent of all */
376  for (j = 4; j < nobj - 1; j++)
377  numaSetValue(na_objs, j, index++);
378  }
379  numaaAddNuma(naa_objs, na_objs, L_INSERT);
380  l_dnaDestroy(&da);
381  }
382 
383  /* Make the Pages object (#3) */
384  str_pages = generatePagesObjStringPdf(napage);
385 
386  /* Build the output */
387  bad = l_byteaCreate(5000);
388  da_outlocs = l_dnaCreate(0); /* locations of all output objects */
389  for (i = 0; i < npages; i++) {
390  bas = (L_BYTEA *)ptraGetPtrToItem(pa_data, i);
391  pdfdata = l_byteaGetData(bas, &size);
392  da_locs = l_dnaaGetDna(daa_locs, i, L_CLONE); /* locs on this page */
393  na_objs = numaaGetNuma(naa_objs, i, L_CLONE); /* obj # on this page */
394  nobj = l_dnaGetCount(da_locs) - 1;
395  da_sizes = l_dnaDiffAdjValues(da_locs); /* object sizes on this page */
396  sizes = l_dnaGetIArray(da_sizes);
397  locs = l_dnaGetIArray(da_locs);
398  if (i == 0) {
399  l_byteaAppendData(bad, pdfdata, sizes[0]);
400  l_byteaAppendData(bad, pdfdata + locs[1], sizes[1]);
401  l_byteaAppendData(bad, pdfdata + locs[2], sizes[2]);
402  l_byteaAppendString(bad, str_pages);
403  for (j = 0; j < 4; j++)
404  l_dnaAddNumber(da_outlocs, locs[j]);
405  }
406  for (j = 4; j < nobj; j++) {
407  l_dnaAddNumber(da_outlocs, l_byteaGetSize(bad));
408  bat1 = l_byteaInitFromMem(pdfdata + locs[j], sizes[j]);
409  bat2 = substituteObjectNumbers(bat1, na_objs);
410  data = l_byteaGetData(bat2, &size);
411  l_byteaAppendData(bad, data, size);
412  l_byteaDestroy(&bat1);
413  l_byteaDestroy(&bat2);
414  }
415  if (i == npages - 1) /* last one */
416  l_dnaAddNumber(da_outlocs, l_byteaGetSize(bad));
417  LEPT_FREE(sizes);
418  LEPT_FREE(locs);
419  l_dnaDestroy(&da_locs);
420  numaDestroy(&na_objs);
421  l_dnaDestroy(&da_sizes);
422  }
423 
424  /* Add the trailer */
425  str_trailer = makeTrailerStringPdf(da_outlocs);
426  l_byteaAppendString(bad, str_trailer);
427 
428  /* Transfer the output data */
429  *pdata = l_byteaCopyData(bad, pnbytes);
430  l_byteaDestroy(&bad);
431 
432 #if DEBUG_MULTIPAGE
433  fprintf(stderr, "******** object mapper **********");
434  numaaWriteStream(stderr, naa_objs);
435 
436  fprintf(stderr, "******** Page object numbers ***********");
437  numaWriteStream(stderr, napage);
438 
439  fprintf(stderr, "******** Pages object ***********\n");
440  fprintf(stderr, "%s\n", str_pages);
441 #endif /* DEBUG_MULTIPAGE */
442 
443  numaDestroy(&napage);
444  numaaDestroy(&naa_objs);
445  l_dnaDestroy(&da_outlocs);
446  l_dnaaDestroy(&daa_locs);
447  LEPT_FREE(str_pages);
448  LEPT_FREE(str_trailer);
449  return 0;
450 }
451 
452 
453 /*---------------------------------------------------------------------*
454  * Convert tiff multipage to pdf file *
455  *---------------------------------------------------------------------*/
469 l_int32
470 convertTiffMultipageToPdf(const char *filein,
471  const char *fileout)
472 {
473 l_int32 istiff;
474 PIXA *pixa;
475 FILE *fp;
476 
477  PROCNAME("convertTiffMultipageToPdf");
478 
479  if ((fp = fopenReadStream(filein)) == NULL)
480  return ERROR_INT("file not found", procName, 1);
481  istiff = fileFormatIsTiff(fp);
482  fclose(fp);
483  if (!istiff)
484  return ERROR_INT("file not tiff format", procName, 1);
485 
486  pixa = pixaReadMultipageTiff(filein);
487  pixaConvertToPdf(pixa, 0, 1.0, 0, 0, "weasel2", fileout);
488  pixaDestroy(&pixa);
489  return 0;
490 }
491 
492 
493 /*---------------------------------------------------------------------*
494  * Low-level CID-based operations *
495  *---------------------------------------------------------------------*/
518 l_int32
519 l_generateCIDataForPdf(const char *fname,
520  PIX *pix,
521  l_int32 quality,
522  L_COMP_DATA **pcid)
523 {
524 l_int32 format, type;
525 L_COMP_DATA *cid;
526 PIX *pixt;
527 
528  PROCNAME("l_generateCIDataForPdf");
529 
530  if (!pcid)
531  return ERROR_INT("&cid not defined", procName, 1);
532  *pcid = cid = NULL;
533  if (!fname && !pix)
534  return ERROR_INT("neither fname nor pix are defined", procName, 1);
535 
536  /* If a compressed file is given that is not 'stdin', see if we
537  * can generate the pdf output without transcoding. */
538  if (fname && strcmp(fname, "-") != 0 && strcmp(fname, "stdin") != 0) {
539  findFileFormat(fname, &format);
540  if (format == IFF_UNKNOWN)
541  L_WARNING("file %s format is unknown\n", procName, fname);
542  if (format == IFF_PS || format == IFF_LPDF) {
543  L_ERROR("file %s is unsupported format %d\n",
544  procName, fname, format);
545  return 1;
546  }
547  if (format == IFF_JFIF_JPEG) {
548  cid = l_generateJpegData(fname, 0);
549  } else if (format == IFF_JP2) {
550  cid = l_generateJp2kData(fname);
551  } else if (format == IFF_PNG) {
552  cid = l_generateFlateDataPdf(fname, pix);
553  }
554 
555  }
556 
557  /* Otherwise, use the pix to generate the pdf output */
558  if (!cid) {
559  if (!pix)
560  pixt = pixRead(fname);
561  else
562  pixt = pixClone(pix);
563  if (!pixt)
564  return ERROR_INT("pixt not made", procName, 1);
565  selectDefaultPdfEncoding(pixt, &type);
566  pixGenerateCIData(pixt, type, quality, 0, &cid);
567  pixDestroy(&pixt);
568  }
569  if (!cid) {
570  L_ERROR("totally kerflummoxed\n", procName);
571  return 1;
572  }
573  *pcid = cid;
574  return 0;
575 }
576 
577 
596 L_COMP_DATA *
597 l_generateFlateDataPdf(const char *fname,
598  PIX *pixs)
599 {
600 l_uint8 *pngcomp = NULL; /* entire PNG compressed file */
601 l_uint8 *datacomp = NULL; /* gzipped raster data */
602 l_uint8 *cmapdata = NULL; /* uncompressed colormap */
603 char *cmapdatahex = NULL; /* hex ascii uncompressed colormap */
604 l_uint32 i, j, n;
605 l_int32 format, interlaced;
606 l_int32 ncolors; /* in colormap */
607 l_int32 bps; /* bits/sample: usually 8 */
608 l_int32 spp; /* samples/pixel: 1-grayscale/cmap); 3-rgb; 4-rgba */
609 l_int32 w, h, cmapflag;
610 l_int32 xres, yres;
611 size_t nbytescomp = 0, nbytespng = 0;
612 FILE *fp;
613 L_COMP_DATA *cid;
614 PIX *pix;
615 PIXCMAP *cmap = NULL;
616 
617  PROCNAME("l_generateFlateDataPdf");
618 
619  if (!fname)
620  return (L_COMP_DATA *)ERROR_PTR("fname not defined", procName, NULL);
621 
622  findFileFormat(fname, &format);
623  spp = 0; /* init to spp != 4 if not png */
624  interlaced = 0; /* initialize to no interlacing */
625  if (format == IFF_PNG) {
626  isPngInterlaced(fname, &interlaced);
627  readHeaderPng(fname, NULL, NULL, NULL, &spp, NULL);
628  }
629 
630  /* PDF is capable of inlining some types of PNG files, but not all
631  of them. We need to transcode anything with interlacing or an
632  alpha channel.
633 
634  Be careful with spp. Any PNG image file with an alpha
635  channel is converted on reading to RGBA (spp == 4). This
636  includes the (gray + alpha) format with spp == 2. You
637  will get different results if you look at spp via
638  readHeaderPng() versus pixGetSpp() */
639  if (format != IFF_PNG || interlaced || spp == 4 || spp == 2) {
640  if (!pixs)
641  pix = pixRead(fname);
642  else
643  pix = pixClone(pixs);
644  if (!pix)
645  return (L_COMP_DATA *)ERROR_PTR("pix not made", procName, NULL);
646  cid = pixGenerateFlateData(pix, 0);
647  pixDestroy(&pix);
648  return cid;
649  }
650 
651  /* It's png. Generate the pdf data without transcoding.
652  * Implementation by Jeff Breidenbach.
653  * First, read the metadata */
654  if ((fp = fopenReadStream(fname)) == NULL)
655  return (L_COMP_DATA *)ERROR_PTR("stream not opened", procName, NULL);
656  freadHeaderPng(fp, &w, &h, &bps, &spp, &cmapflag);
657  fgetPngResolution(fp, &xres, &yres);
658  fclose(fp);
659 
660  /* We get pdf corruption when inlining the data from 16 bpp png. */
661  if (bps == 16)
662  return l_generateFlateData(fname, 0);
663 
664  /* Read the entire png file */
665  if ((pngcomp = l_binaryRead(fname, &nbytespng)) == NULL)
666  return (L_COMP_DATA *)ERROR_PTR("unable to read file",
667  procName, NULL);
668 
669  /* Extract flate data, copying portions of it to memory, including
670  * the predictor information in a byte at the beginning of each
671  * raster line. The flate data makes up the vast majority of
672  * the png file, so after extraction we expect datacomp to
673  * be nearly full (i.e., nbytescomp will be only slightly less
674  * than nbytespng). Also extract the colormap if present. */
675  if ((datacomp = (l_uint8 *)LEPT_CALLOC(1, nbytespng)) == NULL) {
676  LEPT_FREE(pngcomp);
677  return (L_COMP_DATA *)ERROR_PTR("unable to allocate memory",
678  procName, NULL);
679  }
680 
681  /* Parse the png file. Each chunk consists of:
682  * length: 4 bytes
683  * name: 4 bytes (e.g., "IDAT")
684  * data: n bytes
685  * CRC: 4 bytes
686  * Start at the beginning of the data section of the first chunk,
687  * byte 16, because the png file begins with 8 bytes of header,
688  * followed by the first 8 bytes of the first chunk
689  * (length and name). On each loop, increment by 12 bytes to
690  * skip over the CRC, length and name of the next chunk. */
691  for (i = 16; i < nbytespng; i += 12) { /* do each successive chunk */
692  /* Get the chunk length */
693  n = pngcomp[i - 8] << 24;
694  n += pngcomp[i - 7] << 16;
695  n += pngcomp[i - 6] << 8;
696  n += pngcomp[i - 5] << 0;
697  if (i + n >= nbytespng) {
698  LEPT_FREE(pngcomp);
699  LEPT_FREE(datacomp);
700  pixcmapDestroy(&cmap);
701  L_ERROR("invalid png: i = %d, n = %d, nbytes = %lu\n", procName,
702  i, n, (unsigned long)nbytespng);
703  return NULL;
704  }
705 
706  /* Is it a data chunk? */
707  if (strncmp((const char *)(pngcomp + i - 4), "IDAT", 4) == 0) {
708  memcpy(datacomp + nbytescomp, pngcomp + i, n);
709  nbytescomp += n;
710  }
711 
712  /* Is it a palette chunk? */
713  if (cmapflag && !cmap &&
714  strncmp((const char *)(pngcomp + i - 4), "PLTE", 4) == 0) {
715  if ((n / 3) > (1 << bps)) {
716  LEPT_FREE(pngcomp);
717  LEPT_FREE(datacomp);
718  pixcmapDestroy(&cmap);
719  L_ERROR("invalid png: i = %d, n = %d, cmapsize = %d\n",
720  procName, i, n, (1 << bps));
721  return NULL;
722  }
723  cmap = pixcmapCreate(bps);
724  for (j = i; j < i + n; j += 3) {
725  pixcmapAddColor(cmap, pngcomp[j], pngcomp[j + 1],
726  pngcomp[j + 2]);
727  }
728  }
729  i += n; /* move to the end of the data chunk */
730  }
731  LEPT_FREE(pngcomp);
732 
733  if (nbytescomp == 0) {
734  LEPT_FREE(datacomp);
735  pixcmapDestroy(&cmap);
736  return (L_COMP_DATA *)ERROR_PTR("invalid PNG file", procName, NULL);
737  }
738 
739  /* Extract and encode the colormap data as hexascii */
740  ncolors = 0;
741  if (cmap) {
742  pixcmapSerializeToMemory(cmap, 3, &ncolors, &cmapdata);
743  pixcmapDestroy(&cmap);
744  if (!cmapdata) {
745  LEPT_FREE(datacomp);
746  return (L_COMP_DATA *)ERROR_PTR("cmapdata not made",
747  procName, NULL);
748  }
749  cmapdatahex = pixcmapConvertToHex(cmapdata, ncolors);
750  LEPT_FREE(cmapdata);
751  }
752 
753  /* Note that this is the only situation where the predictor
754  * field of the CID is set to 1. Adobe's predictor values on
755  * p. 76 of pdf_reference_1-7.pdf give 1 for no predictor and
756  * 10-14 for inline predictors, the specifics of which are
757  * ignored by the pdf interpreter, which just needs to know that
758  * the first byte on each compressed scanline is some predictor
759  * whose type can be inferred from the byte itself. */
760  cid = (L_COMP_DATA *)LEPT_CALLOC(1, sizeof(L_COMP_DATA));
761  cid->datacomp = datacomp;
762  cid->type = L_FLATE_ENCODE;
763  cid->cmapdatahex = cmapdatahex;
764  cid->nbytescomp = nbytescomp;
765  cid->ncolors = ncolors;
766  cid->predictor = TRUE;
767  cid->w = w;
768  cid->h = h;
769  cid->bps = bps;
770  cid->spp = spp;
771  cid->res = xres;
772  return cid;
773 }
774 
775 
791 L_COMP_DATA *
792 l_generateJpegData(const char *fname,
793  l_int32 ascii85flag)
794 {
795 l_uint8 *datacomp = NULL; /* entire jpeg compressed file */
796 char *data85 = NULL; /* ascii85 encoded jpeg compressed file */
797 l_int32 w, h, xres, yres, bps, spp;
798 l_int32 nbytes85;
799 size_t nbytescomp;
800 FILE *fp;
801 L_COMP_DATA *cid;
802 
803  PROCNAME("l_generateJpegData");
804 
805  if (!fname)
806  return (L_COMP_DATA *)ERROR_PTR("fname not defined", procName, NULL);
807 
808  /* Read the metadata */
809  if ((fp = fopenReadStream(fname)) == NULL)
810  return (L_COMP_DATA *)ERROR_PTR("stream not opened", procName, NULL);
811  freadHeaderJpeg(fp, &w, &h, &spp, NULL, NULL);
812  bps = 8;
813  fgetJpegResolution(fp, &xres, &yres);
814  fclose(fp);
815 
816  /* The returned jpeg data in memory is the entire jpeg file,
817  * which starts with ffd8 and ends with ffd9 */
818  if ((datacomp = l_binaryRead(fname, &nbytescomp)) == NULL)
819  return (L_COMP_DATA *)ERROR_PTR("datacomp not extracted",
820  procName, NULL);
821 
822  /* Optionally, encode the compressed data */
823  if (ascii85flag == 1) {
824  data85 = encodeAscii85(datacomp, nbytescomp, &nbytes85);
825  LEPT_FREE(datacomp);
826  if (!data85)
827  return (L_COMP_DATA *)ERROR_PTR("data85 not made", procName, NULL);
828  else
829  data85[nbytes85 - 1] = '\0'; /* remove the newline */
830  }
831 
832  cid = (L_COMP_DATA *)LEPT_CALLOC(1, sizeof(L_COMP_DATA));
833  if (ascii85flag == 0) {
834  cid->datacomp = datacomp;
835  } else { /* ascii85 */
836  cid->data85 = data85;
837  cid->nbytes85 = nbytes85;
838  }
839  cid->type = L_JPEG_ENCODE;
840  cid->nbytescomp = nbytescomp;
841  cid->w = w;
842  cid->h = h;
843  cid->bps = bps;
844  cid->spp = spp;
845  cid->res = xres;
846  return cid;
847 }
848 
849 
861 static L_COMP_DATA *
862 l_generateJp2kData(const char *fname)
863 {
864 l_int32 w, h, bps, spp;
865 size_t nbytes;
866 L_COMP_DATA *cid;
867 
868  PROCNAME("l_generateJp2kData");
869 
870  if (!fname)
871  return (L_COMP_DATA *)ERROR_PTR("fname not defined", procName, NULL);
872 
873  if ((cid = (L_COMP_DATA *)LEPT_CALLOC(1, sizeof(L_COMP_DATA))) == NULL)
874  return (L_COMP_DATA *)ERROR_PTR("cid not made", procName, NULL);
875 
876  /* The returned jp2k data in memory is the entire jp2k file */
877  if ((cid->datacomp = l_binaryRead(fname, &nbytes)) == NULL) {
878  l_CIDataDestroy(&cid);
879  return (L_COMP_DATA *)ERROR_PTR("data not extracted", procName, NULL);
880  }
881 
882  readHeaderJp2k(fname, &w, &h, &bps, &spp);
883  cid->type = L_JP2K_ENCODE;
884  cid->nbytescomp = nbytes;
885  cid->w = w;
886  cid->h = h;
887  cid->bps = bps;
888  cid->spp = spp;
889  cid->res = 0; /* don't know how to extract this */
890  return cid;
891 }
892 
893 
916 l_int32
917 l_generateCIData(const char *fname,
918  l_int32 type,
919  l_int32 quality,
920  l_int32 ascii85,
921  L_COMP_DATA **pcid)
922 {
923 l_int32 format, d, bps, spp, iscmap;
924 L_COMP_DATA *cid;
925 PIX *pix;
926 
927  PROCNAME("l_generateCIData");
928 
929  if (!pcid)
930  return ERROR_INT("&cid not defined", procName, 1);
931  *pcid = NULL;
932  if (!fname)
933  return ERROR_INT("fname not defined", procName, 1);
934  if (type != L_G4_ENCODE && type != L_JPEG_ENCODE &&
935  type != L_FLATE_ENCODE && type != L_JP2K_ENCODE)
936  return ERROR_INT("invalid conversion type", procName, 1);
937  if (ascii85 != 0 && ascii85 != 1)
938  return ERROR_INT("invalid ascii85", procName, 1);
939 
940  /* Sanity check on requested encoding */
941  pixReadHeader(fname, &format, NULL, NULL, &bps, &spp, &iscmap);
942  d = bps * spp;
943  if (d == 24) d = 32;
944  if (iscmap && type != L_FLATE_ENCODE) {
945  L_WARNING("pixs has cmap; using flate encoding\n", procName);
946  type = L_FLATE_ENCODE;
947  } else if (d < 8 && type == L_JPEG_ENCODE) {
948  L_WARNING("pixs has < 8 bpp; using flate encoding\n", procName);
949  type = L_FLATE_ENCODE;
950  } else if (d < 8 && type == L_JP2K_ENCODE) {
951  L_WARNING("pixs has < 8 bpp; using flate encoding\n", procName);
952  type = L_FLATE_ENCODE;
953  } else if (d > 1 && type == L_G4_ENCODE) {
954  L_WARNING("pixs has > 1 bpp; using flate encoding\n", procName);
955  type = L_FLATE_ENCODE;
956  }
957 
958  if (type == L_JPEG_ENCODE) {
959  if (format == IFF_JFIF_JPEG) { /* do not transcode */
960  cid = l_generateJpegData(fname, ascii85);
961  } else {
962  if ((pix = pixRead(fname)) == NULL)
963  return ERROR_INT("pix not returned", procName, 1);
964  cid = pixGenerateJpegData(pix, ascii85, quality);
965  pixDestroy(&pix);
966  }
967  if (!cid)
968  return ERROR_INT("jpeg data not made", procName, 1);
969  } else if (type == L_JP2K_ENCODE) {
970  if (format == IFF_JP2) { /* do not transcode */
971  cid = l_generateJp2kData(fname);
972  } else {
973  if ((pix = pixRead(fname)) == NULL)
974  return ERROR_INT("pix not returned", procName, 1);
975  cid = pixGenerateJpegData(pix, ascii85, quality);
976  pixDestroy(&pix);
977  }
978  if (!cid)
979  return ERROR_INT("jpeg data not made", procName, 1);
980  } else if (type == L_G4_ENCODE) {
981  if ((cid = l_generateG4Data(fname, ascii85)) == NULL)
982  return ERROR_INT("g4 data not made", procName, 1);
983  } else if (type == L_FLATE_ENCODE) {
984  if ((cid = l_generateFlateData(fname, ascii85)) == NULL)
985  return ERROR_INT("flate data not made", procName, 1);
986  } else {
987  return ERROR_INT("invalid conversion type", procName, 1);
988  }
989  *pcid = cid;
990 
991  return 0;
992 }
993 
994 
1012 l_int32
1014  l_int32 type,
1015  l_int32 quality,
1016  l_int32 ascii85,
1017  L_COMP_DATA **pcid)
1018 {
1019 l_int32 d;
1020 PIXCMAP *cmap;
1021 
1022  PROCNAME("pixGenerateCIData");
1023 
1024  if (!pcid)
1025  return ERROR_INT("&cid not defined", procName, 1);
1026  *pcid = NULL;
1027  if (!pixs)
1028  return ERROR_INT("pixs not defined", procName, 1);
1029  if (type != L_G4_ENCODE && type != L_JPEG_ENCODE &&
1030  type != L_FLATE_ENCODE)
1031  return ERROR_INT("invalid conversion type", procName, 1);
1032  if (ascii85 != 0 && ascii85 != 1)
1033  return ERROR_INT("invalid ascii85", procName, 1);
1034 
1035  /* Sanity check on requested encoding */
1036  d = pixGetDepth(pixs);
1037  cmap = pixGetColormap(pixs);
1038  if (cmap && type != L_FLATE_ENCODE) {
1039  L_WARNING("pixs has cmap; using flate encoding\n", procName);
1040  type = L_FLATE_ENCODE;
1041  } else if (d < 8 && type == L_JPEG_ENCODE) {
1042  L_WARNING("pixs has < 8 bpp; using flate encoding\n", procName);
1043  type = L_FLATE_ENCODE;
1044  } else if (d > 1 && type == L_G4_ENCODE) {
1045  L_WARNING("pixs has > 1 bpp; using flate encoding\n", procName);
1046  type = L_FLATE_ENCODE;
1047  }
1048 
1049  if (type == L_JPEG_ENCODE) {
1050  if ((*pcid = pixGenerateJpegData(pixs, ascii85, quality)) == NULL)
1051  return ERROR_INT("jpeg data not made", procName, 1);
1052  } else if (type == L_G4_ENCODE) {
1053  if ((*pcid = pixGenerateG4Data(pixs, ascii85)) == NULL)
1054  return ERROR_INT("g4 data not made", procName, 1);
1055  } else if (type == L_FLATE_ENCODE) {
1056  if ((*pcid = pixGenerateFlateData(pixs, ascii85)) == NULL)
1057  return ERROR_INT("flate data not made", procName, 1);
1058  } else {
1059  return ERROR_INT("invalid conversion type", procName, 1);
1060  }
1061 
1062  return 0;
1063 }
1064 
1065 
1085 L_COMP_DATA *
1086 l_generateFlateData(const char *fname,
1087  l_int32 ascii85flag)
1088 {
1089 L_COMP_DATA *cid;
1090 PIX *pixs;
1091 
1092  PROCNAME("l_generateFlateData");
1093 
1094  if (!fname)
1095  return (L_COMP_DATA *)ERROR_PTR("fname not defined", procName, NULL);
1096 
1097  if ((pixs = pixRead(fname)) == NULL)
1098  return (L_COMP_DATA *)ERROR_PTR("pixs not made", procName, NULL);
1099  cid = pixGenerateFlateData(pixs, ascii85flag);
1100  pixDestroy(&pixs);
1101  return cid;
1102 }
1103 
1104 
1119 static L_COMP_DATA *
1121  l_int32 ascii85flag)
1122 {
1123 l_uint8 *data = NULL; /* uncompressed raster data in required format */
1124 l_uint8 *datacomp = NULL; /* gzipped raster data */
1125 char *data85 = NULL; /* ascii85 encoded gzipped raster data */
1126 l_uint8 *cmapdata = NULL; /* uncompressed colormap */
1127 char *cmapdata85 = NULL; /* ascii85 encoded uncompressed colormap */
1128 char *cmapdatahex = NULL; /* hex ascii uncompressed colormap */
1129 l_int32 ncolors; /* in colormap; not used if cmapdata85 is null */
1130 l_int32 bps; /* bits/sample: usually 8 */
1131 l_int32 spp; /* samples/pixel: 1-grayscale/cmap); 3-rgb */
1132 l_int32 w, h, d, cmapflag;
1133 l_int32 ncmapbytes85 = 0;
1134 l_int32 nbytes85 = 0;
1135 size_t nbytes, nbytescomp;
1136 L_COMP_DATA *cid;
1137 PIX *pixt;
1138 PIXCMAP *cmap;
1139 
1140  PROCNAME("pixGenerateFlateData");
1141 
1142  if (!pixs)
1143  return (L_COMP_DATA *)ERROR_PTR("pixs not defined", procName, NULL);
1144 
1145  /* Convert the image to one of these 4 types:
1146  * 1 bpp
1147  * 8 bpp, no colormap
1148  * 8 bpp, colormap
1149  * 32 bpp rgb */
1150  pixGetDimensions(pixs, &w, &h, &d);
1151  cmap = pixGetColormap(pixs);
1152  cmapflag = (cmap) ? 1 : 0;
1153  if (d == 2 || d == 4 || d == 16) {
1154  pixt = pixConvertTo8(pixs, cmapflag);
1155  cmap = pixGetColormap(pixt);
1156  d = pixGetDepth(pixt);
1157  } else {
1158  pixt = pixClone(pixs);
1159  }
1160  spp = (d == 32) ? 3 : 1; /* ignores alpha */
1161  bps = (d == 32) ? 8 : d;
1162 
1163  /* Extract and encode the colormap data as both ascii85 and hexascii */
1164  ncolors = 0;
1165  if (cmap) {
1166  pixcmapSerializeToMemory(cmap, 3, &ncolors, &cmapdata);
1167  if (!cmapdata) {
1168  pixDestroy(&pixt);
1169  return (L_COMP_DATA *)ERROR_PTR("cmapdata not made",
1170  procName, NULL);
1171  }
1172 
1173  cmapdata85 = encodeAscii85(cmapdata, 3 * ncolors, &ncmapbytes85);
1174  cmapdatahex = pixcmapConvertToHex(cmapdata, ncolors);
1175  LEPT_FREE(cmapdata);
1176  }
1177 
1178  /* Extract and compress the raster data */
1179  pixGetRasterData(pixt, &data, &nbytes);
1180  pixDestroy(&pixt);
1181  datacomp = zlibCompress(data, nbytes, &nbytescomp);
1182  LEPT_FREE(data);
1183  if (!datacomp) {
1184  LEPT_FREE(cmapdata85);
1185  LEPT_FREE(cmapdatahex);
1186  return (L_COMP_DATA *)ERROR_PTR("datacomp not made", procName, NULL);
1187  }
1188 
1189  /* Optionally, encode the compressed data */
1190  if (ascii85flag == 1) {
1191  data85 = encodeAscii85(datacomp, nbytescomp, &nbytes85);
1192  LEPT_FREE(datacomp);
1193  if (!data85) {
1194  LEPT_FREE(cmapdata85);
1195  LEPT_FREE(cmapdatahex);
1196  return (L_COMP_DATA *)ERROR_PTR("data85 not made", procName, NULL);
1197  } else {
1198  data85[nbytes85 - 1] = '\0'; /* remove the newline */
1199  }
1200  }
1201 
1202  cid = (L_COMP_DATA *)LEPT_CALLOC(1, sizeof(L_COMP_DATA));
1203  if (ascii85flag == 0) {
1204  cid->datacomp = datacomp;
1205  } else { /* ascii85 */
1206  cid->data85 = data85;
1207  cid->nbytes85 = nbytes85;
1208  }
1209  cid->type = L_FLATE_ENCODE;
1210  cid->cmapdatahex = cmapdatahex;
1211  cid->cmapdata85 = cmapdata85;
1212  cid->nbytescomp = nbytescomp;
1213  cid->ncolors = ncolors;
1214  cid->w = w;
1215  cid->h = h;
1216  cid->bps = bps;
1217  cid->spp = spp;
1218  cid->res = pixGetXRes(pixs);
1219  cid->nbytes = nbytes; /* only for debugging */
1220  return cid;
1221 }
1222 
1223 
1239 static L_COMP_DATA *
1241  l_int32 ascii85flag,
1242  l_int32 quality)
1243 {
1244 l_int32 d;
1245 char *fname;
1246 L_COMP_DATA *cid;
1247 
1248  PROCNAME("pixGenerateJpegData");
1249 
1250  if (!pixs)
1251  return (L_COMP_DATA *)ERROR_PTR("pixs not defined", procName, NULL);
1252  if (pixGetColormap(pixs))
1253  return (L_COMP_DATA *)ERROR_PTR("pixs has colormap", procName, NULL);
1254  d = pixGetDepth(pixs);
1255  if (d != 8 && d != 32)
1256  return (L_COMP_DATA *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
1257 
1258  /* Compress to a temp jpeg file */
1259  fname = l_makeTempFilename();
1260  pixWriteJpeg(fname, pixs, quality, 0);
1261 
1262  cid = l_generateJpegData(fname, ascii85flag);
1263  lept_rmfile(fname);
1264  LEPT_FREE(fname);
1265  return cid;
1266 }
1267 
1268 
1283 static L_COMP_DATA *
1285  l_int32 ascii85flag)
1286 {
1287 char *tname;
1288 L_COMP_DATA *cid;
1289 
1290  PROCNAME("pixGenerateG4Data");
1291 
1292  if (!pixs)
1293  return (L_COMP_DATA *)ERROR_PTR("pixs not defined", procName, NULL);
1294  if (pixGetDepth(pixs) != 1)
1295  return (L_COMP_DATA *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
1296 
1297  /* Compress to a temp tiff g4 file */
1298  tname = l_makeTempFilename();
1299  pixWrite(tname, pixs, IFF_TIFF_G4);
1300 
1301  cid = l_generateG4Data(tname, ascii85flag);
1302  lept_rmfile(tname);
1303  LEPT_FREE(tname);
1304  return cid;
1305 }
1306 
1307 
1323 L_COMP_DATA *
1324 l_generateG4Data(const char *fname,
1325  l_int32 ascii85flag)
1326 {
1327 l_uint8 *datacomp = NULL; /* g4 compressed raster data */
1328 char *data85 = NULL; /* ascii85 encoded g4 compressed data */
1329 l_int32 w, h, xres, yres;
1330 l_int32 minisblack; /* TRUE or FALSE */
1331 l_int32 nbytes85;
1332 size_t nbytescomp;
1333 L_COMP_DATA *cid;
1334 FILE *fp;
1335 
1336  PROCNAME("l_generateG4Data");
1337 
1338  if (!fname)
1339  return (L_COMP_DATA *)ERROR_PTR("fname not defined", procName, NULL);
1340 
1341  /* Read the resolution */
1342  if ((fp = fopenReadStream(fname)) == NULL)
1343  return (L_COMP_DATA *)ERROR_PTR("stream not opened", procName, NULL);
1344  getTiffResolution(fp, &xres, &yres);
1345  fclose(fp);
1346 
1347  /* The returned ccitt g4 data in memory is the block of
1348  * bytes in the tiff file, starting after 8 bytes and
1349  * ending before the directory. */
1350  if (extractG4DataFromFile(fname, &datacomp, &nbytescomp,
1351  &w, &h, &minisblack)) {
1352  return (L_COMP_DATA *)ERROR_PTR("datacomp not extracted",
1353  procName, NULL);
1354  }
1355 
1356  /* Optionally, encode the compressed data */
1357  if (ascii85flag == 1) {
1358  data85 = encodeAscii85(datacomp, nbytescomp, &nbytes85);
1359  LEPT_FREE(datacomp);
1360  if (!data85)
1361  return (L_COMP_DATA *)ERROR_PTR("data85 not made", procName, NULL);
1362  else
1363  data85[nbytes85 - 1] = '\0'; /* remove the newline */
1364  }
1365 
1366  cid = (L_COMP_DATA *)LEPT_CALLOC(1, sizeof(L_COMP_DATA));
1367  if (ascii85flag == 0) {
1368  cid->datacomp = datacomp;
1369  } else { /* ascii85 */
1370  cid->data85 = data85;
1371  cid->nbytes85 = nbytes85;
1372  }
1373  cid->type = L_G4_ENCODE;
1374  cid->nbytescomp = nbytescomp;
1375  cid->w = w;
1376  cid->h = h;
1377  cid->bps = 1;
1378  cid->spp = 1;
1379  cid->minisblack = minisblack;
1380  cid->res = xres;
1381  return cid;
1382 }
1383 
1384 
1400 l_int32
1402  const char *title,
1403  l_uint8 **pdata,
1404  size_t *pnbytes)
1405 {
1406 l_int32 res, ret;
1407 l_float32 wpt, hpt;
1408 L_PDF_DATA *lpd = NULL;
1409 
1410  PROCNAME("cidConvertToPdfData");
1411 
1412  if (!pdata || !pnbytes)
1413  return ERROR_INT("&data and &nbytes not both defined", procName, 1);
1414  *pdata = NULL;
1415  *pnbytes = 0;
1416  if (!cid)
1417  return ERROR_INT("cid not defined", procName, 1);
1418 
1419  /* Get media box parameters, in pts */
1420  res = cid->res;
1421  if (res <= 0)
1422  res = DEFAULT_INPUT_RES;
1423  wpt = cid->w * 72. / res;
1424  hpt = cid->h * 72. / res;
1425 
1426  /* Set up the pdf data struct (lpd) */
1427  if ((lpd = pdfdataCreate(title)) == NULL)
1428  return ERROR_INT("lpd not made", procName, 1);
1429  ptraAdd(lpd->cida, cid);
1430  lpd->n++;
1431  ptaAddPt(lpd->xy, 0, 0); /* xpt = ypt = 0 */
1432  ptaAddPt(lpd->wh, wpt, hpt);
1433 
1434  /* Generate the pdf string and destroy the lpd */
1435  ret = l_generatePdf(pdata, pnbytes, lpd);
1436  pdfdataDestroy(&lpd);
1437  if (ret)
1438  return ERROR_INT("pdf output not made", procName, 1);
1439  return 0;
1440 }
1441 
1442 
1449 void
1451 {
1452 L_COMP_DATA *cid;
1453 
1454  PROCNAME("l_CIDataDestroy");
1455 
1456  if (pcid == NULL) {
1457  L_WARNING("ptr address is null!\n", procName);
1458  return;
1459  }
1460  if ((cid = *pcid) == NULL)
1461  return;
1462 
1463  if (cid->datacomp) LEPT_FREE(cid->datacomp);
1464  if (cid->data85) LEPT_FREE(cid->data85);
1465  if (cid->cmapdata85) LEPT_FREE(cid->cmapdata85);
1466  if (cid->cmapdatahex) LEPT_FREE(cid->cmapdatahex);
1467  LEPT_FREE(cid);
1468  *pcid = NULL;
1469  return;
1470 }
1471 
1472 
1473 /*---------------------------------------------------------------------*
1474  * Helper functions for generating the output pdf string *
1475  *---------------------------------------------------------------------*/
1497 static l_int32
1498 l_generatePdf(l_uint8 **pdata,
1499  size_t *pnbytes,
1500  L_PDF_DATA *lpd)
1501 {
1502  PROCNAME("l_generatePdf");
1503 
1504  if (!pdata)
1505  return ERROR_INT("&data not defined", procName, 1);
1506  *pdata = NULL;
1507  if (!pnbytes)
1508  return ERROR_INT("&nbytes not defined", procName, 1);
1509  *pnbytes = 0;
1510  if (!lpd)
1511  return ERROR_INT("lpd not defined", procName, 1);
1512 
1513  generateFixedStringsPdf(lpd);
1514  generateMediaboxPdf(lpd);
1515  generatePageStringPdf(lpd);
1516  generateContentStringPdf(lpd);
1517  generatePreXStringsPdf(lpd);
1518  generateColormapStringsPdf(lpd);
1519  generateTrailerPdf(lpd);
1520  return generateOutputDataPdf(pdata, pnbytes, lpd);
1521 }
1522 
1523 
1524 static void
1525 generateFixedStringsPdf(L_PDF_DATA *lpd)
1526 {
1527 char buf[L_SMALLBUF];
1528 char *version, *datestr;
1529 SARRAY *sa;
1530 
1531  PROCNAME("generateFixedStringsPdf");
1532 
1533  /* Accumulate data for the header and objects 1-3 */
1534  lpd->id = stringNew("%PDF-1.5\n");
1535  l_dnaAddNumber(lpd->objsize, strlen(lpd->id));
1536 
1537  lpd->obj1 = stringNew("1 0 obj\n"
1538  "<<\n"
1539  "/Type /Catalog\n"
1540  "/Pages 3 0 R\n"
1541  ">>\n"
1542  "endobj\n");
1543  l_dnaAddNumber(lpd->objsize, strlen(lpd->obj1));
1544 
1545  sa = sarrayCreate(0);
1546  sarrayAddString(sa, (char *)"2 0 obj\n"
1547  "<<\n", L_COPY);
1548  if (var_WRITE_DATE_AND_VERSION) {
1549  datestr = l_getFormattedDate();
1550  snprintf(buf, sizeof(buf), "/CreationDate (D:%s)\n", datestr);
1551  sarrayAddString(sa, (char *)buf, L_COPY);
1552  LEPT_FREE(datestr);
1553  version = getLeptonicaVersion();
1554  snprintf(buf, sizeof(buf),
1555  "/Producer (leptonica: %s)\n", version);
1556  LEPT_FREE(version);
1557  } else {
1558  snprintf(buf, sizeof(buf), "/Producer (leptonica)\n");
1559  }
1560  sarrayAddString(sa, (char *)buf, L_COPY);
1561  if (lpd->title) {
1562  char *hexstr;
1563  if ((hexstr = generateEscapeString(lpd->title)) != NULL) {
1564  snprintf(buf, sizeof(buf), "/Title %s\n", hexstr);
1565  sarrayAddString(sa, (char *)buf, L_COPY);
1566  } else {
1567  L_ERROR("title string is not ascii\n", procName);
1568  }
1569  LEPT_FREE(hexstr);
1570  }
1571  sarrayAddString(sa, (char *)">>\n"
1572  "endobj\n", L_COPY);
1573  lpd->obj2 = sarrayToString(sa, 0);
1574  l_dnaAddNumber(lpd->objsize, strlen(lpd->obj2));
1575  sarrayDestroy(&sa);
1576 
1577  lpd->obj3 = stringNew("3 0 obj\n"
1578  "<<\n"
1579  "/Type /Pages\n"
1580  "/Kids [ 4 0 R ]\n"
1581  "/Count 1\n"
1582  ">>\n");
1583  l_dnaAddNumber(lpd->objsize, strlen(lpd->obj3));
1584 
1585  /* Do the post-datastream string */
1586  lpd->poststream = stringNew("\n"
1587  "endstream\n"
1588  "endobj\n");
1589  return;
1590 }
1591 
1592 
1609 static char *
1610 generateEscapeString(const char *str)
1611 {
1612 char smallbuf[8];
1613 char *buffer;
1614 l_int32 i, nchar, buflen;
1615 
1616  PROCNAME("generateEscapeString");
1617 
1618  if (!str)
1619  return (char *)ERROR_PTR("str not defined", procName, NULL);
1620  nchar = strlen(str);
1621  for (i = 0; i < nchar; i++) {
1622  if (str[i] < 0)
1623  return (char *)ERROR_PTR("str not all ascii", procName, NULL);
1624  }
1625 
1626  buflen = 4 * nchar + 10;
1627  buffer = (char *)LEPT_CALLOC(buflen, sizeof(char));
1628  stringCat(buffer, buflen, "<feff");
1629  for (i = 0; i < nchar; i++) {
1630  snprintf(smallbuf, sizeof(smallbuf), "%04x", str[i]);
1631  stringCat(buffer, buflen, smallbuf);
1632  }
1633  stringCat(buffer, buflen, ">");
1634  return buffer;
1635 }
1636 
1637 
1638 static void
1639 generateMediaboxPdf(L_PDF_DATA *lpd)
1640 {
1641 l_int32 i;
1642 l_float32 xpt, ypt, wpt, hpt, maxx, maxy;
1643 
1644  /* First get the full extent of all the images.
1645  * This is the mediabox, in pts. */
1646  maxx = maxy = 0;
1647  for (i = 0; i < lpd->n; i++) {
1648  ptaGetPt(lpd->xy, i, &xpt, &ypt);
1649  ptaGetPt(lpd->wh, i, &wpt, &hpt);
1650  maxx = L_MAX(maxx, xpt + wpt);
1651  maxy = L_MAX(maxy, ypt + hpt);
1652  }
1653 
1654  lpd->mediabox = boxCreate(0, 0, (l_int32)(maxx + 0.5),
1655  (l_int32)(maxy + 0.5));
1656 
1657  /* ypt is in standard image coordinates: the location of
1658  * the UL image corner with respect to the UL media box corner.
1659  * Rewrite each ypt for PostScript coordinates: the location of
1660  * the LL image corner with respect to the LL media box corner. */
1661  for (i = 0; i < lpd->n; i++) {
1662  ptaGetPt(lpd->xy, i, &xpt, &ypt);
1663  ptaGetPt(lpd->wh, i, &wpt, &hpt);
1664  ptaSetPt(lpd->xy, i, xpt, maxy - ypt - hpt);
1665  }
1666 
1667  return;
1668 }
1669 
1670 
1671 static l_int32
1672 generatePageStringPdf(L_PDF_DATA *lpd)
1673 {
1674 char *buf;
1675 char *xstr;
1676 l_int32 bufsize, i, wpt, hpt;
1677 SARRAY *sa;
1678 
1679  PROCNAME("generatePageStringPdf");
1680 
1681  /* Allocate 1000 bytes for the boilerplate text, and
1682  * 50 bytes for each reference to an image in the
1683  * ProcSet array. */
1684  bufsize = 1000 + 50 * lpd->n;
1685  if ((buf = (char *)LEPT_CALLOC(bufsize, sizeof(char))) == NULL)
1686  return ERROR_INT("calloc fail for buf", procName, 1);
1687 
1688  boxGetGeometry(lpd->mediabox, NULL, NULL, &wpt, &hpt);
1689  sa = sarrayCreate(lpd->n);
1690  for (i = 0; i < lpd->n; i++) {
1691  snprintf(buf, bufsize, "/Im%d %d 0 R ", i + 1, 6 + i);
1692  sarrayAddString(sa, buf, L_COPY);
1693  }
1694  xstr = sarrayToString(sa, 0);
1695  sarrayDestroy(&sa);
1696  if (!xstr) {
1697  LEPT_FREE(buf);
1698  return ERROR_INT("xstr not made", procName, 1);
1699  }
1700 
1701  snprintf(buf, bufsize, "4 0 obj\n"
1702  "<<\n"
1703  "/Type /Page\n"
1704  "/Parent 3 0 R\n"
1705  "/MediaBox [%d %d %d %d]\n"
1706  "/Contents 5 0 R\n"
1707  "/Resources\n"
1708  "<<\n"
1709  "/XObject << %s >>\n"
1710  "/ProcSet [ /ImageB /ImageI /ImageC ]\n"
1711  ">>\n"
1712  ">>\n"
1713  "endobj\n",
1714  0, 0, wpt, hpt, xstr);
1715 
1716  lpd->obj4 = stringNew(buf);
1717  l_dnaAddNumber(lpd->objsize, strlen(lpd->obj4));
1718  sarrayDestroy(&sa);
1719  LEPT_FREE(buf);
1720  LEPT_FREE(xstr);
1721  return 0;
1722 }
1723 
1724 
1725 static l_int32
1726 generateContentStringPdf(L_PDF_DATA *lpd)
1727 {
1728 char *buf;
1729 char *cstr;
1730 l_int32 i, bufsize;
1731 l_float32 xpt, ypt, wpt, hpt;
1732 SARRAY *sa;
1733 
1734  PROCNAME("generateContentStringPdf");
1735 
1736  bufsize = 1000 + 200 * lpd->n;
1737  if ((buf = (char *)LEPT_CALLOC(bufsize, sizeof(char))) == NULL)
1738  return ERROR_INT("calloc fail for buf", procName, 1);
1739 
1740  sa = sarrayCreate(lpd->n);
1741  for (i = 0; i < lpd->n; i++) {
1742  ptaGetPt(lpd->xy, i, &xpt, &ypt);
1743  ptaGetPt(lpd->wh, i, &wpt, &hpt);
1744  snprintf(buf, bufsize,
1745  "q %.4f %.4f %.4f %.4f %.4f %.4f cm /Im%d Do Q\n",
1746  wpt, 0.0, 0.0, hpt, xpt, ypt, i + 1);
1747  sarrayAddString(sa, buf, L_COPY);
1748  }
1749  cstr = sarrayToString(sa, 0);
1750  sarrayDestroy(&sa);
1751  if (!cstr) {
1752  LEPT_FREE(buf);
1753  return ERROR_INT("cstr not made", procName, 1);
1754  }
1755 
1756  snprintf(buf, bufsize, "5 0 obj\n"
1757  "<< /Length %d >>\n"
1758  "stream\n"
1759  "%s"
1760  "endstream\n"
1761  "endobj\n",
1762  (l_int32)strlen(cstr), cstr);
1763 
1764  lpd->obj5 = stringNew(buf);
1765  l_dnaAddNumber(lpd->objsize, strlen(lpd->obj5));
1766  sarrayDestroy(&sa);
1767  LEPT_FREE(buf);
1768  LEPT_FREE(cstr);
1769  return 0;
1770 }
1771 
1772 
1773 static l_int32
1774 generatePreXStringsPdf(L_PDF_DATA *lpd)
1775 {
1776 char buff[256];
1777 char buf[L_BIGBUF];
1778 char *cstr, *bstr, *fstr, *pstr, *xstr;
1779 l_int32 i, cmindex;
1780 L_COMP_DATA *cid;
1781 SARRAY *sa;
1782 
1783  PROCNAME("generatePreXStringsPdf");
1784 
1785  sa = lpd->saprex;
1786  cmindex = 6 + lpd->n; /* starting value */
1787  for (i = 0; i < lpd->n; i++) {
1788  pstr = cstr = NULL;
1789  if ((cid = pdfdataGetCid(lpd, i)) == NULL)
1790  return ERROR_INT("cid not found", procName, 1);
1791 
1792  if (cid->type == L_G4_ENCODE) {
1793  if (var_WRITE_G4_IMAGE_MASK) {
1794  cstr = stringNew("/ImageMask true\n"
1795  "/ColorSpace /DeviceGray");
1796  } else {
1797  cstr = stringNew("/ColorSpace /DeviceGray");
1798  }
1799  bstr = stringNew("/BitsPerComponent 1\n"
1800  "/Interpolate true");
1801  snprintf(buff, sizeof(buff),
1802  "/Filter /CCITTFaxDecode\n"
1803  "/DecodeParms\n"
1804  "<<\n"
1805  "/K -1\n"
1806  "/Columns %d\n"
1807  ">>", cid->w);
1808  fstr = stringNew(buff);
1809  } else if (cid->type == L_JPEG_ENCODE) {
1810  if (cid->spp == 1)
1811  cstr = stringNew("/ColorSpace /DeviceGray");
1812  else if (cid->spp == 3)
1813  cstr = stringNew("/ColorSpace /DeviceRGB");
1814  else if (cid->spp == 4) /* pdf supports cmyk */
1815  cstr = stringNew("/ColorSpace /DeviceCMYK");
1816  else
1817  L_ERROR("in jpeg: spp != 1, 3 or 4\n", procName);
1818  bstr = stringNew("/BitsPerComponent 8");
1819  fstr = stringNew("/Filter /DCTDecode");
1820  } else if (cid->type == L_JP2K_ENCODE) {
1821  if (cid->spp == 1)
1822  cstr = stringNew("/ColorSpace /DeviceGray");
1823  else if (cid->spp == 3)
1824  cstr = stringNew("/ColorSpace /DeviceRGB");
1825  else
1826  L_ERROR("in jp2k: spp != 1 && spp != 3\n", procName);
1827  bstr = stringNew("/BitsPerComponent 8");
1828  fstr = stringNew("/Filter /JPXDecode");
1829  } else { /* type == L_FLATE_ENCODE */
1830  if (cid->ncolors > 0) { /* cmapped */
1831  snprintf(buff, sizeof(buff), "/ColorSpace %d 0 R", cmindex++);
1832  cstr = stringNew(buff);
1833  } else {
1834  if (cid->spp == 1 && cid->bps == 1)
1835  cstr = stringNew("/ColorSpace /DeviceGray\n"
1836  "/Decode [1 0]");
1837  else if (cid->spp == 1) /* 8 bpp */
1838  cstr = stringNew("/ColorSpace /DeviceGray");
1839  else if (cid->spp == 3)
1840  cstr = stringNew("/ColorSpace /DeviceRGB");
1841  else
1842  L_ERROR("unknown colorspace: spp = %d\n",
1843  procName, cid->spp);
1844  }
1845  snprintf(buff, sizeof(buff), "/BitsPerComponent %d", cid->bps);
1846  bstr = stringNew(buff);
1847  fstr = stringNew("/Filter /FlateDecode");
1848  if (cid->predictor == TRUE) {
1849  snprintf(buff, sizeof(buff),
1850  "/DecodeParms\n"
1851  "<<\n"
1852  " /Columns %d\n"
1853  " /Predictor 14\n"
1854  " /Colors %d\n"
1855  " /BitsPerComponent %d\n"
1856  ">>\n", cid->w, cid->spp, cid->bps);
1857  pstr = stringNew(buff);
1858  }
1859  }
1860  if (!pstr) /* no decode parameters */
1861  pstr = stringNew("");
1862 
1863  snprintf(buf, sizeof(buf),
1864  "%d 0 obj\n"
1865  "<<\n"
1866  "/Length %lu\n"
1867  "/Subtype /Image\n"
1868  "%s\n" /* colorspace */
1869  "/Width %d\n"
1870  "/Height %d\n"
1871  "%s\n" /* bits/component */
1872  "%s\n" /* filter */
1873  "%s" /* decode parms; can be empty */
1874  ">>\n"
1875  "stream\n",
1876  6 + i, (unsigned long)cid->nbytescomp, cstr,
1877  cid->w, cid->h, bstr, fstr, pstr);
1878  xstr = stringNew(buf);
1879  sarrayAddString(sa, xstr, L_INSERT);
1880  l_dnaAddNumber(lpd->objsize,
1881  strlen(xstr) + cid->nbytescomp + strlen(lpd->poststream));
1882  LEPT_FREE(cstr);
1883  LEPT_FREE(bstr);
1884  LEPT_FREE(fstr);
1885  LEPT_FREE(pstr);
1886  }
1887 
1888  return 0;
1889 }
1890 
1891 
1892 static l_int32
1893 generateColormapStringsPdf(L_PDF_DATA *lpd)
1894 {
1895 char buf[L_BIGBUF];
1896 char *cmstr;
1897 l_int32 i, cmindex, ncmap;
1898 L_COMP_DATA *cid;
1899 SARRAY *sa;
1900 
1901  PROCNAME("generateColormapStringsPdf");
1902 
1903  /* In our canonical format, we have 5 objects, followed
1904  * by n XObjects, followed by m colormaps, so the index of
1905  * the first colormap object is 6 + n. */
1906  sa = lpd->sacmap;
1907  cmindex = 6 + lpd->n; /* starting value */
1908  ncmap = 0;
1909  for (i = 0; i < lpd->n; i++) {
1910  if ((cid = pdfdataGetCid(lpd, i)) == NULL)
1911  return ERROR_INT("cid not found", procName, 1);
1912  if (cid->ncolors == 0) continue;
1913 
1914  ncmap++;
1915  snprintf(buf, sizeof(buf), "%d 0 obj\n"
1916  "[ /Indexed /DeviceRGB\n"
1917  "%d\n"
1918  "%s\n"
1919  "]\n"
1920  "endobj\n",
1921  cmindex, cid->ncolors - 1, cid->cmapdatahex);
1922  cmindex++;
1923  cmstr = stringNew(buf);
1924  l_dnaAddNumber(lpd->objsize, strlen(cmstr));
1925  sarrayAddString(sa, cmstr, L_INSERT);
1926  }
1927 
1928  lpd->ncmap = ncmap;
1929  return 0;
1930 }
1931 
1932 
1933 static void
1934 generateTrailerPdf(L_PDF_DATA *lpd)
1935 {
1936 l_int32 i, n, size, linestart;
1937 L_DNA *daloc, *dasize;
1938 
1939  /* Let nobj be the number of numbered objects. These numbered
1940  * objects are indexed by their pdf number in arrays naloc[]
1941  * and nasize[]. The 0th object is the 9 byte header. Then
1942  * the number of objects in nasize, which includes the header,
1943  * is n = nobj + 1. The array naloc[] has n + 1 elements,
1944  * because it includes as the last element the starting
1945  * location of xref. The indexing of these objects, their
1946  * starting locations and sizes are:
1947  *
1948  * Object number Starting location Size
1949  * ------------- ----------------- --------------
1950  * 0 daloc[0] = 0 dasize[0] = 9
1951  * 1 daloc[1] = 9 dasize[1] = 49
1952  * n daloc[n] dasize[n]
1953  * xref daloc[n+1]
1954  *
1955  * We first generate daloc.
1956  */
1957  dasize = lpd->objsize;
1958  daloc = lpd->objloc;
1959  linestart = 0;
1960  l_dnaAddNumber(daloc, linestart); /* header */
1961  n = l_dnaGetCount(dasize);
1962  for (i = 0; i < n; i++) {
1963  l_dnaGetIValue(dasize, i, &size);
1964  linestart += size;
1965  l_dnaAddNumber(daloc, linestart);
1966  }
1967  l_dnaGetIValue(daloc, n, &lpd->xrefloc); /* save it */
1968 
1969  /* Now make the actual trailer string */
1970  lpd->trailer = makeTrailerStringPdf(daloc);
1971 }
1972 
1973 
1974 static char *
1975 makeTrailerStringPdf(L_DNA *daloc)
1976 {
1977 char *outstr;
1978 char buf[L_BIGBUF];
1979 l_int32 i, n, linestart, xrefloc;
1980 SARRAY *sa;
1981 
1982  PROCNAME("makeTrailerStringPdf");
1983 
1984  if (!daloc)
1985  return (char *)ERROR_PTR("daloc not defined", procName, NULL);
1986  n = l_dnaGetCount(daloc) - 1; /* numbered objects + 1 (yes, +1) */
1987 
1988  sa = sarrayCreate(0);
1989  snprintf(buf, sizeof(buf), "xref\n"
1990  "0 %d\n"
1991  "0000000000 65535 f \n", n);
1992  sarrayAddString(sa, (char *)buf, L_COPY);
1993  for (i = 1; i < n; i++) {
1994  l_dnaGetIValue(daloc, i, &linestart);
1995  snprintf(buf, sizeof(buf), "%010d 00000 n \n", linestart);
1996  sarrayAddString(sa, (char *)buf, L_COPY);
1997  }
1998 
1999  l_dnaGetIValue(daloc, n, &xrefloc);
2000  snprintf(buf, sizeof(buf), "trailer\n"
2001  "<<\n"
2002  "/Size %d\n"
2003  "/Root 1 0 R\n"
2004  "/Info 2 0 R\n"
2005  ">>\n"
2006  "startxref\n"
2007  "%d\n"
2008  "%%%%EOF\n", n, xrefloc);
2009  sarrayAddString(sa, (char *)buf, L_COPY);
2010  outstr = sarrayToString(sa, 0);
2011  sarrayDestroy(&sa);
2012  return outstr;
2013 }
2014 
2015 
2029 static l_int32
2030 generateOutputDataPdf(l_uint8 **pdata,
2031  size_t *pnbytes,
2032  L_PDF_DATA *lpd)
2033 {
2034 char *str;
2035 l_uint8 *data;
2036 l_int32 nimages, i, len;
2037 l_int32 *sizes, *locs;
2038 size_t nbytes;
2039 L_COMP_DATA *cid;
2040 
2041  PROCNAME("generateOutputDataPdf");
2042 
2043  if (!pdata)
2044  return ERROR_INT("&data not defined", procName, 1);
2045  *pdata = NULL;
2046  if (!pnbytes)
2047  return ERROR_INT("&nbytes not defined", procName, 1);
2048  nbytes = lpd->xrefloc + strlen(lpd->trailer);
2049  *pnbytes = nbytes;
2050  if ((data = (l_uint8 *)LEPT_CALLOC(nbytes, sizeof(l_uint8))) == NULL)
2051  return ERROR_INT("calloc fail for data", procName, 1);
2052  *pdata = data;
2053 
2054  sizes = l_dnaGetIArray(lpd->objsize);
2055  locs = l_dnaGetIArray(lpd->objloc);
2056  memcpy((char *)data, lpd->id, sizes[0]);
2057  memcpy((char *)(data + locs[1]), lpd->obj1, sizes[1]);
2058  memcpy((char *)(data + locs[2]), lpd->obj2, sizes[2]);
2059  memcpy((char *)(data + locs[3]), lpd->obj3, sizes[3]);
2060  memcpy((char *)(data + locs[4]), lpd->obj4, sizes[4]);
2061  memcpy((char *)(data + locs[5]), lpd->obj5, sizes[5]);
2062 
2063  /* Each image has 3 parts: variable preamble, the compressed
2064  * data stream, and the fixed poststream. */
2065  nimages = lpd->n;
2066  for (i = 0; i < nimages; i++) {
2067  if ((cid = pdfdataGetCid(lpd, i)) == NULL) { /* should not happen */
2068  LEPT_FREE(sizes);
2069  LEPT_FREE(locs);
2070  return ERROR_INT("cid not found", procName, 1);
2071  }
2072  str = sarrayGetString(lpd->saprex, i, L_NOCOPY);
2073  len = strlen(str);
2074  memcpy((char *)(data + locs[6 + i]), str, len);
2075  memcpy((char *)(data + locs[6 + i] + len),
2076  (char *)cid->datacomp, cid->nbytescomp);
2077  memcpy((char *)(data + locs[6 + i] + len + cid->nbytescomp),
2078  lpd->poststream, strlen(lpd->poststream));
2079  }
2080 
2081  /* Each colormap is simply a stored string */
2082  for (i = 0; i < lpd->ncmap; i++) {
2083  str = sarrayGetString(lpd->sacmap, i, L_NOCOPY);
2084  memcpy((char *)(data + locs[6 + nimages + i]), str, strlen(str));
2085  }
2086 
2087  /* And finally the trailer */
2088  memcpy((char *)(data + lpd->xrefloc), lpd->trailer, strlen(lpd->trailer));
2089  LEPT_FREE(sizes);
2090  LEPT_FREE(locs);
2091  return 0;
2092 }
2093 
2094 
2095 /*---------------------------------------------------------------------*
2096  * Helper functions for generating multipage pdf output *
2097  *---------------------------------------------------------------------*/
2105 static l_int32
2107  L_DNA **pda)
2108 {
2109 char *str;
2110 l_uint8 nl = '\n';
2111 l_uint8 *data;
2112 l_int32 i, j, start, startloc, xrefloc, found, loc, nobj, objno, trailer_ok;
2113 size_t size;
2114 L_DNA *da, *daobj, *daxref;
2115 SARRAY *sa;
2116 
2117  PROCNAME("parseTrailerPdf");
2118 
2119  if (!pda)
2120  return ERROR_INT("&da not defined", procName, 1);
2121  *pda = NULL;
2122  if (!bas)
2123  return ERROR_INT("bas not defined", procName, 1);
2124  data = l_byteaGetData(bas, &size);
2125  if (strncmp((char *)data, "%PDF-1.", 7) != 0)
2126  return ERROR_INT("PDF header signature not found", procName, 1);
2127 
2128  /* Search for "startxref" starting 50 bytes from the EOF */
2129  start = 0;
2130  if (size > 50)
2131  start = size - 50;
2132  arrayFindSequence(data + start, size - start,
2133  (l_uint8 *)"startxref\n", 10, &loc, &found);
2134  if (!found)
2135  return ERROR_INT("startxref not found!", procName, 1);
2136  if (sscanf((char *)(data + start + loc + 10), "%d\n", &xrefloc) != 1)
2137  return ERROR_INT("xrefloc not found!", procName, 1);
2138  if (xrefloc < 0 || xrefloc >= size)
2139  return ERROR_INT("invalid xrefloc!", procName, 1);
2140  sa = sarrayCreateLinesFromString((char *)(data + xrefloc), 0);
2141  str = sarrayGetString(sa, 1, L_NOCOPY);
2142  if ((sscanf(str, "0 %d", &nobj)) != 1) {
2143  sarrayDestroy(&sa);
2144  return ERROR_INT("nobj not found", procName, 1);
2145  }
2146 
2147  /* Get starting locations. The numa index is the
2148  * object number. loc[0] is the ID; loc[nobj + 1] is xrefloc. */
2149  da = l_dnaCreate(nobj + 1);
2150  *pda = da;
2151  for (i = 0; i < nobj; i++) {
2152  str = sarrayGetString(sa, i + 2, L_NOCOPY);
2153  sscanf(str, "%d", &startloc);
2154  l_dnaAddNumber(da, startloc);
2155  }
2156  l_dnaAddNumber(da, xrefloc);
2157 
2158 #if DEBUG_MULTIPAGE
2159  fprintf(stderr, "************** Trailer string ************\n");
2160  fprintf(stderr, "xrefloc = %d", xrefloc);
2161  sarrayWriteStream(stderr, sa);
2162 
2163  fprintf(stderr, "************** Object locations ************");
2164  l_dnaWriteStream(stderr, da);
2165 #endif /* DEBUG_MULTIPAGE */
2166  sarrayDestroy(&sa);
2167 
2168  /* Verify correct parsing */
2169  trailer_ok = TRUE;
2170  for (i = 1; i < nobj; i++) {
2171  l_dnaGetIValue(da, i, &startloc);
2172  if ((sscanf((char *)(data + startloc), "%d 0 obj", &objno)) != 1) {
2173  L_ERROR("bad trailer for object %d\n", procName, i);
2174  trailer_ok = FALSE;
2175  break;
2176  }
2177  }
2178 
2179  /* If the trailer is broken, reconstruct the correct obj locations */
2180  if (!trailer_ok) {
2181  L_INFO("rebuilding pdf trailer\n", procName);
2182  l_dnaEmpty(da);
2183  l_dnaAddNumber(da, 0);
2184  l_byteaFindEachSequence(bas, (l_uint8 *)" 0 obj\n", 7, &daobj);
2185  nobj = l_dnaGetCount(daobj);
2186  for (i = 0; i < nobj; i++) {
2187  l_dnaGetIValue(daobj, i, &loc);
2188  for (j = loc - 1; j > 0; j--) {
2189  if (data[j] == nl)
2190  break;
2191  }
2192  l_dnaAddNumber(da, j + 1);
2193  }
2194  l_byteaFindEachSequence(bas, (l_uint8 *)"xref", 4, &daxref);
2195  l_dnaGetIValue(daxref, 0, &loc);
2196  l_dnaAddNumber(da, loc);
2197  l_dnaDestroy(&daobj);
2198  l_dnaDestroy(&daxref);
2199  }
2200 
2201  return 0;
2202 }
2203 
2204 
2205 static char *
2206 generatePagesObjStringPdf(NUMA *napage)
2207 {
2208 char *str;
2209 char *buf;
2210 l_int32 i, n, index, bufsize;
2211 SARRAY *sa;
2212 
2213  PROCNAME("generatePagesObjStringPdf");
2214 
2215  if (!napage)
2216  return (char *)ERROR_PTR("napage not defined", procName, NULL);
2217 
2218  n = numaGetCount(napage);
2219  bufsize = 100 + 16 * n; /* large enough to hold the output string */
2220  buf = (char *)LEPT_CALLOC(bufsize, sizeof(char));
2221  sa = sarrayCreate(n);
2222  for (i = 0; i < n; i++) {
2223  numaGetIValue(napage, i, &index);
2224  snprintf(buf, bufsize, " %d 0 R ", index);
2225  sarrayAddString(sa, buf, L_COPY);
2226  }
2227 
2228  str = sarrayToString(sa, 0);
2229  snprintf(buf, bufsize - 1, "3 0 obj\n"
2230  "<<\n"
2231  "/Type /Pages\n"
2232  "/Kids [%s]\n"
2233  "/Count %d\n"
2234  ">>\n", str, n);
2235  sarrayDestroy(&sa);
2236  LEPT_FREE(str);
2237  return buf;
2238 }
2239 
2240 
2256 static L_BYTEA *
2258  NUMA *na_objs)
2259 {
2260 l_uint8 space = ' ';
2261 l_uint8 *datas;
2262 l_uint8 buf[32]; /* only needs to hold one integer in ascii format */
2263 l_int32 start, nrepl, i, j, objin, objout, found;
2264 l_int32 *objs, *matches;
2265 size_t size;
2266 L_BYTEA *bad;
2267 L_DNA *da_match;
2268 
2269  datas = l_byteaGetData(bas, &size);
2270  bad = l_byteaCreate(100);
2271  objs = numaGetIArray(na_objs); /* object number mapper */
2272 
2273  /* Substitute the object number on the first line */
2274  sscanf((char *)datas, "%d", &objin);
2275  objout = objs[objin];
2276  snprintf((char *)buf, 32, "%d", objout);
2277  l_byteaAppendString(bad, (char *)buf);
2278 
2279  /* Find the set of matching locations for object references */
2280  arrayFindSequence(datas, size, &space, 1, &start, &found);
2281  da_match = arrayFindEachSequence(datas, size, (l_uint8 *)" 0 R", 4);
2282  if (!da_match) {
2283  l_byteaAppendData(bad, datas + start, size - start);
2284  LEPT_FREE(objs);
2285  return bad;
2286  }
2287 
2288  /* Substitute all the object reference numbers */
2289  nrepl = l_dnaGetCount(da_match);
2290  matches = l_dnaGetIArray(da_match);
2291  for (i = 0; i < nrepl; i++) {
2292  /* Find the first space before the object number */
2293  for (j = matches[i] - 1; j > 0; j--) {
2294  if (datas[j] == space)
2295  break;
2296  }
2297  /* Copy bytes from 'start' up to the object number */
2298  l_byteaAppendData(bad, datas + start, j - start + 1);
2299  sscanf((char *)(datas + j + 1), "%d", &objin);
2300  objout = objs[objin];
2301  snprintf((char *)buf, 32, "%d", objout);
2302  l_byteaAppendString(bad, (char *)buf);
2303  start = matches[i];
2304  }
2305  l_byteaAppendData(bad, datas + start, size - start);
2306 
2307  LEPT_FREE(objs);
2308  LEPT_FREE(matches);
2309  l_dnaDestroy(&da_match);
2310  return bad;
2311 }
2312 
2313 
2314 /*---------------------------------------------------------------------*
2315  * Create/destroy/access pdf data *
2316  *---------------------------------------------------------------------*/
2317 static L_PDF_DATA *
2318 pdfdataCreate(const char *title)
2319 {
2320 L_PDF_DATA *lpd;
2321 
2322  lpd = (L_PDF_DATA *)LEPT_CALLOC(1, sizeof(L_PDF_DATA));
2323  if (title) lpd->title = stringNew(title);
2324  lpd->cida = ptraCreate(10);
2325  lpd->xy = ptaCreate(10);
2326  lpd->wh = ptaCreate(10);
2327  lpd->saprex = sarrayCreate(10);
2328  lpd->sacmap = sarrayCreate(10);
2329  lpd->objsize = l_dnaCreate(20);
2330  lpd->objloc = l_dnaCreate(20);
2331  return lpd;
2332 }
2333 
2334 static void
2335 pdfdataDestroy(L_PDF_DATA **plpd)
2336 {
2337 l_int32 i;
2338 L_COMP_DATA *cid;
2339 L_PDF_DATA *lpd;
2340 
2341  PROCNAME("pdfdataDestroy");
2342 
2343  if (plpd== NULL) {
2344  L_WARNING("ptr address is null!\n", procName);
2345  return;
2346  }
2347  if ((lpd = *plpd) == NULL)
2348  return;
2349 
2350  if (lpd->title) LEPT_FREE(lpd->title);
2351  for (i = 0; i < lpd->n; i++) {
2352  cid = (L_COMP_DATA *)ptraRemove(lpd->cida, i, L_NO_COMPACTION);
2353  l_CIDataDestroy(&cid);
2354  }
2355 
2356  ptraDestroy(&lpd->cida, 0, 0);
2357  if (lpd->id) LEPT_FREE(lpd->id);
2358  if (lpd->obj1) LEPT_FREE(lpd->obj1);
2359  if (lpd->obj2) LEPT_FREE(lpd->obj2);
2360  if (lpd->obj3) LEPT_FREE(lpd->obj3);
2361  if (lpd->obj4) LEPT_FREE(lpd->obj4);
2362  if (lpd->obj5) LEPT_FREE(lpd->obj5);
2363  if (lpd->poststream) LEPT_FREE(lpd->poststream);
2364  if (lpd->trailer) LEPT_FREE(lpd->trailer);
2365  if (lpd->xy) ptaDestroy(&lpd->xy);
2366  if (lpd->wh) ptaDestroy(&lpd->wh);
2367  if (lpd->mediabox) boxDestroy(&lpd->mediabox);
2368  if (lpd->saprex) sarrayDestroy(&lpd->saprex);
2369  if (lpd->sacmap) sarrayDestroy(&lpd->sacmap);
2370  if (lpd->objsize) l_dnaDestroy(&lpd->objsize);
2371  if (lpd->objloc) l_dnaDestroy(&lpd->objloc);
2372  LEPT_FREE(lpd);
2373  *plpd = NULL;
2374  return;
2375 }
2376 
2377 
2378 static L_COMP_DATA *
2379 pdfdataGetCid(L_PDF_DATA *lpd,
2380  l_int32 index)
2381 {
2382  PROCNAME("pdfdataGetCid");
2383 
2384  if (!lpd)
2385  return (L_COMP_DATA *)ERROR_PTR("lpd not defined", procName, NULL);
2386  if (index < 0 || index >= lpd->n)
2387  return (L_COMP_DATA *)ERROR_PTR("invalid image index", procName, NULL);
2388 
2389  return (L_COMP_DATA *)ptraGetPtrToItem(lpd->cida, index);
2390 }
2391 
2392 
2393 /*---------------------------------------------------------------------*
2394  * Set flags for special modes *
2395  *---------------------------------------------------------------------*/
2410 void
2411 l_pdfSetG4ImageMask(l_int32 flag)
2412 {
2413  var_WRITE_G4_IMAGE_MASK = flag;
2414 }
2415 
2416 
2430 void
2432 {
2433  var_WRITE_DATE_AND_VERSION = flag;
2434 }
2435 
2436 /* --------------------------------------------*/
2437 #endif /* USE_PDFIO */
2438 /* --------------------------------------------*/
struct Sarray * saprex
Definition: imageio.h:228
l_int32 selectDefaultPdfEncoding(PIX *pix, l_int32 *ptype)
selectDefaultPdfEncoding()
Definition: pdfio1.c:454
void * ptraGetPtrToItem(L_PTRA *pa, l_int32 index)
ptraGetPtrToItem()
Definition: ptra.c:759
l_int32 l_generateCIData(const char *fname, l_int32 type, l_int32 quality, l_int32 ascii85, L_COMP_DATA **pcid)
l_generateCIData()
Definition: pdfio2.c:917
size_t l_byteaGetSize(L_BYTEA *ba)
l_byteaGetSize()
Definition: bytearray.c:281
l_uint8 * zlibCompress(l_uint8 *datain, size_t nin, size_t *pnout)
zlibCompress()
Definition: zlibmem.c:92
char * sarrayToString(SARRAY *sa, l_int32 addnlflag)
sarrayToString()
Definition: sarray1.c:757
l_int32 ncolors
Definition: imageio.h:175
l_int32 numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:472
l_int32 * l_dnaGetIArray(L_DNA *da)
l_dnaGetIArray()
Definition: dnabasic.c:786
PIXA * pixaReadMultipageTiff(const char *filename)
pixaReadMultipageTiff()
Definition: tiffio.c:1226
l_int32 ptraCompactArray(L_PTRA *pa)
ptraCompactArray()
Definition: ptra.c:590
l_int32 l_dnaGetCount(L_DNA *da)
l_dnaGetCount()
Definition: dnabasic.c:597
l_int32 ptaSetPt(PTA *pta, l_int32 index, l_float32 x, l_float32 y)
ptaSetPt()
Definition: ptabasic.c:583
l_int32 ptraConcatenatePdfToData(L_PTRA *pa_data, SARRAY *sa, l_uint8 **pdata, size_t *pnbytes)
ptraConcatenatePdfToData()
Definition: pdfio2.c:306
l_int32 readHeaderPng(const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
readHeaderPng()
Definition: pngio.c:517
char * pixcmapConvertToHex(l_uint8 *data, l_int32 ncolors)
pixcmapConvertToHex()
Definition: colormap.c:2021
l_int32 predictor
Definition: imageio.h:181
static L_COMP_DATA * pixGenerateFlateData(PIX *pixs, l_int32 ascii85flag)
pixGenerateFlateData()
Definition: pdfio2.c:1120
l_int32 numaaWriteStream(FILE *fp, NUMAA *naa)
numaaWriteStream()
Definition: numabasic.c:1899
l_int32 l_dnaAddNumber(L_DNA *da, l_float64 val)
l_dnaAddNumber()
Definition: dnabasic.c:439
l_int32 ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:341
L_DNA * arrayFindEachSequence(const l_uint8 *data, size_t datalen, const l_uint8 *sequence, size_t seqlen)
arrayFindEachSequence()
Definition: utils2.c:973
L_BYTEA * l_byteaCreate(size_t nbytes)
l_byteaCreate()
Definition: bytearray.c:93
L_COMP_DATA * l_generateG4Data(const char *fname, l_int32 ascii85flag)
l_generateG4Data()
Definition: pdfio2.c:1324
static L_COMP_DATA * pixGenerateG4Data(PIX *pixs, l_int32 ascii85flag)
pixGenerateG4Data()
Definition: pdfio2.c:1284
void l_dnaDestroy(L_DNA **pda)
l_dnaDestroy()
Definition: dnabasic.c:321
l_int32 ptaGetPt(PTA *pta, l_int32 index, l_float32 *px, l_float32 *py)
ptaGetPt()
Definition: ptabasic.c:524
static L_COMP_DATA * pixGenerateJpegData(PIX *pixs, l_int32 ascii85flag, l_int32 quality)
pixGenerateJpegData()
Definition: pdfio2.c:1240
l_int32 freadHeaderPng(FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
freadHeaderPng()
Definition: pngio.c:561
l_int32 l_dnaWriteStream(FILE *fp, L_DNA *da)
l_dnaWriteStream()
Definition: dnabasic.c:1087
l_int32 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:181
Definition: pix.h:704
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:202
l_uint8 * l_byteaGetData(L_BYTEA *ba, size_t *psize)
l_byteaGetData()
Definition: bytearray.c:304
char * cmapdata85
Definition: imageio.h:173
struct L_Ptra * cida
Definition: imageio.h:216
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:115
static l_int32 l_generatePdf(l_uint8 **pdata, size_t *pnbytes, L_PDF_DATA *lpd)
l_generatePdf()
Definition: pdfio2.c:1498
char * trailer
Definition: imageio.h:224
l_int32 cidConvertToPdfData(L_COMP_DATA *cid, const char *title, l_uint8 **pdata, size_t *pnbytes)
cidConvertToPdfData()
Definition: pdfio2.c:1401
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3041
L_DNAA * l_dnaaCreate(l_int32 n)
l_dnaaCreate()
Definition: dnabasic.c:1127
static L_BYTEA * substituteObjectNumbers(L_BYTEA *bas, NUMA *na_objs)
substituteObjectNumbers()
Definition: pdfio2.c:2257
NUMA * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
Definition: numafunc1.c:768
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:157
L_DNA * l_dnaaGetDna(L_DNAA *daa, l_int32 index, l_int32 accessflag)
l_dnaaGetDna()
Definition: dnabasic.c:1402
Definition: array.h:83
l_int32 sarrayWriteStream(FILE *fp, SARRAY *sa)
sarrayWriteStream()
Definition: sarray1.c:1507
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
Definition: colormap.c:263
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:186
Definition: array.h:95
l_int32 l_dnaEmpty(L_DNA *da)
l_dnaEmpty()
Definition: dnabasic.c:415
NUMAA * numaaCreate(l_int32 n)
numaaCreate()
Definition: numabasic.c:1307
l_int32 findFileFormat(const char *filename, l_int32 *pformat)
findFileFormat()
Definition: readfile.c:568
l_int32 ptraAdd(L_PTRA *pa, void *item)
ptraAdd()
Definition: ptra.c:242
size_t nbytes85
Definition: imageio.h:172
void numaaDestroy(NUMAA **pnaa)
numaaDestroy()
Definition: numabasic.c:1410
Definition: array.h:116
l_int32 l_dnaGetIValue(L_DNA *da, l_int32 index, l_int32 *pival)
l_dnaGetIValue()
Definition: dnabasic.c:693
l_int32 numaaAddNuma(NUMAA *naa, NUMA *na, l_int32 copyflag)
numaaAddNuma()
Definition: numabasic.c:1448
l_int32 l_byteaFindEachSequence(L_BYTEA *ba, l_uint8 *sequence, l_int32 seqlen, L_DNA **pda)
l_byteaFindEachSequence()
Definition: bytearray.c:540
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:110
l_int32 pixGetRasterData(PIX *pixs, l_uint8 **pdata, size_t *pnbytes)
pixGetRasterData()
Definition: pix2.c:3146
struct L_Dna * objsize
Definition: imageio.h:230
l_int32 type
Definition: imageio.h:168
l_int32 stringCat(char *dest, size_t size, const char *src)
stringCat()
Definition: utils2.c:356
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:819
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1154
char * id
Definition: imageio.h:217
NUMA * numaaGetNuma(NUMAA *naa, l_int32 index, l_int32 accessflag)
numaaGetNuma()
Definition: numabasic.c:1625
void l_CIDataDestroy(L_COMP_DATA **pcid)
l_CIDataDestroy()
Definition: pdfio2.c:1450
Definition: array.h:59
static const l_int32 L_INSERT
Definition: pix.h:710
l_int32 xrefloc
Definition: imageio.h:232
l_int32 pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:299
char * getLeptonicaVersion()
getLeptonicaVersion()
Definition: utils1.c:800
L_PTRA * ptraCreate(l_int32 n)
ptraCreate()
Definition: ptra.c:139
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:630
l_int32 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:431
l_int32 pixWriteJpeg(const char *filename, PIX *pix, l_int32 quality, l_int32 progressive)
pixWriteJpeg()
Definition: jpegio.c:727
void l_pdfSetDateAndVersion(l_int32 flag)
l_pdfSetDateAndVersion()
Definition: pdfio2.c:2431
l_int32 l_byteaAppendString(L_BYTEA *ba, char *str)
l_byteaAppendString()
Definition: bytearray.c:396
Definition: ptra.h:51
l_int32 boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:309
l_uint8 * datacomp
Definition: imageio.h:169
l_int32 l_byteaAppendData(L_BYTEA *ba, l_uint8 *newdata, size_t newbytes)
l_byteaAppendData()
Definition: bytearray.c:363
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:675
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:517
L_DNA * l_dnaDiffAdjValues(L_DNA *das)
l_dnaDiffAdjValues()
Definition: dnafunc1.c:385
l_int32 sarrayAddString(SARRAY *sa, char *string, l_int32 copyflag)
sarrayAddString()
Definition: sarray1.c:439
l_int32 ptraGetActualCount(L_PTRA *pa, l_int32 *pcount)
ptraGetActualCount()
Definition: ptra.c:727
Definition: array.h:71
l_int32 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:749
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:545
NUMA * numaMakeSequence(l_float32 startval, l_float32 increment, l_int32 size)
numaMakeSequence()
Definition: numafunc1.c:737
void l_dnaaDestroy(L_DNAA **pdaa)
l_dnaaDestroy()
Definition: dnabasic.c:1228
L_COMP_DATA * l_generateFlateDataPdf(const char *fname, PIX *pixs)
l_generateFlateDataPdf()
Definition: pdfio2.c:597
char * obj3
Definition: imageio.h:220
l_int32 convertTiffMultipageToPdf(const char *filein, const char *fileout)
convertTiffMultipageToPdf()
Definition: pdfio2.c:470
static l_int32 generateOutputDataPdf(l_uint8 **pdata, size_t *pnbytes, L_PDF_DATA *lpd)
generateEscapeString()
Definition: pdfio2.c:2030
char * obj5
Definition: imageio.h:222
SARRAY * sarrayCreateLinesFromString(const char *string, l_int32 blankflag)
sarrayCreateLinesFromString()
Definition: sarray1.c:270
struct Pta * xy
Definition: imageio.h:225
l_int32 n
Definition: imageio.h:214
Definition: pix.h:454
char * cmapdatahex
Definition: imageio.h:174
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:359
char * obj4
Definition: imageio.h:221
l_int32 isPngInterlaced(const char *filename, l_int32 *pinterlaced)
isPngInterlaced()
Definition: pngio.c:761
char * poststream
Definition: imageio.h:223
static L_COMP_DATA * l_generateJp2kData(const char *fname)
l_generateJp2kData()
Definition: pdfio2.c:862
struct Pta * wh
Definition: imageio.h:226
l_int32 fileFormatIsTiff(FILE *fp)
fileFormatIsTiff()
Definition: readfile.c:783
void ptraDestroy(L_PTRA **ppa, l_int32 freeflag, l_int32 warnflag)
ptraDestroy()
Definition: ptra.c:185
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1593
l_int32 extractG4DataFromFile(const char *filein, l_uint8 **pdata, size_t *pnbytes, l_int32 *pw, l_int32 *ph, l_int32 *pminisblack)
extractG4DataFromFile()
Definition: tiffio.c:1956
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:189
void l_pdfSetG4ImageMask(l_int32 flag)
l_pdfSetG4ImageMask()
Definition: pdfio2.c:2411
l_int32 freadHeaderJpeg(FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk)
freadHeaderJpeg()
Definition: jpegio.c:548
l_int32 numaReplaceNumber(NUMA *na, l_int32 index, l_float32 val)
numaReplaceNumber()
Definition: numabasic.c:601
struct Sarray * sacmap
Definition: imageio.h:229
l_int32 readHeaderJp2k(const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp)
readHeaderJp2k()
Definition: jp2kheader.c:75
L_DNA * l_dnaCreate(l_int32 n)
l_dnaCreate()
Definition: dnabasic.c:169
Definition: pix.h:705
void * ptraRemove(L_PTRA *pa, l_int32 index, l_int32 flag)
ptraRemove()
Definition: ptra.c:434
char * l_getFormattedDate()
l_getFormattedDate()
Definition: utils1.c:1105
char * title
Definition: imageio.h:213
Definition: pix.h:134
l_int32 numaSetValue(NUMA *na, l_int32 index, l_float32 val)
numaSetValue()
Definition: numabasic.c:758
Definition: pix.h:706
l_int32 l_generateCIDataForPdf(const char *fname, PIX *pix, l_int32 quality, L_COMP_DATA **pcid)
l_generateCIDataForPdf()
Definition: pdfio2.c:519
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:191
l_int32 minisblack
Definition: imageio.h:180
char * obj1
Definition: imageio.h:218
char * obj2
Definition: imageio.h:219
l_int32 pixGenerateCIData(PIX *pixs, l_int32 type, l_int32 quality, l_int32 ascii85, L_COMP_DATA **pcid)
pixGenerateCIData()
Definition: pdfio2.c:1013
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:277
struct L_Dna * objloc
Definition: imageio.h:231
l_int32 numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:726
l_int32 pixcmapSerializeToMemory(PIXCMAP *cmap, l_int32 cpc, l_int32 *pncolors, l_uint8 **pdata)
pixcmapSerializeToMemory()
Definition: colormap.c:1912
static l_int32 parseTrailerPdf(L_BYTEA *bas, L_DNA **pda)
parseTrailerPdf()
Definition: pdfio2.c:2106
L_COMP_DATA * l_generateJpegData(const char *fname, l_int32 ascii85flag)
l_generateJpegData()
Definition: pdfio2.c:792
void l_byteaDestroy(L_BYTEA **pba)
l_byteaDestroy()
Definition: bytearray.c:245
l_int32 pixGetDimensions(PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1052
l_int32 l_dnaaAddDna(L_DNAA *daa, L_DNA *da, l_int32 copyflag)
l_dnaaAddDna()
Definition: dnabasic.c:1265
l_int32 getTiffResolution(FILE *fp, l_int32 *pxres, l_int32 *pyres)
getTiffResolution()
Definition: tiffio.c:1524
l_int32 ncmap
Definition: imageio.h:215
struct Box * mediabox
Definition: imageio.h:227
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:398
L_COMP_DATA * l_generateFlateData(const char *fname, l_int32 ascii85flag)
l_generateFlateData()
Definition: pdfio2.c:1086
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:164
L_BYTEA * l_byteaInitFromMem(l_uint8 *data, size_t size)
l_byteaInitFromMem()
Definition: bytearray.c:122
l_uint8 * l_byteaCopyData(L_BYTEA *ba, size_t *psize)
l_byteaCopyData()
Definition: bytearray.c:333
l_int32 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:1033
size_t nbytescomp
Definition: imageio.h:170
l_int32 lept_rmfile(const char *filepath)
lept_rmfile()
Definition: utils2.c:2173
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:349
Definition: array.h:126
l_int32 numaWriteStream(FILE *fp, NUMA *na)
numaWriteStream()
Definition: numabasic.c:1213