Leptonica  1.83.1
Image processing and image analysis suite
pix1.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 
197 #ifdef HAVE_CONFIG_H
198 #include <config_auto.h>
199 #endif /* HAVE_CONFIG_H */
200 
201 #include <string.h>
202 #include "allheaders.h"
203 #include "pix_internal.h"
204 
205 static void pixFree(PIX *pix);
206 
207 /*-------------------------------------------------------------------------*
208  * Pix Memory Management *
209  * *
210  * These functions give you the freedom to specify at compile or run *
211  * time the allocator and deallocator to be used for the pix raster *
212  * image data. They have no effect on any other heap allocation, *
213  * including the pix struct itself, which is controlled by the *
214  * #defines in environ.h. *
215  * *
216  * The default functions for allocating pix raster data are malloc and *
217  * free (or leptonica_* custom allocators if LEPTONICA_INTERCEPT_ALLOC *
218  * is defined). Use setPixMemoryManager() to specify other functions *
219  * to use specifically for pix raster image data. *
220  *-------------------------------------------------------------------------*/
222  /*
223  * <pre>
224  * Notes:
225  * (1) The allocator and deallocator function types,
226  * alloc_fn and dealloc_fn, are defined in pix.h.
227  * </pre>
228  */
230 {
231  alloc_fn allocator;
232  dealloc_fn deallocator;
233 };
234 
236 static struct PixMemoryManager pix_mem_manager = {
237 #ifdef LEPTONICA_INTERCEPT_ALLOC
238  &leptonica_malloc,
239  &leptonica_free
240 #else
241  &malloc,
242  &free
243 #endif /* LEPTONICA_INTERCEPT_ALLOC */
244 };
245 
246 static void *
247 pixdata_malloc(size_t size)
248 {
249 #ifndef _MSC_VER
250  return (*pix_mem_manager.allocator)(size);
251 #else /* _MSC_VER */
252  /* Under MSVC++, pix_mem_manager is initialized after a call to
253  * pixdata_malloc. Just ignore the custom allocator feature. */
254  return LEPT_MALLOC(size);
255 #endif /* _MSC_VER */
256 }
257 
258 static void
259 pixdata_free(void *ptr)
260 {
261 #ifndef _MSC_VER
262  (*pix_mem_manager.deallocator)(ptr);
263 #else /* _MSC_VER */
264  /* Under MSVC++, pix_mem_manager is initialized after a call to
265  * pixdata_malloc. Just ignore the custom allocator feature. */
266  LEPT_FREE(ptr);
267 #endif /* _MSC_VER */
268 }
269 
295 void
297  dealloc_fn deallocator)
298 {
299  if (allocator) pix_mem_manager.allocator = allocator;
300  if (deallocator) pix_mem_manager.deallocator = deallocator;
301 }
302 
303 
304 /*--------------------------------------------------------------------*
305  * Pix Creation *
306  *--------------------------------------------------------------------*/
314 PIX *
315 pixCreate(l_int32 width,
316  l_int32 height,
317  l_int32 depth)
318 {
319 PIX *pixd;
320 
321  if ((pixd = pixCreateNoInit(width, height, depth)) == NULL)
322  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
323  memset(pixd->data, 0, 4LL * pixd->wpl * pixd->h);
324  return pixd;
325 }
326 
327 
343 PIX *
344 pixCreateNoInit(l_int32 width,
345  l_int32 height,
346  l_int32 depth)
347 {
348 l_int32 wpl;
349 PIX *pixd;
350 l_uint32 *data;
351 
352  if ((pixd = pixCreateHeader(width, height, depth)) == NULL)
353  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
354  wpl = pixGetWpl(pixd);
355  if ((data = (l_uint32 *)pixdata_malloc(4LL * wpl * height)) == NULL) {
356  pixDestroy(&pixd);
357  return (PIX *)ERROR_PTR("pixdata_malloc fail for data",
358  __func__, NULL);
359  }
360  pixSetData(pixd, data);
361  pixSetPadBits(pixd, 0);
362  return pixd;
363 }
364 
365 
379 PIX *
380 pixCreateTemplate(const PIX *pixs)
381 {
382 PIX *pixd;
383 
384  if (!pixs)
385  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
386 
387  if ((pixd = pixCreateTemplateNoInit(pixs)) == NULL)
388  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
389  memset(pixd->data, 0, 4LL * pixd->wpl * pixd->h);
390  return pixd;
391 }
392 
393 
411 PIX *
413 {
414 l_int32 w, h, d;
415 PIX *pixd;
416 
417  if (!pixs)
418  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
419 
420  pixGetDimensions(pixs, &w, &h, &d);
421  if ((pixd = pixCreateNoInit(w, h, d)) == NULL)
422  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
423  pixCopySpp(pixd, pixs);
424  pixCopyResolution(pixd, pixs);
425  pixCopyColormap(pixd, pixs);
426  pixCopyText(pixd, pixs);
427  pixCopyInputFormat(pixd, pixs);
428  pixSetPadBits(pixd, 0);
429  return pixd;
430 }
431 
432 
450 PIX *
451 pixCreateWithCmap(l_int32 width,
452  l_int32 height,
453  l_int32 depth,
454  l_int32 initcolor)
455 {
456 PIX *pix;
457 PIXCMAP *cmap;
458 
459  if (depth != 2 && depth != 4 && depth != 8)
460  return (PIX *)ERROR_PTR("depth not 2, 4 or 8 bpp", __func__, NULL);
461 
462  if ((pix = pixCreate(width, height, depth)) == NULL)
463  return (PIX *)ERROR_PTR("pix not made", __func__, NULL);
464  cmap = pixcmapCreate(depth);
465  pixSetColormap(pix, cmap);
466  if (initcolor == L_SET_BLACK)
467  pixcmapAddColor(cmap, 0, 0, 0);
468  else /* L_SET_WHITE */
469  pixcmapAddColor(cmap, 255, 255, 255);
470  return pix;
471 }
472 
473 
494 PIX *
495 pixCreateHeader(l_int32 width,
496  l_int32 height,
497  l_int32 depth)
498 {
499 l_int32 wpl;
500 l_uint64 wpl64, bignum;
501 PIX *pixd;
502 
503  if ((depth != 1) && (depth != 2) && (depth != 4) && (depth != 8)
504  && (depth != 16) && (depth != 24) && (depth != 32))
505  return (PIX *)ERROR_PTR("depth must be {1, 2, 4, 8, 16, 24, 32}",
506  __func__, NULL);
507  if (width <= 0)
508  return (PIX *)ERROR_PTR("width must be > 0", __func__, NULL);
509  if (height <= 0)
510  return (PIX *)ERROR_PTR("height must be > 0", __func__, NULL);
511 
512  /* Avoid overflow in malloc, malicious or otherwise */
513  wpl64 = ((l_uint64)width * (l_uint64)depth + 31) / 32;
514  if (wpl64 > ((1LL << 24) - 1)) {
515  L_ERROR("requested w = %d, h = %d, d = %d\n",
516  __func__, width, height, depth);
517  return (PIX *)ERROR_PTR("wpl >= 2^24", __func__, NULL);
518  }
519  wpl = (l_int32)wpl64;
520  bignum = 4LL * wpl * height; /* number of bytes to be requested */
521  if (bignum > ((1LL << 31) - 1)) {
522  L_ERROR("requested w = %d, h = %d, d = %d\n",
523  __func__, width, height, depth);
524  return (PIX *)ERROR_PTR("requested bytes >= 2^31", __func__, NULL);
525  }
526 
527 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
528  if (bignum > (1LL << 26)) {
529  L_ERROR("fuzzer requested > 64 MB; refused\n", __func__);
530  return NULL;
531  }
532  if (width > 20000) {
533  L_ERROR("fuzzer requested width > 20K; refused\n", __func__);
534  return NULL;
535  }
536  if (height > 20000) {
537  L_ERROR("fuzzer requested height > 20K; refused\n", __func__);
538  return NULL;
539  }
540 #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
541 
542  pixd = (PIX *)LEPT_CALLOC(1, sizeof(PIX));
543  pixSetWidth(pixd, width);
544  pixSetHeight(pixd, height);
545  pixSetDepth(pixd, depth);
546  pixSetWpl(pixd, wpl);
547  if (depth == 24 || depth == 32)
548  pixSetSpp(pixd, 3);
549  else
550  pixSetSpp(pixd, 1);
551  pixd->refcount = 1;
552  pixd->informat = IFF_UNKNOWN;
553  return pixd;
554 }
555 
556 
581 PIX *
582 pixClone(PIX *pixs)
583 {
584  if (!pixs)
585  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
586  ++pixs->refcount;
587 
588  return pixs;
589 }
590 
591 
592 /*--------------------------------------------------------------------*
593  * Pix Destruction *
594  *--------------------------------------------------------------------*/
607 void
609 {
610 PIX *pix;
611 
612  if (!ppix) {
613  L_WARNING("ptr address is null!\n", __func__);
614  return;
615  }
616 
617  if ((pix = *ppix) == NULL)
618  return;
619  pixFree(pix);
620  *ppix = NULL;
621 }
622 
623 
635 static void
637 {
638 l_uint32 *data;
639 char *text;
640 
641  if (!pix) return;
642 
643  if (--pix->refcount == 0) {
644  if ((data = pixGetData(pix)) != NULL)
645  pixdata_free(data);
646  if ((text = pixGetText(pix)) != NULL)
647  LEPT_FREE(text);
648  pixDestroyColormap(pix);
649  LEPT_FREE(pix);
650  }
651  return;
652 }
653 
654 
655 /*-------------------------------------------------------------------------*
656  * Pix Copy *
657  *-------------------------------------------------------------------------*/
688 PIX *
689 pixCopy(PIX *pixd, /* can be null */
690  const PIX *pixs)
691 {
692 l_int32 bytes;
693 
694  if (!pixs)
695  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
696  if (pixs == pixd)
697  return pixd;
698 
699  /* Total bytes in image data */
700  bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
701 
702  /* If we're making a new pix ... */
703  if (!pixd) {
704  if ((pixd = pixCreateTemplate(pixs)) == NULL)
705  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
706  memcpy(pixd->data, pixs->data, bytes);
707  return pixd;
708  }
709 
710  /* Reallocate image data if sizes are different. If this fails,
711  * pixd hasn't been changed. But we want to signal that the copy
712  * failed, so return NULL. This will cause a memory leak if the
713  * return ptr is assigned to pixd, but that is preferred to proceeding
714  * with an incorrect pixd, and in any event this use case of
715  * pixCopy() -- reallocating into an existing pix -- is infrequent. */
716  if (pixResizeImageData(pixd, pixs) == 1)
717  return (PIX *)ERROR_PTR("reallocation of data failed", __func__, NULL);
718 
719  /* Copy non-image data fields */
720  pixCopyColormap(pixd, pixs);
721  pixCopySpp(pixd, pixs);
722  pixCopyResolution(pixd, pixs);
723  pixCopyInputFormat(pixd, pixs);
724  pixCopyText(pixd, pixs);
725 
726  /* Copy image data */
727  memcpy(pixd->data, pixs->data, bytes);
728  return pixd;
729 }
730 
731 
749 l_ok
751  const PIX *pixs)
752 {
753 l_int32 w, h, d, wpl, bytes;
754 l_uint32 *data;
755 
756  if (!pixs)
757  return ERROR_INT("pixs not defined", __func__, 1);
758  if (!pixd)
759  return ERROR_INT("pixd not defined", __func__, 1);
760 
761  if (pixSizesEqual(pixs, pixd)) /* nothing to do */
762  return 0;
763 
764  /* Make sure we can copy the data */
765  pixGetDimensions(pixs, &w, &h, &d);
766  wpl = pixGetWpl(pixs);
767  bytes = 4 * wpl * h;
768  if ((data = (l_uint32 *)pixdata_malloc(bytes)) == NULL)
769  return ERROR_INT("pixdata_malloc fail for data", __func__, 1);
770 
771  /* OK, do it */
772  pixSetWidth(pixd, w);
773  pixSetHeight(pixd, h);
774  pixSetDepth(pixd, d);
775  pixSetWpl(pixd, wpl);
776  pixFreeAndSetData(pixd, data); /* free old data and assign new data */
777  pixCopyResolution(pixd, pixs);
778  return 0;
779 }
780 
781 
794 l_ok
796  const PIX *pixs)
797 {
798 l_int32 valid;
799 const PIXCMAP *cmaps;
800 PIXCMAP *cmapd;
801 
802  if (!pixs)
803  return ERROR_INT("pixs not defined", __func__, 1);
804  if (!pixd)
805  return ERROR_INT("pixd not defined", __func__, 1);
806  if (pixs == pixd)
807  return 0; /* no-op */
808  if (pixGetDepth(pixs) != pixGetDepth(pixd))
809  return ERROR_INT("depths of pixs and pixd differ", __func__, 1);
810 
811  pixDestroyColormap(pixd);
812  if ((cmaps = pixs->colormap) == NULL) /* not an error */
813  return 0;
814  pixcmapIsValid(cmaps, NULL, &valid);
815  if (!valid)
816  return ERROR_INT("cmap not valid", __func__, 1);
817 
818  if ((cmapd = pixcmapCopy(cmaps)) == NULL)
819  return ERROR_INT("cmapd not made", __func__, 1);
820  pixSetColormap(pixd, cmapd);
821  return 0;
822 }
823 
824 
878 l_ok
880  PIX **ppixs,
881  l_int32 copytext,
882  l_int32 copyformat)
883 {
884 l_int32 nbytes;
885 PIX *pixs;
886 
887  if (!ppixs)
888  return ERROR_INT("&pixs not defined", __func__, 1);
889  if ((pixs = *ppixs) == NULL)
890  return ERROR_INT("pixs not defined", __func__, 1);
891  if (!pixd)
892  return ERROR_INT("pixd not defined", __func__, 1);
893  if (pixs == pixd) /* no-op */
894  return ERROR_INT("pixd == pixs", __func__, 1);
895 
896  if (pixs->refcount == 1) { /* transfer the data, cmap, text */
897  pixFreeData(pixd); /* dealloc any existing data */
898  pixSetData(pixd, pixGetData(pixs)); /* transfer new data from pixs */
899  pixs->data = NULL; /* pixs no longer owns data */
900  pixDestroyColormap(pixd); /* free the old one, if it exists */
901  pixd->colormap = pixGetColormap(pixs); /* transfer to pixd */
902  pixs->colormap = NULL; /* pixs no longer owns colormap */
903  if (copytext) {
904  pixSetText(pixd, pixGetText(pixs));
905  pixSetText(pixs, NULL);
906  }
907  } else { /* preserve pixs by making a copy of the data, cmap, text */
908  pixResizeImageData(pixd, pixs);
909  nbytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
910  memcpy(pixGetData(pixd), pixGetData(pixs), nbytes);
911  pixCopyColormap(pixd, pixs);
912  if (copytext)
913  pixCopyText(pixd, pixs);
914  }
915 
916  pixCopySpp(pixd, pixs);
917  pixCopyResolution(pixd, pixs);
918  pixCopyDimensions(pixd, pixs);
919  if (copyformat)
920  pixCopyInputFormat(pixd, pixs);
921 
922  /* This will destroy pixs if data was transferred;
923  * otherwise, it just decrements its refcount. */
924  pixDestroy(ppixs);
925  return 0;
926 }
927 
928 
967 l_ok
969  PIX **ppixs)
970 {
971  if (!ppixd)
972  return ERROR_INT("&pixd not defined", __func__, 1);
973  if (!ppixs)
974  return ERROR_INT("&pixs not defined", __func__, 1);
975  if (*ppixs == NULL)
976  return ERROR_INT("pixs not defined", __func__, 1);
977  if (ppixs == ppixd) /* no-op */
978  return ERROR_INT("&pixd == &pixs", __func__, 1);
979 
980  pixDestroy(ppixd);
981  *ppixd = pixClone(*ppixs);
982  pixDestroy(ppixs);
983  return 0;
984 }
985 
986 
987 /*--------------------------------------------------------------------*
988  * Pix Accessors *
989  *--------------------------------------------------------------------*/
990 l_int32
991 pixGetWidth(const PIX *pix)
992 {
993  if (!pix)
994  return ERROR_INT("pix not defined", __func__, 0);
995 
996  return pix->w;
997 }
998 
999 
1000 l_int32
1001 pixSetWidth(PIX *pix,
1002  l_int32 width)
1003 {
1004  if (!pix)
1005  return ERROR_INT("pix not defined", __func__, 1);
1006  if (width < 0) {
1007  pix->w = 0;
1008  return ERROR_INT("width must be >= 0", __func__, 1);
1009  }
1010 
1011  pix->w = width;
1012  return 0;
1013 }
1014 
1015 
1016 l_int32
1017 pixGetHeight(const PIX *pix)
1018 {
1019  if (!pix)
1020  return ERROR_INT("pix not defined", __func__, 0);
1021 
1022  return pix->h;
1023 }
1024 
1025 
1026 l_int32
1027 pixSetHeight(PIX *pix,
1028  l_int32 height)
1029 {
1030  if (!pix)
1031  return ERROR_INT("pix not defined", __func__, 1);
1032  if (height < 0) {
1033  pix->h = 0;
1034  return ERROR_INT("h must be >= 0", __func__, 1);
1035  }
1036 
1037  pix->h = height;
1038  return 0;
1039 }
1040 
1041 
1042 l_int32
1043 pixGetDepth(const PIX *pix)
1044 {
1045  if (!pix)
1046  return ERROR_INT("pix not defined", __func__, 0);
1047 
1048  return pix->d;
1049 }
1050 
1051 
1052 l_int32
1053 pixSetDepth(PIX *pix,
1054  l_int32 depth)
1055 {
1056  if (!pix)
1057  return ERROR_INT("pix not defined", __func__, 1);
1058  if (depth < 1)
1059  return ERROR_INT("d must be >= 1", __func__, 1);
1060 
1061  pix->d = depth;
1062  return 0;
1063 }
1064 
1065 
1073 l_ok
1075  l_int32 *pw,
1076  l_int32 *ph,
1077  l_int32 *pd)
1078 {
1079  if (pw) *pw = 0;
1080  if (ph) *ph = 0;
1081  if (pd) *pd = 0;
1082  if (!pix)
1083  return ERROR_INT("pix not defined", __func__, 1);
1084  if (pw) *pw = pix->w;
1085  if (ph) *ph = pix->h;
1086  if (pd) *pd = pix->d;
1087  return 0;
1088 }
1089 
1090 
1098 l_ok
1100  l_int32 w,
1101  l_int32 h,
1102  l_int32 d)
1103 {
1104  if (!pix)
1105  return ERROR_INT("pix not defined", __func__, 1);
1106  if (w > 0) pixSetWidth(pix, w);
1107  if (h > 0) pixSetHeight(pix, h);
1108  if (d > 0) pixSetDepth(pix, d);
1109  return 0;
1110 }
1111 
1112 
1120 l_ok
1122  const PIX *pixs)
1123 {
1124  if (!pixd)
1125  return ERROR_INT("pixd not defined", __func__, 1);
1126  if (!pixs)
1127  return ERROR_INT("pixs not defined", __func__, 1);
1128  if (pixs == pixd)
1129  return 0; /* no-op */
1130 
1131  pixSetWidth(pixd, pixGetWidth(pixs));
1132  pixSetHeight(pixd, pixGetHeight(pixs));
1133  pixSetDepth(pixd, pixGetDepth(pixs));
1134  pixSetWpl(pixd, pixGetWpl(pixs));
1135  return 0;
1136 }
1137 
1138 
1139 l_int32
1140 pixGetSpp(const PIX *pix)
1141 {
1142  if (!pix)
1143  return ERROR_INT("pix not defined", __func__, 0);
1144 
1145  return pix->spp;
1146 }
1147 
1148 
1149 /*
1150  * \brief pixSetSpp()
1151  *
1152  * \param[in] pix
1153  * \param[in] spp 1, 3 or 4 samples
1154  * \return 0 if OK, 1 on error
1155  *
1156  * <pre>
1157  * Notes:
1158  * (1) For a 32 bpp pix, this can be used to ignore the
1159  * alpha sample (spp == 3) or to use it (spp == 4).
1160  * For example, to write a spp == 4 image without the alpha
1161  * sample (as an rgb pix), call pixSetSpp(pix, 3) and
1162  * then write it out as a png.
1163  * </pre>
1164  */
1165 l_int32
1166 pixSetSpp(PIX *pix,
1167  l_int32 spp)
1168 {
1169  if (!pix)
1170  return ERROR_INT("pix not defined", __func__, 1);
1171  if (spp < 1)
1172  return ERROR_INT("spp must be >= 1", __func__, 1);
1173 
1174  pix->spp = spp;
1175  return 0;
1176 }
1177 
1178 
1186 l_ok
1188  const PIX *pixs)
1189 {
1190  if (!pixd)
1191  return ERROR_INT("pixd not defined", __func__, 1);
1192  if (!pixs)
1193  return ERROR_INT("pixs not defined", __func__, 1);
1194  if (pixs == pixd)
1195  return 0; /* no-op */
1196 
1197  pixSetSpp(pixd, pixGetSpp(pixs));
1198  return 0;
1199 }
1200 
1201 
1202 l_int32
1203 pixGetWpl(const PIX *pix)
1204 {
1205  if (!pix)
1206  return ERROR_INT("pix not defined", __func__, 0);
1207  return pix->wpl;
1208 }
1209 
1210 
1211 l_int32
1212 pixSetWpl(PIX *pix,
1213  l_int32 wpl)
1214 {
1215  if (!pix)
1216  return ERROR_INT("pix not defined", __func__, 1);
1217 
1218  pix->wpl = wpl;
1219  return 0;
1220 }
1221 
1222 
1223 l_int32
1224 pixGetXRes(const PIX *pix)
1225 {
1226  if (!pix)
1227  return ERROR_INT("pix not defined", __func__, 0);
1228  return pix->xres;
1229 }
1230 
1231 
1232 l_int32
1233 pixSetXRes(PIX *pix,
1234  l_int32 res)
1235 {
1236  if (!pix)
1237  return ERROR_INT("pix not defined", __func__, 1);
1238 
1239  pix->xres = res;
1240  return 0;
1241 }
1242 
1243 
1244 l_int32
1245 pixGetYRes(const PIX *pix)
1246 {
1247  if (!pix)
1248  return ERROR_INT("pix not defined", __func__, 0);
1249  return pix->yres;
1250 }
1251 
1252 
1253 l_int32
1254 pixSetYRes(PIX *pix,
1255  l_int32 res)
1256 {
1257  if (!pix)
1258  return ERROR_INT("pix not defined", __func__, 1);
1259 
1260  pix->yres = res;
1261  return 0;
1262 }
1263 
1264 
1272 l_ok
1274  l_int32 *pxres,
1275  l_int32 *pyres)
1276 {
1277  if (pxres) *pxres = 0;
1278  if (pyres) *pyres = 0;
1279  if (!pxres && !pyres)
1280  return ERROR_INT("no output requested", __func__, 1);
1281  if (!pix)
1282  return ERROR_INT("pix not defined", __func__, 1);
1283  if (pxres) *pxres = pix->xres;
1284  if (pyres) *pyres = pix->yres;
1285  return 0;
1286 }
1287 
1288 
1296 l_ok
1298  l_int32 xres,
1299  l_int32 yres)
1300 {
1301  if (!pix)
1302  return ERROR_INT("pix not defined", __func__, 1);
1303  if (xres > 0) pix->xres = xres;
1304  if (yres > 0) pix->yres = yres;
1305  return 0;
1306 }
1307 
1308 
1309 l_int32
1310 pixCopyResolution(PIX *pixd,
1311  const PIX *pixs)
1312 {
1313  if (!pixs)
1314  return ERROR_INT("pixs not defined", __func__, 1);
1315  if (!pixd)
1316  return ERROR_INT("pixd not defined", __func__, 1);
1317  if (pixs == pixd)
1318  return 0; /* no-op */
1319 
1320  pixSetXRes(pixd, pixGetXRes(pixs));
1321  pixSetYRes(pixd, pixGetYRes(pixs));
1322  return 0;
1323 }
1324 
1325 
1326 l_int32
1327 pixScaleResolution(PIX *pix,
1328  l_float32 xscale,
1329  l_float32 yscale)
1330 {
1331 l_float64 xres, yres;
1332 l_float64 maxres = 100000000.0;
1333 
1334  if (!pix)
1335  return ERROR_INT("pix not defined", __func__, 1);
1336  if (xscale <= 0 || yscale <= 0)
1337  return ERROR_INT("invalid scaling ratio", __func__, 1);
1338 
1339  xres = (l_float64)xscale * (l_float32)(pix->xres) + 0.5;
1340  yres = (l_float64)yscale * (l_float32)(pix->yres) + 0.5;
1341  pix->xres = (l_uint32)L_MIN(xres, maxres);
1342  pix->yres = (l_uint32)L_MIN(yres, maxres);
1343  return 0;
1344 }
1345 
1346 
1347 l_int32
1348 pixGetInputFormat(const PIX *pix)
1349 {
1350  if (!pix)
1351  return ERROR_INT("pix not defined", __func__, 0);
1352  return pix->informat;
1353 }
1354 
1355 
1356 l_int32
1357 pixSetInputFormat(PIX *pix,
1358  l_int32 informat)
1359 {
1360  if (!pix)
1361  return ERROR_INT("pix not defined", __func__, 1);
1362  pix->informat = informat;
1363  return 0;
1364 }
1365 
1366 
1367 l_int32
1368 pixCopyInputFormat(PIX *pixd,
1369  const PIX *pixs)
1370 {
1371  if (!pixs)
1372  return ERROR_INT("pixs not defined", __func__, 1);
1373  if (!pixd)
1374  return ERROR_INT("pixd not defined", __func__, 1);
1375  if (pixs == pixd)
1376  return 0; /* no-op */
1377 
1378  pixSetInputFormat(pixd, pixGetInputFormat(pixs));
1379  return 0;
1380 }
1381 
1382 
1383 l_int32
1384 pixSetSpecial(PIX *pix,
1385  l_int32 special)
1386 {
1387  if (!pix)
1388  return ERROR_INT("pix not defined", __func__, 1);
1389  pix->special = special;
1390  return 0;
1391 }
1392 
1393 
1407 char *
1409 {
1410  if (!pix)
1411  return (char *)ERROR_PTR("pix not defined", __func__, NULL);
1412  return pix->text;
1413 }
1414 
1415 
1429 l_ok
1431  const char *textstring)
1432 {
1433  if (!pix)
1434  return ERROR_INT("pix not defined", __func__, 1);
1435 
1436  stringReplace(&pix->text, textstring);
1437  return 0;
1438 }
1439 
1440 
1455 l_ok
1457  const char *textstring)
1458 {
1459 char *newstring;
1460 
1461  if (!pix)
1462  return ERROR_INT("pix not defined", __func__, 1);
1463 
1464  newstring = stringJoin(pixGetText(pix), textstring);
1465  stringReplace(&pix->text, newstring);
1466  LEPT_FREE(newstring);
1467  return 0;
1468 }
1469 
1470 
1471 l_int32
1472 pixCopyText(PIX *pixd,
1473  const PIX *pixs)
1474 {
1475  if (!pixs)
1476  return ERROR_INT("pixs not defined", __func__, 1);
1477  if (!pixd)
1478  return ERROR_INT("pixd not defined", __func__, 1);
1479  if (pixs == pixd)
1480  return 0; /* no-op */
1481 
1482  pixSetText(pixd, pixs->text);
1483  return 0;
1484 }
1485 
1486 
1504 l_uint8 *
1506  size_t *psize)
1507 {
1508 char *str;
1509 
1510  if (!pix)
1511  return (l_uint8 *)ERROR_PTR("pix not defined", __func__, NULL);
1512  str = pixGetText(pix);
1513  return decodeAscii85WithComp(str, strlen(str), psize);
1514 }
1515 
1516 
1533 l_ok
1535  const l_uint8 *data,
1536  size_t size)
1537 {
1538 size_t encodesize; /* ignored */
1539 
1540  if (!pix)
1541  return ERROR_INT("pix not defined", __func__, 1);
1542 
1543  LEPT_FREE(pix->text);
1544  pix->text = encodeAscii85WithComp(data, size, &encodesize);
1545  return 0;
1546 }
1547 
1548 
1549 PIXCMAP *
1550 pixGetColormap(PIX *pix)
1551 {
1552  if (!pix)
1553  return (PIXCMAP *)ERROR_PTR("pix not defined", __func__, NULL);
1554  return pix->colormap;
1555 }
1556 
1557 
1581 l_ok
1583  PIXCMAP *colormap)
1584 {
1585 l_int32 valid;
1586 
1587  if (!pix)
1588  return ERROR_INT("pix not defined", __func__, 1);
1589  if (!colormap) return 0;
1590 
1591  /* Make sure the colormap doesn't get lost */
1592  pixDestroyColormap(pix);
1593  pix->colormap = colormap;
1594 
1595  pixcmapIsValid(colormap, NULL, &valid);
1596  if (!valid)
1597  return ERROR_INT("colormap is not valid", __func__, 1);
1598  return 0;
1599 }
1600 
1601 
1608 l_ok
1610 {
1611 PIXCMAP *cmap;
1612 
1613  if (!pix)
1614  return ERROR_INT("pix not defined", __func__, 1);
1615 
1616  if ((cmap = pix->colormap) != NULL) {
1617  pixcmapDestroy(&cmap);
1618  pix->colormap = NULL;
1619  }
1620  return 0;
1621 }
1622 
1623 
1641 l_uint32 *
1643 {
1644  if (!pix)
1645  return (l_uint32 *)ERROR_PTR("pix not defined", __func__, NULL);
1646  return pix->data;
1647 }
1648 
1649 
1662 l_int32
1664  l_uint32 *data)
1665 {
1666  if (!pix)
1667  return ERROR_INT("pix not defined", __func__, 1);
1668 
1669  pixFreeData(pix);
1670  pix->data = data;
1671  return 0;
1672 }
1673 
1674 
1688 l_int32
1690  l_uint32 *data)
1691 {
1692  if (!pix)
1693  return ERROR_INT("pix not defined", __func__, 1);
1694 
1695  pix->data = data;
1696  return 0;
1697 }
1698 
1699 
1714 l_int32
1716 {
1717 l_uint32 *data;
1718 
1719  if (!pix)
1720  return ERROR_INT("pix not defined", __func__, 1);
1721 
1722  if ((data = pixGetData(pix)) != NULL) {
1723  pixdata_free(data);
1724  pix->data = NULL;
1725  }
1726  return 0;
1727 }
1728 
1729 
1746 l_uint32 *
1748 {
1749 l_int32 bytes;
1750 l_uint32 *data, *datas;
1751 
1752  if (!pixs)
1753  return (l_uint32 *)ERROR_PTR("pixs not defined", __func__, NULL);
1754 
1755  if (pixs->refcount == 1) { /* extract */
1756  data = pixGetData(pixs);
1757  pixSetData(pixs, NULL);
1758  } else { /* refcount > 1; copy */
1759  bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
1760  datas = pixGetData(pixs);
1761  if ((data = (l_uint32 *)pixdata_malloc(bytes)) == NULL)
1762  return (l_uint32 *)ERROR_PTR("data not made", __func__, NULL);
1763  memcpy(data, datas, bytes);
1764  }
1765 
1766  return data;
1767 }
1768 
1769 
1770 /*--------------------------------------------------------------------*
1771  * Pix line ptrs *
1772  *--------------------------------------------------------------------*/
1843 void **
1845  l_int32 *psize)
1846 {
1847 l_int32 i, h, wpl;
1848 l_uint32 *data;
1849 void **lines;
1850 
1851  if (psize) *psize = 0;
1852  if (!pix)
1853  return (void **)ERROR_PTR("pix not defined", __func__, NULL);
1854 
1855  h = pixGetHeight(pix);
1856  if (psize) *psize = h;
1857  if ((lines = (void **)LEPT_CALLOC(h, sizeof(void *))) == NULL)
1858  return (void **)ERROR_PTR("lines not made", __func__, NULL);
1859  wpl = pixGetWpl(pix);
1860  data = pixGetData(pix);
1861  for (i = 0; i < h; i++)
1862  lines[i] = (void *)(data + i * wpl);
1863 
1864  return lines;
1865 }
1866 
1867 
1868 /*--------------------------------------------------------------------*
1869  * Pix Size Comparisons *
1870  *--------------------------------------------------------------------*/
1877 l_int32
1878 pixSizesEqual(const PIX *pix1,
1879  const PIX *pix2)
1880 {
1881  if (!pix1 || !pix2)
1882  return ERROR_INT("pix1 and pix2 not both defined", __func__, 0);
1883 
1884  if (pix1 == pix2)
1885  return 1;
1886 
1887  if ((pixGetWidth(pix1) != pixGetWidth(pix2)) ||
1888  (pixGetHeight(pix1) != pixGetHeight(pix2)) ||
1889  (pixGetDepth(pix1) != pixGetDepth(pix2)))
1890  return 0;
1891  else
1892  return 1;
1893 }
1894 
1895 
1903 l_ok
1905  l_float32 *pratio)
1906 {
1907 l_int32 w, h;
1908 
1909  if (!pratio)
1910  return ERROR_INT("&ratio not defined", __func__, 1);
1911  *pratio = -1.0;
1912  if (!pixs)
1913  return ERROR_INT("pixs not defined", __func__, 1);
1914  pixGetDimensions(pixs, &w, &h, NULL);
1915  if (w == 0 || h == 0) {
1916  L_ERROR("invalid size: w = %d, h = %d\n", __func__, w, h);
1917  return 1;
1918  }
1919 
1920  *pratio = L_MAX((l_float32)h / (l_float32)w, (l_float32)w / (l_float32)h);
1921  return 0;
1922 }
1923 
1924 
1925 /*--------------------------------------------------------------------*
1926  * Print output for debugging *
1927  *--------------------------------------------------------------------*/
1928 extern const char *ImageFileFormatExtensions[];
1929 
1938 l_ok
1940  const PIX *pix,
1941  const char *text)
1942 {
1943 l_int32 informat;
1944 const PIXCMAP *cmap;
1945 
1946  if (!fp)
1947  return ERROR_INT("fp not defined", __func__, 1);
1948  if (!pix)
1949  return ERROR_INT("pix not defined", __func__, 1);
1950 
1951  if (text)
1952  fprintf(fp, " Pix Info for %s:\n", text);
1953  fprintf(fp, " width = %d, height = %d, depth = %d, spp = %d\n",
1954  pixGetWidth(pix), pixGetHeight(pix), pixGetDepth(pix),
1955  pixGetSpp(pix));
1956  fprintf(fp, " wpl = %d, data = %p, refcount = %d\n",
1957  pixGetWpl(pix), pix->data, pix->refcount);
1958  fprintf(fp, " xres = %d, yres = %d\n", pixGetXRes(pix), pixGetYRes(pix));
1959  if ((cmap = pix->colormap) != NULL)
1960  pixcmapWriteStream(fp, cmap);
1961  else
1962  fprintf(fp, " no colormap\n");
1963  informat = pixGetInputFormat(pix);
1964  fprintf(fp, " input format: %d (%s)\n", informat,
1965  ImageFileFormatExtensions[informat]);
1966  if (pix->text != NULL)
1967  fprintf(fp, " text: %s\n", pix->text);
1968 
1969  return 0;
1970 }
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
Definition: colormap.c:272
l_ok pixcmapIsValid(const PIXCMAP *cmap, PIX *pix, l_int32 *pvalid)
pixcmapIsValid()
Definition: colormap.c:308
l_ok pixcmapWriteStream(FILE *fp, const PIXCMAP *cmap)
pixcmapWriteStream()
Definition: colormap.c:1882
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:126
PIXCMAP * pixcmapCopy(const PIXCMAP *cmaps)
pixcmapCopy()
Definition: colormap.c:243
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:403
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1642
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1582
l_ok pixResizeImageData(PIX *pixd, const PIX *pixs)
pixResizeImageData()
Definition: pix1.c:750
l_ok pixSetResolution(PIX *pix, l_int32 xres, l_int32 yres)
pixSetResolution()
Definition: pix1.c:1297
l_ok pixDestroyColormap(PIX *pix)
pixDestroyColormap()
Definition: pix1.c:1609
void setPixMemoryManager(alloc_fn allocator, dealloc_fn deallocator)
setPixMemoryManager()
Definition: pix1.c:296
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_uint32 * pixExtractData(PIX *pixs)
pixExtractData()
Definition: pix1.c:1747
l_int32 pixFreeData(PIX *pix)
pixFreeData()
Definition: pix1.c:1715
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
l_int32 pixSizesEqual(const PIX *pix1, const PIX *pix2)
pixSizesEqual()
Definition: pix1.c:1878
l_ok pixSetDimensions(PIX *pix, l_int32 w, l_int32 h, l_int32 d)
pixSetDimensions()
Definition: pix1.c:1099
static struct PixMemoryManager pix_mem_manager
Definition: pix1.c:236
PIX * pixCreateHeader(l_int32 width, l_int32 height, l_int32 depth)
pixCreateHeader()
Definition: pix1.c:495
l_ok pixCopyDimensions(PIX *pixd, const PIX *pixs)
pixCopyDimensions()
Definition: pix1.c:1121
char * pixGetText(PIX *pix)
pixGetText()
Definition: pix1.c:1408
l_ok pixSetText(PIX *pix, const char *textstring)
pixSetText()
Definition: pix1.c:1430
l_ok pixCopySpp(PIX *pixd, const PIX *pixs)
pixCopySpp()
Definition: pix1.c:1187
l_ok pixGetResolution(const PIX *pix, l_int32 *pxres, l_int32 *pyres)
pixGetResolution()
Definition: pix1.c:1273
l_ok pixSetTextCompNew(PIX *pix, const l_uint8 *data, size_t size)
pixSetTextCompNew()
Definition: pix1.c:1534
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:689
l_ok pixSwapAndDestroy(PIX **ppixd, PIX **ppixs)
pixSwapAndDestroy()
Definition: pix1.c:968
l_ok pixTransferAllData(PIX *pixd, PIX **ppixs, l_int32 copytext, l_int32 copyformat)
pixTransferAllData()
Definition: pix1.c:879
static void pixFree(PIX *pix)
pixFree()
Definition: pix1.c:636
l_int32 pixSetData(PIX *pix, l_uint32 *data)
pixSetData()
Definition: pix1.c:1689
l_uint8 * pixGetTextCompNew(PIX *pix, size_t *psize)
pixGetTextCompNew()
Definition: pix1.c:1505
PIX * pixCreateTemplateNoInit(const PIX *pixs)
pixCreateTemplateNoInit()
Definition: pix1.c:412
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:380
l_int32 pixFreeAndSetData(PIX *pix, l_uint32 *data)
pixFreeAndSetData()
Definition: pix1.c:1663
l_ok pixAddText(PIX *pix, const char *textstring)
pixAddText()
Definition: pix1.c:1456
l_ok pixPrintStreamInfo(FILE *fp, const PIX *pix, const char *text)
pixPrintStreamInfo()
Definition: pix1.c:1939
l_ok pixMaxAspectRatio(PIX *pixs, l_float32 *pratio)
pixMaxAspectRatio()
Definition: pix1.c:1904
PIX * pixCreateNoInit(l_int32 width, l_int32 height, l_int32 depth)
pixCreateNoInit()
Definition: pix1.c:344
l_ok pixCopyColormap(PIX *pixd, const PIX *pixs)
pixCopyColormap()
Definition: pix1.c:795
PIX * pixCreateWithCmap(l_int32 width, l_int32 height, l_int32 depth, l_int32 initcolor)
pixCreateWithCmap()
Definition: pix1.c:451
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
void ** pixGetLinePtrs(PIX *pix, l_int32 *psize)
pixGetLinePtrs()
Definition: pix1.c:1844
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
Definition: pix2.c:1346
void(* dealloc_fn)(void *)
Definition: pix.h:1092
@ L_SET_BLACK
Definition: pix.h:700
void *(* alloc_fn)(size_t)
Definition: pix.h:1089
l_uint32 d
Definition: pix_internal.h:184
l_uint32 * data
Definition: pix_internal.h:196
l_uint32 spp
Definition: pix_internal.h:185
struct PixColormap * colormap
Definition: pix_internal.h:195
l_atomic refcount
Definition: pix_internal.h:187
l_uint32 wpl
Definition: pix_internal.h:186
l_uint32 w
Definition: pix_internal.h:182
l_int32 xres
Definition: pix_internal.h:188
l_uint32 h
Definition: pix_internal.h:183
l_int32 yres
Definition: pix_internal.h:190
char * text
Definition: pix_internal.h:194
l_int32 special
Definition: pix_internal.h:193
l_int32 informat
Definition: pix_internal.h:192
l_ok stringReplace(char **pdest, const char *src)
stringReplace()
Definition: utils2.c:339
char * stringJoin(const char *src1, const char *src2)
stringJoin()
Definition: utils2.c:506