Leptonica  1.83.1
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  prevq = var_JPEG_QUALITY;
193  newq = (new_quality == 0) ? 75 : new_quality;
194  if (newq < 1 || newq > 100)
195  L_ERROR("invalid jpeg quality; unchanged\n", __func__);
196  else
197  var_JPEG_QUALITY = newq;
198  return prevq;
199 }
200 
201 
202 /*----------------------------------------------------------------------*
203  * Set global variable LeptDebugOK for writing to named temp files *
204  *----------------------------------------------------------------------*/
205 LEPT_DLL l_int32 LeptDebugOK = 0; /* default value */
220 void
221 setLeptDebugOK(l_int32 allow)
222 {
223  if (allow != 0) allow = 1;
224  LeptDebugOK = allow;
225 }
226 
227 
228 /*---------------------------------------------------------------------*
229  * Top-level procedures for writing images to file *
230  *---------------------------------------------------------------------*/
245 l_ok
246 pixaWriteFiles(const char *rootname,
247  PIXA *pixa,
248  l_int32 format)
249 {
250 char bigbuf[Bufsize];
251 l_int32 i, n, pixformat;
252 PIX *pix;
253 
254  if (!rootname)
255  return ERROR_INT("rootname not defined", __func__, 1);
256  if (!pixa)
257  return ERROR_INT("pixa not defined", __func__, 1);
258  if (format < 0 || format == IFF_UNKNOWN ||
259  format >= NumImageFileFormatExtensions)
260  return ERROR_INT("invalid format", __func__, 1);
261 
262  n = pixaGetCount(pixa);
263  for (i = 0; i < n; i++) {
264  pix = pixaGetPix(pixa, i, L_CLONE);
265  if (format == IFF_DEFAULT)
266  pixformat = pixChooseOutputFormat(pix);
267  else
268  pixformat = format;
269  snprintf(bigbuf, Bufsize, "%s%03d.%s", rootname, i,
270  ImageFileFormatExtensions[pixformat]);
271  pixWrite(bigbuf, pix, pixformat);
272  pixDestroy(&pix);
273  }
274 
275  return 0;
276 }
277 
278 
296 l_ok
297 pixWriteDebug(const char *fname,
298  PIX *pix,
299  l_int32 format)
300 {
301  if (LeptDebugOK) {
302  return pixWrite(fname, pix, format);
303  } else {
304  L_INFO("write to named temp file %s is disabled\n", __func__, fname);
305  return 0;
306  }
307 }
308 
309 
331 l_ok
332 pixWrite(const char *fname,
333  PIX *pix,
334  l_int32 format)
335 {
336 l_int32 ret;
337 FILE *fp;
338 
339  if (!pix)
340  return ERROR_INT("pix not defined", __func__, 1);
341  if (!fname)
342  return ERROR_INT("fname not defined", __func__, 1);
343 
344  if ((fp = fopenWriteStream(fname, "wb+")) == NULL)
345  return ERROR_INT("stream not opened", __func__, 1);
346 
347  ret = pixWriteStream(fp, pix, format);
348  fclose(fp);
349  if (ret)
350  return ERROR_INT("pix not written to stream", __func__, 1);
351  return 0;
352 }
353 
354 
362 l_ok
363 pixWriteAutoFormat(const char *filename,
364  PIX *pix)
365 {
366 l_int32 format;
367 
368  if (!pix)
369  return ERROR_INT("pix not defined", __func__, 1);
370  if (!filename)
371  return ERROR_INT("filename not defined", __func__, 1);
372 
373  if (pixGetAutoFormat(pix, &format))
374  return ERROR_INT("auto format not returned", __func__, 1);
375  return pixWrite(filename, pix, format);
376 }
377 
378 
387 l_ok
388 pixWriteStream(FILE *fp,
389  PIX *pix,
390  l_int32 format)
391 {
392  if (!fp)
393  return ERROR_INT("stream not defined", __func__, 1);
394  if (!pix)
395  return ERROR_INT("pix not defined", __func__, 1);
396 
397  if (format == IFF_DEFAULT)
398  format = pixChooseOutputFormat(pix);
399 
400  /* Use bmp format for testing if library for requested
401  * format for jpeg, png or tiff is not available */
402  changeFormatForMissingLib(&format);
403 
404  switch(format)
405  {
406  case IFF_BMP:
407  pixWriteStreamBmp(fp, pix);
408  break;
409 
410  case IFF_JFIF_JPEG: /* default quality; baseline sequential */
411  return pixWriteStreamJpeg(fp, pix, var_JPEG_QUALITY, 0);
412 
413  case IFF_PNG: /* no gamma value stored */
414  return pixWriteStreamPng(fp, pix, 0.0);
415 
416  case IFF_TIFF: /* uncompressed */
417  case IFF_TIFF_PACKBITS: /* compressed, binary only */
418  case IFF_TIFF_RLE: /* compressed, binary only */
419  case IFF_TIFF_G3: /* compressed, binary only */
420  case IFF_TIFF_G4: /* compressed, binary only */
421  case IFF_TIFF_LZW: /* compressed, all depths */
422  case IFF_TIFF_ZIP: /* compressed, all depths */
423  case IFF_TIFF_JPEG: /* compressed, 8 bpp gray and 32 bpp rgb */
424  return pixWriteStreamTiff(fp, pix, format);
425 
426  case IFF_PNM:
427  return pixWriteStreamPnm(fp, pix);
428 
429  case IFF_PS:
430  return pixWriteStreamPS(fp, pix, NULL, 0, DefaultScaling);
431 
432  case IFF_GIF:
433  return pixWriteStreamGif(fp, pix);
434 
435  case IFF_JP2:
436  return pixWriteStreamJp2k(fp, pix, 34, 4, L_JP2_CODEC, 0, 0);
437 
438  case IFF_WEBP:
439  return pixWriteStreamWebP(fp, pix, 80, 0);
440 
441  case IFF_LPDF:
442  return pixWriteStreamPdf(fp, pix, 0, NULL);
443 
444  case IFF_SPIX:
445  return pixWriteStreamSpix(fp, pix);
446 
447  default:
448  return ERROR_INT("unknown format", __func__, 1);
449  }
450 
451  return 0;
452 }
453 
454 
471 l_ok
472 pixWriteImpliedFormat(const char *filename,
473  PIX *pix,
474  l_int32 quality,
475  l_int32 progressive)
476 {
477 l_int32 format;
478 
479  if (!filename)
480  return ERROR_INT("filename not defined", __func__, 1);
481  if (!pix)
482  return ERROR_INT("pix not defined", __func__, 1);
483 
484  /* Determine output format */
485  format = getImpliedFileFormat(filename);
486  if (format == IFF_UNKNOWN) {
487  format = IFF_PNG;
488  } else if (format == IFF_TIFF) {
489  if (pixGetDepth(pix) == 1)
490  format = IFF_TIFF_G4;
491  else
492 #ifdef _WIN32
493  format = IFF_TIFF_LZW; /* poor compression */
494 #else
495  format = IFF_TIFF_ZIP; /* native Windows tools can't handle this */
496 #endif /* _WIN32 */
497  }
498 
499  if (format == IFF_JFIF_JPEG) {
500  quality = L_MIN(quality, 100);
501  quality = L_MAX(quality, 0);
502  if (progressive != 0 && progressive != 1) {
503  progressive = 0;
504  L_WARNING("invalid progressive; setting to baseline\n", __func__);
505  }
506  if (quality == 0)
507  quality = 75;
508  pixWriteJpeg (filename, pix, quality, progressive);
509  } else {
510  pixWrite(filename, pix, format);
511  }
512 
513  return 0;
514 }
515 
516 
517 /*---------------------------------------------------------------------*
518  * Selection of output format if default is requested *
519  *---------------------------------------------------------------------*/
534 l_int32
535 pixChooseOutputFormat(PIX *pix)
536 {
537 l_int32 d, format;
538 
539  if (!pix)
540  return ERROR_INT("pix not defined", __func__, 0);
541 
542  d = pixGetDepth(pix);
543  format = pixGetInputFormat(pix);
544  if (format == IFF_UNKNOWN) { /* output lossless */
545  if (d == 1)
546  format = IFF_TIFF_G4;
547  else
548  format = IFF_PNG;
549  }
550 
551  return format;
552 }
553 
554 
567 l_int32
568 getImpliedFileFormat(const char *filename)
569 {
570 char *extension;
571 int i, numext;
572 l_int32 format = IFF_UNKNOWN;
573 
574  if (splitPathAtExtension (filename, NULL, &extension))
575  return IFF_UNKNOWN;
576 
577  numext = sizeof(extension_map) / sizeof(extension_map[0]);
578  for (i = 0; i < numext; i++) {
579  if (!strcmp(extension, extension_map[i].extension)) {
580  format = extension_map[i].format;
581  break;
582  }
583  }
584 
585  LEPT_FREE(extension);
586  return format;
587 }
588 
589 
608 l_ok
609 pixGetAutoFormat(PIX *pix,
610  l_int32 *pformat)
611 {
612 l_int32 d;
613 PIXCMAP *cmap;
614 
615  if (!pformat)
616  return ERROR_INT("&format not defined", __func__, 0);
617  *pformat = IFF_UNKNOWN;
618  if (!pix)
619  return ERROR_INT("pix not defined", __func__, 0);
620 
621  d = pixGetDepth(pix);
622  cmap = pixGetColormap(pix);
623  if (d == 1 && !cmap) {
624  *pformat = IFF_TIFF_G4;
625  } else if ((d == 8 && !cmap) || d == 24 || d == 32) {
626  *pformat = IFF_JFIF_JPEG;
627  } else {
628  *pformat = IFF_PNG;
629  }
630 
631  return 0;
632 }
633 
634 
647 const char *
648 getFormatExtension(l_int32 format)
649 {
650  if (format < 0 || format >= NumImageFileFormatExtensions)
651  return (const char *)ERROR_PTR("invalid format", __func__, NULL);
652 
653  return ImageFileFormatExtensions[format];
654 }
655 
656 
657 /*---------------------------------------------------------------------*
658  * Write to memory *
659  *---------------------------------------------------------------------*/
680 l_ok
681 pixWriteMem(l_uint8 **pdata,
682  size_t *psize,
683  PIX *pix,
684  l_int32 format)
685 {
686 l_int32 ret;
687 
688  if (!pdata)
689  return ERROR_INT("&data not defined", __func__, 1 );
690  if (!psize)
691  return ERROR_INT("&size not defined", __func__, 1 );
692  if (!pix)
693  return ERROR_INT("&pix not defined", __func__, 1 );
694 
695  if (format == IFF_DEFAULT)
696  format = pixChooseOutputFormat(pix);
697 
698  /* Use bmp format for testing if library for requested
699  * format for jpeg, png or tiff is not available */
700  changeFormatForMissingLib(&format);
701 
702  switch(format)
703  {
704  case IFF_BMP:
705  ret = pixWriteMemBmp(pdata, psize, pix);
706  break;
707 
708  case IFF_JFIF_JPEG: /* default quality; baseline sequential */
709  ret = pixWriteMemJpeg(pdata, psize, pix, var_JPEG_QUALITY, 0);
710  break;
711 
712  case IFF_PNG: /* no gamma value stored */
713  ret = pixWriteMemPng(pdata, psize, pix, 0.0);
714  break;
715 
716  case IFF_TIFF: /* uncompressed */
717  case IFF_TIFF_PACKBITS: /* compressed, binary only */
718  case IFF_TIFF_RLE: /* compressed, binary only */
719  case IFF_TIFF_G3: /* compressed, binary only */
720  case IFF_TIFF_G4: /* compressed, binary only */
721  case IFF_TIFF_LZW: /* compressed, all depths */
722  case IFF_TIFF_ZIP: /* compressed, all depths */
723  case IFF_TIFF_JPEG: /* compressed, 8 bpp gray or 32 bpp rgb */
724  ret = pixWriteMemTiff(pdata, psize, pix, format);
725  break;
726 
727  case IFF_PNM:
728  ret = pixWriteMemPnm(pdata, psize, pix);
729  break;
730 
731  case IFF_PS:
732  ret = pixWriteMemPS(pdata, psize, pix, NULL, 0, DefaultScaling);
733  break;
734 
735  case IFF_GIF:
736  ret = pixWriteMemGif(pdata, psize, pix);
737  break;
738 
739  case IFF_JP2:
740  ret = pixWriteMemJp2k(pdata, psize, pix, 34, 0, 0, 0);
741  break;
742 
743  case IFF_WEBP:
744  ret = pixWriteMemWebP(pdata, psize, pix, 80, 0);
745  break;
746 
747  case IFF_LPDF:
748  ret = pixWriteMemPdf(pdata, psize, pix, 0, NULL);
749  break;
750 
751  case IFF_SPIX:
752  ret = pixWriteMemSpix(pdata, psize, pix);
753  break;
754 
755  default:
756  return ERROR_INT("unknown format", __func__, 1);
757  }
758 
759  return ret;
760 }
761 
762 
763 /*---------------------------------------------------------------------*
764  * Image display for debugging *
765  *---------------------------------------------------------------------*/
782 l_ok
783 l_fileDisplay(const char *fname,
784  l_int32 x,
785  l_int32 y,
786  l_float32 scale)
787 {
788 PIX *pixs, *pixd;
789 
790  if (!LeptDebugOK) {
791  L_INFO("displaying files is disabled; "
792  "use setLeptDebugOK(1) to enable\n", __func__);
793  return 0;
794  }
795  if (scale == 0.0)
796  return 0;
797  if (scale < 0.0)
798  return ERROR_INT("invalid scale factor", __func__, 1);
799  if ((pixs = pixRead(fname)) == NULL)
800  return ERROR_INT("pixs not read", __func__, 1);
801 
802  if (scale == 1.0) {
803  pixd = pixClone(pixs);
804  } else {
805  if (scale < 1.0 && pixGetDepth(pixs) == 1)
806  pixd = pixScaleToGray(pixs, scale);
807  else
808  pixd = pixScale(pixs, scale, scale);
809  }
810  pixDisplay(pixd, x, y);
811  pixDestroy(&pixs);
812  pixDestroy(&pixd);
813  return 0;
814 }
815 
816 
856 l_ok
857 pixDisplay(PIX *pixs,
858  l_int32 x,
859  l_int32 y)
860 {
861  return pixDisplayWithTitle(pixs, x, y, NULL, 1);
862 }
863 
864 
880 l_ok
881 pixDisplayWithTitle(PIX *pixs,
882  l_int32 x,
883  l_int32 y,
884  const char *title,
885  l_int32 dispflag)
886 {
887 char *tempname;
888 char buffer[Bufsize];
889 static l_int32 index = 0; /* caution: not .so or thread safe */
890 l_int32 w, h, d, spp, maxheight, opaque, threeviews;
891 l_float32 ratw, rath, ratmin;
892 PIX *pix0, *pix1, *pix2;
893 PIXCMAP *cmap;
894 #ifndef _WIN32
895 l_int32 wt, ht;
896 #else
897 char *pathname;
898 char fullpath[_MAX_PATH];
899 #endif /* _WIN32 */
900 
901  if (!LeptDebugOK) {
902  L_INFO("displaying images is disabled;\n "
903  "use setLeptDebugOK(1) to enable\n", __func__);
904  return 0;
905  }
906 
907 #ifdef OS_IOS /* iOS 11 does not support system() */
908  return ERROR_INT("iOS 11 does not support system()", __func__, 1);
909 #endif /* OS_IOS */
910 
911  if (dispflag != 1) return 0;
912  if (!pixs)
913  return ERROR_INT("pixs not defined", __func__, 1);
914  if (var_DISPLAY_PROG != L_DISPLAY_WITH_XZGV &&
915  var_DISPLAY_PROG != L_DISPLAY_WITH_XLI &&
916  var_DISPLAY_PROG != L_DISPLAY_WITH_XV &&
917  var_DISPLAY_PROG != L_DISPLAY_WITH_IV &&
918  var_DISPLAY_PROG != L_DISPLAY_WITH_OPEN) {
919  return ERROR_INT("no program chosen for display", __func__, 1);
920  }
921 
922  /* Display with three views if either spp = 4 or if colormapped
923  * and the alpha component is not fully opaque */
924  opaque = TRUE;
925  if ((cmap = pixGetColormap(pixs)) != NULL)
926  pixcmapIsOpaque(cmap, &opaque);
927  spp = pixGetSpp(pixs);
928  threeviews = (spp == 4 || !opaque) ? TRUE : FALSE;
929 
930  /* If colormapped and not opaque, remove the colormap to RGBA */
931  if (!opaque)
933  else
934  pix0 = pixClone(pixs);
935 
936  /* Scale if necessary; this will also remove a colormap */
937  pixGetDimensions(pix0, &w, &h, &d);
938  maxheight = (threeviews) ? MaxDisplayHeight / 3 : MaxDisplayHeight;
939  if (w <= MaxDisplayWidth && h <= maxheight) {
940  if (d == 16) /* take MSB */
941  pix1 = pixConvert16To8(pix0, L_MS_BYTE);
942  else
943  pix1 = pixClone(pix0);
944  } else {
945  ratw = (l_float32)MaxDisplayWidth / (l_float32)w;
946  rath = (l_float32)maxheight / (l_float32)h;
947  ratmin = L_MIN(ratw, rath);
948  if (ratmin < 0.125 && d == 1)
949  pix1 = pixScaleToGray8(pix0);
950  else if (ratmin < 0.25 && d == 1)
951  pix1 = pixScaleToGray4(pix0);
952  else if (ratmin < 0.33 && d == 1)
953  pix1 = pixScaleToGray3(pix0);
954  else if (ratmin < 0.5 && d == 1)
955  pix1 = pixScaleToGray2(pix0);
956  else
957  pix1 = pixScale(pix0, ratmin, ratmin);
958  }
959  pixDestroy(&pix0);
960  if (!pix1)
961  return ERROR_INT("pix1 not made", __func__, 1);
962 
963  /* Generate the three views if required */
964  if (threeviews)
965  pix2 = pixDisplayLayersRGBA(pix1, 0xffffff00, 0);
966  else
967  pix2 = pixClone(pix1);
968 
969  if (index == 0) { /* erase any existing images */
970  lept_rmdir("lept/disp");
971  lept_mkdir("lept/disp");
972  }
973 
974  index++;
975  if (pixGetDepth(pix2) < 8 || pixGetColormap(pix2) ||
976  (w < MaxSizeForPng && h < MaxSizeForPng)) {
977  snprintf(buffer, Bufsize, "/tmp/lept/disp/write.%03d.png", index);
978  pixWrite(buffer, pix2, IFF_PNG);
979  } else {
980  snprintf(buffer, Bufsize, "/tmp/lept/disp/write.%03d.jpg", index);
981  pixWrite(buffer, pix2, IFF_JFIF_JPEG);
982  }
983  tempname = genPathname(buffer, NULL);
984 
985 #ifndef _WIN32
986 
987  /* Unix */
988  if (var_DISPLAY_PROG == L_DISPLAY_WITH_XZGV) {
989  /* no way to display title */
990  pixGetDimensions(pix2, &wt, &ht, NULL);
991  snprintf(buffer, Bufsize,
992  "xzgv --geometry %dx%d+%d+%d %s &", wt + 10, ht + 10,
993  x, y, tempname);
994  } else if (var_DISPLAY_PROG == L_DISPLAY_WITH_XLI) {
995  if (title) {
996  snprintf(buffer, Bufsize,
997  "xli -dispgamma 1.0 -quiet -geometry +%d+%d -title \"%s\" %s &",
998  x, y, title, tempname);
999  } else {
1000  snprintf(buffer, Bufsize,
1001  "xli -dispgamma 1.0 -quiet -geometry +%d+%d %s &",
1002  x, y, tempname);
1003  }
1004  } else if (var_DISPLAY_PROG == L_DISPLAY_WITH_XV) {
1005  if (title) {
1006  snprintf(buffer, Bufsize,
1007  "xv -quit -geometry +%d+%d -name \"%s\" %s &",
1008  x, y, title, tempname);
1009  } else {
1010  snprintf(buffer, Bufsize,
1011  "xv -quit -geometry +%d+%d %s &", x, y, tempname);
1012  }
1013  } else if (var_DISPLAY_PROG == L_DISPLAY_WITH_OPEN) {
1014  snprintf(buffer, Bufsize, "open %s &", tempname);
1015  }
1016  callSystemDebug(buffer);
1017 
1018 #else /* _WIN32 */
1019 
1020  /* Windows: L_DISPLAY_WITH_IV */
1021  pathname = genPathname(tempname, NULL);
1022  _fullpath(fullpath, pathname, sizeof(fullpath));
1023  if (title) {
1024  snprintf(buffer, Bufsize,
1025  "i_view32.exe \"%s\" /pos=(%d,%d) /title=\"%s\"",
1026  fullpath, x, y, title);
1027  } else {
1028  snprintf(buffer, Bufsize, "i_view32.exe \"%s\" /pos=(%d,%d)",
1029  fullpath, x, y);
1030  }
1031  callSystemDebug(buffer);
1032  LEPT_FREE(pathname);
1033 
1034 #endif /* _WIN32 */
1035 
1036  pixDestroy(&pix1);
1037  pixDestroy(&pix2);
1038  LEPT_FREE(tempname);
1039  return 0;
1040 }
1041 
1042 
1059 PIX *
1060 pixMakeColorSquare(l_uint32 color,
1061  l_int32 size,
1062  l_int32 addlabel,
1063  l_int32 location,
1064  l_uint32 textcolor)
1065 {
1066 char buf[32];
1067 l_int32 w, rval, gval, bval;
1068 L_BMF *bmf;
1069 PIX *pix1, *pix2;
1070 
1071  w = (size <= 0) ? 100 : size;
1072  if (addlabel && w < 100) {
1073  L_WARNING("size too small for label; omitting label\n", __func__);
1074  addlabel = 0;
1075  }
1076 
1077  if ((pix1 = pixCreate(w, w, 32)) == NULL)
1078  return (PIX *)ERROR_PTR("pix1 not madel", __func__, NULL);
1079  pixSetAllArbitrary(pix1, color);
1080  if (!addlabel)
1081  return pix1;
1082 
1083  /* Adding text of color component values */
1084  if (location != L_ADD_ABOVE && location != L_ADD_AT_TOP &&
1085  location != L_ADD_AT_BOT && location != L_ADD_BELOW) {
1086  L_ERROR("invalid location: adding below\n", __func__);
1087  location = L_ADD_BELOW;
1088  }
1089  bmf = bmfCreate(NULL, 4);
1090  extractRGBValues(color, &rval, &gval, &bval);
1091  snprintf(buf, sizeof(buf), "%d,%d,%d", rval, gval, bval);
1092  pix2 = pixAddSingleTextblock(pix1, bmf, buf, textcolor, location, NULL);
1093  pixDestroy(&pix1);
1094  bmfDestroy(&bmf);
1095  return pix2;
1096 }
1097 
1098 
1099 void
1100 l_chooseDisplayProg(l_int32 selection)
1101 {
1102  if (selection == L_DISPLAY_WITH_XLI ||
1103  selection == L_DISPLAY_WITH_XZGV ||
1104  selection == L_DISPLAY_WITH_XV ||
1105  selection == L_DISPLAY_WITH_IV ||
1106  selection == L_DISPLAY_WITH_OPEN) {
1107  var_DISPLAY_PROG = selection;
1108  } else {
1109  L_ERROR("invalid display program\n", "l_chooseDisplayProg");
1110  }
1111 }
1112 
1113 
1114 /*---------------------------------------------------------------------*
1115  * Change format for missing lib *
1116  *---------------------------------------------------------------------*/
1130 void
1131 changeFormatForMissingLib(l_int32 *pformat)
1132 {
1133 #if !defined(HAVE_LIBJPEG)
1134  if (*pformat == IFF_JFIF_JPEG) {
1135  L_WARNING("jpeg library missing; output bmp format\n", __func__);
1136  *pformat = IFF_BMP;
1137  }
1138 #endif /* !defined(HAVE_LIBJPEG) */
1139 #if !defined(HAVE_LIBPNG)
1140  if (*pformat == IFF_PNG) {
1141  L_WARNING("png library missing; output bmp format\n", __func__);
1142  *pformat = IFF_BMP;
1143  }
1144 #endif /* !defined(HAVE_LIBPNG) */
1145 #if !defined(HAVE_LIBTIFF)
1146  if (L_FORMAT_IS_TIFF(*pformat)) {
1147  L_WARNING("tiff library missing; output bmp format\n", __func__);
1148  *pformat = IFF_BMP;
1149  }
1150 #endif /* !defined(HAVE_LIBTIFF) */
1151 }
1152 
1153 
1154 /*---------------------------------------------------------------------*
1155  * Deprecated pix output for debugging *
1156  *---------------------------------------------------------------------*/
1169 l_ok
1170 pixDisplayWrite(PIX *pixs,
1171  l_int32 reduction)
1172 {
1173  lept_stderr("\n########################################################\n"
1174  " pixDisplayWrite() was last used in tesseract 3.04,"
1175  " in Feb 2016. As of 1.80, it is a non-functional stub\n"
1176  "########################################################"
1177  "\n\n\n");
1178  return 1;
1179 }
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:168
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:118
l_ok pixWriteStreamBmp(FILE *fp, PIX *pix)
pixWriteStreamBmp()
Definition: bmpio.c:404
l_ok pixWriteMemBmp(l_uint8 **pfdata, size_t *pfsize, PIX *pixs)
pixWriteMemBmp()
Definition: bmpio.c:447
l_ok pixcmapIsOpaque(PIXCMAP *cmap, l_int32 *popaque)
pixcmapIsOpaque()
Definition: colormap.c:1063
@ 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:1110
l_ok pixWriteStreamJpeg(FILE *fp, PIX *pixs, l_int32 quality, l_int32 progressive)
pixWriteStreamJpeg()
Definition: jpegio.c:789
l_ok pixWriteJpeg(const char *filename, PIX *pix, l_int32 quality, l_int32 progressive)
pixWriteJpeg()
Definition: jpegio.c:730
l_ok pixWriteMemPdf(l_uint8 **pdata, size_t *pnbytes, PIX *pix, l_int32 res, const char *title)
pixWriteMemPdf()
Definition: pdfio1.c:1351
l_ok pixWriteStreamPdf(FILE *fp, PIX *pix, l_int32 res, const char *title)
pixWriteStreamPdf()
Definition: pdfio1.c:1305
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
PIX * pixDisplayLayersRGBA(PIX *pixs, l_uint32 val, l_int32 maxw)
pixDisplayLayersRGBA()
Definition: pix2.c:2340
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2793
l_ok pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
Definition: pix2.c:929
@ 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_XV
Definition: pix.h:1041
@ L_DISPLAY_WITH_XZGV
Definition: pix.h:1039
@ L_DISPLAY_WITH_XLI
Definition: pix.h:1040
@ L_DISPLAY_WITH_OPEN
Definition: pix.h:1043
@ L_DISPLAY_WITH_IV
Definition: pix.h:1042
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:629
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:647
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:324
PIX * pixConvert16To8(PIX *pixs, l_int32 type)
pixConvert16To8()
Definition: pixconv.c:1726
l_ok pixWriteStreamPng(FILE *fp, PIX *pix, l_float32 gamma)
pixWriteStreamPng()
Definition: pngio.c:1057
l_ok pixWriteMemPng(l_uint8 **pfiledata, size_t *pfilesize, PIX *pix, l_float32 gamma)
pixWriteMemPng()
Definition: pngio.c:1965
l_ok pixWriteStreamPnm(FILE *fp, PIX *pix)
pixWriteStreamPnm()
Definition: pnmio.c:736
l_ok pixWriteMemPnm(l_uint8 **pdata, size_t *psize, PIX *pix)
pixWriteMemPnm()
Definition: pnmio.c:1218
l_ok pixWriteStreamPS(FILE *fp, PIX *pix, BOX *box, l_int32 res, l_float32 scale)
pixWriteStreamPS()
Definition: psio2.c:239
l_ok pixWriteMemPS(l_uint8 **pdata, size_t *psize, PIX *pix, BOX *box, l_int32 res, l_float32 scale)
pixWriteMemPS()
Definition: psio2.c:1921
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:189
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:250
PIX * pixScaleToGray8(PIX *pixs)
pixScaleToGray8()
Definition: scale2.c:593
PIX * pixScaleToGray3(PIX *pixs)
pixScaleToGray3()
Definition: scale2.c:442
PIX * pixScaleToGray2(PIX *pixs)
pixScaleToGray2()
Definition: scale2.c:386
PIX * pixScaleToGray(PIX *pixs, l_float32 scalefactor)
pixScaleToGray()
Definition: scale2.c:208
PIX * pixScaleToGray4(PIX *pixs)
pixScaleToGray4()
Definition: scale2.c:494
l_ok pixWriteMemSpix(l_uint8 **pdata, size_t *psize, PIX *pix)
pixWriteMemSpix()
Definition: spixio.c:311
l_ok pixWriteStreamSpix(FILE *fp, PIX *pix)
pixWriteStreamSpix()
Definition: spixio.c:265
Definition: bmf.h:47
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:925
l_ok pixWriteMemTiff(l_uint8 **pdata, size_t *psize, PIX *pix, l_int32 comptype)
pixWriteMemTiff()
Definition: tiffio.c:2811
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2213
l_ok splitPathAtExtension(const char *pathname, char **pbasename, char **pextension)
splitPathAtExtension()
Definition: utils2.c:2796
void callSystemDebug(const char *cmd)
callSystemDebug()
Definition: utils2.c:2658
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1905
char * genPathname(const char *dir, const char *fname)
genPathname()
Definition: utils2.c:3068
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2138