Leptonica  1.82.0
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 
96 #ifdef HAVE_CONFIG_H
97 #include <config_auto.h>
98 #endif /* HAVE_CONFIG_H */
99 
100 #include <string.h>
101 #include "allheaders.h"
102 
103 /* --------------------------------------------*/
104 #if USE_PSIO /* defined in environ.h */
105  /* --------------------------------------------*/
106 
107  /* Set default for writing bounding box hint */
108 static l_int32 var_PS_WRITE_BOUNDING_BOX = 1;
109 
110 #define Bufsize 512
111 static const l_int32 DefaultInputRes = 300; /* typical scan res, ppi */
112 static const l_int32 MinRes = 5;
113 static const l_int32 MaxRes = 3000;
114 
115  /* For computing resolution that fills page to desired amount */
116 static const l_int32 LetterWidth = 612; /* points */
117 static const l_int32 LetterHeight = 792; /* points */
118 static const l_int32 A4Width = 595; /* points */
119 static const l_int32 A4Height = 842; /* points */
120 static const l_float32 DefaultFillFraction = 0.95;
121 
122 #ifndef NO_CONSOLE_IO
123 #define DEBUG_JPEG 0
124 #define DEBUG_G4 0
125 #define DEBUG_FLATE 0
126 #endif /* ~NO_CONSOLE_IO */
127 
128 /* Note that the bounding box hint at the top of the generated PostScript
129  * file is required for the "*Embed" functions. These generate a
130  * PostScript file for an individual image that can be translated and
131  * scaled by an application that embeds the image in its output
132  * (e.g., in the PS output from a TeX file).
133  * However, bounding box hints should not be embedded in any
134  * PostScript image that will be composited with other images,
135  * where more than one image may be placed in an arbitrary location
136  * on a page. */
137 
138  /* Static helper functions */
139 static void getScaledParametersPS(BOX *box, l_int32 wpix, l_int32 hpix,
140  l_int32 res, l_float32 scale,
141  l_float32 *pxpt, l_float32 *pypt,
142  l_float32 *pwpt, l_float32 *phpt);
143 static void convertByteToHexAscii(l_uint8 byteval, char *pnib1, char *pnib2);
144 static l_ok convertJpegToPSString(const char *filein, char **poutstr,
145  l_int32 *pnbytes, l_int32 x, l_int32 y,
146  l_int32 res, l_float32 scale,
147  l_int32 pageno, l_int32 endpage);
148 static char *generateJpegPS(const char *filein, L_COMP_DATA *cid,
149  l_float32 xpt, l_float32 ypt, l_float32 wpt,
150  l_float32 hpt, l_int32 pageno, l_int32 endpage);
151 static l_ok convertG4ToPSString(const char *filein, char **poutstr,
152  l_int32 *pnbytes, l_int32 x, l_int32 y,
153  l_int32 res, l_float32 scale, l_int32 pageno,
154  l_int32 maskflag, l_int32 endpage);
155 static char *generateG4PS(const char *filein, L_COMP_DATA *cid, l_float32 xpt,
156  l_float32 ypt, l_float32 wpt, l_float32 hpt,
157  l_int32 maskflag, l_int32 pageno, l_int32 endpage);
158 static l_ok convertFlateToPSString(const char *filein, char **poutstr,
159  l_int32 *pnbytes, l_int32 x, l_int32 y,
160  l_int32 res, l_float32 scale,
161  l_int32 pageno, l_int32 endpage);
162 static char *generateFlatePS(const char *filein, L_COMP_DATA *cid,
163  l_float32 xpt, l_float32 ypt, l_float32 wpt,
164  l_float32 hpt, l_int32 pageno, l_int32 endpage);
165 
166 
167 /*-------------------------------------------------------------*
168  * For uncompressed images *
169  *-------------------------------------------------------------*/
187 l_ok
188 pixWritePSEmbed(const char *filein,
189  const char *fileout)
190 {
191 l_int32 w, h, ret;
192 l_float32 scale;
193 FILE *fp;
194 PIX *pix;
195 
196  PROCNAME("pixWritePSEmbed");
197 
198  if (!filein)
199  return ERROR_INT("filein not defined", procName, 1);
200  if (!fileout)
201  return ERROR_INT("fileout not defined", procName, 1);
202 
203  if ((pix = pixRead(filein)) == NULL)
204  return ERROR_INT("image not read from file", procName, 1);
205  w = pixGetWidth(pix);
206  h = pixGetHeight(pix);
207  if (w * 11.0 > h * 8.5)
208  scale = 8.5 * 300. / (l_float32)w;
209  else
210  scale = 11.0 * 300. / (l_float32)h;
211 
212  if ((fp = fopenWriteStream(fileout, "wb")) == NULL)
213  return ERROR_INT("file not opened for write", procName, 1);
214  ret = pixWriteStreamPS(fp, pix, NULL, 0, scale);
215  fclose(fp);
216 
217  pixDestroy(&pix);
218  return ret;
219 }
220 
221 
240 l_ok
242  PIX *pix,
243  BOX *box,
244  l_int32 res,
245  l_float32 scale)
246 {
247 char *outstr;
248 l_int32 length;
249 PIX *pixc;
250 
251  PROCNAME("pixWriteStreamPS");
252 
253  if (!fp)
254  return (l_int32)ERROR_INT("stream not open", procName, 1);
255  if (!pix)
256  return (l_int32)ERROR_INT("pix not defined", procName, 1);
257 
258  if ((pixc = pixConvertForPSWrap(pix)) == NULL)
259  return (l_int32)ERROR_INT("pixc not made", procName, 1);
260 
261  if ((outstr = pixWriteStringPS(pixc, box, res, scale)) == NULL) {
262  pixDestroy(&pixc);
263  return (l_int32)ERROR_INT("outstr not made", procName, 1);
264  }
265  length = strlen(outstr);
266  fwrite(outstr, 1, length, fp);
267  LEPT_FREE(outstr);
268  pixDestroy(&pixc);
269  return 0;
270 }
271 
272 
340 char *
342  BOX *box,
343  l_int32 res,
344  l_float32 scale)
345 {
346 char nib1, nib2;
347 char *hexdata, *outstr;
348 l_uint8 byteval;
349 l_int32 i, j, k, w, h, d;
350 l_float32 wpt, hpt, xpt, ypt;
351 l_int32 wpl, psbpl, hexbytes, boxflag, bps;
352 l_uint32 *line, *data;
353 PIX *pix;
354 
355  PROCNAME("pixWriteStringPS");
356 
357  if (!pixs)
358  return (char *)ERROR_PTR("pixs not defined", procName, NULL);
359 
360  if ((pix = pixConvertForPSWrap(pixs)) == NULL)
361  return (char *)ERROR_PTR("pix not made", procName, NULL);
362  pixGetDimensions(pix, &w, &h, &d);
363 
364  /* Get the factors by which PS scales and translates, in pts */
365  if (!box)
366  boxflag = 0; /* no scaling; b.b. at center */
367  else
368  boxflag = 1; /* no b.b., specify placement and optional scaling */
369  getScaledParametersPS(box, w, h, res, scale, &xpt, &ypt, &wpt, &hpt);
370 
371  if (d == 1)
372  bps = 1; /* bits/sample */
373  else /* d == 8 || d == 32 */
374  bps = 8;
375 
376  /* Convert image data to hex string. psbpl is the number of
377  * bytes in each raster line when it is packed to the byte
378  * boundary (not the 32 bit word boundary, as with the pix).
379  * When converted to hex, the hex string has 2 bytes for
380  * every byte of raster data. */
381  wpl = pixGetWpl(pix);
382  if (d == 1 || d == 8)
383  psbpl = (w * d + 7) / 8;
384  else /* d == 32 */
385  psbpl = 3 * w;
386  data = pixGetData(pix);
387  hexbytes = 2 * psbpl * h; /* size of ps hex array */
388  if ((hexdata = (char *)LEPT_CALLOC(hexbytes + 1, sizeof(char))) == NULL)
389  return (char *)ERROR_PTR("hexdata not made", procName, NULL);
390  if (d == 1 || d == 8) {
391  for (i = 0, k = 0; i < h; i++) {
392  line = data + i * wpl;
393  for (j = 0; j < psbpl; j++) {
394  byteval = GET_DATA_BYTE(line, j);
395  convertByteToHexAscii(byteval, &nib1, &nib2);
396  hexdata[k++] = nib1;
397  hexdata[k++] = nib2;
398  }
399  }
400  } else { /* d == 32; hexdata bytes packed RGBRGB..., 2 per sample */
401  for (i = 0, k = 0; i < h; i++) {
402  line = data + i * wpl;
403  for (j = 0; j < w; j++) {
404  byteval = GET_DATA_BYTE(line + j, 0); /* red */
405  convertByteToHexAscii(byteval, &nib1, &nib2);
406  hexdata[k++] = nib1;
407  hexdata[k++] = nib2;
408  byteval = GET_DATA_BYTE(line + j, 1); /* green */
409  convertByteToHexAscii(byteval, &nib1, &nib2);
410  hexdata[k++] = nib1;
411  hexdata[k++] = nib2;
412  byteval = GET_DATA_BYTE(line + j, 2); /* blue */
413  convertByteToHexAscii(byteval, &nib1, &nib2);
414  hexdata[k++] = nib1;
415  hexdata[k++] = nib2;
416  }
417  }
418  }
419  hexdata[k] = '\0';
420 
421  outstr = generateUncompressedPS(hexdata, w, h, d, psbpl, bps,
422  xpt, ypt, wpt, hpt, boxflag);
423  pixDestroy(&pix);
424  if (!outstr)
425  return (char *)ERROR_PTR("outstr not made", procName, NULL);
426  return outstr;
427 }
428 
429 
450 char *
452  l_int32 w,
453  l_int32 h,
454  l_int32 d,
455  l_int32 psbpl,
456  l_int32 bps,
457  l_float32 xpt,
458  l_float32 ypt,
459  l_float32 wpt,
460  l_float32 hpt,
461  l_int32 boxflag)
462 {
463 char *outstr;
464 char bigbuf[Bufsize];
465 SARRAY *sa;
466 
467  PROCNAME("generateUncompressedPS");
468 
469  if (!hexdata)
470  return (char *)ERROR_PTR("hexdata not defined", procName, NULL);
471 
472  sa = sarrayCreate(0);
473  sarrayAddString(sa, "%!Adobe-PS", L_COPY);
474  if (boxflag == 0) {
475  snprintf(bigbuf, sizeof(bigbuf),
476  "%%%%BoundingBox: %7.2f %7.2f %7.2f %7.2f",
477  xpt, ypt, xpt + wpt, ypt + hpt);
478  sarrayAddString(sa, bigbuf, L_COPY);
479  } else { /* boxflag == 1 */
480  sarrayAddString(sa, "gsave", L_COPY);
481  }
482 
483  if (d == 1)
484  sarrayAddString(sa,
485  "{1 exch sub} settransfer %invert binary", L_COPY);
486 
487  snprintf(bigbuf, sizeof(bigbuf),
488  "/bpl %d string def %%bpl as a string", psbpl);
489  sarrayAddString(sa, bigbuf, L_COPY);
490  snprintf(bigbuf, sizeof(bigbuf),
491  "%7.2f %7.2f translate %%set image origin in pts", xpt, ypt);
492  sarrayAddString(sa, bigbuf, L_COPY);
493  snprintf(bigbuf, sizeof(bigbuf),
494  "%7.2f %7.2f scale %%set image size in pts", wpt, hpt);
495  sarrayAddString(sa, bigbuf, L_COPY);
496  snprintf(bigbuf, sizeof(bigbuf),
497  "%d %d %d %%image dimensions in pixels", w, h, bps);
498  sarrayAddString(sa, bigbuf, L_COPY);
499  snprintf(bigbuf, sizeof(bigbuf),
500  "[%d %d %d %d %d %d] %%mapping matrix: [w 0 0 -h 0 h]",
501  w, 0, 0, -h, 0, h);
502  sarrayAddString(sa, bigbuf, L_COPY);
503 
504  if (boxflag == 0) {
505  if (d == 1 || d == 8)
506  sarrayAddString(sa,
507  "{currentfile bpl readhexstring pop} image", L_COPY);
508  else /* d == 32 */
509  sarrayAddString(sa,
510  "{currentfile bpl readhexstring pop} false 3 colorimage",
511  L_COPY);
512  } else { /* boxflag == 1 */
513  if (d == 1 || d == 8)
514  sarrayAddString(sa,
515  "{currentfile bpl readhexstring pop} bind image", L_COPY);
516  else /* d == 32 */
517  sarrayAddString(sa,
518  "{currentfile bpl readhexstring pop} bind false 3 colorimage",
519  L_COPY);
520  }
521 
522  sarrayAddString(sa, hexdata, L_INSERT);
523 
524  if (boxflag == 0)
525  sarrayAddString(sa, "\nshowpage", L_COPY);
526  else /* boxflag == 1 */
527  sarrayAddString(sa, "\ngrestore", L_COPY);
528 
529  outstr = sarrayToString(sa, 1);
530  sarrayDestroy(&sa);
531  if (!outstr) L_ERROR("outstr not made\n", procName);
532  return outstr;
533 }
534 
535 
557 static void
559  l_int32 wpix,
560  l_int32 hpix,
561  l_int32 res,
562  l_float32 scale,
563  l_float32 *pxpt,
564  l_float32 *pypt,
565  l_float32 *pwpt,
566  l_float32 *phpt)
567 {
568 l_int32 bx, by, bw, bh;
569 l_float32 winch, hinch, xinch, yinch, fres;
570 
571  PROCNAME("getScaledParametersPS");
572 
573  if (res == 0)
574  res = DefaultInputRes;
575  fres = (l_float32)res;
576 
577  /* Allow the PS interpreter to scale the resolution */
578  if (scale == 0.0)
579  scale = 1.0;
580  if (scale != 1.0) {
581  fres = (l_float32)res / scale;
582  res = (l_int32)fres;
583  }
584 
585  /* Limit valid resolution interval */
586  if (res < MinRes || res > MaxRes) {
587  L_WARNING("res %d out of bounds; using default res; no scaling\n",
588  procName, res);
589  res = DefaultInputRes;
590  fres = (l_float32)res;
591  }
592 
593  if (!box) { /* center on page */
594  winch = (l_float32)wpix / fres;
595  hinch = (l_float32)hpix / fres;
596  xinch = (8.5 - winch) / 2.;
597  yinch = (11.0 - hinch) / 2.;
598  } else {
599  boxGetGeometry(box, &bx, &by, &bw, &bh);
600  if (bw == 0)
601  winch = (l_float32)wpix / fres;
602  else
603  winch = (l_float32)bw / 1000.;
604  if (bh == 0)
605  hinch = (l_float32)hpix / fres;
606  else
607  hinch = (l_float32)bh / 1000.;
608  xinch = (l_float32)bx / 1000.;
609  yinch = (l_float32)by / 1000.;
610  }
611 
612  if (xinch < 0)
613  L_WARNING("left edge < 0.0 inch\n", procName);
614  if (xinch + winch > 8.5)
615  L_WARNING("right edge > 8.5 inch\n", procName);
616  if (yinch < 0.0)
617  L_WARNING("bottom edge < 0.0 inch\n", procName);
618  if (yinch + hinch > 11.0)
619  L_WARNING("top edge > 11.0 inch\n", procName);
620 
621  *pwpt = 72. * winch;
622  *phpt = 72. * hinch;
623  *pxpt = 72. * xinch;
624  *pypt = 72. * yinch;
625  return;
626 }
627 
628 
636 static void
637 convertByteToHexAscii(l_uint8 byteval,
638  char *pnib1,
639  char *pnib2)
640 {
641 l_uint8 nib;
642 
643  nib = byteval >> 4;
644  if (nib < 10)
645  *pnib1 = '0' + nib;
646  else
647  *pnib1 = 'a' + (nib - 10);
648  nib = byteval & 0xf;
649  if (nib < 10)
650  *pnib2 = '0' + nib;
651  else
652  *pnib2 = 'a' + (nib - 10);
653  return;
654 }
655 
656 
657 /*-------------------------------------------------------------*
658  * For jpeg compressed images *
659  *-------------------------------------------------------------*/
677 l_ok
678 convertJpegToPSEmbed(const char *filein,
679  const char *fileout)
680 {
681 char *outstr;
682 l_int32 w, h, nbytes, ret;
683 l_float32 xpt, ypt, wpt, hpt;
684 L_COMP_DATA *cid;
685 
686  PROCNAME("convertJpegToPSEmbed");
687 
688  if (!filein)
689  return ERROR_INT("filein not defined", procName, 1);
690  if (!fileout)
691  return ERROR_INT("fileout not defined", procName, 1);
692 
693  /* Generate the ascii encoded jpeg data */
694  if ((cid = l_generateJpegData(filein, 1)) == NULL)
695  return ERROR_INT("jpeg data not made", procName, 1);
696  w = cid->w;
697  h = cid->h;
698 
699  /* Scale for 20 pt boundary and otherwise full filling
700  * in one direction on 8.5 x 11 inch device */
701  xpt = 20.0;
702  ypt = 20.0;
703  if (w * 11.0 > h * 8.5) {
704  wpt = 572.0; /* 612 - 2 * 20 */
705  hpt = wpt * (l_float32)h / (l_float32)w;
706  } else {
707  hpt = 752.0; /* 792 - 2 * 20 */
708  wpt = hpt * (l_float32)w / (l_float32)h;
709  }
710 
711  /* Generate the PS.
712  * The bounding box information should be inserted (default). */
713  outstr = generateJpegPS(NULL, cid, xpt, ypt, wpt, hpt, 1, 1);
714  l_CIDataDestroy(&cid);
715  if (!outstr)
716  return ERROR_INT("outstr not made", procName, 1);
717  nbytes = strlen(outstr);
718 
719  ret = l_binaryWrite(fileout, "w", outstr, nbytes);
720  LEPT_FREE(outstr);
721  if (ret) L_ERROR("ps string not written to file\n", procName);
722  return ret;
723 }
724 
725 
793 l_ok
794 convertJpegToPS(const char *filein,
795  const char *fileout,
796  const char *operation,
797  l_int32 x,
798  l_int32 y,
799  l_int32 res,
800  l_float32 scale,
801  l_int32 pageno,
802  l_int32 endpage)
803 {
804 char *outstr;
805 l_int32 nbytes;
806 
807  PROCNAME("convertJpegToPS");
808 
809  if (!filein)
810  return ERROR_INT("filein not defined", procName, 1);
811  if (!fileout)
812  return ERROR_INT("fileout not defined", procName, 1);
813  if (strcmp(operation, "w") && strcmp(operation, "a"))
814  return ERROR_INT("operation must be \"w\" or \"a\"", procName, 1);
815 
816  if (convertJpegToPSString(filein, &outstr, &nbytes, x, y, res, scale,
817  pageno, endpage))
818  return ERROR_INT("ps string not made", procName, 1);
819 
820  if (l_binaryWrite(fileout, operation, outstr, nbytes)) {
821  LEPT_FREE(outstr);
822  return ERROR_INT("ps string not written to file", procName, 1);
823  }
824 
825  LEPT_FREE(outstr);
826  return 0;
827 }
828 
829 
855 static l_ok
856 convertJpegToPSString(const char *filein,
857  char **poutstr,
858  l_int32 *pnbytes,
859  l_int32 x,
860  l_int32 y,
861  l_int32 res,
862  l_float32 scale,
863  l_int32 pageno,
864  l_int32 endpage)
865 {
866 char *outstr;
867 l_float32 xpt, ypt, wpt, hpt;
868 L_COMP_DATA *cid;
869 
870  PROCNAME("convertJpegToPSString");
871 
872  if (!poutstr)
873  return ERROR_INT("&outstr not defined", procName, 1);
874  if (!pnbytes)
875  return ERROR_INT("&nbytes not defined", procName, 1);
876  *poutstr = NULL;
877  *pnbytes = 0;
878  if (!filein)
879  return ERROR_INT("filein not defined", procName, 1);
880 
881  /* Generate the ascii encoded jpeg data */
882  if ((cid = l_generateJpegData(filein, 1)) == NULL)
883  return ERROR_INT("jpeg data not made", procName, 1);
884 
885  /* Get scaled location in pts. Guess the input scan resolution
886  * based on the input parameter %res, the resolution data in
887  * the pix, and the size of the image. */
888  if (scale == 0.0)
889  scale = 1.0;
890  if (res <= 0) {
891  if (cid->res > 0)
892  res = cid->res;
893  else
894  res = DefaultInputRes;
895  }
896 
897  /* Get scaled location in pts */
898  if (scale == 0.0)
899  scale = 1.0;
900  xpt = scale * x * 72. / res;
901  ypt = scale * y * 72. / res;
902  wpt = scale * cid->w * 72. / res;
903  hpt = scale * cid->h * 72. / res;
904 
905  if (pageno == 0)
906  pageno = 1;
907 
908 #if DEBUG_JPEG
909  lept_stderr("w = %d, h = %d, bps = %d, spp = %d\n",
910  cid->w, cid->h, cid->bps, cid->spp);
911  lept_stderr("comp bytes = %ld, nbytes85 = %ld, ratio = %5.3f\n",
912  (unsigned long)cid->nbytescomp, (unsigned long)cid->nbytes85,
913  (l_float32)cid->nbytes85 / (l_float32)cid->nbytescomp);
914  lept_stderr("xpt = %7.2f, ypt = %7.2f, wpt = %7.2f, hpt = %7.2f\n",
915  xpt, ypt, wpt, hpt);
916 #endif /* DEBUG_JPEG */
917 
918  /* Generate the PS */
919  outstr = generateJpegPS(NULL, cid, xpt, ypt, wpt, hpt, pageno, endpage);
920  l_CIDataDestroy(&cid);
921  if (!outstr)
922  return ERROR_INT("outstr not made", procName, 1);
923  *poutstr = outstr;
924  *pnbytes = strlen(outstr);
925  return 0;
926 }
927 
928 
949 static char *
950 generateJpegPS(const char *filein,
951  L_COMP_DATA *cid,
952  l_float32 xpt,
953  l_float32 ypt,
954  l_float32 wpt,
955  l_float32 hpt,
956  l_int32 pageno,
957  l_int32 endpage)
958 {
959 l_int32 w, h, bps, spp;
960 char *outstr;
961 char bigbuf[Bufsize];
962 SARRAY *sa;
963 
964  PROCNAME("generateJpegPS");
965 
966  if (!cid)
967  return (char *)ERROR_PTR("jpeg data not defined", procName, NULL);
968  w = cid->w;
969  h = cid->h;
970  bps = cid->bps;
971  spp = cid->spp;
972 
973  sa = sarrayCreate(50);
974  sarrayAddString(sa, "%!PS-Adobe-3.0", L_COPY);
975  sarrayAddString(sa, "%%Creator: leptonica", L_COPY);
976  if (filein)
977  snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: %s", filein);
978  else
979  snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: Jpeg compressed PS");
980  sarrayAddString(sa, bigbuf, L_COPY);
981  sarrayAddString(sa, "%%DocumentData: Clean7Bit", L_COPY);
982 
983  if (var_PS_WRITE_BOUNDING_BOX == 1) {
984  snprintf(bigbuf, sizeof(bigbuf),
985  "%%%%BoundingBox: %7.2f %7.2f %7.2f %7.2f",
986  xpt, ypt, xpt + wpt, ypt + hpt);
987  sarrayAddString(sa, bigbuf, L_COPY);
988  }
989 
990  sarrayAddString(sa, "%%LanguageLevel: 2", L_COPY);
991  sarrayAddString(sa, "%%EndComments", L_COPY);
992  snprintf(bigbuf, sizeof(bigbuf), "%%%%Page: %d %d", pageno, pageno);
993  sarrayAddString(sa, bigbuf, L_COPY);
994 
995  sarrayAddString(sa, "save", L_COPY);
996  sarrayAddString(sa,
997  "/RawData currentfile /ASCII85Decode filter def", L_COPY);
998  sarrayAddString(sa, "/Data RawData << >> /DCTDecode filter def", L_COPY);
999 
1000  snprintf(bigbuf, sizeof(bigbuf),
1001  "%7.2f %7.2f translate %%set image origin in pts", xpt, ypt);
1002  sarrayAddString(sa, bigbuf, L_COPY);
1003 
1004  snprintf(bigbuf, sizeof(bigbuf),
1005  "%7.2f %7.2f scale %%set image size in pts", wpt, hpt);
1006  sarrayAddString(sa, bigbuf, L_COPY);
1007 
1008  if (spp == 1)
1009  sarrayAddString(sa, "/DeviceGray setcolorspace", L_COPY);
1010  else if (spp == 3)
1011  sarrayAddString(sa, "/DeviceRGB setcolorspace", L_COPY);
1012  else /*spp == 4 */
1013  sarrayAddString(sa, "/DeviceCMYK setcolorspace", L_COPY);
1014 
1015  sarrayAddString(sa, "{ << /ImageType 1", L_COPY);
1016  snprintf(bigbuf, sizeof(bigbuf), " /Width %d", w);
1017  sarrayAddString(sa, bigbuf, L_COPY);
1018  snprintf(bigbuf, sizeof(bigbuf), " /Height %d", h);
1019  sarrayAddString(sa, bigbuf, L_COPY);
1020  snprintf(bigbuf, sizeof(bigbuf),
1021  " /ImageMatrix [ %d 0 0 %d 0 %d ]", w, -h, h);
1022  sarrayAddString(sa, bigbuf, L_COPY);
1023  sarrayAddString(sa, " /DataSource Data", L_COPY);
1024  snprintf(bigbuf, sizeof(bigbuf), " /BitsPerComponent %d", bps);
1025  sarrayAddString(sa, bigbuf, L_COPY);
1026 
1027  if (spp == 1)
1028  sarrayAddString(sa, " /Decode [0 1]", L_COPY);
1029  else if (spp == 3)
1030  sarrayAddString(sa, " /Decode [0 1 0 1 0 1]", L_COPY);
1031  else /* spp == 4 */
1032  sarrayAddString(sa, " /Decode [0 1 0 1 0 1 0 1]", L_COPY);
1033 
1034  sarrayAddString(sa, " >> image", L_COPY);
1035  sarrayAddString(sa, " Data closefile", L_COPY);
1036  sarrayAddString(sa, " RawData flushfile", L_COPY);
1037  if (endpage == TRUE)
1038  sarrayAddString(sa, " showpage", L_COPY);
1039  sarrayAddString(sa, " restore", L_COPY);
1040  sarrayAddString(sa, "} exec", L_COPY);
1041 
1042  /* Insert the ascii85 jpeg data; this is now owned by sa */
1043  sarrayAddString(sa, cid->data85, L_INSERT);
1044  cid->data85 = NULL; /* it has been transferred and destroyed */
1045 
1046  /* Generate and return the output string */
1047  outstr = sarrayToString(sa, 1);
1048  sarrayDestroy(&sa);
1049  return outstr;
1050 }
1051 
1052 
1053 /*-------------------------------------------------------------*
1054  * For ccitt g4 compressed images *
1055  *-------------------------------------------------------------*/
1075 l_ok
1076 convertG4ToPSEmbed(const char *filein,
1077  const char *fileout)
1078 {
1079 char *outstr;
1080 l_int32 w, h, nbytes, ret;
1081 l_float32 xpt, ypt, wpt, hpt;
1082 L_COMP_DATA *cid;
1083 
1084  PROCNAME("convertG4ToPSEmbed");
1085 
1086  if (!filein)
1087  return ERROR_INT("filein not defined", procName, 1);
1088  if (!fileout)
1089  return ERROR_INT("fileout not defined", procName, 1);
1090 
1091  if ((cid = l_generateG4Data(filein, 1)) == NULL)
1092  return ERROR_INT("g4 data not made", procName, 1);
1093  w = cid->w;
1094  h = cid->h;
1095 
1096  /* Scale for 20 pt boundary and otherwise full filling
1097  * in one direction on 8.5 x 11 inch device */
1098  xpt = 20.0;
1099  ypt = 20.0;
1100  if (w * 11.0 > h * 8.5) {
1101  wpt = 572.0; /* 612 - 2 * 20 */
1102  hpt = wpt * (l_float32)h / (l_float32)w;
1103  } else {
1104  hpt = 752.0; /* 792 - 2 * 20 */
1105  wpt = hpt * (l_float32)w / (l_float32)h;
1106  }
1107 
1108  /* Generate the PS, painting through the image mask.
1109  * The bounding box information should be inserted (default). */
1110  outstr = generateG4PS(NULL, cid, xpt, ypt, wpt, hpt, 1, 1, 1);
1111  l_CIDataDestroy(&cid);
1112  if (!outstr)
1113  return ERROR_INT("outstr not made", procName, 1);
1114  nbytes = strlen(outstr);
1115 
1116  ret = l_binaryWrite(fileout, "w", outstr, nbytes);
1117  LEPT_FREE(outstr);
1118  if (ret) L_ERROR("ps string not written to file\n", procName);
1119  return ret;
1120 }
1121 
1122 
1181 l_ok
1182 convertG4ToPS(const char *filein,
1183  const char *fileout,
1184  const char *operation,
1185  l_int32 x,
1186  l_int32 y,
1187  l_int32 res,
1188  l_float32 scale,
1189  l_int32 pageno,
1190  l_int32 maskflag,
1191  l_int32 endpage)
1192 {
1193 char *outstr;
1194 l_int32 nbytes, ret;
1195 
1196  PROCNAME("convertG4ToPS");
1197 
1198  if (!filein)
1199  return ERROR_INT("filein not defined", procName, 1);
1200  if (!fileout)
1201  return ERROR_INT("fileout not defined", procName, 1);
1202  if (strcmp(operation, "w") && strcmp(operation, "a"))
1203  return ERROR_INT("operation must be \"w\" or \"a\"", procName, 1);
1204 
1205  if (convertG4ToPSString(filein, &outstr, &nbytes, x, y, res, scale,
1206  pageno, maskflag, endpage))
1207  return ERROR_INT("ps string not made", procName, 1);
1208 
1209  ret = l_binaryWrite(fileout, operation, outstr, nbytes);
1210  LEPT_FREE(outstr);
1211  if (ret)
1212  return ERROR_INT("ps string not written to file", procName, 1);
1213  return 0;
1214 }
1215 
1216 
1244 static l_ok
1245 convertG4ToPSString(const char *filein,
1246  char **poutstr,
1247  l_int32 *pnbytes,
1248  l_int32 x,
1249  l_int32 y,
1250  l_int32 res,
1251  l_float32 scale,
1252  l_int32 pageno,
1253  l_int32 maskflag,
1254  l_int32 endpage)
1255 {
1256 char *outstr;
1257 l_float32 xpt, ypt, wpt, hpt;
1258 L_COMP_DATA *cid;
1259 
1260  PROCNAME("convertG4ToPSString");
1261 
1262  if (!poutstr)
1263  return ERROR_INT("&outstr not defined", procName, 1);
1264  if (!pnbytes)
1265  return ERROR_INT("&nbytes not defined", procName, 1);
1266  *poutstr = NULL;
1267  *pnbytes = 0;
1268  if (!filein)
1269  return ERROR_INT("filein not defined", procName, 1);
1270 
1271  if ((cid = l_generateG4Data(filein, 1)) == NULL)
1272  return ERROR_INT("g4 data not made", procName, 1);
1273 
1274  /* Get scaled location in pts. Guess the input scan resolution
1275  * based on the input parameter %res, the resolution data in
1276  * the pix, and the size of the image. */
1277  if (scale == 0.0)
1278  scale = 1.0;
1279  if (res <= 0) {
1280  if (cid->res > 0) {
1281  res = cid->res;
1282  } else {
1283  if (cid->h <= 3509) /* A4 height at 300 ppi */
1284  res = 300;
1285  else
1286  res = 600;
1287  }
1288  }
1289  xpt = scale * x * 72. / res;
1290  ypt = scale * y * 72. / res;
1291  wpt = scale * cid->w * 72. / res;
1292  hpt = scale * cid->h * 72. / res;
1293 
1294  if (pageno == 0)
1295  pageno = 1;
1296 
1297 #if DEBUG_G4
1298  lept_stderr("w = %d, h = %d, minisblack = %d\n",
1299  cid->w, cid->h, cid->minisblack);
1300  lept_stderr("comp bytes = %ld, nbytes85 = %ld\n",
1301  (unsigned long)cid->nbytescomp, (unsigned long)cid->nbytes85);
1302  lept_stderr("xpt = %7.2f, ypt = %7.2f, wpt = %7.2f, hpt = %7.2f\n",
1303  xpt, ypt, wpt, hpt);
1304 #endif /* DEBUG_G4 */
1305 
1306  /* Generate the PS */
1307  outstr = generateG4PS(NULL, cid, xpt, ypt, wpt, hpt,
1308  maskflag, pageno, endpage);
1309  l_CIDataDestroy(&cid);
1310  if (!outstr)
1311  return ERROR_INT("outstr not made", procName, 1);
1312  *poutstr = outstr;
1313  *pnbytes = strlen(outstr);
1314  return 0;
1315 }
1316 
1317 
1340 static char *
1341 generateG4PS(const char *filein,
1342  L_COMP_DATA *cid,
1343  l_float32 xpt,
1344  l_float32 ypt,
1345  l_float32 wpt,
1346  l_float32 hpt,
1347  l_int32 maskflag,
1348  l_int32 pageno,
1349  l_int32 endpage)
1350 {
1351 l_int32 w, h;
1352 char *outstr;
1353 char bigbuf[Bufsize];
1354 SARRAY *sa;
1355 
1356  PROCNAME("generateG4PS");
1357 
1358  if (!cid)
1359  return (char *)ERROR_PTR("g4 data not defined", procName, NULL);
1360  w = cid->w;
1361  h = cid->h;
1362 
1363  sa = sarrayCreate(50);
1364  sarrayAddString(sa, "%!PS-Adobe-3.0", L_COPY);
1365  sarrayAddString(sa, "%%Creator: leptonica", L_COPY);
1366  if (filein)
1367  snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: %s", filein);
1368  else
1369  snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: G4 compressed PS");
1370  sarrayAddString(sa, bigbuf, L_COPY);
1371  sarrayAddString(sa, "%%DocumentData: Clean7Bit", L_COPY);
1372 
1373  if (var_PS_WRITE_BOUNDING_BOX == 1) {
1374  snprintf(bigbuf, sizeof(bigbuf),
1375  "%%%%BoundingBox: %7.2f %7.2f %7.2f %7.2f",
1376  xpt, ypt, xpt + wpt, ypt + hpt);
1377  sarrayAddString(sa, bigbuf, L_COPY);
1378  }
1379 
1380  sarrayAddString(sa, "%%LanguageLevel: 2", L_COPY);
1381  sarrayAddString(sa, "%%EndComments", L_COPY);
1382  snprintf(bigbuf, sizeof(bigbuf), "%%%%Page: %d %d", pageno, pageno);
1383  sarrayAddString(sa, bigbuf, L_COPY);
1384 
1385  sarrayAddString(sa, "save", L_COPY);
1386  sarrayAddString(sa, "100 dict begin", L_COPY);
1387 
1388  snprintf(bigbuf, sizeof(bigbuf),
1389  "%7.2f %7.2f translate %%set image origin in pts", xpt, ypt);
1390  sarrayAddString(sa, bigbuf, L_COPY);
1391 
1392  snprintf(bigbuf, sizeof(bigbuf),
1393  "%7.2f %7.2f scale %%set image size in pts", wpt, hpt);
1394  sarrayAddString(sa, bigbuf, L_COPY);
1395 
1396  sarrayAddString(sa, "/DeviceGray setcolorspace", L_COPY);
1397 
1398  sarrayAddString(sa, "{", L_COPY);
1399  sarrayAddString(sa,
1400  " /RawData currentfile /ASCII85Decode filter def", L_COPY);
1401  sarrayAddString(sa, " << ", L_COPY);
1402  sarrayAddString(sa, " /ImageType 1", L_COPY);
1403  snprintf(bigbuf, sizeof(bigbuf), " /Width %d", w);
1404  sarrayAddString(sa, bigbuf, L_COPY);
1405  snprintf(bigbuf, sizeof(bigbuf), " /Height %d", h);
1406  sarrayAddString(sa, bigbuf, L_COPY);
1407  snprintf(bigbuf, sizeof(bigbuf),
1408  " /ImageMatrix [ %d 0 0 %d 0 %d ]", w, -h, h);
1409  sarrayAddString(sa, bigbuf, L_COPY);
1410  sarrayAddString(sa, " /BitsPerComponent 1", L_COPY);
1411  sarrayAddString(sa, " /Interpolate true", L_COPY);
1412  if (cid->minisblack)
1413  sarrayAddString(sa, " /Decode [1 0]", L_COPY);
1414  else /* miniswhite; typical for 1 bpp */
1415  sarrayAddString(sa, " /Decode [0 1]", L_COPY);
1416  sarrayAddString(sa, " /DataSource RawData", L_COPY);
1417  sarrayAddString(sa, " <<", L_COPY);
1418  sarrayAddString(sa, " /K -1", L_COPY);
1419  snprintf(bigbuf, sizeof(bigbuf), " /Columns %d", w);
1420  sarrayAddString(sa, bigbuf, L_COPY);
1421  snprintf(bigbuf, sizeof(bigbuf), " /Rows %d", h);
1422  sarrayAddString(sa, bigbuf, L_COPY);
1423  sarrayAddString(sa, " >> /CCITTFaxDecode filter", L_COPY);
1424  if (maskflag == TRUE) /* just paint through the fg */
1425  sarrayAddString(sa, " >> imagemask", L_COPY);
1426  else /* Paint full image */
1427  sarrayAddString(sa, " >> image", L_COPY);
1428  sarrayAddString(sa, " RawData flushfile", L_COPY);
1429  if (endpage == TRUE)
1430  sarrayAddString(sa, " showpage", L_COPY);
1431  sarrayAddString(sa, "}", L_COPY);
1432 
1433  sarrayAddString(sa, "%%BeginData:", L_COPY);
1434  sarrayAddString(sa, "exec", L_COPY);
1435 
1436  /* Insert the ascii85 ccittg4 data; this is now owned by sa */
1437  sarrayAddString(sa, cid->data85, L_INSERT);
1438 
1439  /* Concat the trailing data */
1440  sarrayAddString(sa, "%%EndData", L_COPY);
1441  sarrayAddString(sa, "end", L_COPY);
1442  sarrayAddString(sa, "restore", L_COPY);
1443 
1444  outstr = sarrayToString(sa, 1);
1445  sarrayDestroy(&sa);
1446  cid->data85 = NULL; /* it has been transferred and destroyed */
1447  return outstr;
1448 }
1449 
1450 
1451 /*-------------------------------------------------------------*
1452  * For tiff multipage files *
1453  *-------------------------------------------------------------*/
1472 l_ok
1473 convertTiffMultipageToPS(const char *filein,
1474  const char *fileout,
1475  l_float32 fillfract)
1476 {
1477 char *tempfile;
1478 l_int32 i, npages, w, h, istiff;
1479 l_float32 scale;
1480 PIX *pix, *pixs;
1481 FILE *fp;
1482 
1483  PROCNAME("convertTiffMultipageToPS");
1484 
1485  if (!filein)
1486  return ERROR_INT("filein not defined", procName, 1);
1487  if (!fileout)
1488  return ERROR_INT("fileout not defined", procName, 1);
1489 
1490  if ((fp = fopenReadStream(filein)) == NULL)
1491  return ERROR_INT("file not found", procName, 1);
1492  istiff = fileFormatIsTiff(fp);
1493  if (!istiff) {
1494  fclose(fp);
1495  return ERROR_INT("file not tiff format", procName, 1);
1496  }
1497  tiffGetCount(fp, &npages);
1498  fclose(fp);
1499 
1500  if (fillfract == 0.0)
1501  fillfract = DefaultFillFraction;
1502 
1503  for (i = 0; i < npages; i++) {
1504  if ((pix = pixReadTiff(filein, i)) == NULL)
1505  return ERROR_INT("pix not made", procName, 1);
1506 
1507  pixGetDimensions(pix, &w, &h, NULL);
1508  if (w == 1728 && h < w) /* it's a std res fax */
1509  pixs = pixScale(pix, 1.0, 2.0);
1510  else
1511  pixs = pixClone(pix);
1512 
1513  tempfile = l_makeTempFilename();
1514  pixWrite(tempfile, pixs, IFF_TIFF_G4);
1515  scale = L_MIN(fillfract * 2550 / w, fillfract * 3300 / h);
1516  if (i == 0)
1517  convertG4ToPS(tempfile, fileout, "w", 0, 0, 300, scale,
1518  i + 1, FALSE, TRUE);
1519  else
1520  convertG4ToPS(tempfile, fileout, "a", 0, 0, 300, scale,
1521  i + 1, FALSE, TRUE);
1522  lept_rmfile(tempfile);
1523  LEPT_FREE(tempfile);
1524  pixDestroy(&pix);
1525  pixDestroy(&pixs);
1526  }
1527 
1528  return 0;
1529 }
1530 
1531 
1532 /*---------------------------------------------------------------------*
1533  * For flate (gzip) compressed images (e.g., png) *
1534  *---------------------------------------------------------------------*/
1552 l_ok
1553 convertFlateToPSEmbed(const char *filein,
1554  const char *fileout)
1555 {
1556 char *outstr;
1557 l_int32 w, h, nbytes, ret;
1558 l_float32 xpt, ypt, wpt, hpt;
1559 L_COMP_DATA *cid;
1560 
1561  PROCNAME("convertFlateToPSEmbed");
1562 
1563  if (!filein)
1564  return ERROR_INT("filein not defined", procName, 1);
1565  if (!fileout)
1566  return ERROR_INT("fileout not defined", procName, 1);
1567 
1568  if ((cid = l_generateFlateData(filein, 1)) == NULL)
1569  return ERROR_INT("flate data not made", procName, 1);
1570  w = cid->w;
1571  h = cid->h;
1572 
1573  /* Scale for 20 pt boundary and otherwise full filling
1574  * in one direction on 8.5 x 11 inch device */
1575  xpt = 20.0;
1576  ypt = 20.0;
1577  if (w * 11.0 > h * 8.5) {
1578  wpt = 572.0; /* 612 - 2 * 20 */
1579  hpt = wpt * (l_float32)h / (l_float32)w;
1580  } else {
1581  hpt = 752.0; /* 792 - 2 * 20 */
1582  wpt = hpt * (l_float32)w / (l_float32)h;
1583  }
1584 
1585  /* Generate the PS.
1586  * The bounding box information should be inserted (default). */
1587  outstr = generateFlatePS(NULL, cid, xpt, ypt, wpt, hpt, 1, 1);
1588  l_CIDataDestroy(&cid);
1589  if (!outstr)
1590  return ERROR_INT("outstr not made", procName, 1);
1591  nbytes = strlen(outstr);
1592 
1593  ret = l_binaryWrite(fileout, "w", outstr, nbytes);
1594  LEPT_FREE(outstr);
1595  if (ret) L_ERROR("ps string not written to file\n", procName);
1596  return ret;
1597 }
1598 
1599 
1666 l_ok
1667 convertFlateToPS(const char *filein,
1668  const char *fileout,
1669  const char *operation,
1670  l_int32 x,
1671  l_int32 y,
1672  l_int32 res,
1673  l_float32 scale,
1674  l_int32 pageno,
1675  l_int32 endpage)
1676 {
1677 char *outstr;
1678 l_int32 nbytes, ret;
1679 
1680  PROCNAME("convertFlateToPS");
1681 
1682  if (!filein)
1683  return ERROR_INT("filein not defined", procName, 1);
1684  if (!fileout)
1685  return ERROR_INT("fileout not defined", procName, 1);
1686  if (strcmp(operation, "w") && strcmp(operation, "a"))
1687  return ERROR_INT("operation must be \"w\" or \"a\"", procName, 1);
1688 
1689  if (convertFlateToPSString(filein, &outstr, &nbytes, x, y, res, scale,
1690  pageno, endpage))
1691  return ERROR_INT("ps string not made", procName, 1);
1692 
1693  ret = l_binaryWrite(fileout, operation, outstr, nbytes);
1694  LEPT_FREE(outstr);
1695  if (ret) L_ERROR("ps string not written to file\n", procName);
1696  return ret;
1697 }
1698 
1699 
1733 static l_ok
1734 convertFlateToPSString(const char *filein,
1735  char **poutstr,
1736  l_int32 *pnbytes,
1737  l_int32 x,
1738  l_int32 y,
1739  l_int32 res,
1740  l_float32 scale,
1741  l_int32 pageno,
1742  l_int32 endpage)
1743 {
1744 char *outstr;
1745 l_float32 xpt, ypt, wpt, hpt;
1746 L_COMP_DATA *cid;
1747 
1748  PROCNAME("convertFlateToPSString");
1749 
1750  if (!poutstr)
1751  return ERROR_INT("&outstr not defined", procName, 1);
1752  if (!pnbytes)
1753  return ERROR_INT("&nbytes not defined", procName, 1);
1754  *pnbytes = 0;
1755  *poutstr = NULL;
1756  if (!filein)
1757  return ERROR_INT("filein not defined", procName, 1);
1758 
1759  if ((cid = l_generateFlateData(filein, 1)) == NULL)
1760  return ERROR_INT("flate data not made", procName, 1);
1761 
1762  /* Get scaled location in pts. Guess the input scan resolution
1763  * based on the input parameter %res, the resolution data in
1764  * the pix, and the size of the image. */
1765  if (scale == 0.0)
1766  scale = 1.0;
1767  if (res <= 0) {
1768  if (cid->res > 0)
1769  res = cid->res;
1770  else
1771  res = DefaultInputRes;
1772  }
1773  xpt = scale * x * 72. / res;
1774  ypt = scale * y * 72. / res;
1775  wpt = scale * cid->w * 72. / res;
1776  hpt = scale * cid->h * 72. / res;
1777 
1778  if (pageno == 0)
1779  pageno = 1;
1780 
1781 #if DEBUG_FLATE
1782  lept_stderr("w = %d, h = %d, bps = %d, spp = %d\n",
1783  cid->w, cid->h, cid->bps, cid->spp);
1784  lept_stderr("uncomp bytes = %ld, comp bytes = %ld, nbytes85 = %ld\n",
1785  (unsigned long)cid->nbytes, (unsigned long)cid->nbytescomp,
1786  (unsigned long)cid->nbytes85);
1787  lept_stderr("xpt = %7.2f, ypt = %7.2f, wpt = %7.2f, hpt = %7.2f\n",
1788  xpt, ypt, wpt, hpt);
1789 #endif /* DEBUG_FLATE */
1790 
1791  /* Generate the PS */
1792  outstr = generateFlatePS(NULL, cid, xpt, ypt, wpt, hpt, pageno, endpage);
1793  l_CIDataDestroy(&cid);
1794  if (!outstr)
1795  return ERROR_INT("outstr not made", procName, 1);
1796  *poutstr = outstr;
1797  *pnbytes = strlen(outstr);
1798  return 0;
1799 }
1800 
1801 
1817 static char *
1818 generateFlatePS(const char *filein,
1819  L_COMP_DATA *cid,
1820  l_float32 xpt,
1821  l_float32 ypt,
1822  l_float32 wpt,
1823  l_float32 hpt,
1824  l_int32 pageno,
1825  l_int32 endpage)
1826 {
1827 l_int32 w, h, bps, spp;
1828 char *outstr;
1829 char bigbuf[Bufsize];
1830 SARRAY *sa;
1831 
1832  PROCNAME("generateFlatePS");
1833 
1834  if (!cid)
1835  return (char *)ERROR_PTR("flate data not defined", procName, NULL);
1836  w = cid->w;
1837  h = cid->h;
1838  bps = cid->bps;
1839  spp = cid->spp;
1840 
1841  sa = sarrayCreate(50);
1842  sarrayAddString(sa, "%!PS-Adobe-3.0 EPSF-3.0", L_COPY);
1843  sarrayAddString(sa, "%%Creator: leptonica", L_COPY);
1844  if (filein)
1845  snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: %s", filein);
1846  else
1847  snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: Flate compressed PS");
1848  sarrayAddString(sa, bigbuf, L_COPY);
1849  sarrayAddString(sa, "%%DocumentData: Clean7Bit", L_COPY);
1850 
1851  if (var_PS_WRITE_BOUNDING_BOX == 1) {
1852  snprintf(bigbuf, sizeof(bigbuf),
1853  "%%%%BoundingBox: %7.2f %7.2f %7.2f %7.2f",
1854  xpt, ypt, xpt + wpt, ypt + hpt);
1855  sarrayAddString(sa, bigbuf, L_COPY);
1856  }
1857 
1858  sarrayAddString(sa, "%%LanguageLevel: 3", L_COPY);
1859  sarrayAddString(sa, "%%EndComments", L_COPY);
1860  snprintf(bigbuf, sizeof(bigbuf), "%%%%Page: %d %d", pageno, pageno);
1861  sarrayAddString(sa, bigbuf, L_COPY);
1862 
1863  sarrayAddString(sa, "save", L_COPY);
1864  snprintf(bigbuf, sizeof(bigbuf),
1865  "%7.2f %7.2f translate %%set image origin in pts", xpt, ypt);
1866  sarrayAddString(sa, bigbuf, L_COPY);
1867 
1868  snprintf(bigbuf, sizeof(bigbuf),
1869  "%7.2f %7.2f scale %%set image size in pts", wpt, hpt);
1870  sarrayAddString(sa, bigbuf, L_COPY);
1871 
1872  /* If there is a colormap, add the data; it is now owned by sa */
1873  if (cid->cmapdata85) {
1874  snprintf(bigbuf, sizeof(bigbuf),
1875  "[ /Indexed /DeviceRGB %d %%set colormap type/size",
1876  cid->ncolors - 1);
1877  sarrayAddString(sa, bigbuf, L_COPY);
1878  sarrayAddString(sa, " <~", L_COPY);
1879  sarrayAddString(sa, cid->cmapdata85, L_INSERT);
1880  sarrayAddString(sa, " ] setcolorspace", L_COPY);
1881  } else if (spp == 1) {
1882  sarrayAddString(sa, "/DeviceGray setcolorspace", L_COPY);
1883  } else { /* spp == 3 */
1884  sarrayAddString(sa, "/DeviceRGB setcolorspace", L_COPY);
1885  }
1886 
1887  sarrayAddString(sa,
1888  "/RawData currentfile /ASCII85Decode filter def", L_COPY);
1889  sarrayAddString(sa,
1890  "/Data RawData << >> /FlateDecode filter def", L_COPY);
1891 
1892  sarrayAddString(sa, "{ << /ImageType 1", L_COPY);
1893  snprintf(bigbuf, sizeof(bigbuf), " /Width %d", w);
1894  sarrayAddString(sa, bigbuf, L_COPY);
1895  snprintf(bigbuf, sizeof(bigbuf), " /Height %d", h);
1896  sarrayAddString(sa, bigbuf, L_COPY);
1897  snprintf(bigbuf, sizeof(bigbuf), " /BitsPerComponent %d", bps);
1898  sarrayAddString(sa, bigbuf, L_COPY);
1899  snprintf(bigbuf, sizeof(bigbuf),
1900  " /ImageMatrix [ %d 0 0 %d 0 %d ]", w, -h, h);
1901  sarrayAddString(sa, bigbuf, L_COPY);
1902 
1903  if (cid->cmapdata85) {
1904  sarrayAddString(sa, " /Decode [0 255]", L_COPY);
1905  } else if (spp == 1) {
1906  if (bps == 1) /* miniswhite photometry */
1907  sarrayAddString(sa, " /Decode [1 0]", L_COPY);
1908  else /* bps > 1 */
1909  sarrayAddString(sa, " /Decode [0 1]", L_COPY);
1910  } else { /* spp == 3 */
1911  sarrayAddString(sa, " /Decode [0 1 0 1 0 1]", L_COPY);
1912  }
1913 
1914  sarrayAddString(sa, " /DataSource Data", L_COPY);
1915  sarrayAddString(sa, " >> image", L_COPY);
1916  sarrayAddString(sa, " Data closefile", L_COPY);
1917  sarrayAddString(sa, " RawData flushfile", L_COPY);
1918  if (endpage == TRUE)
1919  sarrayAddString(sa, " showpage", L_COPY);
1920  sarrayAddString(sa, " restore", L_COPY);
1921  sarrayAddString(sa, "} exec", L_COPY);
1922 
1923  /* Insert the ascii85 gzipped data; this is now owned by sa */
1924  sarrayAddString(sa, cid->data85, L_INSERT);
1925 
1926  /* Generate and return the output string */
1927  outstr = sarrayToString(sa, 1);
1928  sarrayDestroy(&sa);
1929  cid->cmapdata85 = NULL; /* it has been transferred to sa and destroyed */
1930  cid->data85 = NULL; /* it has been transferred to sa and destroyed */
1931  return outstr;
1932 }
1933 
1934 
1935 /*---------------------------------------------------------------------*
1936  * Write to memory *
1937  *---------------------------------------------------------------------*/
1956 l_ok
1957 pixWriteMemPS(l_uint8 **pdata,
1958  size_t *psize,
1959  PIX *pix,
1960  BOX *box,
1961  l_int32 res,
1962  l_float32 scale)
1963 {
1964  PROCNAME("pixWriteMemPS");
1965 
1966  if (!pdata)
1967  return ERROR_INT("&data not defined", procName, 1 );
1968  if (!psize)
1969  return ERROR_INT("&size not defined", procName, 1 );
1970  if (!pix)
1971  return ERROR_INT("&pix not defined", procName, 1 );
1972 
1973  *pdata = (l_uint8 *)pixWriteStringPS(pix, box, res, scale);
1974  *psize = strlen((char *)(*pdata));
1975  return 0;
1976 }
1977 
1978 
1979 /*-------------------------------------------------------------*
1980  * Converting resolution *
1981  *-------------------------------------------------------------*/
1991 l_int32
1993  l_int32 h,
1994  l_float32 fillfract)
1995 {
1996 l_int32 resw, resh, res;
1997 
1998  if (fillfract == 0.0)
1999  fillfract = DefaultFillFraction;
2000  resw = (l_int32)((w * 72.) / (LetterWidth * fillfract));
2001  resh = (l_int32)((h * 72.) / (LetterHeight * fillfract));
2002  res = L_MAX(resw, resh);
2003  return res;
2004 }
2005 
2006 
2016 l_int32
2017 getResA4Page(l_int32 w,
2018  l_int32 h,
2019  l_float32 fillfract)
2020 {
2021 l_int32 resw, resh, res;
2022 
2023  if (fillfract == 0.0)
2024  fillfract = DefaultFillFraction;
2025  resw = (l_int32)((w * 72.) / (A4Width * fillfract));
2026  resh = (l_int32)((h * 72.) / (A4Height * fillfract));
2027  res = L_MAX(resw, resh);
2028  return res;
2029 }
2030 
2031 
2032 /*-------------------------------------------------------------*
2033  * Setting flag for writing bounding box hint *
2034  *-------------------------------------------------------------*/
2035 void
2036 l_psWriteBoundingBox(l_int32 flag)
2037 {
2038  var_PS_WRITE_BOUNDING_BOX = flag;
2039 }
2040 
2041 
2042 /* --------------------------------------------*/
2043 #endif /* USE_PSIO */
2044 /* --------------------------------------------*/
static 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:558
l_ok pixWriteMemPS(l_uint8 **pdata, size_t *psize, PIX *pix, BOX *box, l_int32 res, l_float32 scale)
pixWriteMemPS()
Definition: psio2.c:1957
char * sarrayToString(SARRAY *sa, l_int32 addnlflag)
sarrayToString()
Definition: sarray1.c:785
l_int32 ncolors
Definition: imageio.h:190
static 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:1818
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:451
char * l_makeTempFilename(void)
l_makeTempFilename()
Definition: utils2.c:3397
L_COMP_DATA * l_generateG4Data(const char *fname, l_int32 ascii85flag)
l_generateG4Data()
Definition: pdfio2.c:1118
Definition: pix.h:712
char * cmapdata85
Definition: imageio.h:188
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
static l_ok 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:1245
l_ok convertJpegToPSEmbed(const char *filein, const char *fileout)
convertJpegToPSEmbed()
Definition: psio2.c:678
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:170
l_ok convertFlateToPSEmbed(const char *filein, const char *fileout)
convertFlateToPSEmbed()
Definition: psio2.c:1553
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok pixWritePSEmbed(const char *filein, const char *fileout)
pixWritePSEmbed()
Definition: psio2.c:188
static l_ok 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:856
char * pixWriteStringPS(PIX *pixs, BOX *box, l_int32 res, l_float32 scale)
pixWriteStringPS()
Definition: psio2.c:341
static 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:950
static l_ok 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:1734
size_t nbytes85
Definition: imageio.h:187
static 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:1341
Definition: array.h:126
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1569
void l_CIDataDestroy(L_COMP_DATA **pcid)
l_CIDataDestroy()
Definition: pdfio2.c:1656
l_ok sarrayAddString(SARRAY *sa, const char *string, l_int32 copyflag)
sarrayAddString()
Definition: sarray1.c:451
l_int32 getResA4Page(l_int32 w, l_int32 h, l_float32 fillfract)
getResA4Page()
Definition: psio2.c:2017
l_ok convertG4ToPSEmbed(const char *filein, const char *fileout)
convertG4ToPSEmbed()
Definition: psio2.c:1076
l_ok 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:794
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
l_int32 getResLetterPage(l_int32 w, l_int32 h, l_float32 fillfract)
getResLetterPage()
Definition: psio2.c:1992
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
l_ok 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:1182
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
Definition: pix.h:711
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1975
l_int32 fileFormatIsTiff(FILE *fp)
fileFormatIsTiff()
Definition: readfile.c:800
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1932
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:193
PIX * pixConvertForPSWrap(PIX *pixs)
pixConvertForPSWrap()
Definition: pixconv.c:3931
l_ok pixWriteStreamPS(FILE *fp, PIX *pix, BOX *box, l_int32 res, l_float32 scale)
pixWriteStreamPS()
Definition: psio2.c:241
l_ok convertTiffMultipageToPS(const char *filein, const char *fileout, l_float32 fillfract)
convertTiffMultipageToPS()
Definition: psio2.c:1473
static void convertByteToHexAscii(l_uint8 byteval, char *pnib1, char *pnib2)
convertByteToHexAscii()
Definition: psio2.c:637
Definition: pix.h:138
l_int32 minisblack
Definition: imageio.h:195
PIX * pixReadTiff(const char *filename, l_int32 n)
pixReadTiff()
Definition: tiffio.c:383
l_ok 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:1667
L_COMP_DATA * l_generateJpegData(const char *fname, l_int32 ascii85flag)
l_generateJpegData()
Definition: pdfio2.c:929
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:313
Definition: pix.h:480
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:250
l_ok tiffGetCount(FILE *fp, l_int32 *pn)
tiffGetCount()
Definition: tiffio.c:1637
L_COMP_DATA * l_generateFlateData(const char *fname, l_int32 ascii85flag)
l_generateFlateData()
Definition: pdfio2.c:1305
size_t nbytescomp
Definition: imageio.h:185
l_int32 lept_rmfile(const char *filepath)
lept_rmfile()
Definition: utils2.c:2517
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:362