Leptonica 1.83.1
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
196
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 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
581PIX *
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 *--------------------------------------------------------------------*/
607void
609{
610PIX *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
635static void
637{
638l_uint32 *data;
639char *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);
649 LEPT_FREE(pix);
650 }
651 return;
652}
653
654
655/*-------------------------------------------------------------------------*
656 * Pix Copy *
657 *-------------------------------------------------------------------------*/
688PIX *
689pixCopy(PIX *pixd, /* can be null */
690 const PIX *pixs)
691{
692l_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
749l_ok
751 const PIX *pixs)
752{
753l_int32 w, h, d, wpl, bytes;
754l_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
794l_ok
796 const PIX *pixs)
797{
798l_int32 valid;
799const PIXCMAP *cmaps;
800PIXCMAP *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
878l_ok
880 PIX **ppixs,
881 l_int32 copytext,
882 l_int32 copyformat)
883{
884l_int32 nbytes;
885PIX *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
967l_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 *--------------------------------------------------------------------*/
990l_int32
991pixGetWidth(const PIX *pix)
992{
993 if (!pix)
994 return ERROR_INT("pix not defined", __func__, 0);
995
996 return pix->w;
997}
998
999
1000l_int32
1001pixSetWidth(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
1016l_int32
1017pixGetHeight(const PIX *pix)
1018{
1019 if (!pix)
1020 return ERROR_INT("pix not defined", __func__, 0);
1021
1022 return pix->h;
1023}
1024
1025
1026l_int32
1027pixSetHeight(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
1042l_int32
1043pixGetDepth(const PIX *pix)
1044{
1045 if (!pix)
1046 return ERROR_INT("pix not defined", __func__, 0);
1047
1048 return pix->d;
1049}
1050
1051
1052l_int32
1053pixSetDepth(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
1073l_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
1098l_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
1120l_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
1139l_int32
1140pixGetSpp(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 */
1165l_int32
1166pixSetSpp(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
1186l_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
1202l_int32
1203pixGetWpl(const PIX *pix)
1204{
1205 if (!pix)
1206 return ERROR_INT("pix not defined", __func__, 0);
1207 return pix->wpl;
1208}
1209
1210
1211l_int32
1212pixSetWpl(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
1223l_int32
1224pixGetXRes(const PIX *pix)
1225{
1226 if (!pix)
1227 return ERROR_INT("pix not defined", __func__, 0);
1228 return pix->xres;
1229}
1230
1231
1232l_int32
1233pixSetXRes(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
1244l_int32
1245pixGetYRes(const PIX *pix)
1246{
1247 if (!pix)
1248 return ERROR_INT("pix not defined", __func__, 0);
1249 return pix->yres;
1250}
1251
1252
1253l_int32
1254pixSetYRes(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
1272l_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
1296l_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
1309l_int32
1310pixCopyResolution(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
1326l_int32
1327pixScaleResolution(PIX *pix,
1328 l_float32 xscale,
1329 l_float32 yscale)
1330{
1331l_float64 xres, yres;
1332l_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
1347l_int32
1348pixGetInputFormat(const PIX *pix)
1349{
1350 if (!pix)
1351 return ERROR_INT("pix not defined", __func__, 0);
1352 return pix->informat;
1353}
1354
1355
1356l_int32
1357pixSetInputFormat(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
1367l_int32
1368pixCopyInputFormat(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
1383l_int32
1384pixSetSpecial(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
1407char *
1409{
1410 if (!pix)
1411 return (char *)ERROR_PTR("pix not defined", __func__, NULL);
1412 return pix->text;
1413}
1414
1415
1429l_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
1455l_ok
1457 const char *textstring)
1458{
1459char *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
1471l_int32
1472pixCopyText(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
1504l_uint8 *
1506 size_t *psize)
1507{
1508char *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
1533l_ok
1535 const l_uint8 *data,
1536 size_t size)
1537{
1538size_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
1549PIXCMAP *
1550pixGetColormap(PIX *pix)
1551{
1552 if (!pix)
1553 return (PIXCMAP *)ERROR_PTR("pix not defined", __func__, NULL);
1554 return pix->colormap;
1555}
1556
1557
1581l_ok
1583 PIXCMAP *colormap)
1584{
1585l_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
1608l_ok
1610{
1611PIXCMAP *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
1641l_uint32 *
1643{
1644 if (!pix)
1645 return (l_uint32 *)ERROR_PTR("pix not defined", __func__, NULL);
1646 return pix->data;
1647}
1648
1649
1662l_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
1688l_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
1714l_int32
1716{
1717l_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
1746l_uint32 *
1748{
1749l_int32 bytes;
1750l_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 *--------------------------------------------------------------------*/
1843void **
1845 l_int32 *psize)
1846{
1847l_int32 i, h, wpl;
1848l_uint32 *data;
1849void **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 *--------------------------------------------------------------------*/
1877l_int32
1878pixSizesEqual(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
1903l_ok
1905 l_float32 *pratio)
1906{
1907l_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 *--------------------------------------------------------------------*/
1928extern const char *ImageFileFormatExtensions[];
1929
1938l_ok
1940 const PIX *pix,
1941 const char *text)
1942{
1943l_int32 informat;
1944const 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}
l_uint8 * pixGetTextCompNew(PIX *pix, size_t *psize)
pixGetTextCompNew()
Definition pix1.c:1505
void ** pixGetLinePtrs(PIX *pix, l_int32 *psize)
pixGetLinePtrs()
Definition pix1.c:1844
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
l_ok pixCopyDimensions(PIX *pixd, const PIX *pixs)
pixCopyDimensions()
Definition pix1.c:1121
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 * pixClone(PIX *pixs)
pixClone()
Definition pix1.c:582
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
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:636
l_int32 pixSetData(PIX *pix, l_uint32 *data)
pixSetData()
Definition pix1.c:1689
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: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
l_ok pixCopyColormap(PIX *pixd, const PIX *pixs)
pixCopyColormap()
Definition pix1.c:795
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition pix1.c:689
char * pixGetText(PIX *pix)
pixGetText()
Definition pix1.c:1408
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:1642
PIX * pixCreateTemplateNoInit(const PIX *pixs)
pixCreateTemplateNoInit()
Definition pix1.c:412
void *(* alloc_fn)(size_t)
Definition pix.h:1089
void(* dealloc_fn)(void *)
Definition pix.h:1092
@ L_SET_BLACK
Definition pix.h:700
struct Pix PIX
Definition pix.h:228
struct PixColormap PIXCMAP
Definition pix.h:231
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