Leptonica 1.82.0
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
198#ifdef HAVE_CONFIG_H
199#include <config_auto.h>
200#endif /* HAVE_CONFIG_H */
201
202#include <string.h>
203#include "allheaders.h"
204
205static 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
237#ifdef LEPTONICA_INTERCEPT_ALLOC
238 &leptonica_malloc,
239 &leptonica_free
240#else
241 &malloc,
242 &free
243#endif /* LEPTONICA_INTERCEPT_ALLOC */
244};
245
246static void *
247pixdata_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
258static void
259pixdata_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
295void
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 *--------------------------------------------------------------------*/
314PIX *
315pixCreate(l_int32 width,
316 l_int32 height,
317 l_int32 depth)
318{
319PIX *pixd;
320
321 PROCNAME("pixCreate");
322
323 if ((pixd = pixCreateNoInit(width, height, depth)) == NULL)
324 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
325 memset(pixd->data, 0, 4LL * pixd->wpl * pixd->h);
326 return pixd;
327}
328
329
345PIX *
346pixCreateNoInit(l_int32 width,
347 l_int32 height,
348 l_int32 depth)
349{
350l_int32 wpl;
351PIX *pixd;
352l_uint32 *data;
353
354 PROCNAME("pixCreateNoInit");
355 if ((pixd = pixCreateHeader(width, height, depth)) == NULL)
356 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
357 wpl = pixGetWpl(pixd);
358 if ((data = (l_uint32 *)pixdata_malloc(4LL * wpl * height)) == NULL) {
359 pixDestroy(&pixd);
360 return (PIX *)ERROR_PTR("pixdata_malloc fail for data",
361 procName, NULL);
362 }
363 pixSetData(pixd, data);
364 pixSetPadBits(pixd, 0);
365 return pixd;
366}
367
368
382PIX *
384{
385PIX *pixd;
386
387 PROCNAME("pixCreateTemplate");
388
389 if (!pixs)
390 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
391
392 if ((pixd = pixCreateTemplateNoInit(pixs)) == NULL)
393 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
394 memset(pixd->data, 0, 4LL * pixd->wpl * pixd->h);
395 return pixd;
396}
397
398
416PIX *
418{
419l_int32 w, h, d;
420PIX *pixd;
421
422 PROCNAME("pixCreateTemplateNoInit");
423
424 if (!pixs)
425 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
426
427 pixGetDimensions(pixs, &w, &h, &d);
428 if ((pixd = pixCreateNoInit(w, h, d)) == NULL)
429 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
430 pixCopySpp(pixd, pixs);
431 pixCopyResolution(pixd, pixs);
432 pixCopyColormap(pixd, pixs);
433 pixCopyText(pixd, pixs);
434 pixCopyInputFormat(pixd, pixs);
435 pixSetPadBits(pixd, 0);
436 return pixd;
437}
438
439
457PIX *
458pixCreateWithCmap(l_int32 width,
459 l_int32 height,
460 l_int32 depth,
461 l_int32 initcolor)
462{
463PIX *pix;
464PIXCMAP *cmap;
465
466 PROCNAME("pixCreateWithCmap");
467
468 if (depth != 2 && depth != 4 && depth != 8)
469 return (PIX *)ERROR_PTR("depth not 2, 4 or 8 bpp", procName, NULL);
470
471 if ((pix = pixCreate(width, height, depth)) == NULL)
472 return (PIX *)ERROR_PTR("pix not made", procName, NULL);
473 cmap = pixcmapCreate(depth);
474 pixSetColormap(pix, cmap);
475 if (initcolor == L_SET_BLACK)
476 pixcmapAddColor(cmap, 0, 0, 0);
477 else /* L_SET_WHITE */
478 pixcmapAddColor(cmap, 255, 255, 255);
479 return pix;
480}
481
482
503PIX *
504pixCreateHeader(l_int32 width,
505 l_int32 height,
506 l_int32 depth)
507{
508l_int32 wpl;
509l_uint64 wpl64, bignum;
510PIX *pixd;
511
512 PROCNAME("pixCreateHeader");
513
514 if ((depth != 1) && (depth != 2) && (depth != 4) && (depth != 8)
515 && (depth != 16) && (depth != 24) && (depth != 32))
516 return (PIX *)ERROR_PTR("depth must be {1, 2, 4, 8, 16, 24, 32}",
517 procName, NULL);
518 if (width <= 0)
519 return (PIX *)ERROR_PTR("width must be > 0", procName, NULL);
520 if (height <= 0)
521 return (PIX *)ERROR_PTR("height must be > 0", procName, NULL);
522
523 /* Avoid overflow in malloc, malicious or otherwise */
524 wpl64 = ((l_uint64)width * (l_uint64)depth + 31) / 32;
525 if (wpl64 > ((1LL << 24) - 1)) {
526 L_ERROR("requested w = %d, h = %d, d = %d\n",
527 procName, width, height, depth);
528 return (PIX *)ERROR_PTR("wpl >= 2^24", procName, NULL);
529 }
530 wpl = (l_int32)wpl64;
531 bignum = 4LL * wpl * height; /* number of bytes to be requested */
532 if (bignum > ((1LL << 31) - 1)) {
533 L_ERROR("requested w = %d, h = %d, d = %d\n",
534 procName, width, height, depth);
535 return (PIX *)ERROR_PTR("requested bytes >= 2^31", procName, NULL);
536 }
537
538#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
539 if (bignum > (1LL << 26)) {
540 L_ERROR("fuzzer requested > 64 MB; refused\n", procName);
541 return NULL;
542 }
543 if (width > 20000) {
544 L_ERROR("fuzzer requested width > 20K; refused\n", procName);
545 return NULL;
546 }
547 if (height > 20000) {
548 L_ERROR("fuzzer requested height > 20K; refused\n", procName);
549 return NULL;
550 }
551#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
552
553 pixd = (PIX *)LEPT_CALLOC(1, sizeof(PIX));
554 pixSetWidth(pixd, width);
555 pixSetHeight(pixd, height);
556 pixSetDepth(pixd, depth);
557 pixSetWpl(pixd, wpl);
558 if (depth == 24 || depth == 32)
559 pixSetSpp(pixd, 3);
560 else
561 pixSetSpp(pixd, 1);
562 pixd->refcount = 1;
563 pixd->informat = IFF_UNKNOWN;
564 return pixd;
565}
566
567
592PIX *
594{
595 PROCNAME("pixClone");
596
597 if (!pixs)
598 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
599 pixChangeRefcount(pixs, 1);
600
601 return pixs;
602}
603
604
605/*--------------------------------------------------------------------*
606 * Pix Destruction *
607 *--------------------------------------------------------------------*/
620void
622{
623PIX *pix;
624
625 PROCNAME("pixDestroy");
626
627 if (!ppix) {
628 L_WARNING("ptr address is null!\n", procName);
629 return;
630 }
631
632 if ((pix = *ppix) == NULL)
633 return;
634 pixFree(pix);
635 *ppix = NULL;
636}
637
638
650static void
652{
653l_uint32 *data;
654char *text;
655
656 if (!pix) return;
657
658 pixChangeRefcount(pix, -1);
659 if (pixGetRefcount(pix) <= 0) {
660 if ((data = pixGetData(pix)) != NULL)
661 pixdata_free(data);
662 if ((text = pixGetText(pix)) != NULL)
663 LEPT_FREE(text);
665 LEPT_FREE(pix);
666 }
667 return;
668}
669
670
671/*-------------------------------------------------------------------------*
672 * Pix Copy *
673 *-------------------------------------------------------------------------*/
704PIX *
705pixCopy(PIX *pixd, /* can be null */
706 const PIX *pixs)
707{
708l_int32 bytes;
709
710 PROCNAME("pixCopy");
711
712 if (!pixs)
713 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
714 if (pixs == pixd)
715 return pixd;
716
717 /* Total bytes in image data */
718 bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
719
720 /* If we're making a new pix ... */
721 if (!pixd) {
722 if ((pixd = pixCreateTemplate(pixs)) == NULL)
723 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
724 memcpy(pixd->data, pixs->data, bytes);
725 return pixd;
726 }
727
728 /* Reallocate image data if sizes are different. If this fails,
729 * pixd hasn't been changed. But we want to signal that the copy
730 * failed, so return NULL. This will cause a memory leak if the
731 * return ptr is assigned to pixd, but that is preferred to proceeding
732 * with an incorrect pixd, and in any event this use case of
733 * pixCopy() -- reallocating into an existing pix -- is infrequent. */
734 if (pixResizeImageData(pixd, pixs) == 1)
735 return (PIX *)ERROR_PTR("reallocation of data failed", procName, NULL);
736
737 /* Copy non-image data fields */
738 pixCopyColormap(pixd, pixs);
739 pixCopySpp(pixd, pixs);
740 pixCopyResolution(pixd, pixs);
741 pixCopyInputFormat(pixd, pixs);
742 pixCopyText(pixd, pixs);
743
744 /* Copy image data */
745 memcpy(pixd->data, pixs->data, bytes);
746 return pixd;
747}
748
749
767l_ok
769 const PIX *pixs)
770{
771l_int32 w, h, d, wpl, bytes;
772l_uint32 *data;
773
774 PROCNAME("pixResizeImageData");
775
776 if (!pixs)
777 return ERROR_INT("pixs not defined", procName, 1);
778 if (!pixd)
779 return ERROR_INT("pixd not defined", procName, 1);
780
781 if (pixSizesEqual(pixs, pixd)) /* nothing to do */
782 return 0;
783
784 /* Make sure we can copy the data */
785 pixGetDimensions(pixs, &w, &h, &d);
786 wpl = pixGetWpl(pixs);
787 bytes = 4 * wpl * h;
788 if ((data = (l_uint32 *)pixdata_malloc(bytes)) == NULL)
789 return ERROR_INT("pixdata_malloc fail for data", procName, 1);
790
791 /* OK, do it */
792 pixSetWidth(pixd, w);
793 pixSetHeight(pixd, h);
794 pixSetDepth(pixd, d);
795 pixSetWpl(pixd, wpl);
796 pixFreeData(pixd); /* free any existing image data */
797 pixSetData(pixd, data); /* set the uninitialized memory buffer */
798 pixCopyResolution(pixd, pixs);
799 return 0;
800}
801
802
815l_ok
817 const PIX *pixs)
818{
819l_int32 valid;
820const PIXCMAP *cmaps;
821PIXCMAP *cmapd;
822
823 PROCNAME("pixCopyColormap");
824
825 if (!pixs)
826 return ERROR_INT("pixs not defined", procName, 1);
827 if (!pixd)
828 return ERROR_INT("pixd not defined", procName, 1);
829 if (pixs == pixd)
830 return 0; /* no-op */
831 if (pixGetDepth(pixs) != pixGetDepth(pixd))
832 return ERROR_INT("depths of pixs and pixd differ", procName, 1);
833
834 pixDestroyColormap(pixd);
835 if ((cmaps = pixs->colormap) == NULL) /* not an error */
836 return 0;
837 pixcmapIsValid(cmaps, NULL, &valid);
838 if (!valid)
839 return ERROR_INT("cmap not valid", procName, 1);
840
841 if ((cmapd = pixcmapCopy(cmaps)) == NULL)
842 return ERROR_INT("cmapd not made", procName, 1);
843 pixSetColormap(pixd, cmapd);
844 return 0;
845}
846
847
901l_ok
903 PIX **ppixs,
904 l_int32 copytext,
905 l_int32 copyformat)
906{
907l_int32 nbytes;
908PIX *pixs;
909
910 PROCNAME("pixTransferAllData");
911
912 if (!ppixs)
913 return ERROR_INT("&pixs not defined", procName, 1);
914 if ((pixs = *ppixs) == NULL)
915 return ERROR_INT("pixs not defined", procName, 1);
916 if (!pixd)
917 return ERROR_INT("pixd not defined", procName, 1);
918 if (pixs == pixd) /* no-op */
919 return ERROR_INT("pixd == pixs", procName, 1);
920
921 if (pixGetRefcount(pixs) == 1) { /* transfer the data, cmap, text */
922 pixFreeData(pixd); /* dealloc any existing data */
923 pixSetData(pixd, pixGetData(pixs)); /* transfer new data from pixs */
924 pixs->data = NULL; /* pixs no longer owns data */
925 pixDestroyColormap(pixd); /* free the old one, if it exists */
926 pixd->colormap = pixGetColormap(pixs); /* transfer to pixd */
927 pixs->colormap = NULL; /* pixs no longer owns colormap */
928 if (copytext) {
929 pixSetText(pixd, pixGetText(pixs));
930 pixSetText(pixs, NULL);
931 }
932 } else { /* preserve pixs by making a copy of the data, cmap, text */
933 pixResizeImageData(pixd, pixs);
934 nbytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
935 memcpy(pixGetData(pixd), pixGetData(pixs), nbytes);
936 pixCopyColormap(pixd, pixs);
937 if (copytext)
938 pixCopyText(pixd, pixs);
939 }
940
941 pixCopySpp(pixd, pixs);
942 pixCopyResolution(pixd, pixs);
943 pixCopyDimensions(pixd, pixs);
944 if (copyformat)
945 pixCopyInputFormat(pixd, pixs);
946
947 /* This will destroy pixs if data was transferred;
948 * otherwise, it just decrements its refcount. */
949 pixDestroy(ppixs);
950 return 0;
951}
952
953
992l_ok
994 PIX **ppixs)
995{
996 PROCNAME("pixSwapAndDestroy");
997
998 if (!ppixd)
999 return ERROR_INT("&pixd not defined", procName, 1);
1000 if (!ppixs)
1001 return ERROR_INT("&pixs not defined", procName, 1);
1002 if (*ppixs == NULL)
1003 return ERROR_INT("pixs not defined", procName, 1);
1004 if (ppixs == ppixd) /* no-op */
1005 return ERROR_INT("&pixd == &pixs", procName, 1);
1006
1007 pixDestroy(ppixd);
1008 *ppixd = pixClone(*ppixs);
1009 pixDestroy(ppixs);
1010 return 0;
1011}
1012
1013
1014/*--------------------------------------------------------------------*
1015 * Pix Accessors *
1016 *--------------------------------------------------------------------*/
1017l_int32
1018pixGetWidth(const PIX *pix)
1019{
1020 PROCNAME("pixGetWidth");
1021
1022 if (!pix)
1023 return ERROR_INT("pix not defined", procName, 0);
1024
1025 return pix->w;
1026}
1027
1028
1029l_int32
1030pixSetWidth(PIX *pix,
1031 l_int32 width)
1032{
1033 PROCNAME("pixSetWidth");
1034
1035 if (!pix)
1036 return ERROR_INT("pix not defined", procName, 1);
1037 if (width < 0) {
1038 pix->w = 0;
1039 return ERROR_INT("width must be >= 0", procName, 1);
1040 }
1041
1042 pix->w = width;
1043 return 0;
1044}
1045
1046
1047l_int32
1048pixGetHeight(const PIX *pix)
1049{
1050 PROCNAME("pixGetHeight");
1051
1052 if (!pix)
1053 return ERROR_INT("pix not defined", procName, 0);
1054
1055 return pix->h;
1056}
1057
1058
1059l_int32
1060pixSetHeight(PIX *pix,
1061 l_int32 height)
1062{
1063 PROCNAME("pixSetHeight");
1064
1065 if (!pix)
1066 return ERROR_INT("pix not defined", procName, 1);
1067 if (height < 0) {
1068 pix->h = 0;
1069 return ERROR_INT("h must be >= 0", procName, 1);
1070 }
1071
1072 pix->h = height;
1073 return 0;
1074}
1075
1076
1077l_int32
1078pixGetDepth(const PIX *pix)
1079{
1080 PROCNAME("pixGetDepth");
1081
1082 if (!pix)
1083 return ERROR_INT("pix not defined", procName, 0);
1084
1085 return pix->d;
1086}
1087
1088
1089l_int32
1090pixSetDepth(PIX *pix,
1091 l_int32 depth)
1092{
1093 PROCNAME("pixSetDepth");
1094
1095 if (!pix)
1096 return ERROR_INT("pix not defined", procName, 1);
1097 if (depth < 1)
1098 return ERROR_INT("d must be >= 1", procName, 1);
1099
1100 pix->d = depth;
1101 return 0;
1102}
1103
1104
1112l_ok
1114 l_int32 *pw,
1115 l_int32 *ph,
1116 l_int32 *pd)
1117{
1118 PROCNAME("pixGetDimensions");
1119
1120 if (pw) *pw = 0;
1121 if (ph) *ph = 0;
1122 if (pd) *pd = 0;
1123 if (!pix)
1124 return ERROR_INT("pix not defined", procName, 1);
1125 if (pw) *pw = pix->w;
1126 if (ph) *ph = pix->h;
1127 if (pd) *pd = pix->d;
1128 return 0;
1129}
1130
1131
1139l_ok
1141 l_int32 w,
1142 l_int32 h,
1143 l_int32 d)
1144{
1145 PROCNAME("pixSetDimensions");
1146
1147 if (!pix)
1148 return ERROR_INT("pix not defined", procName, 1);
1149 if (w > 0) pixSetWidth(pix, w);
1150 if (h > 0) pixSetHeight(pix, h);
1151 if (d > 0) pixSetDepth(pix, d);
1152 return 0;
1153}
1154
1155
1163l_ok
1165 const PIX *pixs)
1166{
1167 PROCNAME("pixCopyDimensions");
1168
1169 if (!pixd)
1170 return ERROR_INT("pixd not defined", procName, 1);
1171 if (!pixs)
1172 return ERROR_INT("pixs not defined", procName, 1);
1173 if (pixs == pixd)
1174 return 0; /* no-op */
1175
1176 pixSetWidth(pixd, pixGetWidth(pixs));
1177 pixSetHeight(pixd, pixGetHeight(pixs));
1178 pixSetDepth(pixd, pixGetDepth(pixs));
1179 pixSetWpl(pixd, pixGetWpl(pixs));
1180 return 0;
1181}
1182
1183
1184l_int32
1185pixGetSpp(const PIX *pix)
1186{
1187 PROCNAME("pixGetSpp");
1188
1189 if (!pix)
1190 return ERROR_INT("pix not defined", procName, 0);
1191
1192 return pix->spp;
1193}
1194
1195
1196/*
1197 * \brief pixSetSpp()
1198 *
1199 * \param[in] pix
1200 * \param[in] spp 1, 3 or 4 samples
1201 * \return 0 if OK, 1 on error
1202 *
1203 * <pre>
1204 * Notes:
1205 * (1) For a 32 bpp pix, this can be used to ignore the
1206 * alpha sample (spp == 3) or to use it (spp == 4).
1207 * For example, to write a spp == 4 image without the alpha
1208 * sample (as an rgb pix), call pixSetSpp(pix, 3) and
1209 * then write it out as a png.
1210 * </pre>
1211 */
1212l_int32
1213pixSetSpp(PIX *pix,
1214 l_int32 spp)
1215{
1216 PROCNAME("pixSetSpp");
1217
1218 if (!pix)
1219 return ERROR_INT("pix not defined", procName, 1);
1220 if (spp < 1)
1221 return ERROR_INT("spp must be >= 1", procName, 1);
1222
1223 pix->spp = spp;
1224 return 0;
1225}
1226
1227
1235l_ok
1237 const PIX *pixs)
1238{
1239 PROCNAME("pixCopySpp");
1240
1241 if (!pixd)
1242 return ERROR_INT("pixd not defined", procName, 1);
1243 if (!pixs)
1244 return ERROR_INT("pixs not defined", procName, 1);
1245 if (pixs == pixd)
1246 return 0; /* no-op */
1247
1248 pixSetSpp(pixd, pixGetSpp(pixs));
1249 return 0;
1250}
1251
1252
1253l_int32
1254pixGetWpl(const PIX *pix)
1255{
1256 PROCNAME("pixGetWpl");
1257
1258 if (!pix)
1259 return ERROR_INT("pix not defined", procName, 0);
1260 return pix->wpl;
1261}
1262
1263
1264l_int32
1265pixSetWpl(PIX *pix,
1266 l_int32 wpl)
1267{
1268 PROCNAME("pixSetWpl");
1269
1270 if (!pix)
1271 return ERROR_INT("pix not defined", procName, 1);
1272
1273 pix->wpl = wpl;
1274 return 0;
1275}
1276
1277
1278l_int32
1279pixGetRefcount(const PIX *pix)
1280{
1281 PROCNAME("pixGetRefcount");
1282
1283 if (!pix)
1284 return ERROR_INT("pix not defined", procName, 0);
1285 return pix->refcount;
1286}
1287
1288
1289l_int32
1290pixChangeRefcount(PIX *pix,
1291 l_int32 delta)
1292{
1293 PROCNAME("pixChangeRefcount");
1294
1295 if (!pix)
1296 return ERROR_INT("pix not defined", procName, 1);
1297
1298 pix->refcount += delta;
1299 return 0;
1300}
1301
1302
1303l_int32
1304pixGetXRes(const PIX *pix)
1305{
1306 PROCNAME("pixGetXRes");
1307
1308 if (!pix)
1309 return ERROR_INT("pix not defined", procName, 0);
1310 return pix->xres;
1311}
1312
1313
1314l_int32
1315pixSetXRes(PIX *pix,
1316 l_int32 res)
1317{
1318 PROCNAME("pixSetXRes");
1319
1320 if (!pix)
1321 return ERROR_INT("pix not defined", procName, 1);
1322
1323 pix->xres = res;
1324 return 0;
1325}
1326
1327
1328l_int32
1329pixGetYRes(const PIX *pix)
1330{
1331 PROCNAME("pixGetYRes");
1332
1333 if (!pix)
1334 return ERROR_INT("pix not defined", procName, 0);
1335 return pix->yres;
1336}
1337
1338
1339l_int32
1340pixSetYRes(PIX *pix,
1341 l_int32 res)
1342{
1343 PROCNAME("pixSetYRes");
1344
1345 if (!pix)
1346 return ERROR_INT("pix not defined", procName, 1);
1347
1348 pix->yres = res;
1349 return 0;
1350}
1351
1352
1360l_ok
1362 l_int32 *pxres,
1363 l_int32 *pyres)
1364{
1365 PROCNAME("pixGetResolution");
1366
1367 if (pxres) *pxres = 0;
1368 if (pyres) *pyres = 0;
1369 if (!pxres && !pyres)
1370 return ERROR_INT("no output requested", procName, 1);
1371 if (!pix)
1372 return ERROR_INT("pix not defined", procName, 1);
1373 if (pxres) *pxres = pix->xres;
1374 if (pyres) *pyres = pix->yres;
1375 return 0;
1376}
1377
1378
1386l_ok
1388 l_int32 xres,
1389 l_int32 yres)
1390{
1391 PROCNAME("pixSetResolution");
1392
1393 if (!pix)
1394 return ERROR_INT("pix not defined", procName, 1);
1395 if (xres > 0) pix->xres = xres;
1396 if (yres > 0) pix->yres = yres;
1397 return 0;
1398}
1399
1400
1401l_int32
1402pixCopyResolution(PIX *pixd,
1403 const PIX *pixs)
1404{
1405 PROCNAME("pixCopyResolution");
1406
1407 if (!pixs)
1408 return ERROR_INT("pixs not defined", procName, 1);
1409 if (!pixd)
1410 return ERROR_INT("pixd not defined", procName, 1);
1411 if (pixs == pixd)
1412 return 0; /* no-op */
1413
1414 pixSetXRes(pixd, pixGetXRes(pixs));
1415 pixSetYRes(pixd, pixGetYRes(pixs));
1416 return 0;
1417}
1418
1419
1420l_int32
1421pixScaleResolution(PIX *pix,
1422 l_float32 xscale,
1423 l_float32 yscale)
1424{
1425l_float64 xres, yres;
1426l_float64 maxres = 100000000.0;
1427
1428 PROCNAME("pixScaleResolution");
1429
1430 if (!pix)
1431 return ERROR_INT("pix not defined", procName, 1);
1432 if (xscale <= 0 || yscale <= 0)
1433 return ERROR_INT("invalid scaling ratio", procName, 1);
1434
1435 xres = (l_float64)xscale * (l_float32)(pix->xres) + 0.5;
1436 yres = (l_float64)yscale * (l_float32)(pix->yres) + 0.5;
1437 pix->xres = (l_uint32)L_MIN(xres, maxres);
1438 pix->yres = (l_uint32)L_MIN(yres, maxres);
1439 return 0;
1440}
1441
1442
1443l_int32
1444pixGetInputFormat(const PIX *pix)
1445{
1446 PROCNAME("pixGetInputFormat");
1447
1448 if (!pix)
1449 return ERROR_INT("pix not defined", procName, 0);
1450 return pix->informat;
1451}
1452
1453
1454l_int32
1455pixSetInputFormat(PIX *pix,
1456 l_int32 informat)
1457{
1458 PROCNAME("pixSetInputFormat");
1459
1460 if (!pix)
1461 return ERROR_INT("pix not defined", procName, 1);
1462 pix->informat = informat;
1463 return 0;
1464}
1465
1466
1467l_int32
1468pixCopyInputFormat(PIX *pixd,
1469 const PIX *pixs)
1470{
1471 PROCNAME("pixCopyInputFormat");
1472
1473 if (!pixs)
1474 return ERROR_INT("pixs not defined", procName, 1);
1475 if (!pixd)
1476 return ERROR_INT("pixd not defined", procName, 1);
1477 if (pixs == pixd)
1478 return 0; /* no-op */
1479
1480 pixSetInputFormat(pixd, pixGetInputFormat(pixs));
1481 return 0;
1482}
1483
1484
1485l_int32
1486pixSetSpecial(PIX *pix,
1487 l_int32 special)
1488{
1489 PROCNAME("pixSetSpecial");
1490
1491 if (!pix)
1492 return ERROR_INT("pix not defined", procName, 1);
1493 pix->special = special;
1494 return 0;
1495}
1496
1497
1511char *
1513{
1514 PROCNAME("pixGetText");
1515
1516 if (!pix)
1517 return (char *)ERROR_PTR("pix not defined", procName, NULL);
1518 return pix->text;
1519}
1520
1521
1535l_ok
1537 const char *textstring)
1538{
1539 PROCNAME("pixSetText");
1540
1541 if (!pix)
1542 return ERROR_INT("pix not defined", procName, 1);
1543
1544 stringReplace(&pix->text, textstring);
1545 return 0;
1546}
1547
1548
1563l_ok
1565 const char *textstring)
1566{
1567char *newstring;
1568
1569 PROCNAME("pixAddText");
1570
1571 if (!pix)
1572 return ERROR_INT("pix not defined", procName, 1);
1573
1574 newstring = stringJoin(pixGetText(pix), textstring);
1575 stringReplace(&pix->text, newstring);
1576 LEPT_FREE(newstring);
1577 return 0;
1578}
1579
1580
1581l_int32
1582pixCopyText(PIX *pixd,
1583 const PIX *pixs)
1584{
1585 PROCNAME("pixCopyText");
1586
1587 if (!pixs)
1588 return ERROR_INT("pixs not defined", procName, 1);
1589 if (!pixd)
1590 return ERROR_INT("pixd not defined", procName, 1);
1591 if (pixs == pixd)
1592 return 0; /* no-op */
1593
1594 pixSetText(pixd, pixs->text);
1595 return 0;
1596}
1597
1598
1616l_uint8 *
1618 size_t *psize)
1619{
1620char *str;
1621
1622 PROCNAME("pixGetTextCompNew");
1623
1624 if (!pix)
1625 return (l_uint8 *)ERROR_PTR("pix not defined", procName, NULL);
1626 str = pixGetText(pix);
1627 return decodeAscii85WithComp(str, strlen(str), psize);
1628}
1629
1630
1647l_ok
1649 const l_uint8 *data,
1650 size_t size)
1651{
1652size_t encodesize; /* ignored */
1653
1654 PROCNAME("pixSetTextCompNew");
1655
1656 if (!pix)
1657 return ERROR_INT("pix not defined", procName, 1);
1658
1659 stringReplace(&pix->text, encodeAscii85WithComp(data, size, &encodesize));
1660 return 0;
1661}
1662
1663
1664PIXCMAP *
1665pixGetColormap(PIX *pix)
1666{
1667 PROCNAME("pixGetColormap");
1668
1669 if (!pix)
1670 return (PIXCMAP *)ERROR_PTR("pix not defined", procName, NULL);
1671 return pix->colormap;
1672}
1673
1674
1698l_ok
1700 PIXCMAP *colormap)
1701{
1702l_int32 valid;
1703
1704 PROCNAME("pixSetColormap");
1705
1706 if (!pix)
1707 return ERROR_INT("pix not defined", procName, 1);
1708 if (!colormap) return 0;
1709
1710 /* Make sure the colormap doesn't get lost */
1711 pixDestroyColormap(pix);
1712 pix->colormap = colormap;
1713
1714 pixcmapIsValid(colormap, NULL, &valid);
1715 if (!valid)
1716 return ERROR_INT("colormap is not valid", procName, 1);
1717 return 0;
1718}
1719
1720
1727l_ok
1729{
1730PIXCMAP *cmap;
1731
1732 PROCNAME("pixDestroyColormap");
1733
1734 if (!pix)
1735 return ERROR_INT("pix not defined", procName, 1);
1736
1737 if ((cmap = pix->colormap) != NULL) {
1738 pixcmapDestroy(&cmap);
1739 pix->colormap = NULL;
1740 }
1741 return 0;
1742}
1743
1744
1762l_uint32 *
1764{
1765 PROCNAME("pixGetData");
1766
1767 if (!pix)
1768 return (l_uint32 *)ERROR_PTR("pix not defined", procName, NULL);
1769 return pix->data;
1770}
1771
1772
1786l_int32
1788 l_uint32 *data)
1789{
1790 PROCNAME("pixSetData");
1791
1792 if (!pix)
1793 return ERROR_INT("pix not defined", procName, 1);
1794
1795 pix->data = data;
1796 return 0;
1797}
1798
1799
1816l_uint32 *
1818{
1819l_int32 count, bytes;
1820l_uint32 *data, *datas;
1821
1822 PROCNAME("pixExtractData");
1823
1824 if (!pixs)
1825 return (l_uint32 *)ERROR_PTR("pixs not defined", procName, NULL);
1826
1827 count = pixGetRefcount(pixs);
1828 if (count == 1) { /* extract */
1829 data = pixGetData(pixs);
1830 pixSetData(pixs, NULL);
1831 } else { /* refcount > 1; copy */
1832 bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
1833 datas = pixGetData(pixs);
1834 if ((data = (l_uint32 *)pixdata_malloc(bytes)) == NULL)
1835 return (l_uint32 *)ERROR_PTR("data not made", procName, NULL);
1836 memcpy(data, datas, bytes);
1837 }
1838
1839 return data;
1840}
1841
1842
1857l_int32
1859{
1860l_uint32 *data;
1861
1862 PROCNAME("pixFreeData");
1863
1864 if (!pix)
1865 return ERROR_INT("pix not defined", procName, 1);
1866
1867 if ((data = pixGetData(pix)) != NULL) {
1868 pixdata_free(data);
1869 pix->data = NULL;
1870 }
1871 return 0;
1872}
1873
1874
1875/*--------------------------------------------------------------------*
1876 * Pix line ptrs *
1877 *--------------------------------------------------------------------*/
1948void **
1950 l_int32 *psize)
1951{
1952l_int32 i, h, wpl;
1953l_uint32 *data;
1954void **lines;
1955
1956 PROCNAME("pixGetLinePtrs");
1957
1958 if (psize) *psize = 0;
1959 if (!pix)
1960 return (void **)ERROR_PTR("pix not defined", procName, NULL);
1961
1962 h = pixGetHeight(pix);
1963 if (psize) *psize = h;
1964 if ((lines = (void **)LEPT_CALLOC(h, sizeof(void *))) == NULL)
1965 return (void **)ERROR_PTR("lines not made", procName, NULL);
1966 wpl = pixGetWpl(pix);
1967 data = pixGetData(pix);
1968 for (i = 0; i < h; i++)
1969 lines[i] = (void *)(data + i * wpl);
1970
1971 return lines;
1972}
1973
1974
1975/*--------------------------------------------------------------------*
1976 * Pix Size Comparisons *
1977 *--------------------------------------------------------------------*/
1984l_int32
1985pixSizesEqual(const PIX *pix1,
1986 const PIX *pix2)
1987{
1988 PROCNAME("pixSizesEqual");
1989
1990 if (!pix1 || !pix2)
1991 return ERROR_INT("pix1 and pix2 not both defined", procName, 0);
1992
1993 if (pix1 == pix2)
1994 return 1;
1995
1996 if ((pixGetWidth(pix1) != pixGetWidth(pix2)) ||
1997 (pixGetHeight(pix1) != pixGetHeight(pix2)) ||
1998 (pixGetDepth(pix1) != pixGetDepth(pix2)))
1999 return 0;
2000 else
2001 return 1;
2002}
2003
2004
2012l_ok
2014 l_float32 *pratio)
2015{
2016l_int32 w, h;
2017
2018 PROCNAME("pixMaxAspectRatio");
2019
2020 if (!pratio)
2021 return ERROR_INT("&ratio not defined", procName, 1);
2022 *pratio = -1.0;
2023 if (!pixs)
2024 return ERROR_INT("pixs not defined", procName, 1);
2025 pixGetDimensions(pixs, &w, &h, NULL);
2026 if (w == 0 || h == 0) {
2027 L_ERROR("invalid size: w = %d, h = %d\n", procName, w, h);
2028 return 1;
2029 }
2030
2031 *pratio = L_MAX((l_float32)h / (l_float32)w, (l_float32)w / (l_float32)h);
2032 return 0;
2033}
2034
2035
2036/*--------------------------------------------------------------------*
2037 * Print output for debugging *
2038 *--------------------------------------------------------------------*/
2039extern const char *ImageFileFormatExtensions[];
2040
2049l_ok
2051 const PIX *pix,
2052 const char *text)
2053{
2054l_int32 informat;
2055const PIXCMAP *cmap;
2056
2057 PROCNAME("pixPrintStreamInfo");
2058
2059 if (!fp)
2060 return ERROR_INT("fp not defined", procName, 1);
2061 if (!pix)
2062 return ERROR_INT("pix not defined", procName, 1);
2063
2064 if (text)
2065 fprintf(fp, " Pix Info for %s:\n", text);
2066 fprintf(fp, " width = %d, height = %d, depth = %d, spp = %d\n",
2067 pixGetWidth(pix), pixGetHeight(pix), pixGetDepth(pix),
2068 pixGetSpp(pix));
2069 fprintf(fp, " wpl = %d, data = %p, refcount = %d\n",
2070 pixGetWpl(pix), pix->data, pixGetRefcount(pix));
2071 fprintf(fp, " xres = %d, yres = %d\n", pixGetXRes(pix), pixGetYRes(pix));
2072 if ((cmap = pix->colormap) != NULL)
2073 pixcmapWriteStream(fp, cmap);
2074 else
2075 fprintf(fp, " no colormap\n");
2076 informat = pixGetInputFormat(pix);
2077 fprintf(fp, " input format: %d (%s)\n", informat,
2078 ImageFileFormatExtensions[informat]);
2079 if (pix->text != NULL)
2080 fprintf(fp, " text: %s\n", pix->text);
2081
2082 return 0;
2083}
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
Definition: colormap.c:279
l_ok pixcmapIsValid(const PIXCMAP *cmap, PIX *pix, l_int32 *pvalid)
pixcmapIsValid()
Definition: colormap.c:317
PIXCMAP * pixcmapCopy(const PIXCMAP *cmaps)
pixcmapCopy()
Definition: colormap.c:248
l_ok pixcmapWriteStream(FILE *fp, const PIXCMAP *cmap)
pixcmapWriteStream()
Definition: colormap.c:1965
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:125
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:414
l_uint8 * pixGetTextCompNew(PIX *pix, size_t *psize)
pixGetTextCompNew()
Definition: pix1.c:1617
void ** pixGetLinePtrs(PIX *pix, l_int32 *psize)
pixGetLinePtrs()
Definition: pix1.c:1949
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1699
l_ok pixResizeImageData(PIX *pixd, const PIX *pixs)
pixResizeImageData()
Definition: pix1.c:768
l_ok pixSetResolution(PIX *pix, l_int32 xres, l_int32 yres)
pixSetResolution()
Definition: pix1.c:1387
l_ok pixDestroyColormap(PIX *pix)
pixDestroyColormap()
Definition: pix1.c:1728
void setPixMemoryManager(alloc_fn allocator, dealloc_fn deallocator)
setPixMemoryManager()
Definition: pix1.c:296
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_uint32 * pixExtractData(PIX *pixs)
pixExtractData()
Definition: pix1.c:1817
l_int32 pixFreeData(PIX *pix)
pixFreeData()
Definition: pix1.c:1858
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
l_int32 pixSizesEqual(const PIX *pix1, const PIX *pix2)
pixSizesEqual()
Definition: pix1.c:1985
l_ok pixSetDimensions(PIX *pix, l_int32 w, l_int32 h, l_int32 d)
pixSetDimensions()
Definition: pix1.c:1140
static struct PixMemoryManager pix_mem_manager
Definition: pix1.c:236
l_ok pixCopyDimensions(PIX *pixd, const PIX *pixs)
pixCopyDimensions()
Definition: pix1.c:1164
l_ok pixSetText(PIX *pix, const char *textstring)
pixSetText()
Definition: pix1.c:1536
l_ok pixCopySpp(PIX *pixd, const PIX *pixs)
pixCopySpp()
Definition: pix1.c:1236
l_ok pixGetResolution(const PIX *pix, l_int32 *pxres, l_int32 *pyres)
pixGetResolution()
Definition: pix1.c:1361
l_ok pixSetTextCompNew(PIX *pix, const l_uint8 *data, size_t size)
pixSetTextCompNew()
Definition: pix1.c:1648
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
l_ok pixSwapAndDestroy(PIX **ppixd, PIX **ppixs)
pixSwapAndDestroy()
Definition: pix1.c:993
l_ok pixTransferAllData(PIX *pixd, PIX **ppixs, l_int32 copytext, l_int32 copyformat)
pixTransferAllData()
Definition: pix1.c:902
PIX * pixCreateWithCmap(l_int32 width, l_int32 height, l_int32 depth, l_int32 initcolor)
pixCreateWithCmap()
Definition: pix1.c:458
static void pixFree(PIX *pix)
pixFree()
Definition: pix1.c:651
l_int32 pixSetData(PIX *pix, l_uint32 *data)
pixSetData()
Definition: pix1.c:1787
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_ok pixAddText(PIX *pix, const char *textstring)
pixAddText()
Definition: pix1.c:1564
l_ok pixPrintStreamInfo(FILE *fp, const PIX *pix, const char *text)
pixPrintStreamInfo()
Definition: pix1.c:2050
l_ok pixMaxAspectRatio(PIX *pixs, l_float32 *pratio)
pixMaxAspectRatio()
Definition: pix1.c:2013
l_ok pixCopyColormap(PIX *pixd, const PIX *pixs)
pixCopyColormap()
Definition: pix1.c:816
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
char * pixGetText(PIX *pix)
pixGetText()
Definition: pix1.c:1512
PIX * pixCreateHeader(l_int32 width, l_int32 height, l_int32 depth)
pixCreateHeader()
Definition: pix1.c:504
PIX * pixCreateNoInit(l_int32 width, l_int32 height, l_int32 depth)
pixCreateNoInit()
Definition: pix1.c:346
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
PIX * pixCreateTemplateNoInit(const PIX *pixs)
pixCreateTemplateNoInit()
Definition: pix1.c:417
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
Definition: pix2.c:1382
void *(* alloc_fn)(size_t)
Definition: pix.h:1296
void(* dealloc_fn)(void *)
Definition: pix.h:1299
@ L_SET_BLACK
Definition: pix.h:907
Definition: pix.h:139
l_uint32 d
Definition: pix.h:142
l_uint32 * data
Definition: pix.h:154
l_uint32 spp
Definition: pix.h:143
struct PixColormap * colormap
Definition: pix.h:153
l_uint32 wpl
Definition: pix.h:144
l_uint32 w
Definition: pix.h:140
l_uint32 refcount
Definition: pix.h:145
l_int32 xres
Definition: pix.h:146
l_uint32 h
Definition: pix.h:141
l_int32 yres
Definition: pix.h:148
char * text
Definition: pix.h:152
l_int32 special
Definition: pix.h:151
l_int32 informat
Definition: pix.h:150
l_ok stringReplace(char **pdest, const char *src)
stringReplace()
Definition: utils2.c:345
char * stringJoin(const char *src1, const char *src2)
stringJoin()
Definition: utils2.c:518