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 */
108static l_int32 var_PS_WRITE_BOUNDING_BOX = 1;
109
110#define Bufsize 512
111static const l_int32 DefaultInputRes = 300; /* typical scan res, ppi */
112static const l_int32 MinRes = 5;
113static const l_int32 MaxRes = 3000;
114
115 /* For computing resolution that fills page to desired amount */
116static const l_int32 LetterWidth = 612; /* points */
117static const l_int32 LetterHeight = 792; /* points */
118static const l_int32 A4Width = 595; /* points */
119static const l_int32 A4Height = 842; /* points */
120static 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 */
139static 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);
143static void convertByteToHexAscii(l_uint8 byteval, char *pnib1, char *pnib2);
144static 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);
148static 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);
151static 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);
155static 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);
158static 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);
162static 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 *-------------------------------------------------------------*/
187l_ok
188pixWritePSEmbed(const char *filein,
189 const char *fileout)
190{
191l_int32 w, h, ret;
192l_float32 scale;
193FILE *fp;
194PIX *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
240l_ok
242 PIX *pix,
243 BOX *box,
244 l_int32 res,
245 l_float32 scale)
246{
247char *outstr;
248l_int32 length;
249PIX *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
340char *
342 BOX *box,
343 l_int32 res,
344 l_float32 scale)
345{
346char nib1, nib2;
347char *hexdata, *outstr;
348l_uint8 byteval;
349l_int32 i, j, k, w, h, d;
350l_float32 wpt, hpt, xpt, ypt;
351l_int32 wpl, psbpl, hexbytes, boxflag, bps;
352l_uint32 *line, *data;
353PIX *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
450char *
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{
463char *outstr;
464char bigbuf[Bufsize];
465SARRAY *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)
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)
507 "{currentfile bpl readhexstring pop} image", L_COPY);
508 else /* d == 32 */
510 "{currentfile bpl readhexstring pop} false 3 colorimage",
511 L_COPY);
512 } else { /* boxflag == 1 */
513 if (d == 1 || d == 8)
515 "{currentfile bpl readhexstring pop} bind image", L_COPY);
516 else /* d == 32 */
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
557static 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{
568l_int32 bx, by, bw, bh;
569l_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
636static void
637convertByteToHexAscii(l_uint8 byteval,
638 char *pnib1,
639 char *pnib2)
640{
641l_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 *-------------------------------------------------------------*/
677l_ok
678convertJpegToPSEmbed(const char *filein,
679 const char *fileout)
680{
681char *outstr;
682l_int32 w, h, nbytes, ret;
683l_float32 xpt, ypt, wpt, hpt;
684L_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
793l_ok
794convertJpegToPS(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{
804char *outstr;
805l_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
855static l_ok
856convertJpegToPSString(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{
866char *outstr;
867l_float32 xpt, ypt, wpt, hpt;
868L_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
949static char *
950generateJpegPS(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{
959l_int32 w, h, bps, spp;
960char *outstr;
961char bigbuf[Bufsize];
962SARRAY *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);
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 *-------------------------------------------------------------*/
1075l_ok
1076convertG4ToPSEmbed(const char *filein,
1077 const char *fileout)
1078{
1079char *outstr;
1080l_int32 w, h, nbytes, ret;
1081l_float32 xpt, ypt, wpt, hpt;
1082L_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
1181l_ok
1182convertG4ToPS(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{
1193char *outstr;
1194l_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
1244static l_ok
1245convertG4ToPSString(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{
1256char *outstr;
1257l_float32 xpt, ypt, wpt, hpt;
1258L_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
1340static char *
1341generateG4PS(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{
1351l_int32 w, h;
1352char *outstr;
1353char bigbuf[Bufsize];
1354SARRAY *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 *-------------------------------------------------------------*/
1472l_ok
1473convertTiffMultipageToPS(const char *filein,
1474 const char *fileout,
1475 l_float32 fillfract)
1476{
1477char *tempfile;
1478l_int32 i, npages, w, h, istiff;
1479l_float32 scale;
1480PIX *pix, *pixs;
1481FILE *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 *---------------------------------------------------------------------*/
1552l_ok
1553convertFlateToPSEmbed(const char *filein,
1554 const char *fileout)
1555{
1556char *outstr;
1557l_int32 w, h, nbytes, ret;
1558l_float32 xpt, ypt, wpt, hpt;
1559L_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
1666l_ok
1667convertFlateToPS(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{
1677char *outstr;
1678l_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
1733static l_ok
1734convertFlateToPSString(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{
1744char *outstr;
1745l_float32 xpt, ypt, wpt, hpt;
1746L_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
1817static char *
1818generateFlatePS(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{
1827l_int32 w, h, bps, spp;
1828char *outstr;
1829char bigbuf[Bufsize];
1830SARRAY *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);
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 *---------------------------------------------------------------------*/
1956l_ok
1957pixWriteMemPS(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 *-------------------------------------------------------------*/
1991l_int32
1993 l_int32 h,
1994 l_float32 fillfract)
1995{
1996l_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
2016l_int32
2018 l_int32 h,
2019 l_float32 fillfract)
2020{
2021l_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 *-------------------------------------------------------------*/
2035void
2036l_psWriteBoundingBox(l_int32 flag)
2037{
2038 var_PS_WRITE_BOUNDING_BOX = flag;
2039}
2040
2041
2042/* --------------------------------------------*/
2043#endif /* USE_PSIO */
2044/* --------------------------------------------*/
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:313
void l_CIDataDestroy(L_COMP_DATA **pcid)
l_CIDataDestroy()
Definition: pdfio2.c:1656
L_COMP_DATA * l_generateFlateData(const char *fname, l_int32 ascii85flag)
l_generateFlateData()
Definition: pdfio2.c:1305
L_COMP_DATA * l_generateJpegData(const char *fname, l_int32 ascii85flag)
l_generateJpegData()
Definition: pdfio2.c:929
L_COMP_DATA * l_generateG4Data(const char *fname, l_int32 ascii85flag)
l_generateG4Data()
Definition: pdfio2.c:1118
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
@ L_COPY
Definition: pix.h:712
@ L_INSERT
Definition: pix.h:711
PIX * pixConvertForPSWrap(PIX *pixs)
pixConvertForPSWrap()
Definition: pixconv.c:3931
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
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 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
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
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
l_ok pixWriteStreamPS(FILE *fp, PIX *pix, BOX *box, l_int32 res, l_float32 scale)
pixWriteStreamPS()
Definition: psio2.c:241
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
l_int32 getResA4Page(l_int32 w, l_int32 h, l_float32 fillfract)
getResA4Page()
Definition: psio2.c:2017
l_ok pixWritePSEmbed(const char *filein, const char *fileout)
pixWritePSEmbed()
Definition: psio2.c:188
char * pixWriteStringPS(PIX *pixs, BOX *box, l_int32 res, l_float32 scale)
pixWriteStringPS()
Definition: psio2.c:341
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
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
l_ok convertFlateToPSEmbed(const char *filein, const char *fileout)
convertFlateToPSEmbed()
Definition: psio2.c:1553
l_ok convertG4ToPSEmbed(const char *filein, const char *fileout)
convertG4ToPSEmbed()
Definition: psio2.c:1076
l_ok pixWriteMemPS(l_uint8 **pdata, size_t *psize, PIX *pix, BOX *box, l_int32 res, l_float32 scale)
pixWriteMemPS()
Definition: psio2.c:1957
l_ok convertJpegToPSEmbed(const char *filein, const char *fileout)
convertJpegToPSEmbed()
Definition: psio2.c:678
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
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
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
l_int32 getResLetterPage(l_int32 w, l_int32 h, l_float32 fillfract)
getResLetterPage()
Definition: psio2.c:1992
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
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:193
l_int32 fileFormatIsTiff(FILE *fp)
fileFormatIsTiff()
Definition: readfile.c:800
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:170
char * sarrayToString(SARRAY *sa, l_int32 addnlflag)
sarrayToString()
Definition: sarray1.c:785
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:362
l_ok sarrayAddString(SARRAY *sa, const char *string, l_int32 copyflag)
sarrayAddString()
Definition: sarray1.c:451
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:250
Definition: pix.h:481
l_int32 ncolors
Definition: imageio.h:190
size_t nbytescomp
Definition: imageio.h:185
l_int32 minisblack
Definition: imageio.h:195
char * cmapdata85
Definition: imageio.h:188
size_t nbytes85
Definition: imageio.h:187
Definition: pix.h:139
Definition: array.h:127
PIX * pixReadTiff(const char *filename, l_int32 n)
pixReadTiff()
Definition: tiffio.c:383
l_ok tiffGetCount(FILE *fp, l_int32 *pn)
tiffGetCount()
Definition: tiffio.c:1637
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
l_int32 lept_rmfile(const char *filepath)
lept_rmfile()
Definition: utils2.c:2517
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1975
char * l_makeTempFilename(void)
l_makeTempFilename()
Definition: utils2.c:3397
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1932
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1569