Leptonica 1.85.0
Image processing and image analysis suite
Loading...
Searching...
No Matches
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
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 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
343PIX *
344pixCreateNoInit(l_int32 width,
345 l_int32 height,
346 l_int32 depth)
347{
348l_int32 wpl;
349PIX *pixd;
350l_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
379PIX *
381{
382PIX *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
411PIX *
413{
414l_int32 w, h, d;
415PIX *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
450PIX *
451pixCreateWithCmap(l_int32 width,
452 l_int32 height,
453 l_int32 depth,
454 l_int32 initcolor)
455{
456PIX *pix;
457PIXCMAP *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
494PIX *
495pixCreateHeader(l_int32 width,
496 l_int32 height,
497 l_int32 depth)
498{
499l_int32 wpl;
500l_uint64 wpl64, bignum;
501PIX *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 if ((pixd = (PIX *)LEPT_CALLOC(1, sizeof(PIX))) == NULL)
543 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
544 pixSetWidth(pixd, width);
545 pixSetHeight(pixd, height);
546 pixSetDepth(pixd, depth);
547 pixSetWpl(pixd, wpl);
548 if (depth == 24 || depth == 32)
549 pixSetSpp(pixd, 3);
550 else
551 pixSetSpp(pixd, 1);
552 pixd->refcount = 1;
553 pixd->informat = IFF_UNKNOWN;
554 return pixd;
555}
556
557
582PIX *
584{
585 if (!pixs)
586 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
587 ++pixs->refcount;
588
589 return pixs;
590}
591
592
593/*--------------------------------------------------------------------*
594 * Pix Destruction *
595 *--------------------------------------------------------------------*/
608void
610{
611PIX *pix;
612
613 if (!ppix) {
614 L_WARNING("ptr address is null!\n", __func__);
615 return;
616 }
617
618 if ((pix = *ppix) == NULL)
619 return;
620 pixFree(pix);
621 *ppix = NULL;
622}
623
624
636static void
638{
639l_uint32 *data;
640char *text;
641
642 if (!pix) return;
643
644 if (--pix->refcount == 0) {
645 if ((data = pixGetData(pix)) != NULL)
646 pixdata_free(data);
647 if ((text = pixGetText(pix)) != NULL)
648 LEPT_FREE(text);
650 LEPT_FREE(pix);
651 }
652 return;
653}
654
655
656/*-------------------------------------------------------------------------*
657 * Pix Copy *
658 *-------------------------------------------------------------------------*/
689PIX *
690pixCopy(PIX *pixd, /* can be null */
691 const PIX *pixs)
692{
693l_int32 bytes;
694
695 if (!pixs)
696 return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
697 if (pixs == pixd)
698 return pixd;
699
700 /* Total bytes in image data */
701 bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
702
703 /* If we're making a new pix ... */
704 if (!pixd) {
705 if ((pixd = pixCreateTemplate(pixs)) == NULL)
706 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
707 memcpy(pixd->data, pixs->data, bytes);
708 return pixd;
709 }
710
711 /* Reallocate image data if sizes are different. If this fails,
712 * pixd hasn't been changed. But we want to signal that the copy
713 * failed, so return NULL. This will cause a memory leak if the
714 * return ptr is assigned to pixd, but that is preferred to proceeding
715 * with an incorrect pixd, and in any event this use case of
716 * pixCopy() -- reallocating into an existing pix -- is infrequent. */
717 if (pixResizeImageData(pixd, pixs) == 1)
718 return (PIX *)ERROR_PTR("reallocation of data failed", __func__, NULL);
719
720 /* Copy non-image data fields */
721 pixCopyColormap(pixd, pixs);
722 pixCopySpp(pixd, pixs);
723 pixCopyResolution(pixd, pixs);
724 pixCopyInputFormat(pixd, pixs);
725 pixCopyText(pixd, pixs);
726
727 /* Copy image data */
728 memcpy(pixd->data, pixs->data, bytes);
729 return pixd;
730}
731
732
750l_ok
752 const PIX *pixs)
753{
754l_int32 w, h, d, wpl, bytes;
755l_uint32 *data;
756
757 if (!pixs)
758 return ERROR_INT("pixs not defined", __func__, 1);
759 if (!pixd)
760 return ERROR_INT("pixd not defined", __func__, 1);
761
762 if (pixSizesEqual(pixs, pixd)) /* nothing to do */
763 return 0;
764
765 /* Make sure we can copy the data */
766 pixGetDimensions(pixs, &w, &h, &d);
767 wpl = pixGetWpl(pixs);
768 bytes = 4 * wpl * h;
769 if ((data = (l_uint32 *)pixdata_malloc(bytes)) == NULL)
770 return ERROR_INT("pixdata_malloc fail for data", __func__, 1);
771
772 /* OK, do it */
773 pixSetWidth(pixd, w);
774 pixSetHeight(pixd, h);
775 pixSetDepth(pixd, d);
776 pixSetWpl(pixd, wpl);
777 pixFreeAndSetData(pixd, data); /* free old data and assign new data */
778 pixCopyResolution(pixd, pixs);
779 return 0;
780}
781
782
795l_ok
797 const PIX *pixs)
798{
799l_int32 valid;
800const PIXCMAP *cmaps;
801PIXCMAP *cmapd;
802
803 if (!pixs)
804 return ERROR_INT("pixs not defined", __func__, 1);
805 if (!pixd)
806 return ERROR_INT("pixd not defined", __func__, 1);
807 if (pixs == pixd)
808 return 0; /* no-op */
809 if (pixGetDepth(pixs) != pixGetDepth(pixd))
810 return ERROR_INT("depths of pixs and pixd differ", __func__, 1);
811
812 pixDestroyColormap(pixd);
813 if ((cmaps = pixs->colormap) == NULL) /* not an error */
814 return 0;
815 pixcmapIsValid(cmaps, NULL, &valid);
816 if (!valid)
817 return ERROR_INT("cmap not valid", __func__, 1);
818
819 if ((cmapd = pixcmapCopy(cmaps)) == NULL)
820 return ERROR_INT("cmapd not made", __func__, 1);
821 pixSetColormap(pixd, cmapd);
822 return 0;
823}
824
825
879l_ok
881 PIX **ppixs,
882 l_int32 copytext,
883 l_int32 copyformat)
884{
885l_int32 nbytes;
886PIX *pixs;
887
888 if (!ppixs)
889 return ERROR_INT("&pixs not defined", __func__, 1);
890 if ((pixs = *ppixs) == NULL)
891 return ERROR_INT("pixs not defined", __func__, 1);
892 if (!pixd)
893 return ERROR_INT("pixd not defined", __func__, 1);
894 if (pixs == pixd) /* no-op */
895 return ERROR_INT("pixd == pixs", __func__, 1);
896
897 if (pixs->refcount == 1) { /* transfer the data, cmap, text */
898 pixFreeData(pixd); /* dealloc any existing data */
899 pixSetData(pixd, pixGetData(pixs)); /* transfer new data from pixs */
900 pixs->data = NULL; /* pixs no longer owns data */
901 pixDestroyColormap(pixd); /* free the old one, if it exists */
902 pixd->colormap = pixGetColormap(pixs); /* transfer to pixd */
903 pixs->colormap = NULL; /* pixs no longer owns colormap */
904 if (copytext) {
905 pixSetText(pixd, pixGetText(pixs));
906 pixSetText(pixs, NULL);
907 }
908 } else { /* preserve pixs by making a copy of the data, cmap, text */
909 pixResizeImageData(pixd, pixs);
910 nbytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
911 memcpy(pixGetData(pixd), pixGetData(pixs), nbytes);
912 pixCopyColormap(pixd, pixs);
913 if (copytext)
914 pixCopyText(pixd, pixs);
915 }
916
917 pixCopySpp(pixd, pixs);
918 pixCopyResolution(pixd, pixs);
919 pixCopyDimensions(pixd, pixs);
920 if (copyformat)
921 pixCopyInputFormat(pixd, pixs);
922
923 /* This will destroy pixs if data was transferred;
924 * otherwise, it just decrements its refcount. */
925 pixDestroy(ppixs);
926 return 0;
927}
928
929
968l_ok
970 PIX **ppixs)
971{
972 if (!ppixd)
973 return ERROR_INT("&pixd not defined", __func__, 1);
974 if (!ppixs)
975 return ERROR_INT("&pixs not defined", __func__, 1);
976 if (*ppixs == NULL)
977 return ERROR_INT("pixs not defined", __func__, 1);
978 if (ppixs == ppixd) /* no-op */
979 return ERROR_INT("&pixd == &pixs", __func__, 1);
980
981 pixDestroy(ppixd);
982 *ppixd = pixClone(*ppixs);
983 pixDestroy(ppixs);
984 return 0;
985}
986
987
988/*--------------------------------------------------------------------*
989 * Pix Accessors *
990 *--------------------------------------------------------------------*/
991l_int32
992pixGetWidth(const PIX *pix)
993{
994 if (!pix)
995 return ERROR_INT("pix not defined", __func__, 0);
996
997 return pix->w;
998}
999
1000
1001l_int32
1002pixSetWidth(PIX *pix,
1003 l_int32 width)
1004{
1005 if (!pix)
1006 return ERROR_INT("pix not defined", __func__, 1);
1007 if (width < 0) {
1008 pix->w = 0;
1009 return ERROR_INT("width must be >= 0", __func__, 1);
1010 }
1011
1012 pix->w = width;
1013 return 0;
1014}
1015
1016
1017l_int32
1018pixGetHeight(const PIX *pix)
1019{
1020 if (!pix)
1021 return ERROR_INT("pix not defined", __func__, 0);
1022
1023 return pix->h;
1024}
1025
1026
1027l_int32
1028pixSetHeight(PIX *pix,
1029 l_int32 height)
1030{
1031 if (!pix)
1032 return ERROR_INT("pix not defined", __func__, 1);
1033 if (height < 0) {
1034 pix->h = 0;
1035 return ERROR_INT("h must be >= 0", __func__, 1);
1036 }
1037
1038 pix->h = height;
1039 return 0;
1040}
1041
1042
1043l_int32
1044pixGetDepth(const PIX *pix)
1045{
1046 if (!pix)
1047 return ERROR_INT("pix not defined", __func__, 0);
1048
1049 return pix->d;
1050}
1051
1052
1053l_int32
1054pixSetDepth(PIX *pix,
1055 l_int32 depth)
1056{
1057 if (!pix)
1058 return ERROR_INT("pix not defined", __func__, 1);
1059 if (depth < 1)
1060 return ERROR_INT("d must be >= 1", __func__, 1);
1061
1062 pix->d = depth;
1063 return 0;
1064}
1065
1066
1074l_ok
1076 l_int32 *pw,
1077 l_int32 *ph,
1078 l_int32 *pd)
1079{
1080 if (pw) *pw = 0;
1081 if (ph) *ph = 0;
1082 if (pd) *pd = 0;
1083 if (!pix)
1084 return ERROR_INT("pix not defined", __func__, 1);
1085 if (pw) *pw = pix->w;
1086 if (ph) *ph = pix->h;
1087 if (pd) *pd = pix->d;
1088 return 0;
1089}
1090
1091
1099l_ok
1101 l_int32 w,
1102 l_int32 h,
1103 l_int32 d)
1104{
1105 if (!pix)
1106 return ERROR_INT("pix not defined", __func__, 1);
1107 if (w > 0) pixSetWidth(pix, w);
1108 if (h > 0) pixSetHeight(pix, h);
1109 if (d > 0) pixSetDepth(pix, d);
1110 return 0;
1111}
1112
1113
1121l_ok
1123 const PIX *pixs)
1124{
1125 if (!pixd)
1126 return ERROR_INT("pixd not defined", __func__, 1);
1127 if (!pixs)
1128 return ERROR_INT("pixs not defined", __func__, 1);
1129 if (pixs == pixd)
1130 return 0; /* no-op */
1131
1132 pixSetWidth(pixd, pixGetWidth(pixs));
1133 pixSetHeight(pixd, pixGetHeight(pixs));
1134 pixSetDepth(pixd, pixGetDepth(pixs));
1135 pixSetWpl(pixd, pixGetWpl(pixs));
1136 return 0;
1137}
1138
1139
1140l_int32
1141pixGetSpp(const PIX *pix)
1142{
1143 if (!pix)
1144 return ERROR_INT("pix not defined", __func__, 0);
1145
1146 return pix->spp;
1147}
1148
1149
1150/*
1151 * \brief pixSetSpp()
1152 *
1153 * \param[in] pix
1154 * \param[in] spp 1, 3 or 4 samples
1155 * \return 0 if OK, 1 on error
1156 *
1157 * <pre>
1158 * Notes:
1159 * (1) For a 32 bpp pix, this can be used to ignore the
1160 * alpha sample (spp == 3) or to use it (spp == 4).
1161 * For example, to write a spp == 4 image without the alpha
1162 * sample (as an rgb pix), call pixSetSpp(pix, 3) and
1163 * then write it out as a png.
1164 * </pre>
1165 */
1166l_int32
1167pixSetSpp(PIX *pix,
1168 l_int32 spp)
1169{
1170 if (!pix)
1171 return ERROR_INT("pix not defined", __func__, 1);
1172 if (spp < 1)
1173 return ERROR_INT("spp must be >= 1", __func__, 1);
1174
1175 pix->spp = spp;
1176 return 0;
1177}
1178
1179
1187l_ok
1189 const PIX *pixs)
1190{
1191 if (!pixd)
1192 return ERROR_INT("pixd not defined", __func__, 1);
1193 if (!pixs)
1194 return ERROR_INT("pixs not defined", __func__, 1);
1195 if (pixs == pixd)
1196 return 0; /* no-op */
1197
1198 pixSetSpp(pixd, pixGetSpp(pixs));
1199 return 0;
1200}
1201
1202
1203l_int32
1204pixGetWpl(const PIX *pix)
1205{
1206 if (!pix)
1207 return ERROR_INT("pix not defined", __func__, 0);
1208 return pix->wpl;
1209}
1210
1211
1212l_int32
1213pixSetWpl(PIX *pix,
1214 l_int32 wpl)
1215{
1216 if (!pix)
1217 return ERROR_INT("pix not defined", __func__, 1);
1218
1219 pix->wpl = wpl;
1220 return 0;
1221}
1222
1223
1224l_int32
1225pixGetXRes(const PIX *pix)
1226{
1227 if (!pix)
1228 return ERROR_INT("pix not defined", __func__, 0);
1229 return pix->xres;
1230}
1231
1232
1233l_int32
1234pixSetXRes(PIX *pix,
1235 l_int32 res)
1236{
1237 if (!pix)
1238 return ERROR_INT("pix not defined", __func__, 1);
1239
1240 pix->xres = res;
1241 return 0;
1242}
1243
1244
1245l_int32
1246pixGetYRes(const PIX *pix)
1247{
1248 if (!pix)
1249 return ERROR_INT("pix not defined", __func__, 0);
1250 return pix->yres;
1251}
1252
1253
1254l_int32
1255pixSetYRes(PIX *pix,
1256 l_int32 res)
1257{
1258 if (!pix)
1259 return ERROR_INT("pix not defined", __func__, 1);
1260
1261 pix->yres = res;
1262 return 0;
1263}
1264
1265
1273l_ok
1275 l_int32 *pxres,
1276 l_int32 *pyres)
1277{
1278 if (pxres) *pxres = 0;
1279 if (pyres) *pyres = 0;
1280 if (!pxres && !pyres)
1281 return ERROR_INT("no output requested", __func__, 1);
1282 if (!pix)
1283 return ERROR_INT("pix not defined", __func__, 1);
1284 if (pxres) *pxres = pix->xres;
1285 if (pyres) *pyres = pix->yres;
1286 return 0;
1287}
1288
1289
1297l_ok
1299 l_int32 xres,
1300 l_int32 yres)
1301{
1302 if (!pix)
1303 return ERROR_INT("pix not defined", __func__, 1);
1304 if (xres > 0) pix->xres = xres;
1305 if (yres > 0) pix->yres = yres;
1306 return 0;
1307}
1308
1309
1310l_int32
1311pixCopyResolution(PIX *pixd,
1312 const PIX *pixs)
1313{
1314 if (!pixs)
1315 return ERROR_INT("pixs not defined", __func__, 1);
1316 if (!pixd)
1317 return ERROR_INT("pixd not defined", __func__, 1);
1318 if (pixs == pixd)
1319 return 0; /* no-op */
1320
1321 pixSetXRes(pixd, pixGetXRes(pixs));
1322 pixSetYRes(pixd, pixGetYRes(pixs));
1323 return 0;
1324}
1325
1326
1327l_int32
1328pixScaleResolution(PIX *pix,
1329 l_float32 xscale,
1330 l_float32 yscale)
1331{
1332l_float64 xres, yres;
1333l_float64 maxres = 100000000.0;
1334
1335 if (!pix)
1336 return ERROR_INT("pix not defined", __func__, 1);
1337 if (xscale <= 0 || yscale <= 0)
1338 return ERROR_INT("invalid scaling ratio", __func__, 1);
1339
1340 xres = (l_float64)xscale * (l_float32)(pix->xres) + 0.5;
1341 yres = (l_float64)yscale * (l_float32)(pix->yres) + 0.5;
1342 pix->xres = (l_uint32)L_MIN(xres, maxres);
1343 pix->yres = (l_uint32)L_MIN(yres, maxres);
1344 return 0;
1345}
1346
1347
1348l_int32
1349pixGetInputFormat(const PIX *pix)
1350{
1351 if (!pix)
1352 return ERROR_INT("pix not defined", __func__, 0);
1353 return pix->informat;
1354}
1355
1356
1357l_int32
1358pixSetInputFormat(PIX *pix,
1359 l_int32 informat)
1360{
1361 if (!pix)
1362 return ERROR_INT("pix not defined", __func__, 1);
1363 pix->informat = informat;
1364 return 0;
1365}
1366
1367
1368l_int32
1369pixCopyInputFormat(PIX *pixd,
1370 const PIX *pixs)
1371{
1372 if (!pixs)
1373 return ERROR_INT("pixs not defined", __func__, 1);
1374 if (!pixd)
1375 return ERROR_INT("pixd not defined", __func__, 1);
1376 if (pixs == pixd)
1377 return 0; /* no-op */
1378
1379 pixSetInputFormat(pixd, pixGetInputFormat(pixs));
1380 return 0;
1381}
1382
1383
1384l_int32
1385pixSetSpecial(PIX *pix,
1386 l_int32 special)
1387{
1388 if (!pix)
1389 return ERROR_INT("pix not defined", __func__, 1);
1390 pix->special = special;
1391 return 0;
1392}
1393
1394
1408char *
1410{
1411 if (!pix)
1412 return (char *)ERROR_PTR("pix not defined", __func__, NULL);
1413 return pix->text;
1414}
1415
1416
1430l_ok
1432 const char *textstring)
1433{
1434 if (!pix)
1435 return ERROR_INT("pix not defined", __func__, 1);
1436
1437 stringReplace(&pix->text, textstring);
1438 return 0;
1439}
1440
1441
1456l_ok
1458 const char *textstring)
1459{
1460char *newstring;
1461
1462 if (!pix)
1463 return ERROR_INT("pix not defined", __func__, 1);
1464
1465 newstring = stringJoin(pixGetText(pix), textstring);
1466 stringReplace(&pix->text, newstring);
1467 LEPT_FREE(newstring);
1468 return 0;
1469}
1470
1471
1472l_int32
1473pixCopyText(PIX *pixd,
1474 const PIX *pixs)
1475{
1476 if (!pixs)
1477 return ERROR_INT("pixs not defined", __func__, 1);
1478 if (!pixd)
1479 return ERROR_INT("pixd not defined", __func__, 1);
1480 if (pixs == pixd)
1481 return 0; /* no-op */
1482
1483 pixSetText(pixd, pixs->text);
1484 return 0;
1485}
1486
1487
1505l_uint8 *
1507 size_t *psize)
1508{
1509char *str;
1510
1511 if (!pix)
1512 return (l_uint8 *)ERROR_PTR("pix not defined", __func__, NULL);
1513 str = pixGetText(pix);
1514 return decodeAscii85WithComp(str, strlen(str), psize);
1515}
1516
1517
1534l_ok
1536 const l_uint8 *data,
1537 size_t size)
1538{
1539size_t encodesize; /* ignored */
1540
1541 if (!pix)
1542 return ERROR_INT("pix not defined", __func__, 1);
1543
1544 LEPT_FREE(pix->text);
1545 pix->text = encodeAscii85WithComp(data, size, &encodesize);
1546 return 0;
1547}
1548
1549
1550PIXCMAP *
1551pixGetColormap(PIX *pix)
1552{
1553 if (!pix)
1554 return (PIXCMAP *)ERROR_PTR("pix not defined", __func__, NULL);
1555 return pix->colormap;
1556}
1557
1558
1582l_ok
1584 PIXCMAP *colormap)
1585{
1586l_int32 valid;
1587
1588 if (!pix)
1589 return ERROR_INT("pix not defined", __func__, 1);
1590 if (!colormap) return 0;
1591
1592 /* Make sure the colormap doesn't get lost */
1593 pixDestroyColormap(pix);
1594 pix->colormap = colormap;
1595
1596 pixcmapIsValid(colormap, NULL, &valid);
1597 if (!valid)
1598 return ERROR_INT("colormap is not valid", __func__, 1);
1599 return 0;
1600}
1601
1602
1609l_ok
1611{
1612PIXCMAP *cmap;
1613
1614 if (!pix)
1615 return ERROR_INT("pix not defined", __func__, 1);
1616
1617 if ((cmap = pix->colormap) != NULL) {
1618 pixcmapDestroy(&cmap);
1619 pix->colormap = NULL;
1620 }
1621 return 0;
1622}
1623
1624
1642l_uint32 *
1644{
1645 if (!pix)
1646 return (l_uint32 *)ERROR_PTR("pix not defined", __func__, NULL);
1647 return pix->data;
1648}
1649
1650
1663l_int32
1665 l_uint32 *data)
1666{
1667 if (!pix)
1668 return ERROR_INT("pix not defined", __func__, 1);
1669
1670 pixFreeData(pix);
1671 pix->data = data;
1672 return 0;
1673}
1674
1675
1689l_int32
1691 l_uint32 *data)
1692{
1693 if (!pix)
1694 return ERROR_INT("pix not defined", __func__, 1);
1695
1696 pix->data = data;
1697 return 0;
1698}
1699
1700
1715l_int32
1717{
1718l_uint32 *data;
1719
1720 if (!pix)
1721 return ERROR_INT("pix not defined", __func__, 1);
1722
1723 if ((data = pixGetData(pix)) != NULL) {
1724 pixdata_free(data);
1725 pix->data = NULL;
1726 }
1727 return 0;
1728}
1729
1730
1747l_uint32 *
1749{
1750l_int32 bytes;
1751l_uint32 *data, *datas;
1752
1753 if (!pixs)
1754 return (l_uint32 *)ERROR_PTR("pixs not defined", __func__, NULL);
1755
1756 if (pixs->refcount == 1) { /* extract */
1757 data = pixGetData(pixs);
1758 pixSetData(pixs, NULL);
1759 } else { /* refcount > 1; copy */
1760 bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
1761 datas = pixGetData(pixs);
1762 if ((data = (l_uint32 *)pixdata_malloc(bytes)) == NULL)
1763 return (l_uint32 *)ERROR_PTR("data not made", __func__, NULL);
1764 memcpy(data, datas, bytes);
1765 }
1766
1767 return data;
1768}
1769
1770
1771/*--------------------------------------------------------------------*
1772 * Pix line ptrs *
1773 *--------------------------------------------------------------------*/
1844void **
1846 l_int32 *psize)
1847{
1848l_int32 i, h, wpl;
1849l_uint32 *data;
1850void **lines;
1851
1852 if (psize) *psize = 0;
1853 if (!pix)
1854 return (void **)ERROR_PTR("pix not defined", __func__, NULL);
1855
1856 h = pixGetHeight(pix);
1857 if (psize) *psize = h;
1858 if ((lines = (void **)LEPT_CALLOC(h, sizeof(void *))) == NULL)
1859 return (void **)ERROR_PTR("lines not made", __func__, NULL);
1860 wpl = pixGetWpl(pix);
1861 data = pixGetData(pix);
1862 for (i = 0; i < h; i++)
1863 lines[i] = (void *)(data + i * wpl);
1864
1865 return lines;
1866}
1867
1868
1869/*--------------------------------------------------------------------*
1870 * Pix Size Comparisons *
1871 *--------------------------------------------------------------------*/
1878l_int32
1879pixSizesEqual(const PIX *pix1,
1880 const PIX *pix2)
1881{
1882 if (!pix1 || !pix2)
1883 return ERROR_INT("pix1 and pix2 not both defined", __func__, 0);
1884
1885 if (pix1 == pix2)
1886 return 1;
1887
1888 if ((pixGetWidth(pix1) != pixGetWidth(pix2)) ||
1889 (pixGetHeight(pix1) != pixGetHeight(pix2)) ||
1890 (pixGetDepth(pix1) != pixGetDepth(pix2)))
1891 return 0;
1892 else
1893 return 1;
1894}
1895
1896
1904l_ok
1906 l_float32 *pratio)
1907{
1908l_int32 w, h;
1909
1910 if (!pratio)
1911 return ERROR_INT("&ratio not defined", __func__, 1);
1912 *pratio = -1.0;
1913 if (!pixs)
1914 return ERROR_INT("pixs not defined", __func__, 1);
1915 pixGetDimensions(pixs, &w, &h, NULL);
1916 if (w == 0 || h == 0) {
1917 L_ERROR("invalid size: w = %d, h = %d\n", __func__, w, h);
1918 return 1;
1919 }
1920
1921 *pratio = L_MAX((l_float32)h / (l_float32)w, (l_float32)w / (l_float32)h);
1922 return 0;
1923}
1924
1925
1926/*--------------------------------------------------------------------*
1927 * Print output for debugging *
1928 *--------------------------------------------------------------------*/
1929extern const char *ImageFileFormatExtensions[];
1930
1939l_ok
1941 const PIX *pix,
1942 const char *text)
1943{
1944l_int32 informat;
1945const PIXCMAP *cmap;
1946
1947 if (!fp)
1948 return ERROR_INT("fp not defined", __func__, 1);
1949 if (!pix)
1950 return ERROR_INT("pix not defined", __func__, 1);
1951
1952 if (text)
1953 fprintf(fp, " Pix Info for %s:\n", text);
1954 fprintf(fp, " width = %d, height = %d, depth = %d, spp = %d\n",
1955 pixGetWidth(pix), pixGetHeight(pix), pixGetDepth(pix),
1956 pixGetSpp(pix));
1957 fprintf(fp, " wpl = %d, data = %p, refcount = %d\n",
1958 pixGetWpl(pix), pix->data, pix->refcount);
1959 fprintf(fp, " xres = %d, yres = %d\n", pixGetXRes(pix), pixGetYRes(pix));
1960 if ((cmap = pix->colormap) != NULL)
1961 pixcmapWriteStream(fp, cmap);
1962 else
1963 fprintf(fp, " no colormap\n");
1964 informat = pixGetInputFormat(pix);
1965 fprintf(fp, " input format: %d (%s)\n", informat,
1966 ImageFileFormatExtensions[informat]);
1967 if (pix->text != NULL)
1968 fprintf(fp, " text: %s\n", pix->text);
1969
1970 return 0;
1971}
l_uint8 * pixGetTextCompNew(PIX *pix, size_t *psize)
pixGetTextCompNew()
Definition pix1.c:1506
void ** pixGetLinePtrs(PIX *pix, l_int32 *psize)
pixGetLinePtrs()
Definition pix1.c:1845
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition pix1.c:1583
l_ok pixResizeImageData(PIX *pixd, const PIX *pixs)
pixResizeImageData()
Definition pix1.c:751
l_ok pixSetResolution(PIX *pix, l_int32 xres, l_int32 yres)
pixSetResolution()
Definition pix1.c:1298
l_ok pixDestroyColormap(PIX *pix)
pixDestroyColormap()
Definition pix1.c:1610
void setPixMemoryManager(alloc_fn allocator, dealloc_fn deallocator)
setPixMemoryManager()
Definition pix1.c:296
void pixDestroy(PIX **ppix)
pixDestroy()
Definition pix1.c:609
l_uint32 * pixExtractData(PIX *pixs)
pixExtractData()
Definition pix1.c:1748
l_int32 pixFreeData(PIX *pix)
pixFreeData()
Definition pix1.c:1716
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition pix1.c:1075
l_int32 pixSizesEqual(const PIX *pix1, const PIX *pix2)
pixSizesEqual()
Definition pix1.c:1879
l_ok pixSetDimensions(PIX *pix, l_int32 w, l_int32 h, l_int32 d)
pixSetDimensions()
Definition pix1.c:1100
static struct PixMemoryManager pix_mem_manager
Definition pix1.c:236
l_ok pixCopyDimensions(PIX *pixd, const PIX *pixs)
pixCopyDimensions()
Definition pix1.c:1122
l_ok pixSetText(PIX *pix, const char *textstring)
pixSetText()
Definition pix1.c:1431
l_ok pixCopySpp(PIX *pixd, const PIX *pixs)
pixCopySpp()
Definition pix1.c:1188
l_ok pixGetResolution(const PIX *pix, l_int32 *pxres, l_int32 *pyres)
pixGetResolution()
Definition pix1.c:1274
l_ok pixSetTextCompNew(PIX *pix, const l_uint8 *data, size_t size)
pixSetTextCompNew()
Definition pix1.c:1535
PIX * pixClone(PIX *pixs)
pixClone()
Definition pix1.c:583
l_ok pixSwapAndDestroy(PIX **ppixd, PIX **ppixs)
pixSwapAndDestroy()
Definition pix1.c:969
l_ok pixTransferAllData(PIX *pixd, PIX **ppixs, l_int32 copytext, l_int32 copyformat)
pixTransferAllData()
Definition pix1.c:880
PIX * pixCreateWithCmap(l_int32 width, l_int32 height, l_int32 depth, l_int32 initcolor)
pixCreateWithCmap()
Definition pix1.c:451
static void pixFree(PIX *pix)
pixFree()
Definition pix1.c:637
l_int32 pixSetData(PIX *pix, l_uint32 *data)
pixSetData()
Definition pix1.c:1690
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition pix1.c:380
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition pix1.c:315
l_int32 pixFreeAndSetData(PIX *pix, l_uint32 *data)
pixFreeAndSetData()
Definition pix1.c:1664
l_ok pixAddText(PIX *pix, const char *textstring)
pixAddText()
Definition pix1.c:1457
l_ok pixPrintStreamInfo(FILE *fp, const PIX *pix, const char *text)
pixPrintStreamInfo()
Definition pix1.c:1940
l_ok pixMaxAspectRatio(PIX *pixs, l_float32 *pratio)
pixMaxAspectRatio()
Definition pix1.c:1905
l_ok pixCopyColormap(PIX *pixd, const PIX *pixs)
pixCopyColormap()
Definition pix1.c:796
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition pix1.c:690
char * pixGetText(PIX *pix)
pixGetText()
Definition pix1.c:1409
PIX * pixCreateHeader(l_int32 width, l_int32 height, l_int32 depth)
pixCreateHeader()
Definition pix1.c:495
PIX * pixCreateNoInit(l_int32 width, l_int32 height, l_int32 depth)
pixCreateNoInit()
Definition pix1.c:344
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition pix1.c:1643
PIX * pixCreateTemplateNoInit(const PIX *pixs)
pixCreateTemplateNoInit()
Definition pix1.c:412
void *(* alloc_fn)(size_t)
Definition pix.h:1090
void(* dealloc_fn)(void *)
Definition pix.h:1093
@ L_SET_BLACK
Definition pix.h:700
l_uint32 d
l_uint32 * data
l_uint32 spp
struct PixColormap * colormap
l_atomic refcount
l_uint32 wpl
l_uint32 w
l_int32 xres
l_uint32 h
l_int32 yres
char * text
l_int32 special
l_int32 informat