Leptonica  1.73
Image processing and image analysis suite
psio2.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 
90 #include <string.h>
91 #include "allheaders.h"
92 
93 /* --------------------------------------------*/
94 #if USE_PSIO /* defined in environ.h */
95  /* --------------------------------------------*/
96 
97  /* Set default for writing bounding box hint */
98 static l_int32 var_PS_WRITE_BOUNDING_BOX = 1;
99 
100 static const l_int32 L_BUF_SIZE = 512;
101 static const l_int32 DEFAULT_INPUT_RES = 300; /* typical scan res, ppi */
102 static const l_int32 MIN_RES = 5;
103 static const l_int32 MAX_RES = 3000;
104 
105  /* For computing resolution that fills page to desired amount */
106 static const l_int32 LETTER_WIDTH = 612; /* points */
107 static const l_int32 LETTER_HEIGHT = 792; /* points */
108 static const l_int32 A4_WIDTH = 595; /* points */
109 static const l_int32 A4_HEIGHT = 842; /* points */
110 static const l_float32 DEFAULT_FILL_FRACTION = 0.95;
111 
112 #ifndef NO_CONSOLE_IO
113 #define DEBUG_JPEG 0
114 #define DEBUG_G4 0
115 #define DEBUG_FLATE 0
116 #endif /* ~NO_CONSOLE_IO */
117 
118 /* Note that the bounding box hint at the top of the generated PostScript
119  * file is required for the "*Embed" functions. These generate a
120  * PostScript file for an individual image that can be translated and
121  * scaled by an application that embeds the image in its output
122  * (e.g., in the PS output from a TeX file).
123  * However, bounding box hints should not be embedded in any
124  * PostScript image that will be composited with other images,
125  * where more than one image may be placed in an arbitrary location
126  * on a page. */
127 
128 
129 /*-------------------------------------------------------------*
130  * For uncompressed images *
131  *-------------------------------------------------------------*/
149 l_int32
150 pixWritePSEmbed(const char *filein,
151  const char *fileout)
152 {
153 l_int32 w, h;
154 l_float32 scale;
155 FILE *fp;
156 PIX *pix;
157 
158  PROCNAME("pixWritePSEmbed");
159 
160  if (!filein)
161  return ERROR_INT("filein not defined", procName, 1);
162  if (!fileout)
163  return ERROR_INT("fileout not defined", procName, 1);
164 
165  if ((pix = pixRead(filein)) == NULL)
166  return ERROR_INT("image not read from file", procName, 1);
167  w = pixGetWidth(pix);
168  h = pixGetHeight(pix);
169  if (w * 11.0 > h * 8.5)
170  scale = 8.5 * 300. / (l_float32)w;
171  else
172  scale = 11.0 * 300. / (l_float32)h;
173 
174  if ((fp = fopenWriteStream(fileout, "wb")) == NULL)
175  return ERROR_INT("file not opened for write", procName, 1);
176  pixWriteStreamPS(fp, pix, NULL, 0, scale);
177  fclose(fp);
178 
179  pixDestroy(&pix);
180  return 0;
181 }
182 
183 
202 l_int32
204  PIX *pix,
205  BOX *box,
206  l_int32 res,
207  l_float32 scale)
208 {
209 char *outstr;
210 l_int32 length;
211 PIX *pixc;
212 
213  PROCNAME("pixWriteStreamPS");
214 
215  if (!fp)
216  return (l_int32)ERROR_INT("stream not open", procName, 1);
217  if (!pix)
218  return (l_int32)ERROR_INT("pix not defined", procName, 1);
219 
220  if ((pixc = pixConvertForPSWrap(pix)) == NULL)
221  return (l_int32)ERROR_INT("pixc not made", procName, 1);
222 
223  outstr = pixWriteStringPS(pixc, box, res, scale);
224  length = strlen(outstr);
225  fwrite(outstr, 1, length, fp);
226  LEPT_FREE(outstr);
227  pixDestroy(&pixc);
228 
229  return 0;
230 }
231 
232 
300 char *
302  BOX *box,
303  l_int32 res,
304  l_float32 scale)
305 {
306 char nib1, nib2;
307 char *hexdata, *outstr;
308 l_uint8 byteval;
309 l_int32 i, j, k, w, h, d;
310 l_float32 wpt, hpt, xpt, ypt;
311 l_int32 wpl, psbpl, hexbytes, boxflag, bps;
312 l_uint32 *line, *data;
313 PIX *pix;
314 
315  PROCNAME("pixWriteStringPS");
316 
317  if (!pixs)
318  return (char *)ERROR_PTR("pixs not defined", procName, NULL);
319 
320  if ((pix = pixConvertForPSWrap(pixs)) == NULL)
321  return (char *)ERROR_PTR("pix not made", procName, NULL);
322  pixGetDimensions(pix, &w, &h, &d);
323 
324  /* Get the factors by which PS scales and translates, in pts */
325  if (!box)
326  boxflag = 0; /* no scaling; b.b. at center */
327  else
328  boxflag = 1; /* no b.b., specify placement and optional scaling */
329  getScaledParametersPS(box, w, h, res, scale, &xpt, &ypt, &wpt, &hpt);
330 
331  if (d == 1)
332  bps = 1; /* bits/sample */
333  else /* d == 8 || d == 32 */
334  bps = 8;
335 
336  /* Convert image data to hex string. psbpl is the number of
337  * bytes in each raster line when it is packed to the byte
338  * boundary (not the 32 bit word boundary, as with the pix).
339  * When converted to hex, the hex string has 2 bytes for
340  * every byte of raster data. */
341  wpl = pixGetWpl(pix);
342  if (d == 1 || d == 8)
343  psbpl = (w * d + 7) / 8;
344  else /* d == 32 */
345  psbpl = 3 * w;
346  data = pixGetData(pix);
347  hexbytes = 2 * psbpl * h; /* size of ps hex array */
348  if ((hexdata = (char *)LEPT_CALLOC(hexbytes + 1, sizeof(char))) == NULL)
349  return (char *)ERROR_PTR("hexdata not made", procName, NULL);
350  if (d == 1 || d == 8) {
351  for (i = 0, k = 0; i < h; i++) {
352  line = data + i * wpl;
353  for (j = 0; j < psbpl; j++) {
354  byteval = GET_DATA_BYTE(line, j);
355  convertByteToHexAscii(byteval, &nib1, &nib2);
356  hexdata[k++] = nib1;
357  hexdata[k++] = nib2;
358  }
359  }
360  } else { /* d == 32; hexdata bytes packed RGBRGB..., 2 per sample */
361  for (i = 0, k = 0; i < h; i++) {
362  line = data + i * wpl;
363  for (j = 0; j < w; j++) {
364  byteval = GET_DATA_BYTE(line + j, 0); /* red */
365  convertByteToHexAscii(byteval, &nib1, &nib2);
366  hexdata[k++] = nib1;
367  hexdata[k++] = nib2;
368  byteval = GET_DATA_BYTE(line + j, 1); /* green */
369  convertByteToHexAscii(byteval, &nib1, &nib2);
370  hexdata[k++] = nib1;
371  hexdata[k++] = nib2;
372  byteval = GET_DATA_BYTE(line + j, 2); /* blue */
373  convertByteToHexAscii(byteval, &nib1, &nib2);
374  hexdata[k++] = nib1;
375  hexdata[k++] = nib2;
376  }
377  }
378  }
379  hexdata[k] = '\0';
380 
381  outstr = generateUncompressedPS(hexdata, w, h, d, psbpl, bps,
382  xpt, ypt, wpt, hpt, boxflag);
383  if (!outstr)
384  return (char *)ERROR_PTR("outstr not made", procName, NULL);
385  pixDestroy(&pix);
386  return outstr;
387 }
388 
389 
410 char *
412  l_int32 w,
413  l_int32 h,
414  l_int32 d,
415  l_int32 psbpl,
416  l_int32 bps,
417  l_float32 xpt,
418  l_float32 ypt,
419  l_float32 wpt,
420  l_float32 hpt,
421  l_int32 boxflag)
422 {
423 char *outstr;
424 char bigbuf[L_BUF_SIZE];
425 SARRAY *sa;
426 
427  PROCNAME("generateUncompressedPS");
428 
429  if (!hexdata)
430  return (char *)ERROR_PTR("hexdata not defined", procName, NULL);
431 
432  if ((sa = sarrayCreate(0)) == NULL)
433  return (char *)ERROR_PTR("sa not made", procName, NULL);
434  sarrayAddString(sa, (char *)"%!Adobe-PS", L_COPY);
435  if (boxflag == 0) {
436  snprintf(bigbuf, sizeof(bigbuf),
437  "%%%%BoundingBox: %7.2f %7.2f %7.2f %7.2f",
438  xpt, ypt, xpt + wpt, ypt + hpt);
439  sarrayAddString(sa, bigbuf, L_COPY);
440  } else { /* boxflag == 1 */
441  sarrayAddString(sa, (char *)"gsave", L_COPY);
442  }
443 
444  if (d == 1)
445  sarrayAddString(sa,
446  (char *)"{1 exch sub} settransfer %invert binary", L_COPY);
447 
448  snprintf(bigbuf, sizeof(bigbuf),
449  "/bpl %d string def %%bpl as a string", psbpl);
450  sarrayAddString(sa, bigbuf, L_COPY);
451  snprintf(bigbuf, sizeof(bigbuf),
452  "%7.2f %7.2f translate %%set image origin in pts", xpt, ypt);
453  sarrayAddString(sa, bigbuf, L_COPY);
454  snprintf(bigbuf, sizeof(bigbuf),
455  "%7.2f %7.2f scale %%set image size in pts", wpt, hpt);
456  sarrayAddString(sa, bigbuf, L_COPY);
457  snprintf(bigbuf, sizeof(bigbuf),
458  "%d %d %d %%image dimensions in pixels", w, h, bps);
459  sarrayAddString(sa, bigbuf, L_COPY);
460  snprintf(bigbuf, sizeof(bigbuf),
461  "[%d %d %d %d %d %d] %%mapping matrix: [w 0 0 -h 0 h]",
462  w, 0, 0, -h, 0, h);
463  sarrayAddString(sa, bigbuf, L_COPY);
464 
465  if (boxflag == 0) {
466  if (d == 1 || d == 8)
467  sarrayAddString(sa,
468  (char *)"{currentfile bpl readhexstring pop} image", L_COPY);
469  else /* d == 32 */
470  sarrayAddString(sa,
471  (char *)"{currentfile bpl readhexstring pop} false 3 colorimage",
472  L_COPY);
473  } else { /* boxflag == 1 */
474  if (d == 1 || d == 8)
475  sarrayAddString(sa,
476  (char *)"{currentfile bpl readhexstring pop} bind image", L_COPY);
477  else /* d == 32 */
478  sarrayAddString(sa,
479  (char *)"{currentfile bpl readhexstring pop} bind false 3 colorimage",
480  L_COPY);
481  }
482 
483  sarrayAddString(sa, hexdata, L_INSERT);
484 
485  if (boxflag == 0)
486  sarrayAddString(sa, (char *)"\nshowpage", L_COPY);
487  else /* boxflag == 1 */
488  sarrayAddString(sa, (char *)"\ngrestore", L_COPY);
489 
490  outstr = sarrayToString(sa, 1);
491  sarrayDestroy(&sa);
492  if (!outstr) L_ERROR("outstr not made\n", procName);
493  return outstr;
494 }
495 
496 
519 void
521  l_int32 wpix,
522  l_int32 hpix,
523  l_int32 res,
524  l_float32 scale,
525  l_float32 *pxpt,
526  l_float32 *pypt,
527  l_float32 *pwpt,
528  l_float32 *phpt)
529 {
530 l_int32 bx, by, bw, bh;
531 l_float32 winch, hinch, xinch, yinch, fres;
532 
533  PROCNAME("getScaledParametersPS");
534 
535  if (res == 0)
536  res = DEFAULT_INPUT_RES;
537  fres = (l_float32)res;
538 
539  /* Allow the PS interpreter to scale the resolution */
540  if (scale == 0.0)
541  scale = 1.0;
542  if (scale != 1.0) {
543  fres = (l_float32)res / scale;
544  res = (l_int32)fres;
545  }
546 
547  /* Limit valid resolution interval */
548  if (res < MIN_RES || res > MAX_RES) {
549  L_WARNING("res %d out of bounds; using default res; no scaling\n",
550  procName, res);
551  res = DEFAULT_INPUT_RES;
552  fres = (l_float32)res;
553  }
554 
555  if (!box) { /* center on page */
556  winch = (l_float32)wpix / fres;
557  hinch = (l_float32)hpix / fres;
558  xinch = (8.5 - winch) / 2.;
559  yinch = (11.0 - hinch) / 2.;
560  } else {
561  boxGetGeometry(box, &bx, &by, &bw, &bh);
562  if (bw == 0)
563  winch = (l_float32)wpix / fres;
564  else
565  winch = (l_float32)bw / 1000.;
566  if (bh == 0)
567  hinch = (l_float32)hpix / fres;
568  else
569  hinch = (l_float32)bh / 1000.;
570  xinch = (l_float32)bx / 1000.;
571  yinch = (l_float32)by / 1000.;
572  }
573 
574  if (xinch < 0)
575  L_WARNING("left edge < 0.0 inch\n", procName);
576  if (xinch + winch > 8.5)
577  L_WARNING("right edge > 8.5 inch\n", procName);
578  if (yinch < 0.0)
579  L_WARNING("bottom edge < 0.0 inch\n", procName);
580  if (yinch + hinch > 11.0)
581  L_WARNING("top edge > 11.0 inch\n", procName);
582 
583  *pwpt = 72. * winch;
584  *phpt = 72. * hinch;
585  *pxpt = 72. * xinch;
586  *pypt = 72. * yinch;
587  return;
588 }
589 
590 
598 void
599 convertByteToHexAscii(l_uint8 byteval,
600  char *pnib1,
601  char *pnib2)
602 {
603 l_uint8 nib;
604 
605  nib = byteval >> 4;
606  if (nib < 10)
607  *pnib1 = '0' + nib;
608  else
609  *pnib1 = 'a' + (nib - 10);
610  nib = byteval & 0xf;
611  if (nib < 10)
612  *pnib2 = '0' + nib;
613  else
614  *pnib2 = 'a' + (nib - 10);
615 
616  return;
617 }
618 
619 
620 /*-------------------------------------------------------------*
621  * For jpeg compressed images *
622  *-------------------------------------------------------------*/
640 l_int32
641 convertJpegToPSEmbed(const char *filein,
642  const char *fileout)
643 {
644 char *outstr;
645 l_int32 w, h, nbytes, ret;
646 l_float32 xpt, ypt, wpt, hpt;
647 L_COMP_DATA *cid;
648 
649  PROCNAME("convertJpegToPSEmbed");
650 
651  if (!filein)
652  return ERROR_INT("filein not defined", procName, 1);
653  if (!fileout)
654  return ERROR_INT("fileout not defined", procName, 1);
655 
656  /* Generate the ascii encoded jpeg data */
657  if ((cid = l_generateJpegData(filein, 1)) == NULL)
658  return ERROR_INT("jpeg data not made", procName, 1);
659  w = cid->w;
660  h = cid->h;
661 
662  /* Scale for 20 pt boundary and otherwise full filling
663  * in one direction on 8.5 x 11 inch device */
664  xpt = 20.0;
665  ypt = 20.0;
666  if (w * 11.0 > h * 8.5) {
667  wpt = 572.0; /* 612 - 2 * 20 */
668  hpt = wpt * (l_float32)h / (l_float32)w;
669  } else {
670  hpt = 752.0; /* 792 - 2 * 20 */
671  wpt = hpt * (l_float32)w / (l_float32)h;
672  }
673 
674  /* Generate the PS.
675  * The bounding box information should be inserted (default). */
676  outstr = generateJpegPS(NULL, cid, xpt, ypt, wpt, hpt, 1, 1);
677  l_CIDataDestroy(&cid);
678  if (!outstr)
679  return ERROR_INT("outstr not made", procName, 1);
680  nbytes = strlen(outstr);
681 
682  ret = l_binaryWrite(fileout, "w", outstr, nbytes);
683  LEPT_FREE(outstr);
684  if (ret) L_ERROR("ps string not written to file\n", procName);
685  return ret;
686 }
687 
688 
755 l_int32
756 convertJpegToPS(const char *filein,
757  const char *fileout,
758  const char *operation,
759  l_int32 x,
760  l_int32 y,
761  l_int32 res,
762  l_float32 scale,
763  l_int32 pageno,
764  l_int32 endpage)
765 {
766 char *outstr;
767 l_int32 nbytes;
768 
769  PROCNAME("convertJpegToPS");
770 
771  if (!filein)
772  return ERROR_INT("filein not defined", procName, 1);
773  if (!fileout)
774  return ERROR_INT("fileout not defined", procName, 1);
775  if (strcmp(operation, "w") && strcmp(operation, "a"))
776  return ERROR_INT("operation must be \"w\" or \"a\"", procName, 1);
777 
778  if (convertJpegToPSString(filein, &outstr, &nbytes, x, y, res, scale,
779  pageno, endpage))
780  return ERROR_INT("ps string not made", procName, 1);
781 
782  if (l_binaryWrite(fileout, operation, outstr, nbytes))
783  return ERROR_INT("ps string not written to file", procName, 1);
784 
785  LEPT_FREE(outstr);
786  return 0;
787 }
788 
789 
814 l_int32
815 convertJpegToPSString(const char *filein,
816  char **poutstr,
817  l_int32 *pnbytes,
818  l_int32 x,
819  l_int32 y,
820  l_int32 res,
821  l_float32 scale,
822  l_int32 pageno,
823  l_int32 endpage)
824 {
825 char *outstr;
826 l_float32 xpt, ypt, wpt, hpt;
827 L_COMP_DATA *cid;
828 
829  PROCNAME("convertJpegToPSString");
830 
831  if (!poutstr)
832  return ERROR_INT("&outstr not defined", procName, 1);
833  if (!pnbytes)
834  return ERROR_INT("&nbytes not defined", procName, 1);
835  *poutstr = NULL;
836  *pnbytes = 0;
837  if (!filein)
838  return ERROR_INT("filein not defined", procName, 1);
839 
840  /* Generate the ascii encoded jpeg data */
841  if ((cid = l_generateJpegData(filein, 1)) == NULL)
842  return ERROR_INT("jpeg data not made", procName, 1);
843 
844  /* Get scaled location in pts. Guess the input scan resolution
845  * based on the input parameter %res, the resolution data in
846  * the pix, and the size of the image. */
847  if (scale == 0.0)
848  scale = 1.0;
849  if (res <= 0) {
850  if (cid->res > 0)
851  res = cid->res;
852  else
853  res = DEFAULT_INPUT_RES;
854  }
855 
856  /* Get scaled location in pts */
857  if (scale == 0.0)
858  scale = 1.0;
859  xpt = scale * x * 72. / res;
860  ypt = scale * y * 72. / res;
861  wpt = scale * cid->w * 72. / res;
862  hpt = scale * cid->h * 72. / res;
863 
864  if (pageno == 0)
865  pageno = 1;
866 
867 #if DEBUG_JPEG
868  fprintf(stderr, "w = %d, h = %d, bps = %d, spp = %d\n",
869  cid->w, cid->h, cid->bps, cid->spp);
870  fprintf(stderr, "comp bytes = %ld, nbytes85 = %ld, ratio = %5.3f\n",
871  (unsigned long)cid->nbytescomp, (unsigned long)cid->nbytes85,
872  (l_float32)cid->nbytes85 / (l_float32)cid->nbytescomp);
873  fprintf(stderr, "xpt = %7.2f, ypt = %7.2f, wpt = %7.2f, hpt = %7.2f\n",
874  xpt, ypt, wpt, hpt);
875 #endif /* DEBUG_JPEG */
876 
877  /* Generate the PS */
878  outstr = generateJpegPS(NULL, cid, xpt, ypt, wpt, hpt, pageno, endpage);
879  if (!outstr)
880  return ERROR_INT("outstr not made", procName, 1);
881  *poutstr = outstr;
882  *pnbytes = strlen(outstr);
883  l_CIDataDestroy(&cid);
884  return 0;
885 }
886 
887 
908 char *
909 generateJpegPS(const char *filein,
910  L_COMP_DATA *cid,
911  l_float32 xpt,
912  l_float32 ypt,
913  l_float32 wpt,
914  l_float32 hpt,
915  l_int32 pageno,
916  l_int32 endpage)
917 {
918 l_int32 w, h, bps, spp;
919 char *outstr;
920 char bigbuf[L_BUF_SIZE];
921 SARRAY *sa;
922 
923  PROCNAME("generateJpegPS");
924 
925  if (!cid)
926  return (char *)ERROR_PTR("jpeg data not defined", procName, NULL);
927  w = cid->w;
928  h = cid->h;
929  bps = cid->bps;
930  spp = cid->spp;
931 
932  if ((sa = sarrayCreate(50)) == NULL)
933  return (char *)ERROR_PTR("sa not made", procName, NULL);
934 
935  sarrayAddString(sa, (char *)"%!PS-Adobe-3.0", L_COPY);
936  sarrayAddString(sa, (char *)"%%Creator: leptonica", L_COPY);
937  if (filein)
938  snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: %s", filein);
939  else
940  snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: Jpeg compressed PS");
941  sarrayAddString(sa, bigbuf, L_COPY);
942  sarrayAddString(sa, (char *)"%%DocumentData: Clean7Bit", L_COPY);
943 
944  if (var_PS_WRITE_BOUNDING_BOX == 1) {
945  snprintf(bigbuf, sizeof(bigbuf),
946  "%%%%BoundingBox: %7.2f %7.2f %7.2f %7.2f",
947  xpt, ypt, xpt + wpt, ypt + hpt);
948  sarrayAddString(sa, bigbuf, L_COPY);
949  }
950 
951  sarrayAddString(sa, (char *)"%%LanguageLevel: 2", L_COPY);
952  sarrayAddString(sa, (char *)"%%EndComments", L_COPY);
953  snprintf(bigbuf, sizeof(bigbuf), "%%%%Page: %d %d", pageno, pageno);
954  sarrayAddString(sa, bigbuf, L_COPY);
955 
956  sarrayAddString(sa, (char *)"save", L_COPY);
957  sarrayAddString(sa,
958  (char *)"/RawData currentfile /ASCII85Decode filter def", L_COPY);
959  sarrayAddString(sa,
960  (char *)"/Data RawData << >> /DCTDecode filter def", L_COPY);
961 
962  snprintf(bigbuf, sizeof(bigbuf),
963  "%7.2f %7.2f translate %%set image origin in pts", xpt, ypt);
964  sarrayAddString(sa, bigbuf, L_COPY);
965 
966  snprintf(bigbuf, sizeof(bigbuf),
967  "%7.2f %7.2f scale %%set image size in pts", wpt, hpt);
968  sarrayAddString(sa, bigbuf, L_COPY);
969 
970  if (spp == 1)
971  sarrayAddString(sa, (char *)"/DeviceGray setcolorspace", L_COPY);
972  else if (spp == 3)
973  sarrayAddString(sa, (char *)"/DeviceRGB setcolorspace", L_COPY);
974  else /*spp == 4 */
975  sarrayAddString(sa, (char *)"/DeviceCMYK setcolorspace", L_COPY);
976 
977  sarrayAddString(sa, (char *)"{ << /ImageType 1", L_COPY);
978  snprintf(bigbuf, sizeof(bigbuf), " /Width %d", w);
979  sarrayAddString(sa, bigbuf, L_COPY);
980  snprintf(bigbuf, sizeof(bigbuf), " /Height %d", h);
981  sarrayAddString(sa, bigbuf, L_COPY);
982  snprintf(bigbuf, sizeof(bigbuf),
983  " /ImageMatrix [ %d 0 0 %d 0 %d ]", w, -h, h);
984  sarrayAddString(sa, bigbuf, L_COPY);
985  sarrayAddString(sa, (char *)" /DataSource Data", L_COPY);
986  snprintf(bigbuf, sizeof(bigbuf), " /BitsPerComponent %d", bps);
987  sarrayAddString(sa, bigbuf, L_COPY);
988 
989  if (spp == 1)
990  sarrayAddString(sa, (char *)" /Decode [0 1]", L_COPY);
991  else if (spp == 3)
992  sarrayAddString(sa, (char *)" /Decode [0 1 0 1 0 1]", L_COPY);
993  else /* spp == 4 */
994  sarrayAddString(sa, (char *)" /Decode [0 1 0 1 0 1 0 1]", L_COPY);
995 
996  sarrayAddString(sa, (char *)" >> image", L_COPY);
997  sarrayAddString(sa, (char *)" Data closefile", L_COPY);
998  sarrayAddString(sa, (char *)" RawData flushfile", L_COPY);
999  if (endpage == TRUE)
1000  sarrayAddString(sa, (char *)" showpage", L_COPY);
1001  sarrayAddString(sa, (char *)" restore", L_COPY);
1002  sarrayAddString(sa, (char *)"} exec", L_COPY);
1003 
1004  /* Insert the ascii85 jpeg data; this is now owned by sa */
1005  sarrayAddString(sa, cid->data85, L_INSERT);
1006  cid->data85 = NULL; /* it has been transferred and destroyed */
1007 
1008  /* Generate and return the output string */
1009  outstr = sarrayToString(sa, 1);
1010  sarrayDestroy(&sa);
1011  return outstr;
1012 }
1013 
1014 
1015 /*-------------------------------------------------------------*
1016  * For ccitt g4 compressed images *
1017  *-------------------------------------------------------------*/
1037 l_int32
1038 convertG4ToPSEmbed(const char *filein,
1039  const char *fileout)
1040 {
1041 char *outstr;
1042 l_int32 w, h, nbytes, ret;
1043 l_float32 xpt, ypt, wpt, hpt;
1044 L_COMP_DATA *cid;
1045 
1046  PROCNAME("convertG4ToPSEmbed");
1047 
1048  if (!filein)
1049  return ERROR_INT("filein not defined", procName, 1);
1050  if (!fileout)
1051  return ERROR_INT("fileout not defined", procName, 1);
1052 
1053  if ((cid = l_generateG4Data(filein, 1)) == NULL)
1054  return ERROR_INT("g4 data not made", procName, 1);
1055  w = cid->w;
1056  h = cid->h;
1057 
1058  /* Scale for 20 pt boundary and otherwise full filling
1059  * in one direction on 8.5 x 11 inch device */
1060  xpt = 20.0;
1061  ypt = 20.0;
1062  if (w * 11.0 > h * 8.5) {
1063  wpt = 572.0; /* 612 - 2 * 20 */
1064  hpt = wpt * (l_float32)h / (l_float32)w;
1065  } else {
1066  hpt = 752.0; /* 792 - 2 * 20 */
1067  wpt = hpt * (l_float32)w / (l_float32)h;
1068  }
1069 
1070  /* Generate the PS, painting through the image mask.
1071  * The bounding box information should be inserted (default). */
1072  outstr = generateG4PS(NULL, cid, xpt, ypt, wpt, hpt, 1, 1, 1);
1073  l_CIDataDestroy(&cid);
1074  if (!outstr)
1075  return ERROR_INT("outstr not made", procName, 1);
1076  nbytes = strlen(outstr);
1077 
1078  ret = l_binaryWrite(fileout, "w", outstr, nbytes);
1079  LEPT_FREE(outstr);
1080  if (ret) L_ERROR("ps string not written to file\n", procName);
1081  return ret;
1082 }
1083 
1084 
1143 l_int32
1144 convertG4ToPS(const char *filein,
1145  const char *fileout,
1146  const char *operation,
1147  l_int32 x,
1148  l_int32 y,
1149  l_int32 res,
1150  l_float32 scale,
1151  l_int32 pageno,
1152  l_int32 maskflag,
1153  l_int32 endpage)
1154 {
1155 char *outstr;
1156 l_int32 nbytes;
1157 
1158  PROCNAME("convertG4ToPS");
1159 
1160  if (!filein)
1161  return ERROR_INT("filein not defined", procName, 1);
1162  if (!fileout)
1163  return ERROR_INT("fileout not defined", procName, 1);
1164  if (strcmp(operation, "w") && strcmp(operation, "a"))
1165  return ERROR_INT("operation must be \"w\" or \"a\"", procName, 1);
1166 
1167  if (convertG4ToPSString(filein, &outstr, &nbytes, x, y, res, scale,
1168  pageno, maskflag, endpage))
1169  return ERROR_INT("ps string not made", procName, 1);
1170 
1171  if (l_binaryWrite(fileout, operation, outstr, nbytes))
1172  return ERROR_INT("ps string not written to file", procName, 1);
1173 
1174  LEPT_FREE(outstr);
1175  return 0;
1176 }
1177 
1178 
1206 l_int32
1207 convertG4ToPSString(const char *filein,
1208  char **poutstr,
1209  l_int32 *pnbytes,
1210  l_int32 x,
1211  l_int32 y,
1212  l_int32 res,
1213  l_float32 scale,
1214  l_int32 pageno,
1215  l_int32 maskflag,
1216  l_int32 endpage)
1217 {
1218 char *outstr;
1219 l_float32 xpt, ypt, wpt, hpt;
1220 L_COMP_DATA *cid;
1221 
1222  PROCNAME("convertG4ToPSString");
1223 
1224  if (!poutstr)
1225  return ERROR_INT("&outstr not defined", procName, 1);
1226  if (!pnbytes)
1227  return ERROR_INT("&nbytes not defined", procName, 1);
1228  *poutstr = NULL;
1229  *pnbytes = 0;
1230  if (!filein)
1231  return ERROR_INT("filein not defined", procName, 1);
1232 
1233  if ((cid = l_generateG4Data(filein, 1)) == NULL)
1234  return ERROR_INT("g4 data not made", procName, 1);
1235 
1236  /* Get scaled location in pts. Guess the input scan resolution
1237  * based on the input parameter %res, the resolution data in
1238  * the pix, and the size of the image. */
1239  if (scale == 0.0)
1240  scale = 1.0;
1241  if (res <= 0) {
1242  if (cid->res > 0) {
1243  res = cid->res;
1244  } else {
1245  if (cid->h <= 3509) /* A4 height at 300 ppi */
1246  res = 300;
1247  else
1248  res = 600;
1249  }
1250  }
1251  xpt = scale * x * 72. / res;
1252  ypt = scale * y * 72. / res;
1253  wpt = scale * cid->w * 72. / res;
1254  hpt = scale * cid->h * 72. / res;
1255 
1256  if (pageno == 0)
1257  pageno = 1;
1258 
1259 #if DEBUG_G4
1260  fprintf(stderr, "w = %d, h = %d, minisblack = %d\n",
1261  cid->w, cid->h, cid->minisblack);
1262  fprintf(stderr, "comp bytes = %ld, nbytes85 = %ld\n",
1263  (unsigned long)cid->nbytescomp, (unsigned long)cid->nbytes85);
1264  fprintf(stderr, "xpt = %7.2f, ypt = %7.2f, wpt = %7.2f, hpt = %7.2f\n",
1265  xpt, ypt, wpt, hpt);
1266 #endif /* DEBUG_G4 */
1267 
1268  /* Generate the PS */
1269  outstr = generateG4PS(NULL, cid, xpt, ypt, wpt, hpt,
1270  maskflag, pageno, endpage);
1271  if (!outstr)
1272  return ERROR_INT("outstr not made", procName, 1);
1273  *poutstr = outstr;
1274  *pnbytes = strlen(outstr);
1275  l_CIDataDestroy(&cid);
1276  return 0;
1277 }
1278 
1279 
1302 char *
1303 generateG4PS(const char *filein,
1304  L_COMP_DATA *cid,
1305  l_float32 xpt,
1306  l_float32 ypt,
1307  l_float32 wpt,
1308  l_float32 hpt,
1309  l_int32 maskflag,
1310  l_int32 pageno,
1311  l_int32 endpage)
1312 {
1313 l_int32 w, h;
1314 char *outstr;
1315 char bigbuf[L_BUF_SIZE];
1316 SARRAY *sa;
1317 
1318  PROCNAME("generateG4PS");
1319 
1320  if (!cid)
1321  return (char *)ERROR_PTR("g4 data not defined", procName, NULL);
1322  w = cid->w;
1323  h = cid->h;
1324 
1325  if ((sa = sarrayCreate(50)) == NULL)
1326  return (char *)ERROR_PTR("sa not made", procName, NULL);
1327 
1328  sarrayAddString(sa, (char *)"%!PS-Adobe-3.0", L_COPY);
1329  sarrayAddString(sa, (char *)"%%Creator: leptonica", L_COPY);
1330  if (filein)
1331  snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: %s", filein);
1332  else
1333  snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: G4 compressed PS");
1334  sarrayAddString(sa, bigbuf, L_COPY);
1335  sarrayAddString(sa, (char *)"%%DocumentData: Clean7Bit", L_COPY);
1336 
1337  if (var_PS_WRITE_BOUNDING_BOX == 1) {
1338  snprintf(bigbuf, sizeof(bigbuf),
1339  "%%%%BoundingBox: %7.2f %7.2f %7.2f %7.2f",
1340  xpt, ypt, xpt + wpt, ypt + hpt);
1341  sarrayAddString(sa, bigbuf, L_COPY);
1342  }
1343 
1344  sarrayAddString(sa, (char *)"%%LanguageLevel: 2", L_COPY);
1345  sarrayAddString(sa, (char *)"%%EndComments", L_COPY);
1346  snprintf(bigbuf, sizeof(bigbuf), "%%%%Page: %d %d", pageno, pageno);
1347  sarrayAddString(sa, bigbuf, L_COPY);
1348 
1349  sarrayAddString(sa, (char *)"save", L_COPY);
1350  sarrayAddString(sa, (char *)"100 dict begin", L_COPY);
1351 
1352  snprintf(bigbuf, sizeof(bigbuf),
1353  "%7.2f %7.2f translate %%set image origin in pts", xpt, ypt);
1354  sarrayAddString(sa, bigbuf, L_COPY);
1355 
1356  snprintf(bigbuf, sizeof(bigbuf),
1357  "%7.2f %7.2f scale %%set image size in pts", wpt, hpt);
1358  sarrayAddString(sa, bigbuf, L_COPY);
1359 
1360  sarrayAddString(sa, (char *)"/DeviceGray setcolorspace", L_COPY);
1361 
1362  sarrayAddString(sa, (char *)"{", L_COPY);
1363  sarrayAddString(sa,
1364  (char *)" /RawData currentfile /ASCII85Decode filter def", L_COPY);
1365  sarrayAddString(sa, (char *)" << ", L_COPY);
1366  sarrayAddString(sa, (char *)" /ImageType 1", L_COPY);
1367  snprintf(bigbuf, sizeof(bigbuf), " /Width %d", w);
1368  sarrayAddString(sa, bigbuf, L_COPY);
1369  snprintf(bigbuf, sizeof(bigbuf), " /Height %d", h);
1370  sarrayAddString(sa, bigbuf, L_COPY);
1371  snprintf(bigbuf, sizeof(bigbuf),
1372  " /ImageMatrix [ %d 0 0 %d 0 %d ]", w, -h, h);
1373  sarrayAddString(sa, bigbuf, L_COPY);
1374  sarrayAddString(sa, (char *)" /BitsPerComponent 1", L_COPY);
1375  sarrayAddString(sa, (char *)" /Interpolate true", L_COPY);
1376  if (cid->minisblack)
1377  sarrayAddString(sa, (char *)" /Decode [1 0]", L_COPY);
1378  else /* miniswhite; typical for 1 bpp */
1379  sarrayAddString(sa, (char *)" /Decode [0 1]", L_COPY);
1380  sarrayAddString(sa, (char *)" /DataSource RawData", L_COPY);
1381  sarrayAddString(sa, (char *)" <<", L_COPY);
1382  sarrayAddString(sa, (char *)" /K -1", L_COPY);
1383  snprintf(bigbuf, sizeof(bigbuf), " /Columns %d", w);
1384  sarrayAddString(sa, bigbuf, L_COPY);
1385  snprintf(bigbuf, sizeof(bigbuf), " /Rows %d", h);
1386  sarrayAddString(sa, bigbuf, L_COPY);
1387  sarrayAddString(sa, (char *)" >> /CCITTFaxDecode filter", L_COPY);
1388  if (maskflag == TRUE) /* just paint through the fg */
1389  sarrayAddString(sa, (char *)" >> imagemask", L_COPY);
1390  else /* Paint full image */
1391  sarrayAddString(sa, (char *)" >> image", L_COPY);
1392  sarrayAddString(sa, (char *)" RawData flushfile", L_COPY);
1393  if (endpage == TRUE)
1394  sarrayAddString(sa, (char *)" showpage", L_COPY);
1395  sarrayAddString(sa, (char *)"}", L_COPY);
1396 
1397  sarrayAddString(sa, (char *)"%%BeginData:", L_COPY);
1398  sarrayAddString(sa, (char *)"exec", L_COPY);
1399 
1400  /* Insert the ascii85 ccittg4 data; this is now owned by sa */
1401  sarrayAddString(sa, cid->data85, L_INSERT);
1402 
1403  /* Concat the trailing data */
1404  sarrayAddString(sa, (char *)"%%EndData", L_COPY);
1405  sarrayAddString(sa, (char *)"end", L_COPY);
1406  sarrayAddString(sa, (char *)"restore", L_COPY);
1407 
1408  outstr = sarrayToString(sa, 1);
1409  sarrayDestroy(&sa);
1410  cid->data85 = NULL; /* it has been transferred and destroyed */
1411  return outstr;
1412 }
1413 
1414 
1415 /*-------------------------------------------------------------*
1416  * For tiff multipage files *
1417  *-------------------------------------------------------------*/
1436 l_int32
1437 convertTiffMultipageToPS(const char *filein,
1438  const char *fileout,
1439  l_float32 fillfract)
1440 {
1441 char *tempfile;
1442 l_int32 i, npages, w, h, istiff;
1443 l_float32 scale;
1444 PIX *pix, *pixs;
1445 FILE *fp;
1446 
1447  PROCNAME("convertTiffMultipageToPS");
1448 
1449  if (!filein)
1450  return ERROR_INT("filein not defined", procName, 1);
1451  if (!fileout)
1452  return ERROR_INT("fileout not defined", procName, 1);
1453 
1454  if ((fp = fopenReadStream(filein)) == NULL)
1455  return ERROR_INT("file not found", procName, 1);
1456  istiff = fileFormatIsTiff(fp);
1457  if (!istiff) {
1458  fclose(fp);
1459  return ERROR_INT("file not tiff format", procName, 1);
1460  }
1461  tiffGetCount(fp, &npages);
1462  fclose(fp);
1463 
1464  if (fillfract == 0.0)
1465  fillfract = DEFAULT_FILL_FRACTION;
1466 
1467  for (i = 0; i < npages; i++) {
1468  if ((pix = pixReadTiff(filein, i)) == NULL)
1469  return ERROR_INT("pix not made", procName, 1);
1470 
1471  pixGetDimensions(pix, &w, &h, NULL);
1472  if (w == 1728 && h < w) /* it's a std res fax */
1473  pixs = pixScale(pix, 1.0, 2.0);
1474  else
1475  pixs = pixClone(pix);
1476 
1477  tempfile = l_makeTempFilename();
1478  pixWrite(tempfile, pixs, IFF_TIFF_G4);
1479  scale = L_MIN(fillfract * 2550 / w, fillfract * 3300 / h);
1480  if (i == 0)
1481  convertG4ToPS(tempfile, fileout, "w", 0, 0, 300, scale,
1482  i + 1, FALSE, TRUE);
1483  else
1484  convertG4ToPS(tempfile, fileout, "a", 0, 0, 300, scale,
1485  i + 1, FALSE, TRUE);
1486  lept_rmfile(tempfile);
1487  LEPT_FREE(tempfile);
1488  pixDestroy(&pix);
1489  pixDestroy(&pixs);
1490  }
1491 
1492  return 0;
1493 }
1494 
1495 
1496 /*---------------------------------------------------------------------*
1497  * For flate (gzip) compressed images (e.g., png) *
1498  *---------------------------------------------------------------------*/
1516 l_int32
1517 convertFlateToPSEmbed(const char *filein,
1518  const char *fileout)
1519 {
1520 char *outstr;
1521 l_int32 w, h, nbytes, ret;
1522 l_float32 xpt, ypt, wpt, hpt;
1523 L_COMP_DATA *cid;
1524 
1525  PROCNAME("convertFlateToPSEmbed");
1526 
1527  if (!filein)
1528  return ERROR_INT("filein not defined", procName, 1);
1529  if (!fileout)
1530  return ERROR_INT("fileout not defined", procName, 1);
1531 
1532  if ((cid = l_generateFlateData(filein, 1)) == NULL)
1533  return ERROR_INT("flate data not made", procName, 1);
1534  w = cid->w;
1535  h = cid->h;
1536 
1537  /* Scale for 20 pt boundary and otherwise full filling
1538  * in one direction on 8.5 x 11 inch device */
1539  xpt = 20.0;
1540  ypt = 20.0;
1541  if (w * 11.0 > h * 8.5) {
1542  wpt = 572.0; /* 612 - 2 * 20 */
1543  hpt = wpt * (l_float32)h / (l_float32)w;
1544  } else {
1545  hpt = 752.0; /* 792 - 2 * 20 */
1546  wpt = hpt * (l_float32)w / (l_float32)h;
1547  }
1548 
1549  /* Generate the PS.
1550  * The bounding box information should be inserted (default). */
1551  outstr = generateFlatePS(NULL, cid, xpt, ypt, wpt, hpt, 1, 1);
1552  l_CIDataDestroy(&cid);
1553  if (!outstr)
1554  return ERROR_INT("outstr not made", procName, 1);
1555  nbytes = strlen(outstr);
1556 
1557  ret = l_binaryWrite(fileout, "w", outstr, nbytes);
1558  LEPT_FREE(outstr);
1559  if (ret) L_ERROR("ps string not written to file\n", procName);
1560  return ret;
1561 }
1562 
1563 
1629 l_int32
1630 convertFlateToPS(const char *filein,
1631  const char *fileout,
1632  const char *operation,
1633  l_int32 x,
1634  l_int32 y,
1635  l_int32 res,
1636  l_float32 scale,
1637  l_int32 pageno,
1638  l_int32 endpage)
1639 {
1640 char *outstr;
1641 l_int32 nbytes, ret;
1642 
1643  PROCNAME("convertFlateToPS");
1644 
1645  if (!filein)
1646  return ERROR_INT("filein not defined", procName, 1);
1647  if (!fileout)
1648  return ERROR_INT("fileout not defined", procName, 1);
1649  if (strcmp(operation, "w") && strcmp(operation, "a"))
1650  return ERROR_INT("operation must be \"w\" or \"a\"", procName, 1);
1651 
1652  if (convertFlateToPSString(filein, &outstr, &nbytes, x, y, res, scale,
1653  pageno, endpage))
1654  return ERROR_INT("ps string not made", procName, 1);
1655 
1656  ret = l_binaryWrite(fileout, operation, outstr, nbytes);
1657  LEPT_FREE(outstr);
1658  if (ret) L_ERROR("ps string not written to file\n", procName);
1659  return ret;
1660 }
1661 
1662 
1695 l_int32
1696 convertFlateToPSString(const char *filein,
1697  char **poutstr,
1698  l_int32 *pnbytes,
1699  l_int32 x,
1700  l_int32 y,
1701  l_int32 res,
1702  l_float32 scale,
1703  l_int32 pageno,
1704  l_int32 endpage)
1705 {
1706 char *outstr;
1707 l_float32 xpt, ypt, wpt, hpt;
1708 L_COMP_DATA *cid;
1709 
1710  PROCNAME("convertFlateToPSString");
1711 
1712  if (!poutstr)
1713  return ERROR_INT("&outstr not defined", procName, 1);
1714  if (!pnbytes)
1715  return ERROR_INT("&nbytes not defined", procName, 1);
1716  *pnbytes = 0;
1717  *poutstr = NULL;
1718  if (!filein)
1719  return ERROR_INT("filein not defined", procName, 1);
1720 
1721  if ((cid = l_generateFlateData(filein, 1)) == NULL)
1722  return ERROR_INT("flate data not made", procName, 1);
1723 
1724  /* Get scaled location in pts. Guess the input scan resolution
1725  * based on the input parameter %res, the resolution data in
1726  * the pix, and the size of the image. */
1727  if (scale == 0.0)
1728  scale = 1.0;
1729  if (res <= 0) {
1730  if (cid->res > 0)
1731  res = cid->res;
1732  else
1733  res = DEFAULT_INPUT_RES;
1734  }
1735  xpt = scale * x * 72. / res;
1736  ypt = scale * y * 72. / res;
1737  wpt = scale * cid->w * 72. / res;
1738  hpt = scale * cid->h * 72. / res;
1739 
1740  if (pageno == 0)
1741  pageno = 1;
1742 
1743 #if DEBUG_FLATE
1744  fprintf(stderr, "w = %d, h = %d, bps = %d, spp = %d\n",
1745  cid->w, cid->h, cid->bps, cid->spp);
1746  fprintf(stderr, "uncomp bytes = %ld, comp bytes = %ld, nbytes85 = %ld\n",
1747  (unsigned long)cid->nbytes, (unsigned long)cid->nbytescomp,
1748  (unsigned long)cid->nbytes85);
1749  fprintf(stderr, "xpt = %7.2f, ypt = %7.2f, wpt = %7.2f, hpt = %7.2f\n",
1750  xpt, ypt, wpt, hpt);
1751 #endif /* DEBUG_FLATE */
1752 
1753  /* Generate the PS */
1754  outstr = generateFlatePS(NULL, cid, xpt, ypt, wpt, hpt, pageno, endpage);
1755  if (!outstr)
1756  return ERROR_INT("outstr not made", procName, 1);
1757  *poutstr = outstr;
1758  *pnbytes = strlen(outstr);
1759  l_CIDataDestroy(&cid);
1760  return 0;
1761 }
1762 
1763 
1779 char *
1780 generateFlatePS(const char *filein,
1781  L_COMP_DATA *cid,
1782  l_float32 xpt,
1783  l_float32 ypt,
1784  l_float32 wpt,
1785  l_float32 hpt,
1786  l_int32 pageno,
1787  l_int32 endpage)
1788 {
1789 l_int32 w, h, bps, spp;
1790 char *outstr;
1791 char bigbuf[L_BUF_SIZE];
1792 SARRAY *sa;
1793 
1794  PROCNAME("generateFlatePS");
1795 
1796  if (!cid)
1797  return (char *)ERROR_PTR("flate data not defined", procName, NULL);
1798  w = cid->w;
1799  h = cid->h;
1800  bps = cid->bps;
1801  spp = cid->spp;
1802 
1803  if ((sa = sarrayCreate(50)) == NULL)
1804  return (char *)ERROR_PTR("sa not made", procName, NULL);
1805 
1806  sarrayAddString(sa, (char *)"%!PS-Adobe-3.0 EPSF-3.0", L_COPY);
1807  sarrayAddString(sa, (char *)"%%Creator: leptonica", L_COPY);
1808  if (filein)
1809  snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: %s", filein);
1810  else
1811  snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: Flate compressed PS");
1812  sarrayAddString(sa, bigbuf, L_COPY);
1813  sarrayAddString(sa, (char *)"%%DocumentData: Clean7Bit", L_COPY);
1814 
1815  if (var_PS_WRITE_BOUNDING_BOX == 1) {
1816  snprintf(bigbuf, sizeof(bigbuf),
1817  "%%%%BoundingBox: %7.2f %7.2f %7.2f %7.2f",
1818  xpt, ypt, xpt + wpt, ypt + hpt);
1819  sarrayAddString(sa, bigbuf, L_COPY);
1820  }
1821 
1822  sarrayAddString(sa, (char *)"%%LanguageLevel: 3", L_COPY);
1823  sarrayAddString(sa, (char *)"%%EndComments", L_COPY);
1824  snprintf(bigbuf, sizeof(bigbuf), "%%%%Page: %d %d", pageno, pageno);
1825  sarrayAddString(sa, bigbuf, L_COPY);
1826 
1827  sarrayAddString(sa, (char *)"save", L_COPY);
1828  snprintf(bigbuf, sizeof(bigbuf),
1829  "%7.2f %7.2f translate %%set image origin in pts", xpt, ypt);
1830  sarrayAddString(sa, bigbuf, L_COPY);
1831 
1832  snprintf(bigbuf, sizeof(bigbuf),
1833  "%7.2f %7.2f scale %%set image size in pts", wpt, hpt);
1834  sarrayAddString(sa, bigbuf, L_COPY);
1835 
1836  /* If there is a colormap, add the data; it is now owned by sa */
1837  if (cid->cmapdata85) {
1838  snprintf(bigbuf, sizeof(bigbuf),
1839  "[ /Indexed /DeviceRGB %d %%set colormap type/size",
1840  cid->ncolors - 1);
1841  sarrayAddString(sa, bigbuf, L_COPY);
1842  sarrayAddString(sa, (char *)" <~", L_COPY);
1843  sarrayAddString(sa, cid->cmapdata85, L_INSERT);
1844  sarrayAddString(sa, (char *)" ] setcolorspace", L_COPY);
1845  } else if (spp == 1) {
1846  sarrayAddString(sa, (char *)"/DeviceGray setcolorspace", L_COPY);
1847  } else { /* spp == 3 */
1848  sarrayAddString(sa, (char *)"/DeviceRGB setcolorspace", L_COPY);
1849  }
1850 
1851  sarrayAddString(sa,
1852  (char *)"/RawData currentfile /ASCII85Decode filter def", L_COPY);
1853  sarrayAddString(sa,
1854  (char *)"/Data RawData << >> /FlateDecode filter def", L_COPY);
1855 
1856  sarrayAddString(sa, (char *)"{ << /ImageType 1", L_COPY);
1857  snprintf(bigbuf, sizeof(bigbuf), " /Width %d", w);
1858  sarrayAddString(sa, bigbuf, L_COPY);
1859  snprintf(bigbuf, sizeof(bigbuf), " /Height %d", h);
1860  sarrayAddString(sa, bigbuf, L_COPY);
1861  snprintf(bigbuf, sizeof(bigbuf), " /BitsPerComponent %d", bps);
1862  sarrayAddString(sa, bigbuf, L_COPY);
1863  snprintf(bigbuf, sizeof(bigbuf),
1864  " /ImageMatrix [ %d 0 0 %d 0 %d ]", w, -h, h);
1865  sarrayAddString(sa, bigbuf, L_COPY);
1866 
1867  if (cid->cmapdata85) {
1868  sarrayAddString(sa, (char *)" /Decode [0 255]", L_COPY);
1869  } else if (spp == 1) {
1870  if (bps == 1) /* miniswhite photometry */
1871  sarrayAddString(sa, (char *)" /Decode [1 0]", L_COPY);
1872  else /* bps > 1 */
1873  sarrayAddString(sa, (char *)" /Decode [0 1]", L_COPY);
1874  } else { /* spp == 3 */
1875  sarrayAddString(sa, (char *)" /Decode [0 1 0 1 0 1]", L_COPY);
1876  }
1877 
1878  sarrayAddString(sa, (char *)" /DataSource Data", L_COPY);
1879  sarrayAddString(sa, (char *)" >> image", L_COPY);
1880  sarrayAddString(sa, (char *)" Data closefile", L_COPY);
1881  sarrayAddString(sa, (char *)" RawData flushfile", L_COPY);
1882  if (endpage == TRUE)
1883  sarrayAddString(sa, (char *)" showpage", L_COPY);
1884  sarrayAddString(sa, (char *)" restore", L_COPY);
1885  sarrayAddString(sa, (char *)"} exec", L_COPY);
1886 
1887  /* Insert the ascii85 gzipped data; this is now owned by sa */
1888  sarrayAddString(sa, cid->data85, L_INSERT);
1889 
1890  /* Generate and return the output string */
1891  outstr = sarrayToString(sa, 1);
1892  sarrayDestroy(&sa);
1893  cid->cmapdata85 = NULL; /* it has been transferred to sa and destroyed */
1894  cid->data85 = NULL; /* it has been transferred to sa and destroyed */
1895  return outstr;
1896 }
1897 
1898 
1899 /*---------------------------------------------------------------------*
1900  * Write to memory *
1901  *---------------------------------------------------------------------*/
1920 l_int32
1921 pixWriteMemPS(l_uint8 **pdata,
1922  size_t *psize,
1923  PIX *pix,
1924  BOX *box,
1925  l_int32 res,
1926  l_float32 scale)
1927 {
1928  PROCNAME("pixWriteMemPS");
1929 
1930  if (!pdata)
1931  return ERROR_INT("&data not defined", procName, 1 );
1932  if (!psize)
1933  return ERROR_INT("&size not defined", procName, 1 );
1934  if (!pix)
1935  return ERROR_INT("&pix not defined", procName, 1 );
1936 
1937  *pdata = (l_uint8 *)pixWriteStringPS(pix, box, res, scale);
1938  *psize = strlen((char *)(*pdata));
1939  return 0;
1940 }
1941 
1942 
1943 /*-------------------------------------------------------------*
1944  * Converting resolution *
1945  *-------------------------------------------------------------*/
1955 l_int32
1957  l_int32 h,
1958  l_float32 fillfract)
1959 {
1960 l_int32 resw, resh, res;
1961 
1962  if (fillfract == 0.0)
1963  fillfract = DEFAULT_FILL_FRACTION;
1964  resw = (l_int32)((w * 72.) / (LETTER_WIDTH * fillfract));
1965  resh = (l_int32)((h * 72.) / (LETTER_HEIGHT * fillfract));
1966  res = L_MAX(resw, resh);
1967  return res;
1968 }
1969 
1970 
1980 l_int32
1981 getResA4Page(l_int32 w,
1982  l_int32 h,
1983  l_float32 fillfract)
1984 {
1985 l_int32 resw, resh, res;
1986 
1987  if (fillfract == 0.0)
1988  fillfract = DEFAULT_FILL_FRACTION;
1989  resw = (l_int32)((w * 72.) / (A4_WIDTH * fillfract));
1990  resh = (l_int32)((h * 72.) / (A4_HEIGHT * fillfract));
1991  res = L_MAX(resw, resh);
1992  return res;
1993 }
1994 
1995 
1996 /*-------------------------------------------------------------*
1997  * Setting flag for writing bounding box hint *
1998  *-------------------------------------------------------------*/
1999 void
2000 l_psWriteBoundingBox(l_int32 flag)
2001 {
2002  var_PS_WRITE_BOUNDING_BOX = flag;
2003 }
2004 
2005 
2006 /* --------------------------------------------*/
2007 #endif /* USE_PSIO */
2008 /* --------------------------------------------*/
l_int32 pixWriteStreamPS(FILE *fp, PIX *pix, BOX *box, l_int32 res, l_float32 scale)
pixWriteStreamPS()
Definition: psio2.c:203
char * sarrayToString(SARRAY *sa, l_int32 addnlflag)
sarrayToString()
Definition: sarray1.c:757
l_int32 pixWritePSEmbed(const char *filein, const char *fileout)
pixWritePSEmbed()
Definition: psio2.c:150
l_int32 ncolors
Definition: imageio.h:175
l_int32 convertJpegToPSString(const char *filein, char **poutstr, l_int32 *pnbytes, l_int32 x, l_int32 y, l_int32 res, l_float32 scale, l_int32 pageno, l_int32 endpage)
convertJpegToPSString()
Definition: psio2.c:815
char * generateUncompressedPS(char *hexdata, l_int32 w, l_int32 h, l_int32 d, l_int32 psbpl, l_int32 bps, l_float32 xpt, l_float32 ypt, l_float32 wpt, l_float32 hpt, l_int32 boxflag)
generateUncompressedPS()
Definition: psio2.c:411
l_int32 pixWriteMemPS(l_uint8 **pdata, size_t *psize, PIX *pix, BOX *box, l_int32 res, l_float32 scale)
pixWriteMemPS()
Definition: psio2.c:1921
L_COMP_DATA * l_generateG4Data(const char *fname, l_int32 ascii85flag)
l_generateG4Data()
Definition: pdfio2.c:1324
char * cmapdata85
Definition: imageio.h:173
l_int32 convertJpegToPSEmbed(const char *filein, const char *fileout)
convertJpegToPSEmbed()
Definition: psio2.c:641
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:157
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1602
char * pixWriteStringPS(PIX *pixs, BOX *box, l_int32 res, l_float32 scale)
pixWriteStringPS()
Definition: psio2.c:301
l_int32 convertFlateToPS(const char *filein, const char *fileout, const char *operation, l_int32 x, l_int32 y, l_int32 res, l_float32 scale, l_int32 pageno, l_int32 endpage)
convertFlateToPS()
Definition: psio2.c:1630
l_int32 convertJpegToPS(const char *filein, const char *fileout, const char *operation, l_int32 x, l_int32 y, l_int32 res, l_float32 scale, l_int32 pageno, l_int32 endpage)
convertJpegToPS()
Definition: psio2.c:756
size_t nbytes85
Definition: imageio.h:172
Definition: array.h:116
void l_CIDataDestroy(L_COMP_DATA **pcid)
l_CIDataDestroy()
Definition: pdfio2.c:1450
static const l_int32 L_INSERT
Definition: pix.h:710
l_int32 tiffGetCount(FILE *fp, l_int32 *pn)
tiffGetCount()
Definition: tiffio.c:1476
l_int32 getResA4Page(l_int32 w, l_int32 h, l_float32 fillfract)
getResA4Page()
Definition: psio2.c:1981
void getScaledParametersPS(BOX *box, l_int32 wpix, l_int32 hpix, l_int32 res, l_float32 scale, l_float32 *pxpt, l_float32 *pypt, l_float32 *pwpt, l_float32 *phpt)
getScaledParametersPS()
Definition: psio2.c:520
char * generateG4PS(const char *filein, L_COMP_DATA *cid, l_float32 xpt, l_float32 ypt, l_float32 wpt, l_float32 hpt, l_int32 maskflag, l_int32 pageno, l_int32 endpage)
generateG4PS()
Definition: psio2.c:1303
l_int32 convertFlateToPSEmbed(const char *filein, const char *fileout)
convertFlateToPSEmbed()
Definition: psio2.c:1517
l_int32 boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:309
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:182
l_int32 convertG4ToPSString(const char *filein, char **poutstr, l_int32 *pnbytes, l_int32 x, l_int32 y, l_int32 res, l_float32 scale, l_int32 pageno, l_int32 maskflag, l_int32 endpage)
convertG4ToPSString()
Definition: psio2.c:1207
l_int32 getResLetterPage(l_int32 w, l_int32 h, l_float32 fillfract)
getResLetterPage()
Definition: psio2.c:1956
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:517
l_int32 sarrayAddString(SARRAY *sa, char *string, l_int32 copyflag)
sarrayAddString()
Definition: sarray1.c:439
char * generateFlatePS(const char *filein, L_COMP_DATA *cid, l_float32 xpt, l_float32 ypt, l_float32 wpt, l_float32 hpt, l_int32 pageno, l_int32 endpage)
generateFlatePS()
Definition: psio2.c:1780
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:545
l_int32 convertG4ToPSEmbed(const char *filein, const char *fileout)
convertG4ToPSEmbed()
Definition: psio2.c:1038
l_int32 convertTiffMultipageToPS(const char *filein, const char *fileout, l_float32 fillfract)
convertTiffMultipageToPS()
Definition: psio2.c:1437
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1636
l_int32 fileFormatIsTiff(FILE *fp)
fileFormatIsTiff()
Definition: readfile.c:783
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1593
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:189
PIX * pixConvertForPSWrap(PIX *pixs)
pixConvertForPSWrap()
Definition: pixconv.c:3832
l_int32 l_binaryWrite(const char *filename, const char *operation, void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1367
char * generateJpegPS(const char *filein, L_COMP_DATA *cid, l_float32 xpt, l_float32 ypt, l_float32 wpt, l_float32 hpt, l_int32 pageno, l_int32 endpage)
generateJpegPS()
Definition: psio2.c:909
Definition: pix.h:705
Definition: pix.h:134
l_int32 minisblack
Definition: imageio.h:180
PIX * pixReadTiff(const char *filename, l_int32 n)
pixReadTiff()
Definition: tiffio.c:371
void convertByteToHexAscii(l_uint8 byteval, char *pnib1, char *pnib2)
convertByteToHexAscii()
Definition: psio2.c:599
l_int32 convertG4ToPS(const char *filein, const char *fileout, const char *operation, l_int32 x, l_int32 y, l_int32 res, l_float32 scale, l_int32 pageno, l_int32 maskflag, l_int32 endpage)
convertG4ToPS()
Definition: psio2.c:1144
L_COMP_DATA * l_generateJpegData(const char *fname, l_int32 ascii85flag)
l_generateJpegData()
Definition: pdfio2.c:792
l_int32 pixGetDimensions(PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1052
l_int32 convertFlateToPSString(const char *filein, char **poutstr, l_int32 *pnbytes, l_int32 x, l_int32 y, l_int32 res, l_float32 scale, l_int32 pageno, l_int32 endpage)
convertFlateToPSString()
Definition: psio2.c:1696
Definition: pix.h:480
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:243
L_COMP_DATA * l_generateFlateData(const char *fname, l_int32 ascii85flag)
l_generateFlateData()
Definition: pdfio2.c:1086
size_t nbytescomp
Definition: imageio.h:170
static const l_int32 L_BUF_SIZE
Definition: classapp.c:55
l_int32 lept_rmfile(const char *filepath)
lept_rmfile()
Definition: utils2.c:2173
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:349