Leptonica  1.82.0
Image processing and image analysis suite
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 pixGetAutoFormat()
48  * const char *getFormatExtension()
49  *
50  * Write to memory
51  * l_int32 pixWriteMem()
52  *
53  * Image display for debugging
54  * l_int32 l_fileDisplay()
55  * l_int32 pixDisplay()
56  * l_int32 pixDisplayWithTitle()
57  * PIX *pixMakeColorSquare()
58  * void l_chooseDisplayProg()
59  *
60  * Change format for missing library
61  * void changeFormatForMissingLib()
62  *
63  * Nonfunctional stub of pix output for debugging
64  * l_int32 pixDisplayWrite()
65  *
66  * Supported file formats:
67  * (1) Writing is supported without any external libraries:
68  * bmp
69  * pnm (including pbm, pgm, etc)
70  * spix (raw serialized)
71  * (2) Writing is supported with installation of external libraries:
72  * png
73  * jpg (standard jfif version)
74  * tiff (including most varieties of compression)
75  * gif
76  * webp
77  * jp2 (jpeg2000)
78  * (3) Writing is supported through special interfaces:
79  * ps (PostScript, in psio1.c, psio2.c):
80  * level 1 (uncompressed)
81  * level 2 (g4 and dct encoding: requires tiff, jpg)
82  * level 3 (g4, dct and flate encoding: requires tiff, jpg, zlib)
83  * pdf (PDF, in pdfio.c):
84  * level 1 (g4 and dct encoding: requires tiff, jpg)
85  * level 2 (g4, dct and flate encoding: requires tiff, jpg, zlib)
86  */
87 
88 #ifdef HAVE_CONFIG_H
89 #include <config_auto.h>
90 #endif /* HAVE_CONFIG_H */
91 
92 #include <string.h>
93 #include "allheaders.h"
94 
95  /* Display program (xv, xli, xzgv, open) to be invoked by pixDisplay() */
96 #ifdef _WIN32
97 static l_int32 var_DISPLAY_PROG = L_DISPLAY_WITH_IV; /* default */
98 #elif defined(__APPLE__)
99 static l_int32 var_DISPLAY_PROG = L_DISPLAY_WITH_OPEN; /* default */
100 #else
101 static l_int32 var_DISPLAY_PROG = L_DISPLAY_WITH_XZGV; /* default */
102 #endif /* _WIN32 */
103 
104 #define Bufsize 512
105 static const l_int32 MaxDisplayWidth = 1000;
106 static const l_int32 MaxDisplayHeight = 800;
107 static const l_int32 MaxSizeForPng = 200;
108 
109  /* PostScript output for printing */
110 static const l_float32 DefaultScaling = 1.0;
111 
112  /* Global array of image file format extension names. */
113  /* This is in 1-1 corrspondence with format enum in imageio.h. */
114  /* The empty string at the end represents the serialized format, */
115  /* which has no recognizable extension name, but the array must */
116  /* be padded to agree with the format enum. */
117  /* (Note on 'const': The size of the array can't be defined 'const' */
118  /* because that makes it static. The 'const' in the definition of */
119  /* the array refers to the strings in the array; the ptr to the */
120  /* array is not const and can be used 'extern' in other files.) */
121 LEPT_DLL l_int32 NumImageFileFormatExtensions = 20; /* array size */
122 LEPT_DLL const char *ImageFileFormatExtensions[] =
123  {"unknown",
124  "bmp",
125  "jpg",
126  "png",
127  "tif",
128  "tif",
129  "tif",
130  "tif",
131  "tif",
132  "tif",
133  "tif",
134  "pnm",
135  "ps",
136  "gif",
137  "jp2",
138  "webp",
139  "pdf",
140  "tif",
141  "default",
142  ""};
143 
144  /* Local map of image file name extension to output format */
146 {
147  char extension[8];
148  l_int32 format;
149 };
150 static const struct ExtensionMap extension_map[] =
151  { { ".bmp", IFF_BMP },
152  { ".jpg", IFF_JFIF_JPEG },
153  { ".jpeg", IFF_JFIF_JPEG },
154  { ".png", IFF_PNG },
155  { ".tif", IFF_TIFF },
156  { ".tiff", IFF_TIFF },
157  { ".pnm", IFF_PNM },
158  { ".gif", IFF_GIF },
159  { ".jp2", IFF_JP2 },
160  { ".ps", IFF_PS },
161  { ".pdf", IFF_LPDF },
162  { ".webp", IFF_WEBP } };
163 
164 
165 /*---------------------------------------------------------------------*
166  * Set jpeg quality for pixWrite() and pixWriteMem() *
167  *---------------------------------------------------------------------*/
168  /* Parameter that controls jpeg quality for high-level calls. */
169 static l_int32 var_JPEG_QUALITY = 75; /* default */
170 
187 l_int32
188 l_jpegSetQuality(l_int32 new_quality)
189 {
190 l_int32 prevq, newq;
191 
192  PROCNAME("l_jpeqSetQuality");
193 
194  prevq = var_JPEG_QUALITY;
195  newq = (new_quality == 0) ? 75 : new_quality;
196  if (newq < 1 || newq > 100)
197  L_ERROR("invalid jpeg quality; unchanged\n", procName);
198  else
199  var_JPEG_QUALITY = newq;
200  return prevq;
201 }
202 
203 
204 /*----------------------------------------------------------------------*
205  * Set global variable LeptDebugOK for writing to named temp files *
206  *----------------------------------------------------------------------*/
207 LEPT_DLL l_int32 LeptDebugOK = 0; /* default value */
222 void
223 setLeptDebugOK(l_int32 allow)
224 {
225  if (allow != 0) allow = 1;
226  LeptDebugOK = allow;
227 }
228 
229 
230 /*---------------------------------------------------------------------*
231  * Top-level procedures for writing images to file *
232  *---------------------------------------------------------------------*/
247 l_ok
248 pixaWriteFiles(const char *rootname,
249  PIXA *pixa,
250  l_int32 format)
251 {
252 char bigbuf[Bufsize];
253 l_int32 i, n, pixformat;
254 PIX *pix;
255 
256  PROCNAME("pixaWriteFiles");
257 
258  if (!rootname)
259  return ERROR_INT("rootname not defined", procName, 1);
260  if (!pixa)
261  return ERROR_INT("pixa not defined", procName, 1);
262  if (format < 0 || format == IFF_UNKNOWN ||
263  format >= NumImageFileFormatExtensions)
264  return ERROR_INT("invalid format", procName, 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 
300 l_ok
301 pixWriteDebug(const char *fname,
302  PIX *pix,
303  l_int32 format)
304 {
305  PROCNAME("pixWriteDebug");
306 
307  if (LeptDebugOK) {
308  return pixWrite(fname, pix, format);
309  } else {
310  L_INFO("write to named temp file %s is disabled\n", procName, fname);
311  return 0;
312  }
313 }
314 
315 
337 l_ok
338 pixWrite(const char *fname,
339  PIX *pix,
340  l_int32 format)
341 {
342 l_int32 ret;
343 FILE *fp;
344 
345  PROCNAME("pixWrite");
346 
347  if (!pix)
348  return ERROR_INT("pix not defined", procName, 1);
349  if (!fname)
350  return ERROR_INT("fname not defined", procName, 1);
351 
352  if ((fp = fopenWriteStream(fname, "wb+")) == NULL)
353  return ERROR_INT("stream not opened", procName, 1);
354 
355  ret = pixWriteStream(fp, pix, format);
356  fclose(fp);
357  if (ret)
358  return ERROR_INT("pix not written to stream", procName, 1);
359  return 0;
360 }
361 
362 
370 l_ok
371 pixWriteAutoFormat(const char *filename,
372  PIX *pix)
373 {
374 l_int32 format;
375 
376  PROCNAME("pixWriteAutoFormat");
377 
378  if (!pix)
379  return ERROR_INT("pix not defined", procName, 1);
380  if (!filename)
381  return ERROR_INT("filename not defined", procName, 1);
382 
383  if (pixGetAutoFormat(pix, &format))
384  return ERROR_INT("auto format not returned", procName, 1);
385  return pixWrite(filename, pix, format);
386 }
387 
388 
397 l_ok
398 pixWriteStream(FILE *fp,
399  PIX *pix,
400  l_int32 format)
401 {
402  PROCNAME("pixWriteStream");
403 
404  if (!fp)
405  return ERROR_INT("stream not defined", procName, 1);
406  if (!pix)
407  return ERROR_INT("pix not defined", procName, 1);
408 
409  if (format == IFF_DEFAULT)
410  format = pixChooseOutputFormat(pix);
411 
412  /* Use bmp format for testing if library for requested
413  * format for jpeg, png or tiff is not available */
414  changeFormatForMissingLib(&format);
415 
416  switch(format)
417  {
418  case IFF_BMP:
419  pixWriteStreamBmp(fp, pix);
420  break;
421 
422  case IFF_JFIF_JPEG: /* default quality; baseline sequential */
423  return pixWriteStreamJpeg(fp, pix, var_JPEG_QUALITY, 0);
424 
425  case IFF_PNG: /* no gamma value stored */
426  return pixWriteStreamPng(fp, pix, 0.0);
427 
428  case IFF_TIFF: /* uncompressed */
429  case IFF_TIFF_PACKBITS: /* compressed, binary only */
430  case IFF_TIFF_RLE: /* compressed, binary only */
431  case IFF_TIFF_G3: /* compressed, binary only */
432  case IFF_TIFF_G4: /* compressed, binary only */
433  case IFF_TIFF_LZW: /* compressed, all depths */
434  case IFF_TIFF_ZIP: /* compressed, all depths */
435  case IFF_TIFF_JPEG: /* compressed, 8 bpp gray and 32 bpp rgb */
436  return pixWriteStreamTiff(fp, pix, format);
437 
438  case IFF_PNM:
439  return pixWriteStreamPnm(fp, pix);
440 
441  case IFF_PS:
442  return pixWriteStreamPS(fp, pix, NULL, 0, DefaultScaling);
443 
444  case IFF_GIF:
445  return pixWriteStreamGif(fp, pix);
446 
447  case IFF_JP2:
448  return pixWriteStreamJp2k(fp, pix, 34, 4, L_JP2_CODEC, 0, 0);
449 
450  case IFF_WEBP:
451  return pixWriteStreamWebP(fp, pix, 80, 0);
452 
453  case IFF_LPDF:
454  return pixWriteStreamPdf(fp, pix, 0, NULL);
455 
456  case IFF_SPIX:
457  return pixWriteStreamSpix(fp, pix);
458 
459  default:
460  return ERROR_INT("unknown format", procName, 1);
461  }
462 
463  return 0;
464 }
465 
466 
483 l_ok
484 pixWriteImpliedFormat(const char *filename,
485  PIX *pix,
486  l_int32 quality,
487  l_int32 progressive)
488 {
489 l_int32 format;
490 
491  PROCNAME("pixWriteImpliedFormat");
492 
493  if (!filename)
494  return ERROR_INT("filename not defined", procName, 1);
495  if (!pix)
496  return ERROR_INT("pix not defined", procName, 1);
497 
498  /* Determine output format */
499  format = getImpliedFileFormat(filename);
500  if (format == IFF_UNKNOWN) {
501  format = IFF_PNG;
502  } else if (format == IFF_TIFF) {
503  if (pixGetDepth(pix) == 1)
504  format = IFF_TIFF_G4;
505  else
506 #ifdef _WIN32
507  format = IFF_TIFF_LZW; /* poor compression */
508 #else
509  format = IFF_TIFF_ZIP; /* native windows tools can't handle this */
510 #endif /* _WIN32 */
511  }
512 
513  if (format == IFF_JFIF_JPEG) {
514  quality = L_MIN(quality, 100);
515  quality = L_MAX(quality, 0);
516  if (progressive != 0 && progressive != 1) {
517  progressive = 0;
518  L_WARNING("invalid progressive; setting to baseline\n", procName);
519  }
520  if (quality == 0)
521  quality = 75;
522  pixWriteJpeg (filename, pix, quality, progressive);
523  } else {
524  pixWrite(filename, pix, format);
525  }
526 
527  return 0;
528 }
529 
530 
531 /*---------------------------------------------------------------------*
532  * Selection of output format if default is requested *
533  *---------------------------------------------------------------------*/
548 l_int32
549 pixChooseOutputFormat(PIX *pix)
550 {
551 l_int32 d, format;
552 
553  PROCNAME("pixChooseOutputFormat");
554 
555  if (!pix)
556  return ERROR_INT("pix not defined", procName, 0);
557 
558  d = pixGetDepth(pix);
559  format = pixGetInputFormat(pix);
560  if (format == IFF_UNKNOWN) { /* output lossless */
561  if (d == 1)
562  format = IFF_TIFF_G4;
563  else
564  format = IFF_PNG;
565  }
566 
567  return format;
568 }
569 
570 
583 l_int32
584 getImpliedFileFormat(const char *filename)
585 {
586 char *extension;
587 int i, numext;
588 l_int32 format = IFF_UNKNOWN;
589 
590  if (splitPathAtExtension (filename, NULL, &extension))
591  return IFF_UNKNOWN;
592 
593  numext = sizeof(extension_map) / sizeof(extension_map[0]);
594  for (i = 0; i < numext; i++) {
595  if (!strcmp(extension, extension_map[i].extension)) {
596  format = extension_map[i].format;
597  break;
598  }
599  }
600 
601  LEPT_FREE(extension);
602  return format;
603 }
604 
605 
624 l_ok
625 pixGetAutoFormat(PIX *pix,
626  l_int32 *pformat)
627 {
628 l_int32 d;
629 PIXCMAP *cmap;
630 
631  PROCNAME("pixGetAutoFormat");
632 
633  if (!pformat)
634  return ERROR_INT("&format not defined", procName, 0);
635  *pformat = IFF_UNKNOWN;
636  if (!pix)
637  return ERROR_INT("pix not defined", procName, 0);
638 
639  d = pixGetDepth(pix);
640  cmap = pixGetColormap(pix);
641  if (d == 1 && !cmap) {
642  *pformat = IFF_TIFF_G4;
643  } else if ((d == 8 && !cmap) || d == 24 || d == 32) {
644  *pformat = IFF_JFIF_JPEG;
645  } else {
646  *pformat = IFF_PNG;
647  }
648 
649  return 0;
650 }
651 
652 
665 const char *
666 getFormatExtension(l_int32 format)
667 {
668  PROCNAME("getFormatExtension");
669 
670  if (format < 0 || format >= NumImageFileFormatExtensions)
671  return (const char *)ERROR_PTR("invalid format", procName, NULL);
672 
673  return ImageFileFormatExtensions[format];
674 }
675 
676 
677 /*---------------------------------------------------------------------*
678  * Write to memory *
679  *---------------------------------------------------------------------*/
700 l_ok
701 pixWriteMem(l_uint8 **pdata,
702  size_t *psize,
703  PIX *pix,
704  l_int32 format)
705 {
706 l_int32 ret;
707 
708  PROCNAME("pixWriteMem");
709 
710  if (!pdata)
711  return ERROR_INT("&data not defined", procName, 1 );
712  if (!psize)
713  return ERROR_INT("&size not defined", procName, 1 );
714  if (!pix)
715  return ERROR_INT("&pix not defined", procName, 1 );
716 
717  if (format == IFF_DEFAULT)
718  format = pixChooseOutputFormat(pix);
719 
720  /* Use bmp format for testing if library for requested
721  * format for jpeg, png or tiff is not available */
722  changeFormatForMissingLib(&format);
723 
724  switch(format)
725  {
726  case IFF_BMP:
727  ret = pixWriteMemBmp(pdata, psize, pix);
728  break;
729 
730  case IFF_JFIF_JPEG: /* default quality; baseline sequential */
731  ret = pixWriteMemJpeg(pdata, psize, pix, var_JPEG_QUALITY, 0);
732  break;
733 
734  case IFF_PNG: /* no gamma value stored */
735  ret = pixWriteMemPng(pdata, psize, pix, 0.0);
736  break;
737 
738  case IFF_TIFF: /* uncompressed */
739  case IFF_TIFF_PACKBITS: /* compressed, binary only */
740  case IFF_TIFF_RLE: /* compressed, binary only */
741  case IFF_TIFF_G3: /* compressed, binary only */
742  case IFF_TIFF_G4: /* compressed, binary only */
743  case IFF_TIFF_LZW: /* compressed, all depths */
744  case IFF_TIFF_ZIP: /* compressed, all depths */
745  case IFF_TIFF_JPEG: /* compressed, 8 bpp gray or 32 bpp rgb */
746  ret = pixWriteMemTiff(pdata, psize, pix, format);
747  break;
748 
749  case IFF_PNM:
750  ret = pixWriteMemPnm(pdata, psize, pix);
751  break;
752 
753  case IFF_PS:
754  ret = pixWriteMemPS(pdata, psize, pix, NULL, 0, DefaultScaling);
755  break;
756 
757  case IFF_GIF:
758  ret = pixWriteMemGif(pdata, psize, pix);
759  break;
760 
761  case IFF_JP2:
762  ret = pixWriteMemJp2k(pdata, psize, pix, 34, 0, 0, 0);
763  break;
764 
765  case IFF_WEBP:
766  ret = pixWriteMemWebP(pdata, psize, pix, 80, 0);
767  break;
768 
769  case IFF_LPDF:
770  ret = pixWriteMemPdf(pdata, psize, pix, 0, NULL);
771  break;
772 
773  case IFF_SPIX:
774  ret = pixWriteMemSpix(pdata, psize, pix);
775  break;
776 
777  default:
778  return ERROR_INT("unknown format", procName, 1);
779  }
780 
781  return ret;
782 }
783 
784 
785 /*---------------------------------------------------------------------*
786  * Image display for debugging *
787  *---------------------------------------------------------------------*/
804 l_ok
805 l_fileDisplay(const char *fname,
806  l_int32 x,
807  l_int32 y,
808  l_float32 scale)
809 {
810 PIX *pixs, *pixd;
811 
812  PROCNAME("l_fileDisplay");
813 
814  if (!LeptDebugOK) {
815  L_INFO("displaying files is disabled; "
816  "use setLeptDebugOK(1) to enable\n", procName);
817  return 0;
818  }
819  if (scale == 0.0)
820  return 0;
821  if (scale < 0.0)
822  return ERROR_INT("invalid scale factor", procName, 1);
823  if ((pixs = pixRead(fname)) == NULL)
824  return ERROR_INT("pixs not read", procName, 1);
825 
826  if (scale == 1.0) {
827  pixd = pixClone(pixs);
828  } else {
829  if (scale < 1.0 && pixGetDepth(pixs) == 1)
830  pixd = pixScaleToGray(pixs, scale);
831  else
832  pixd = pixScale(pixs, scale, scale);
833  }
834  pixDisplay(pixd, x, y);
835  pixDestroy(&pixs);
836  pixDestroy(&pixd);
837  return 0;
838 }
839 
840 
880 l_ok
881 pixDisplay(PIX *pixs,
882  l_int32 x,
883  l_int32 y)
884 {
885  return pixDisplayWithTitle(pixs, x, y, NULL, 1);
886 }
887 
888 
904 l_ok
905 pixDisplayWithTitle(PIX *pixs,
906  l_int32 x,
907  l_int32 y,
908  const char *title,
909  l_int32 dispflag)
910 {
911 char *tempname;
912 char buffer[Bufsize];
913 static l_int32 index = 0; /* caution: not .so or thread safe */
914 l_int32 w, h, d, spp, maxheight, opaque, threeviews;
915 l_float32 ratw, rath, ratmin;
916 PIX *pix0, *pix1, *pix2;
917 PIXCMAP *cmap;
918 #ifndef _WIN32
919 l_int32 wt, ht;
920 #else
921 char *pathname;
922 char fullpath[_MAX_PATH];
923 #endif /* _WIN32 */
924 
925  PROCNAME("pixDisplayWithTitle");
926 
927  if (!LeptDebugOK) {
928  L_INFO("displaying images is disabled;\n "
929  "use setLeptDebugOK(1) to enable\n", procName);
930  return 0;
931  }
932 
933 #ifdef OS_IOS /* iOS 11 does not support system() */
934  return ERROR_INT("iOS 11 does not support system()", procName, 1);
935 #endif /* OS_IOS */
936 
937  if (dispflag != 1) return 0;
938  if (!pixs)
939  return ERROR_INT("pixs not defined", procName, 1);
940  if (var_DISPLAY_PROG != L_DISPLAY_WITH_XZGV &&
941  var_DISPLAY_PROG != L_DISPLAY_WITH_XLI &&
942  var_DISPLAY_PROG != L_DISPLAY_WITH_XV &&
943  var_DISPLAY_PROG != L_DISPLAY_WITH_IV &&
944  var_DISPLAY_PROG != L_DISPLAY_WITH_OPEN) {
945  return ERROR_INT("no program chosen for display", procName, 1);
946  }
947 
948  /* Display with three views if either spp = 4 or if colormapped
949  * and the alpha component is not fully opaque */
950  opaque = TRUE;
951  if ((cmap = pixGetColormap(pixs)) != NULL)
952  pixcmapIsOpaque(cmap, &opaque);
953  spp = pixGetSpp(pixs);
954  threeviews = (spp == 4 || !opaque) ? TRUE : FALSE;
955 
956  /* If colormapped and not opaque, remove the colormap to RGBA */
957  if (!opaque)
959  else
960  pix0 = pixClone(pixs);
961 
962  /* Scale if necessary; this will also remove a colormap */
963  pixGetDimensions(pix0, &w, &h, &d);
964  maxheight = (threeviews) ? MaxDisplayHeight / 3 : MaxDisplayHeight;
965  if (w <= MaxDisplayWidth && h <= maxheight) {
966  if (d == 16) /* take MSB */
967  pix1 = pixConvert16To8(pix0, L_MS_BYTE);
968  else
969  pix1 = pixClone(pix0);
970  } else {
971  ratw = (l_float32)MaxDisplayWidth / (l_float32)w;
972  rath = (l_float32)maxheight / (l_float32)h;
973  ratmin = L_MIN(ratw, rath);
974  if (ratmin < 0.125 && d == 1)
975  pix1 = pixScaleToGray8(pix0);
976  else if (ratmin < 0.25 && d == 1)
977  pix1 = pixScaleToGray4(pix0);
978  else if (ratmin < 0.33 && d == 1)
979  pix1 = pixScaleToGray3(pix0);
980  else if (ratmin < 0.5 && d == 1)
981  pix1 = pixScaleToGray2(pix0);
982  else
983  pix1 = pixScale(pix0, ratmin, ratmin);
984  }
985  pixDestroy(&pix0);
986  if (!pix1)
987  return ERROR_INT("pix1 not made", procName, 1);
988 
989  /* Generate the three views if required */
990  if (threeviews)
991  pix2 = pixDisplayLayersRGBA(pix1, 0xffffff00, 0);
992  else
993  pix2 = pixClone(pix1);
994 
995  if (index == 0) { /* erase any existing images */
996  lept_rmdir("lept/disp");
997  lept_mkdir("lept/disp");
998  }
999 
1000  index++;
1001  if (pixGetDepth(pix2) < 8 || pixGetColormap(pix2) ||
1002  (w < MaxSizeForPng && h < MaxSizeForPng)) {
1003  snprintf(buffer, Bufsize, "/tmp/lept/disp/write.%03d.png", index);
1004  pixWrite(buffer, pix2, IFF_PNG);
1005  } else {
1006  snprintf(buffer, Bufsize, "/tmp/lept/disp/write.%03d.jpg", index);
1007  pixWrite(buffer, pix2, IFF_JFIF_JPEG);
1008  }
1009  tempname = genPathname(buffer, NULL);
1010 
1011 #ifndef _WIN32
1012 
1013  /* Unix */
1014  if (var_DISPLAY_PROG == L_DISPLAY_WITH_XZGV) {
1015  /* no way to display title */
1016  pixGetDimensions(pix2, &wt, &ht, NULL);
1017  snprintf(buffer, Bufsize,
1018  "xzgv --geometry %dx%d+%d+%d %s &", wt + 10, ht + 10,
1019  x, y, tempname);
1020  } else if (var_DISPLAY_PROG == L_DISPLAY_WITH_XLI) {
1021  if (title) {
1022  snprintf(buffer, Bufsize,
1023  "xli -dispgamma 1.0 -quiet -geometry +%d+%d -title \"%s\" %s &",
1024  x, y, title, tempname);
1025  } else {
1026  snprintf(buffer, Bufsize,
1027  "xli -dispgamma 1.0 -quiet -geometry +%d+%d %s &",
1028  x, y, tempname);
1029  }
1030  } else if (var_DISPLAY_PROG == L_DISPLAY_WITH_XV) {
1031  if (title) {
1032  snprintf(buffer, Bufsize,
1033  "xv -quit -geometry +%d+%d -name \"%s\" %s &",
1034  x, y, title, tempname);
1035  } else {
1036  snprintf(buffer, Bufsize,
1037  "xv -quit -geometry +%d+%d %s &", x, y, tempname);
1038  }
1039  } else if (var_DISPLAY_PROG == L_DISPLAY_WITH_OPEN) {
1040  snprintf(buffer, Bufsize, "open %s &", tempname);
1041  }
1042  callSystemDebug(buffer);
1043 
1044 #else /* _WIN32 */
1045 
1046  /* Windows: L_DISPLAY_WITH_IV */
1047  pathname = genPathname(tempname, NULL);
1048  _fullpath(fullpath, pathname, sizeof(fullpath));
1049  if (title) {
1050  snprintf(buffer, Bufsize,
1051  "i_view32.exe \"%s\" /pos=(%d,%d) /title=\"%s\"",
1052  fullpath, x, y, title);
1053  } else {
1054  snprintf(buffer, Bufsize, "i_view32.exe \"%s\" /pos=(%d,%d)",
1055  fullpath, x, y);
1056  }
1057  callSystemDebug(buffer);
1058  LEPT_FREE(pathname);
1059 
1060 #endif /* _WIN32 */
1061 
1062  pixDestroy(&pix1);
1063  pixDestroy(&pix2);
1064  LEPT_FREE(tempname);
1065  return 0;
1066 }
1067 
1068 
1085 PIX *
1086 pixMakeColorSquare(l_uint32 color,
1087  l_int32 size,
1088  l_int32 addlabel,
1089  l_int32 location,
1090  l_uint32 textcolor)
1091 {
1092 char buf[32];
1093 l_int32 w, rval, gval, bval;
1094 L_BMF *bmf;
1095 PIX *pix1, *pix2;
1096 
1097  PROCNAME("pixMakeColorSquare");
1098 
1099  w = (size <= 0) ? 100 : size;
1100  if (addlabel && w < 100) {
1101  L_WARNING("size too small for label; omitting label\n", procName);
1102  addlabel = 0;
1103  }
1104 
1105  if ((pix1 = pixCreate(w, w, 32)) == NULL)
1106  return (PIX *)ERROR_PTR("pix1 not madel", procName, NULL);
1107  pixSetAllArbitrary(pix1, color);
1108  if (!addlabel)
1109  return pix1;
1110 
1111  /* Adding text of color component values */
1112  if (location != L_ADD_ABOVE && location != L_ADD_AT_TOP &&
1113  location != L_ADD_AT_BOT && location != L_ADD_BELOW) {
1114  L_ERROR("invalid location: adding below\n", procName);
1115  location = L_ADD_BELOW;
1116  }
1117  bmf = bmfCreate(NULL, 4);
1118  extractRGBValues(color, &rval, &gval, &bval);
1119  snprintf(buf, sizeof(buf), "%d,%d,%d", rval, gval, bval);
1120  pix2 = pixAddSingleTextblock(pix1, bmf, buf, textcolor, location, NULL);
1121  pixDestroy(&pix1);
1122  bmfDestroy(&bmf);
1123  return pix2;
1124 }
1125 
1126 
1127 void
1128 l_chooseDisplayProg(l_int32 selection)
1129 {
1130  if (selection == L_DISPLAY_WITH_XLI ||
1131  selection == L_DISPLAY_WITH_XZGV ||
1132  selection == L_DISPLAY_WITH_XV ||
1133  selection == L_DISPLAY_WITH_IV ||
1134  selection == L_DISPLAY_WITH_OPEN) {
1135  var_DISPLAY_PROG = selection;
1136  } else {
1137  L_ERROR("invalid display program\n", "l_chooseDisplayProg");
1138  }
1139 }
1140 
1141 
1142 /*---------------------------------------------------------------------*
1143  * Change format for missing lib *
1144  *---------------------------------------------------------------------*/
1158 void
1159 changeFormatForMissingLib(l_int32 *pformat)
1160 {
1161  PROCNAME("changeFormatForMissingLib");
1162 
1163 #if !defined(HAVE_LIBJPEG)
1164  if (*pformat == IFF_JFIF_JPEG) {
1165  L_WARNING("jpeg library missing; output bmp format\n", procName);
1166  *pformat = IFF_BMP;
1167  }
1168 #endif /* !defined(HAVE_LIBJPEG) */
1169 #if !defined(HAVE_LIBPNG)
1170  if (*pformat == IFF_PNG) {
1171  L_WARNING("png library missing; output bmp format\n", procName);
1172  *pformat = IFF_BMP;
1173  }
1174 #endif /* !defined(HAVE_LIBPNG) */
1175 #if !defined(HAVE_LIBTIFF)
1176  if (L_FORMAT_IS_TIFF(*pformat)) {
1177  L_WARNING("tiff library missing; output bmp format\n", procName);
1178  *pformat = IFF_BMP;
1179  }
1180 #endif /* !defined(HAVE_LIBTIFF) */
1181 }
1182 
1183 
1184 /*---------------------------------------------------------------------*
1185  * Deprecated pix output for debugging *
1186  *---------------------------------------------------------------------*/
1199 l_ok
1200 pixDisplayWrite(PIX *pixs,
1201  l_int32 reduction)
1202 {
1203  lept_stderr("\n########################################################\n"
1204  " pixDisplayWrite() was last used in tesseract 3.04,"
1205  " in Feb 2016. As of 1.80, it is a non-functional stub\n"
1206  "########################################################"
1207  "\n\n\n");
1208  return 1;
1209 }
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:169
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:117
l_ok pixWriteStreamBmp(FILE *fp, PIX *pix)
pixWriteStreamBmp()
Definition: bmpio.c:400
l_ok pixWriteMemBmp(l_uint8 **pfdata, size_t *pfsize, PIX *pixs)
pixWriteMemBmp()
Definition: bmpio.c:445
l_ok pixcmapIsOpaque(PIXCMAP *cmap, l_int32 *popaque)
pixcmapIsOpaque()
Definition: colormap.c:1114
@ L_JP2_CODEC
Definition: imageio.h:149
l_ok pixWriteMemJpeg(l_uint8 **pdata, size_t *psize, PIX *pix, l_int32 quality, l_int32 progressive)
pixWriteMemJpeg()
Definition: jpegio.c:1131
l_ok pixWriteStreamJpeg(FILE *fp, PIX *pixs, l_int32 quality, l_int32 progressive)
pixWriteStreamJpeg()
Definition: jpegio.c:802
l_ok pixWriteJpeg(const char *filename, PIX *pix, l_int32 quality, l_int32 progressive)
pixWriteJpeg()
Definition: jpegio.c:741
l_ok pixWriteMemPdf(l_uint8 **pdata, size_t *pnbytes, PIX *pix, l_int32 res, const char *title)
pixWriteMemPdf()
Definition: pdfio1.c:1395
l_ok pixWriteStreamPdf(FILE *fp, PIX *pix, l_int32 res, const char *title)
pixWriteStreamPdf()
Definition: pdfio1.c:1346
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 * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixDisplayLayersRGBA(PIX *pixs, l_uint32 val, l_int32 maxw)
pixDisplayLayersRGBA()
Definition: pix2.c:2351
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2820
l_ok pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
Definition: pix2.c:951
@ REMOVE_CMAP_WITH_ALPHA
Definition: pix.h:259
@ L_ADD_AT_BOT
Definition: pix.h:1214
@ L_ADD_BELOW
Definition: pix.h:1210
@ L_ADD_AT_TOP
Definition: pix.h:1213
@ L_ADD_ABOVE
Definition: pix.h:1209
@ L_CLONE
Definition: pix.h:713
@ L_MS_BYTE
Definition: pix.h:849
@ L_DISPLAY_WITH_XV
Definition: pix.h:1248
@ L_DISPLAY_WITH_XZGV
Definition: pix.h:1246
@ L_DISPLAY_WITH_XLI
Definition: pix.h:1247
@ L_DISPLAY_WITH_OPEN
Definition: pix.h:1250
@ L_DISPLAY_WITH_IV
Definition: pix.h:1249
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:650
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:691
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
PIX * pixConvert16To8(PIX *pixs, l_int32 type)
pixConvert16To8()
Definition: pixconv.c:1762
l_ok pixWriteStreamPng(FILE *fp, PIX *pix, l_float32 gamma)
pixWriteStreamPng()
Definition: pngio.c:1072
l_ok pixWriteMemPng(l_uint8 **pfiledata, size_t *pfilesize, PIX *pix, l_float32 gamma)
pixWriteMemPng()
Definition: pngio.c:1986
l_ok pixWriteStreamPnm(FILE *fp, PIX *pix)
pixWriteStreamPnm()
Definition: pnmio.c:742
l_ok pixWriteMemPnm(l_uint8 **pdata, size_t *psize, PIX *pix)
pixWriteMemPnm()
Definition: pnmio.c:1234
l_ok pixWriteStreamPS(FILE *fp, PIX *pix, BOX *box, l_int32 res, l_float32 scale)
pixWriteStreamPS()
Definition: psio2.c:241
l_ok pixWriteMemPS(l_uint8 **pdata, size_t *psize, PIX *pix, BOX *box, l_int32 res, l_float32 scale)
pixWriteMemPS()
Definition: psio2.c:1957
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:193
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:250
PIX * pixScaleToGray8(PIX *pixs)
pixScaleToGray8()
Definition: scale2.c:605
PIX * pixScaleToGray3(PIX *pixs)
pixScaleToGray3()
Definition: scale2.c:448
PIX * pixScaleToGray2(PIX *pixs)
pixScaleToGray2()
Definition: scale2.c:390
PIX * pixScaleToGray(PIX *pixs, l_float32 scalefactor)
pixScaleToGray()
Definition: scale2.c:208
PIX * pixScaleToGray4(PIX *pixs)
pixScaleToGray4()
Definition: scale2.c:502
l_ok pixWriteMemSpix(l_uint8 **pdata, size_t *psize, PIX *pix)
pixWriteMemSpix()
Definition: spixio.c:321
l_ok pixWriteStreamSpix(FILE *fp, PIX *pix)
pixWriteStreamSpix()
Definition: spixio.c:273
Definition: bmf.h:47
Definition: pix.h:139
Definition: pix.h:456
PIX * pixAddSingleTextblock(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow)
pixAddSingleTextblock()
Definition: textops.c:120
l_ok pixWriteStreamTiff(FILE *fp, PIX *pix, l_int32 comptype)
pixWriteStreamTiff()
Definition: tiffio.c:911
l_ok pixWriteMemTiff(l_uint8 **pdata, size_t *psize, PIX *pix, l_int32 comptype)
pixWriteMemTiff()
Definition: tiffio.c:2841
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2295
l_ok splitPathAtExtension(const char *pathname, char **pbasename, char **pextension)
splitPathAtExtension()
Definition: utils2.c:2894
void callSystemDebug(const char *cmd)
callSystemDebug()
Definition: utils2.c:2752
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1975
char * genPathname(const char *dir, const char *fname)
genPathname()
Definition: utils2.c:3173
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2218