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