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