Leptonica 1.84.1
Image processing and image analysis suite
Loading...
Searching...
No Matches
writefile.c
1/*====================================================================*
2 - Copyright (C) 2001-2016 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
27/*
28 * writefile.c
29 *
30 * Set jpeg quality for pixWrite() and pixWriteMem()
31 * l_int32 l_jpegSetQuality()
32 *
33 * Set global variable LeptDebugOK for writing to named temp files
34 * l_int32 setLeptDebugOK()
35 *
36 * High-level procedures for writing images to file:
37 * l_int32 pixaWriteFiles()
38 * l_int32 pixWriteDebug()
39 * l_int32 pixWrite()
40 * l_int32 pixWriteAutoFormat()
41 * l_int32 pixWriteStream()
42 * l_int32 pixWriteImpliedFormat()
43 *
44 * Selection of output format if default is requested
45 * l_int32 pixChooseOutputFormat()
46 * l_int32 getImpliedFileFormat()
47 * l_int32 getFormatFromExtension()
48 * l_int32 pixGetAutoFormat()
49 * const char *getFormatExtension()
50 *
51 * Write to memory
52 * l_int32 pixWriteMem()
53 *
54 * Image display for debugging
55 * l_int32 l_fileDisplay()
56 * l_int32 pixDisplay()
57 * l_int32 pixDisplayWithTitle()
58 * PIX *pixMakeColorSquare()
59 * void l_chooseDisplayProg()
60 *
61 * Change format for missing library
62 * void changeFormatForMissingLib()
63 *
64 * Nonfunctional stub of pix output for debugging
65 * l_int32 pixDisplayWrite()
66 *
67 * Supported file formats:
68 * (1) Writing is supported without any external libraries:
69 * bmp
70 * pnm (including pbm, pgm, etc)
71 * spix (raw serialized)
72 * (2) Writing is supported with installation of external libraries:
73 * png
74 * jpg (standard jfif version)
75 * tiff (including most varieties of compression)
76 * gif
77 * webp
78 * jp2 (jpeg2000)
79 * (3) Writing is supported through special interfaces:
80 * ps (PostScript, in psio1.c, psio2.c):
81 * level 1 (uncompressed)
82 * level 2 (g4 and dct encoding: requires tiff, jpg)
83 * level 3 (g4, dct and flate encoding: requires tiff, jpg, zlib)
84 * pdf (PDF, in pdfio.c):
85 * level 1 (g4 and dct encoding: requires tiff, jpg)
86 * level 2 (g4, dct and flate encoding: requires tiff, jpg, zlib)
87 */
88
89#ifdef HAVE_CONFIG_H
90#include <config_auto.h>
91#endif /* HAVE_CONFIG_H */
92
93#include <string.h>
94#include "allheaders.h"
95
96 /* Set defaults for the display program (xv, xli, xzgv, open, irfanview)
97 * that is invoked by pixDisplay() */
98#ifdef _WIN32
99static l_int32 var_DISPLAY_PROG = L_DISPLAY_WITH_IV; /* default */
100#elif defined(__APPLE__)
101static l_int32 var_DISPLAY_PROG = L_DISPLAY_WITH_OPEN; /* default */
102#else
103static l_int32 var_DISPLAY_PROG = L_DISPLAY_WITH_XZGV; /* default */
104#endif /* _WIN32 */
105
106#define Bufsize 512
107static const l_int32 MaxDisplayWidth = 1000;
108static const l_int32 MaxDisplayHeight = 800;
109static const l_int32 MaxSizeForPng = 200;
110
111 /* PostScript output for printing */
112static const l_float32 DefaultScaling = 1.0;
113
114 /* Global array of image file format extension names. */
115 /* This is in 1-1 correspondence with format enum in imageio.h. */
116 /* The empty string at the end represents the serialized format, */
117 /* which has no recognizable extension name, but the array must */
118 /* be padded to agree with the format enum. */
119 /* (Note on 'const': The size of the array can't be defined 'const' */
120 /* because that makes it static. The 'const' in the definition of */
121 /* the array refers to the strings in the array; the ptr to the */
122 /* array is not const and can be used 'extern' in other files.) */
123LEPT_DLL l_int32 NumImageFileFormatExtensions = 20; /* array size */
124LEPT_DLL const char *ImageFileFormatExtensions[] =
125 {"unknown",
126 "bmp",
127 "jpg",
128 "png",
129 "tif",
130 "tif",
131 "tif",
132 "tif",
133 "tif",
134 "tif",
135 "tif",
136 "pnm",
137 "ps",
138 "gif",
139 "jp2",
140 "webp",
141 "pdf",
142 "tif",
143 "default",
144 ""};
145
146 /* Local map of image file name extension to output format */
148{
149 char extension[16];
150 l_int32 format;
151};
152static const struct ExtensionMap extension_map[] =
153 { { ".bmp", IFF_BMP },
154 { ".jpg", IFF_JFIF_JPEG },
155 { ".jpeg", IFF_JFIF_JPEG },
156 { ".JPG", IFF_JFIF_JPEG },
157 { ".png", IFF_PNG },
158 { ".tif", IFF_TIFF },
159 { ".tiff", IFF_TIFF },
160 { ".tiffg4", IFF_TIFF_G4 },
161 { ".pnm", IFF_PNM },
162 { ".gif", IFF_GIF },
163 { ".jp2", IFF_JP2 },
164 { ".ps", IFF_PS },
165 { ".pdf", IFF_LPDF },
166 { ".webp", IFF_WEBP } };
167
168
169/*---------------------------------------------------------------------*
170 * Set jpeg quality for pixWrite() and pixWriteMem() *
171 *---------------------------------------------------------------------*/
172 /* Parameter that controls jpeg quality for high-level calls. */
173static l_int32 var_JPEG_QUALITY = 75; /* default */
174
191l_int32
192l_jpegSetQuality(l_int32 new_quality)
193{
194l_int32 prevq, newq;
195
196 prevq = var_JPEG_QUALITY;
197 newq = (new_quality == 0) ? 75 : new_quality;
198 if (newq < 1 || newq > 100)
199 L_ERROR("invalid jpeg quality; unchanged\n", __func__);
200 else
201 var_JPEG_QUALITY = newq;
202 return prevq;
203}
204
205
206/*----------------------------------------------------------------------*
207 * Set global variable LeptDebugOK for writing to named temp files *
208 *----------------------------------------------------------------------*/
209LEPT_DLL l_int32 LeptDebugOK = 0; /* default value */
224void
225setLeptDebugOK(l_int32 allow)
226{
227 if (allow != 0) allow = 1;
228 LeptDebugOK = allow;
229}
230
231
232/*---------------------------------------------------------------------*
233 * Top-level procedures for writing images to file *
234 *---------------------------------------------------------------------*/
249l_ok
250pixaWriteFiles(const char *rootname,
251 PIXA *pixa,
252 l_int32 format)
253{
254char bigbuf[Bufsize];
255l_int32 i, n, pixformat;
256PIX *pix;
257
258 if (!rootname)
259 return ERROR_INT("rootname not defined", __func__, 1);
260 if (!pixa)
261 return ERROR_INT("pixa not defined", __func__, 1);
262 if (format < 0 || format == IFF_UNKNOWN ||
263 format >= NumImageFileFormatExtensions)
264 return ERROR_INT("invalid format", __func__, 1);
265
266 n = pixaGetCount(pixa);
267 for (i = 0; i < n; i++) {
268 pix = pixaGetPix(pixa, i, L_CLONE);
269 if (format == IFF_DEFAULT)
270 pixformat = pixChooseOutputFormat(pix);
271 else
272 pixformat = format;
273 snprintf(bigbuf, Bufsize, "%s%03d.%s", rootname, i,
274 ImageFileFormatExtensions[pixformat]);
275 pixWrite(bigbuf, pix, pixformat);
276 pixDestroy(&pix);
277 }
278
279 return 0;
280}
281
282
300l_ok
301pixWriteDebug(const char *fname,
302 PIX *pix,
303 l_int32 format)
304{
305 if (LeptDebugOK) {
306 return pixWrite(fname, pix, format);
307 } else {
308 L_INFO("write to named temp file %s is disabled\n", __func__, fname);
309 return 0;
310 }
311}
312
313
335l_ok
336pixWrite(const char *fname,
337 PIX *pix,
338 l_int32 format)
339{
340l_int32 ret;
341FILE *fp;
342
343 if (!pix)
344 return ERROR_INT("pix not defined", __func__, 1);
345 if (!fname)
346 return ERROR_INT("fname not defined", __func__, 1);
347
348 if ((fp = fopenWriteStream(fname, "wb+")) == NULL)
349 return ERROR_INT_1("stream not opened", fname, __func__, 1);
350
351 ret = pixWriteStream(fp, pix, format);
352 fclose(fp);
353 if (ret)
354 return ERROR_INT_1("pix not written to stream", fname, __func__, 1);
355 return 0;
356}
357
358
366l_ok
367pixWriteAutoFormat(const char *filename,
368 PIX *pix)
369{
370l_int32 format;
371
372 if (!pix)
373 return ERROR_INT("pix not defined", __func__, 1);
374 if (!filename)
375 return ERROR_INT("filename not defined", __func__, 1);
376
377 if (pixGetAutoFormat(pix, &format))
378 return ERROR_INT("auto format not returned", __func__, 1);
379 return pixWrite(filename, pix, format);
380}
381
382
391l_ok
392pixWriteStream(FILE *fp,
393 PIX *pix,
394 l_int32 format)
395{
396 if (!fp)
397 return ERROR_INT("stream not defined", __func__, 1);
398 if (!pix)
399 return ERROR_INT("pix not defined", __func__, 1);
400
401 if (format == IFF_DEFAULT)
402 format = pixChooseOutputFormat(pix);
403
404 /* Use bmp format for testing if library for requested
405 * format for jpeg, png or tiff is not available */
406 changeFormatForMissingLib(&format);
407
408 switch(format)
409 {
410 case IFF_BMP:
411 pixWriteStreamBmp(fp, pix);
412 break;
413
414 case IFF_JFIF_JPEG: /* default quality; baseline sequential */
415 return pixWriteStreamJpeg(fp, pix, var_JPEG_QUALITY, 0);
416
417 case IFF_PNG: /* no gamma value stored */
418 return pixWriteStreamPng(fp, pix, 0.0);
419
420 case IFF_TIFF: /* uncompressed */
421 case IFF_TIFF_PACKBITS: /* compressed, binary only */
422 case IFF_TIFF_RLE: /* compressed, binary only */
423 case IFF_TIFF_G3: /* compressed, binary only */
424 case IFF_TIFF_G4: /* compressed, binary only */
425 case IFF_TIFF_LZW: /* compressed, all depths */
426 case IFF_TIFF_ZIP: /* compressed, all depths */
427 case IFF_TIFF_JPEG: /* compressed, 8 bpp gray and 32 bpp rgb */
428 return pixWriteStreamTiff(fp, pix, format);
429
430 case IFF_PNM:
431 return pixWriteStreamPnm(fp, pix);
432
433 case IFF_PS:
434 return pixWriteStreamPS(fp, pix, NULL, 0, DefaultScaling);
435
436 case IFF_GIF:
437 return pixWriteStreamGif(fp, pix);
438
439 case IFF_JP2:
440 return pixWriteStreamJp2k(fp, pix, 34, 4, L_JP2_CODEC, 0, 0);
441
442 case IFF_WEBP:
443 return pixWriteStreamWebP(fp, pix, 80, 0);
444
445 case IFF_LPDF:
446 return pixWriteStreamPdf(fp, pix, 0, NULL);
447
448 case IFF_SPIX:
449 return pixWriteStreamSpix(fp, pix);
450
451 default:
452 return ERROR_INT("unknown format", __func__, 1);
453 }
454
455 return 0;
456}
457
458
475l_ok
476pixWriteImpliedFormat(const char *filename,
477 PIX *pix,
478 l_int32 quality,
479 l_int32 progressive)
480{
481l_int32 format;
482
483 if (!filename)
484 return ERROR_INT("filename not defined", __func__, 1);
485 if (!pix)
486 return ERROR_INT("pix not defined", __func__, 1);
487
488 /* Determine output format */
489 format = getImpliedFileFormat(filename);
490 if (format == IFF_UNKNOWN) {
491 format = IFF_PNG;
492 } else if (format == IFF_TIFF) {
493 if (pixGetDepth(pix) == 1)
494 format = IFF_TIFF_G4;
495 else
496#ifdef _WIN32
497 format = IFF_TIFF_LZW; /* poor compression */
498#else
499 format = IFF_TIFF_ZIP; /* native Windows tools can't handle this */
500#endif /* _WIN32 */
501 }
502
503 if (format == IFF_JFIF_JPEG) {
504 quality = L_MIN(quality, 100);
505 quality = L_MAX(quality, 0);
506 if (progressive != 0 && progressive != 1) {
507 progressive = 0;
508 L_WARNING("invalid progressive; setting to baseline\n", __func__);
509 }
510 if (quality == 0)
511 quality = 75;
512 pixWriteJpeg (filename, pix, quality, progressive);
513 } else {
514 pixWrite(filename, pix, format);
515 }
516
517 return 0;
518}
519
520
521/*---------------------------------------------------------------------*
522 * Selection of output format if default is requested *
523 *---------------------------------------------------------------------*/
538l_int32
539pixChooseOutputFormat(PIX *pix)
540{
541l_int32 d, format;
542
543 if (!pix)
544 return ERROR_INT("pix not defined", __func__, 0);
545
546 d = pixGetDepth(pix);
547 format = pixGetInputFormat(pix);
548 if (format == IFF_UNKNOWN) { /* output lossless */
549 if (d == 1)
550 format = IFF_TIFF_G4;
551 else
552 format = IFF_PNG;
553 }
554
555 return format;
556}
557
558
571l_int32
572getImpliedFileFormat(const char *filename)
573{
574char *extension;
575l_int32 format = IFF_UNKNOWN;
576
577 if (!filename)
578 return ERROR_INT("extension not defined", __func__, IFF_UNKNOWN);
579
580 if (splitPathAtExtension (filename, NULL, &extension))
581 return IFF_UNKNOWN;
582
583 format = getFormatFromExtension(extension);
584 LEPT_FREE(extension);
585 return format;
586}
587
588
603l_int32
604getFormatFromExtension(const char *extension)
605{
606int i, numext;
607l_int32 format = IFF_UNKNOWN;
608
609 if (!extension)
610 return ERROR_INT("extension not defined", __func__, IFF_UNKNOWN);
611
612 numext = sizeof(extension_map) / sizeof(extension_map[0]);
613 for (i = 0; i < numext; i++) {
614 if (!strcmp(extension, extension_map[i].extension)) {
615 format = extension_map[i].format;
616 break;
617 }
618 }
619 return format;
620}
621
622
641l_ok
642pixGetAutoFormat(PIX *pix,
643 l_int32 *pformat)
644{
645l_int32 d;
646PIXCMAP *cmap;
647
648 if (!pformat)
649 return ERROR_INT("&format not defined", __func__, 0);
650 *pformat = IFF_UNKNOWN;
651 if (!pix)
652 return ERROR_INT("pix not defined", __func__, 0);
653
654 d = pixGetDepth(pix);
655 cmap = pixGetColormap(pix);
656 if (d == 1 && !cmap) {
657 *pformat = IFF_TIFF_G4;
658 } else if ((d == 8 && !cmap) || d == 24 || d == 32) {
659 *pformat = IFF_JFIF_JPEG;
660 } else {
661 *pformat = IFF_PNG;
662 }
663
664 return 0;
665}
666
667
680const char *
681getFormatExtension(l_int32 format)
682{
683 if (format < 0 || format >= NumImageFileFormatExtensions)
684 return (const char *)ERROR_PTR("invalid format", __func__, NULL);
685
686 return ImageFileFormatExtensions[format];
687}
688
689
690/*---------------------------------------------------------------------*
691 * Write to memory *
692 *---------------------------------------------------------------------*/
713l_ok
714pixWriteMem(l_uint8 **pdata,
715 size_t *psize,
716 PIX *pix,
717 l_int32 format)
718{
719l_int32 ret;
720
721 if (!pdata)
722 return ERROR_INT("&data not defined", __func__, 1 );
723 if (!psize)
724 return ERROR_INT("&size not defined", __func__, 1 );
725 if (!pix)
726 return ERROR_INT("&pix not defined", __func__, 1 );
727
728 if (format == IFF_DEFAULT)
729 format = pixChooseOutputFormat(pix);
730
731 /* Use bmp format for testing if library for requested
732 * format for jpeg, png or tiff is not available */
733 changeFormatForMissingLib(&format);
734
735 switch(format)
736 {
737 case IFF_BMP:
738 ret = pixWriteMemBmp(pdata, psize, pix);
739 break;
740
741 case IFF_JFIF_JPEG: /* default quality; baseline sequential */
742 ret = pixWriteMemJpeg(pdata, psize, pix, var_JPEG_QUALITY, 0);
743 break;
744
745 case IFF_PNG: /* no gamma value stored */
746 ret = pixWriteMemPng(pdata, psize, pix, 0.0);
747 break;
748
749 case IFF_TIFF: /* uncompressed */
750 case IFF_TIFF_PACKBITS: /* compressed, binary only */
751 case IFF_TIFF_RLE: /* compressed, binary only */
752 case IFF_TIFF_G3: /* compressed, binary only */
753 case IFF_TIFF_G4: /* compressed, binary only */
754 case IFF_TIFF_LZW: /* compressed, all depths */
755 case IFF_TIFF_ZIP: /* compressed, all depths */
756 case IFF_TIFF_JPEG: /* compressed, 8 bpp gray or 32 bpp rgb */
757 ret = pixWriteMemTiff(pdata, psize, pix, format);
758 break;
759
760 case IFF_PNM:
761 ret = pixWriteMemPnm(pdata, psize, pix);
762 break;
763
764 case IFF_PS:
765 ret = pixWriteMemPS(pdata, psize, pix, NULL, 0, DefaultScaling);
766 break;
767
768 case IFF_GIF:
769 ret = pixWriteMemGif(pdata, psize, pix);
770 break;
771
772 case IFF_JP2:
773 ret = pixWriteMemJp2k(pdata, psize, pix, 34, 0, 0, 0);
774 break;
775
776 case IFF_WEBP:
777 ret = pixWriteMemWebP(pdata, psize, pix, 80, 0);
778 break;
779
780 case IFF_LPDF:
781 ret = pixWriteMemPdf(pdata, psize, pix, 0, NULL);
782 break;
783
784 case IFF_SPIX:
785 ret = pixWriteMemSpix(pdata, psize, pix);
786 break;
787
788 default:
789 return ERROR_INT("unknown format", __func__, 1);
790 }
791
792 return ret;
793}
794
795
796/*---------------------------------------------------------------------*
797 * Image display for debugging *
798 *---------------------------------------------------------------------*/
815l_ok
816l_fileDisplay(const char *fname,
817 l_int32 x,
818 l_int32 y,
819 l_float32 scale)
820{
821PIX *pixs, *pixd;
822
823 if (!LeptDebugOK) {
824 L_INFO("displaying files is disabled; "
825 "use setLeptDebugOK(1) to enable\n", __func__);
826 return 0;
827 }
828 if (scale == 0.0)
829 return 0;
830 if (scale < 0.0)
831 return ERROR_INT("invalid scale factor", __func__, 1);
832 if ((pixs = pixRead(fname)) == NULL)
833 return ERROR_INT("pixs not read", __func__, 1);
834
835 if (scale == 1.0) {
836 pixd = pixClone(pixs);
837 } else {
838 if (scale < 1.0 && pixGetDepth(pixs) == 1)
839 pixd = pixScaleToGray(pixs, scale);
840 else
841 pixd = pixScale(pixs, scale, scale);
842 }
843 pixDisplay(pixd, x, y);
844 pixDestroy(&pixs);
845 pixDestroy(&pixd);
846 return 0;
847}
848
849
893l_ok
894pixDisplay(PIX *pixs,
895 l_int32 x,
896 l_int32 y)
897{
898 return pixDisplayWithTitle(pixs, x, y, NULL, 1);
899}
900
901
918l_ok
919pixDisplayWithTitle(PIX *pixs,
920 l_int32 x,
921 l_int32 y,
922 const char *title,
923 l_int32 dispflag)
924{
925char *tempname;
926char buffer[Bufsize];
927static l_atomic index = 0; /* caution: not .so safe */
928l_int32 w, h, d, spp, maxheight, opaque, threeviews;
929l_float32 ratw, rath, ratmin;
930PIX *pix0, *pix1, *pix2;
931PIXCMAP *cmap;
932#ifndef _WIN32
933l_int32 wt, ht;
934#else
935char *pathname;
936char fullpath[_MAX_PATH];
937#endif /* _WIN32 */
938
939 if (!LeptDebugOK) {
940 L_INFO("displaying images is disabled;\n "
941 "use setLeptDebugOK(1) to enable\n", __func__);
942 return 0;
943 }
944
945#ifdef OS_IOS /* iOS 11 does not support system() */
946 return ERROR_INT("iOS 11 does not support system()", __func__, 1);
947#endif /* OS_IOS */
948
949 if (dispflag != 1 || var_DISPLAY_PROG == L_DISPLAY_WITH_NONE)
950 return 0;
951 if (!pixs)
952 return ERROR_INT("pixs not defined", __func__, 1);
953
954#ifndef _WIN32 /* unix */
955 if (var_DISPLAY_PROG != L_DISPLAY_WITH_XZGV &&
956 var_DISPLAY_PROG != L_DISPLAY_WITH_XLI &&
957 var_DISPLAY_PROG != L_DISPLAY_WITH_XV &&
958 var_DISPLAY_PROG != L_DISPLAY_WITH_OPEN)
959 return ERROR_INT("invalid unix program chosen for display",
960 __func__, 1);
961#else /* _WIN32 */
962 if (var_DISPLAY_PROG != L_DISPLAY_WITH_IV &&
963 var_DISPLAY_PROG != L_DISPLAY_WITH_OPEN)
964 return ERROR_INT("invalid windows program chosen for display",
965 __func__, 1);
966#endif /* _WIN32 */
967
968 /* Display with three views if either spp = 4 or if colormapped
969 * and the alpha component is not fully opaque */
970 opaque = TRUE;
971 if ((cmap = pixGetColormap(pixs)) != NULL)
972 pixcmapIsOpaque(cmap, &opaque);
973 spp = pixGetSpp(pixs);
974 threeviews = (spp == 4 || !opaque) ? TRUE : FALSE;
975
976 /* If colormapped and not opaque, remove the colormap to RGBA */
977 if (!opaque)
978 pix0 = pixRemoveColormap(pixs, REMOVE_CMAP_WITH_ALPHA);
979 else
980 pix0 = pixClone(pixs);
981
982 /* Scale if necessary; this will also remove a colormap */
983 pixGetDimensions(pix0, &w, &h, &d);
984 maxheight = (threeviews) ? MaxDisplayHeight / 3 : MaxDisplayHeight;
985 if (w <= MaxDisplayWidth && h <= maxheight) {
986 if (d == 16) /* take MSB */
987 pix1 = pixConvert16To8(pix0, L_MS_BYTE);
988 else
989 pix1 = pixClone(pix0);
990 } else {
991 ratw = (l_float32)MaxDisplayWidth / (l_float32)w;
992 rath = (l_float32)maxheight / (l_float32)h;
993 ratmin = L_MIN(ratw, rath);
994 if (ratmin < 0.125 && d == 1)
995 pix1 = pixScaleToGray8(pix0);
996 else if (ratmin < 0.25 && d == 1)
997 pix1 = pixScaleToGray4(pix0);
998 else if (ratmin < 0.33 && d == 1)
999 pix1 = pixScaleToGray3(pix0);
1000 else if (ratmin < 0.5 && d == 1)
1001 pix1 = pixScaleToGray2(pix0);
1002 else
1003 pix1 = pixScale(pix0, ratmin, ratmin);
1004 }
1005 pixDestroy(&pix0);
1006 if (!pix1)
1007 return ERROR_INT("pix1 not made", __func__, 1);
1008
1009 /* Generate the three views if required */
1010 if (threeviews)
1011 pix2 = pixDisplayLayersRGBA(pix1, 0xffffff00, 0);
1012 else
1013 pix2 = pixClone(pix1);
1014
1015 if (index == 0) { /* erase any existing images */
1016 lept_rmdir("lept/disp");
1017 lept_mkdir("lept/disp");
1018 }
1019
1020 index++;
1021 if (pixGetDepth(pix2) < 8 || pixGetColormap(pix2) ||
1022 (w < MaxSizeForPng && h < MaxSizeForPng)) {
1023 snprintf(buffer, Bufsize, "/tmp/lept/disp/write.%03d.png", index);
1024 pixWrite(buffer, pix2, IFF_PNG);
1025 } else {
1026 snprintf(buffer, Bufsize, "/tmp/lept/disp/write.%03d.jpg", index);
1027 pixWrite(buffer, pix2, IFF_JFIF_JPEG);
1028 }
1029 tempname = genPathname(buffer, NULL);
1030
1031#ifndef _WIN32
1032
1033 /* Unix */
1034 if (var_DISPLAY_PROG == L_DISPLAY_WITH_XZGV) {
1035 /* no way to display title */
1036 pixGetDimensions(pix2, &wt, &ht, NULL);
1037 snprintf(buffer, Bufsize,
1038 "xzgv --geometry %dx%d+%d+%d %s &", wt + 10, ht + 10,
1039 x, y, tempname);
1040 } else if (var_DISPLAY_PROG == L_DISPLAY_WITH_XLI) {
1041 if (title) {
1042 snprintf(buffer, Bufsize,
1043 "xli -dispgamma 1.0 -quiet -geometry +%d+%d -title \"%s\" %s &",
1044 x, y, title, tempname);
1045 } else {
1046 snprintf(buffer, Bufsize,
1047 "xli -dispgamma 1.0 -quiet -geometry +%d+%d %s &",
1048 x, y, tempname);
1049 }
1050 } else if (var_DISPLAY_PROG == L_DISPLAY_WITH_XV) {
1051 if (title) {
1052 snprintf(buffer, Bufsize,
1053 "xv -quit -geometry +%d+%d -name \"%s\" %s &",
1054 x, y, title, tempname);
1055 } else {
1056 snprintf(buffer, Bufsize,
1057 "xv -quit -geometry +%d+%d %s &", x, y, tempname);
1058 }
1059 } else { /* L_DISPLAY_WITH_OPEN */
1060 snprintf(buffer, Bufsize, "open %s &", tempname);
1061 }
1062 callSystemDebug(buffer);
1063
1064#else /* _WIN32 */
1065
1066 /* Windows: L_DISPLAY_WITH_IV || L_DISPLAY_WITH_OPEN */
1067 pathname = genPathname(tempname, NULL);
1068 _fullpath(fullpath, pathname, sizeof(fullpath));
1069 if (var_DISPLAY_PROG == L_DISPLAY_WITH_IV) {
1070 if (title) {
1071 snprintf(buffer, Bufsize,
1072 "i_view32.exe \"%s\" /pos=(%d,%d) /title=\"%s\"",
1073 fullpath, x, y, title);
1074 } else {
1075 snprintf(buffer, Bufsize, "i_view32.exe \"%s\" /pos=(%d,%d)",
1076 fullpath, x, y);
1077 }
1078 } else { /* L_DISPLAY_WITH_OPEN */
1079 snprintf(buffer, Bufsize, "explorer.exe /open,\"%s\"", fullpath);
1080 }
1081 callSystemDebug(buffer);
1082 LEPT_FREE(pathname);
1083
1084#endif /* _WIN32 */
1085
1086 pixDestroy(&pix1);
1087 pixDestroy(&pix2);
1088 LEPT_FREE(tempname);
1089 return 0;
1090}
1091
1092
1109PIX *
1110pixMakeColorSquare(l_uint32 color,
1111 l_int32 size,
1112 l_int32 addlabel,
1113 l_int32 location,
1114 l_uint32 textcolor)
1115{
1116char buf[32];
1117l_int32 w, rval, gval, bval;
1118L_BMF *bmf;
1119PIX *pix1, *pix2;
1120
1121 w = (size <= 0) ? 100 : size;
1122 if (addlabel && w < 100) {
1123 L_WARNING("size too small for label; omitting label\n", __func__);
1124 addlabel = 0;
1125 }
1126
1127 if ((pix1 = pixCreate(w, w, 32)) == NULL)
1128 return (PIX *)ERROR_PTR("pix1 not madel", __func__, NULL);
1129 pixSetAllArbitrary(pix1, color);
1130 if (!addlabel)
1131 return pix1;
1132
1133 /* Adding text of color component values */
1134 if (location != L_ADD_ABOVE && location != L_ADD_AT_TOP &&
1135 location != L_ADD_AT_BOT && location != L_ADD_BELOW) {
1136 L_ERROR("invalid location: adding below\n", __func__);
1137 location = L_ADD_BELOW;
1138 }
1139 bmf = bmfCreate(NULL, 4);
1140 extractRGBValues(color, &rval, &gval, &bval);
1141 snprintf(buf, sizeof(buf), "%d,%d,%d", rval, gval, bval);
1142 pix2 = pixAddSingleTextblock(pix1, bmf, buf, textcolor, location, NULL);
1143 pixDestroy(&pix1);
1144 bmfDestroy(&bmf);
1145 return pix2;
1146}
1147
1148
1149void
1150l_chooseDisplayProg(l_int32 selection)
1151{
1152 if (selection == L_DISPLAY_WITH_XLI ||
1153 selection == L_DISPLAY_WITH_XZGV ||
1154 selection == L_DISPLAY_WITH_XV ||
1155 selection == L_DISPLAY_WITH_IV ||
1156 selection == L_DISPLAY_WITH_OPEN) {
1157 var_DISPLAY_PROG = selection;
1158 } else {
1159 L_ERROR("invalid display program\n", "l_chooseDisplayProg");
1160 }
1161}
1162
1163
1164/*---------------------------------------------------------------------*
1165 * Change format for missing lib *
1166 *---------------------------------------------------------------------*/
1180void
1181changeFormatForMissingLib(l_int32 *pformat)
1182{
1183#if !defined(HAVE_LIBJPEG)
1184 if (*pformat == IFF_JFIF_JPEG) {
1185 L_WARNING("jpeg library missing; output bmp format\n", __func__);
1186 *pformat = IFF_BMP;
1187 }
1188#endif /* !defined(HAVE_LIBJPEG) */
1189#if !defined(HAVE_LIBPNG)
1190 if (*pformat == IFF_PNG) {
1191 L_WARNING("png library missing; output bmp format\n", __func__);
1192 *pformat = IFF_BMP;
1193 }
1194#endif /* !defined(HAVE_LIBPNG) */
1195#if !defined(HAVE_LIBTIFF)
1196 if (L_FORMAT_IS_TIFF(*pformat)) {
1197 L_WARNING("tiff library missing; output bmp format\n", __func__);
1198 *pformat = IFF_BMP;
1199 }
1200#endif /* !defined(HAVE_LIBTIFF) */
1201}
1202
1203
1204/*---------------------------------------------------------------------*
1205 * Deprecated pix output for debugging *
1206 *---------------------------------------------------------------------*/
1219l_ok
1220pixDisplayWrite(PIX *pixs,
1221 l_int32 reduction)
1222{
1223 lept_stderr("\n########################################################\n"
1224 " pixDisplayWrite() was last used in tesseract 3.04,"
1225 " in Feb 2016. As of 1.80, it is a non-functional stub\n"
1226 "########################################################"
1227 "\n\n\n");
1228 return 1;
1229}
@ L_JP2_CODEC
Definition imageio.h:149
@ REMOVE_CMAP_WITH_ALPHA
Definition pix.h:383
@ L_ADD_AT_BOT
Definition pix.h:1007
@ L_ADD_BELOW
Definition pix.h:1003
@ L_ADD_AT_TOP
Definition pix.h:1006
@ L_ADD_ABOVE
Definition pix.h:1002
@ L_CLONE
Definition pix.h:506
@ L_MS_BYTE
Definition pix.h:642
@ L_DISPLAY_WITH_NONE
Definition pix.h:1039
@ L_DISPLAY_WITH_XV
Definition pix.h:1042
@ L_DISPLAY_WITH_XZGV
Definition pix.h:1040
@ L_DISPLAY_WITH_XLI
Definition pix.h:1041
@ L_DISPLAY_WITH_OPEN
Definition pix.h:1044
@ L_DISPLAY_WITH_IV
Definition pix.h:1043
Definition bmf.h:47