Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/leptonica/src/pix1.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 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 | |
| 27 /*! | |
| 28 * \file pix1.c | |
| 29 * <pre> | |
| 30 * | |
| 31 * The pixN.c {N = 1,2,3,4,5} files are sorted by the type of operation. | |
| 32 * The primary functions in these files are: | |
| 33 * | |
| 34 * pix1.c: constructors, destructors and field accessors | |
| 35 * pix2.c: pixel poking of image, pad and border pixels | |
| 36 * pix3.c: masking and logical ops, counting, mirrored tiling | |
| 37 * pix4.c: histograms, statistics, fg/bg estimation | |
| 38 * pix5.c: property measurements, rectangle extraction | |
| 39 * | |
| 40 * | |
| 41 * This file has the basic constructors, destructors and field accessors | |
| 42 * | |
| 43 * Pix memory management (allows custom allocator and deallocator) | |
| 44 * static void *pixdata_malloc() | |
| 45 * static void pixdata_free() | |
| 46 * void setPixMemoryManager() | |
| 47 * | |
| 48 * Pix creation | |
| 49 * PIX *pixCreate() | |
| 50 * PIX *pixCreateNoInit() | |
| 51 * PIX *pixCreateTemplate() | |
| 52 * PIX *pixCreateTemplateNoInit() | |
| 53 * PIX *pixCreateWithCmap() | |
| 54 * PIX *pixCreateHeader() | |
| 55 * PIX *pixClone() | |
| 56 * | |
| 57 * Pix destruction | |
| 58 * void pixDestroy() | |
| 59 * static void pixFree() | |
| 60 * | |
| 61 * Pix copy | |
| 62 * PIX *pixCopy() | |
| 63 * l_int32 pixResizeImageData() | |
| 64 * l_int32 pixCopyColormap() | |
| 65 * l_int32 pixTransferAllData() | |
| 66 * l_int32 pixSwapAndDestroy() | |
| 67 * | |
| 68 * Pix accessors | |
| 69 * l_int32 pixGetWidth() | |
| 70 * l_int32 pixSetWidth() | |
| 71 * l_int32 pixGetHeight() | |
| 72 * l_int32 pixSetHeight() | |
| 73 * l_int32 pixGetDepth() | |
| 74 * l_int32 pixSetDepth() | |
| 75 * l_int32 pixGetDimensions() | |
| 76 * l_int32 pixSetDimensions() | |
| 77 * l_int32 pixCopyDimensions() | |
| 78 * l_int32 pixGetSpp() | |
| 79 * l_int32 pixSetSpp() | |
| 80 * l_int32 pixCopySpp() | |
| 81 * l_int32 pixGetWpl() | |
| 82 * l_int32 pixSetWpl() | |
| 83 * l_uint32 pixGetXRes() | |
| 84 * l_int32 pixSetXRes() | |
| 85 * l_uint32 pixGetYRes() | |
| 86 * l_int32 pixSetYRes() | |
| 87 * l_int32 pixGetResolution() | |
| 88 * l_int32 pixSetResolution() | |
| 89 * l_int32 pixCopyResolution() | |
| 90 * l_int32 pixScaleResolution() | |
| 91 * l_int32 pixGetInputFormat() | |
| 92 * l_int32 pixSetInputFormat() | |
| 93 * l_int32 pixCopyInputFormat() | |
| 94 * l_int32 pixSetSpecial() | |
| 95 * char *pixGetText() | |
| 96 * l_int32 pixSetText() | |
| 97 * l_int32 pixAddText() | |
| 98 * l_int32 pixCopyText() | |
| 99 * l_uint8 *pixGetTextCompNew() | |
| 100 * l_int32 *pixSetTextCompNew() | |
| 101 * PIXCMAP *pixGetColormap() | |
| 102 * l_int32 pixSetColormap() | |
| 103 * l_int32 pixDestroyColormap() | |
| 104 * l_uint32 *pixGetData() | |
| 105 * l_int32 pixFreeAndSetData() | |
| 106 * l_int32 pixSetData() | |
| 107 * l_int32 pixFreeData() | |
| 108 * l_uint32 *pixExtractData() | |
| 109 * | |
| 110 * Pix line ptrs | |
| 111 * void **pixGetLinePtrs() | |
| 112 * | |
| 113 * Pix size comparisons | |
| 114 * l_int32 pixSizesEqual() | |
| 115 * l_int32 pixMaxAspectRatio() | |
| 116 * | |
| 117 * Pix debug | |
| 118 * l_int32 pixPrintStreamInfo() | |
| 119 * | |
| 120 * | |
| 121 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
| 122 * Important notes on direct management of pix image data | |
| 123 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
| 124 * | |
| 125 * Custom allocator and deallocator | |
| 126 * -------------------------------- | |
| 127 * | |
| 128 * At the lowest level, you can specify the function that does the | |
| 129 * allocation and deallocation of the data field in the pix. | |
| 130 * By default, this is malloc and free. However, by calling | |
| 131 * setPixMemoryManager(), custom functions can be substituted. | |
| 132 * When using this, keep two things in mind: | |
| 133 * | |
| 134 * (1) Call setPixMemoryManager() before any pix have been allocated | |
| 135 * (2) Destroy all pix as usual, in order to prevent leaks. | |
| 136 * | |
| 137 * In pixalloc.c, we provide an example custom allocator and deallocator. | |
| 138 * To use it, you must call pmsCreate() before any pix have been allocated | |
| 139 * and pmsDestroy() at the end after all pix have been destroyed. | |
| 140 * | |
| 141 * | |
| 142 * Direct manipulation of the pix data field | |
| 143 * ----------------------------------------- | |
| 144 * | |
| 145 * Memory management of the (image) data field in the pix is | |
| 146 * handled differently from that in the colormap and text fields. | |
| 147 * For colormap and text, the functions pixSetColormap() and | |
| 148 * pixSetText() remove the existing heap data and insert the | |
| 149 * new data. For the image data, pixSetData() just reassigns the | |
| 150 * data field; any existing data will be lost if there isn't | |
| 151 * another handle for it. | |
| 152 * | |
| 153 * Why is pixSetData() limited in this way? Because the image | |
| 154 * data can be very large, we need flexible ways to handle it, | |
| 155 * particularly when you want to re-use the data in a different | |
| 156 * context without making a copy. Here are some different | |
| 157 * things you might want to do: | |
| 158 * | |
| 159 * (1) Use pixCopy(pixd, pixs) where pixd is not the same size | |
| 160 * as pixs. This will remove the data in pixd, allocate a | |
| 161 * new data field in pixd, and copy the data from pixs, leaving | |
| 162 * pixs unchanged. | |
| 163 * | |
| 164 * (2) Use pixTransferAllData(pixd, &pixs, ...) to transfer the | |
| 165 * data from pixs to pixd without making a copy of it. If | |
| 166 * pixs is not cloned, this will do the transfer and destroy pixs. | |
| 167 * But if the refcount of pixs is greater than 1, it just copies | |
| 168 * the data and decrements the ref count. | |
| 169 * | |
| 170 * (3) Use pixSwapAndDestroy(pixd, &pixs) to replace pixs by an | |
| 171 * existing pixd. This is similar to pixTransferAllData(), but | |
| 172 * simpler, in that it never makes any copies and if pixs is | |
| 173 * cloned, the other references are not changed by this operation. | |
| 174 * | |
| 175 * (4) Use pixExtractData() to extract the image data from the pix | |
| 176 * without copying if possible. This could be used, for example, | |
| 177 * to convert from a pix to some other data structure with minimal | |
| 178 * heap allocation. After the data is extracated, the pixels can | |
| 179 * be munged and used in another context. However, the danger | |
| 180 * here is that the pix might have a refcount > 1, in which case | |
| 181 * a copy of the data must be made and the input pix left unchanged. | |
| 182 * If there are no clones, the image data can be extracted without | |
| 183 * a copy, and the data ptr in the pix must be nulled before | |
| 184 * destroying it because the pix will no longer 'own' the data. | |
| 185 * | |
| 186 * We have provided accessors and functions here that should be | |
| 187 * sufficient so that you can do anything you want without | |
| 188 * explicitly referencing any of the pix member fields. | |
| 189 * | |
| 190 * However, to avoid memory smashes and leaks when doing special operations | |
| 191 * on the pix data field, look carefully at the behavior of the image | |
| 192 * data accessors and keep in mind that when you invoke pixDestroy(), | |
| 193 * the pix considers itself the owner of all its heap data. | |
| 194 * </pre> | |
| 195 */ | |
| 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 | |
| 205 static void pixFree(PIX *pix); | |
| 206 | |
| 207 /*-------------------------------------------------------------------------* | |
| 208 * Pix Memory Management * | |
| 209 * * | |
| 210 * These functions give you the freedom to specify at compile or run * | |
| 211 * time the allocator and deallocator to be used for the pix raster * | |
| 212 * image data. They have no effect on any other heap allocation, * | |
| 213 * including the pix struct itself, which is controlled by the * | |
| 214 * #defines in environ.h. * | |
| 215 * * | |
| 216 * The default functions for allocating pix raster data are malloc and * | |
| 217 * free (or leptonica_* custom allocators if LEPTONICA_INTERCEPT_ALLOC * | |
| 218 * is defined). Use setPixMemoryManager() to specify other functions * | |
| 219 * to use specifically for pix raster image data. * | |
| 220 *-------------------------------------------------------------------------*/ | |
| 221 /*! Pix memory manager */ | |
| 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 */ | |
| 229 struct PixMemoryManager | |
| 230 { | |
| 231 alloc_fn allocator; | |
| 232 dealloc_fn deallocator; | |
| 233 }; | |
| 234 | |
| 235 /*! Default Pix memory manager */ | |
| 236 static struct PixMemoryManager pix_mem_manager = { | |
| 237 #ifdef LEPTONICA_INTERCEPT_ALLOC | |
| 238 &leptonica_malloc, | |
| 239 &leptonica_free | |
| 240 #else | |
| 241 &malloc, | |
| 242 &free | |
| 243 #endif /* LEPTONICA_INTERCEPT_ALLOC */ | |
| 244 }; | |
| 245 | |
| 246 static void * | |
| 247 pixdata_malloc(size_t size) | |
| 248 { | |
| 249 #ifndef _MSC_VER | |
| 250 return (*pix_mem_manager.allocator)(size); | |
| 251 #else /* _MSC_VER */ | |
| 252 /* Under MSVC++, pix_mem_manager is initialized after a call to | |
| 253 * pixdata_malloc. Just ignore the custom allocator feature. */ | |
| 254 return LEPT_MALLOC(size); | |
| 255 #endif /* _MSC_VER */ | |
| 256 } | |
| 257 | |
| 258 static void | |
| 259 pixdata_free(void *ptr) | |
| 260 { | |
| 261 #ifndef _MSC_VER | |
| 262 (*pix_mem_manager.deallocator)(ptr); | |
| 263 #else /* _MSC_VER */ | |
| 264 /* Under MSVC++, pix_mem_manager is initialized after a call to | |
| 265 * pixdata_malloc. Just ignore the custom allocator feature. */ | |
| 266 LEPT_FREE(ptr); | |
| 267 #endif /* _MSC_VER */ | |
| 268 } | |
| 269 | |
| 270 /*! | |
| 271 * \brief setPixMemoryManager() | |
| 272 * | |
| 273 * \param[in] allocator [optional] use NULL to skip | |
| 274 * \param[in] deallocator [optional] use NULL to skip | |
| 275 * \return void | |
| 276 * | |
| 277 * <pre> | |
| 278 * Notes: | |
| 279 * (1) Use this to change the alloc and/or dealloc functions; | |
| 280 * e.g., setPixMemoryManager(my_malloc, my_free). | |
| 281 * (2) The C99 standard (section 6.7.5.3, par. 8) says: | |
| 282 * A declaration of a parameter as "function returning type" | |
| 283 * shall be adjusted to "pointer to function returning type" | |
| 284 * so that it can be in either of these two forms: | |
| 285 * (a) type (function-ptr(type, ...)) | |
| 286 * (b) type ((*function-ptr)(type, ...)) | |
| 287 * because form (a) is implicitly converted to form (b), as in the | |
| 288 * definition of struct PixMemoryManager above. So, for example, | |
| 289 * we should be able to declare either of these: | |
| 290 * (a) void *(allocator(size_t)) | |
| 291 * (b) void *((*allocator)(size_t)) | |
| 292 * However, MSVC++ only accepts the second version. | |
| 293 * </pre> | |
| 294 */ | |
| 295 void | |
| 296 setPixMemoryManager(alloc_fn allocator, | |
| 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 *--------------------------------------------------------------------*/ | |
| 307 /*! | |
| 308 * \brief pixCreate() | |
| 309 * | |
| 310 * \param[in] width, height, depth | |
| 311 * \return pixd with data allocated and initialized to 0, | |
| 312 * or NULL on error | |
| 313 */ | |
| 314 PIX * | |
| 315 pixCreate(l_int32 width, | |
| 316 l_int32 height, | |
| 317 l_int32 depth) | |
| 318 { | |
| 319 PIX *pixd; | |
| 320 | |
| 321 if ((pixd = pixCreateNoInit(width, height, depth)) == NULL) | |
| 322 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); | |
| 323 memset(pixd->data, 0, 4LL * pixd->wpl * pixd->h); | |
| 324 return pixd; | |
| 325 } | |
| 326 | |
| 327 | |
| 328 /*! | |
| 329 * \brief pixCreateNoInit() | |
| 330 * | |
| 331 * \param[in] width, height, depth | |
| 332 * \return pixd with data allocated but not initialized, | |
| 333 * or NULL on error | |
| 334 * | |
| 335 * <pre> | |
| 336 * Notes: | |
| 337 * (1) Pad bits are set to avoid reading uninitialized data, because | |
| 338 * some optimized routines read from pad bits. | |
| 339 * (2) Initializing memory is very fast, so this optimization is | |
| 340 * not used in the library. | |
| 341 * </pre> | |
| 342 */ | |
| 343 PIX * | |
| 344 pixCreateNoInit(l_int32 width, | |
| 345 l_int32 height, | |
| 346 l_int32 depth) | |
| 347 { | |
| 348 l_int32 wpl; | |
| 349 PIX *pixd; | |
| 350 l_uint32 *data; | |
| 351 | |
| 352 if ((pixd = pixCreateHeader(width, height, depth)) == NULL) | |
| 353 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); | |
| 354 wpl = pixGetWpl(pixd); | |
| 355 if ((data = (l_uint32 *)pixdata_malloc(4LL * wpl * height)) == NULL) { | |
| 356 pixDestroy(&pixd); | |
| 357 return (PIX *)ERROR_PTR("pixdata_malloc fail for data", | |
| 358 __func__, NULL); | |
| 359 } | |
| 360 pixSetData(pixd, data); | |
| 361 pixSetPadBits(pixd, 0); | |
| 362 return pixd; | |
| 363 } | |
| 364 | |
| 365 | |
| 366 /*! | |
| 367 * \brief pixCreateTemplate() | |
| 368 * | |
| 369 * \param[in] pixs | |
| 370 * \return pixd, or NULL on error | |
| 371 * | |
| 372 * <pre> | |
| 373 * Notes: | |
| 374 * (1) Makes a Pix of the same size as the input Pix, with the | |
| 375 * data array allocated and initialized to 0. | |
| 376 * (2) Copies the other fields, including colormap if it exists. | |
| 377 * </pre> | |
| 378 */ | |
| 379 PIX * | |
| 380 pixCreateTemplate(const PIX *pixs) | |
| 381 { | |
| 382 PIX *pixd; | |
| 383 | |
| 384 if (!pixs) | |
| 385 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL); | |
| 386 | |
| 387 if ((pixd = pixCreateTemplateNoInit(pixs)) == NULL) | |
| 388 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); | |
| 389 memset(pixd->data, 0, 4LL * pixd->wpl * pixd->h); | |
| 390 return pixd; | |
| 391 } | |
| 392 | |
| 393 | |
| 394 /*! | |
| 395 * \brief pixCreateTemplateNoInit() | |
| 396 * | |
| 397 * \param[in] pixs | |
| 398 * \return pixd, or NULL on error | |
| 399 * | |
| 400 * <pre> | |
| 401 * Notes: | |
| 402 * (1) Makes a Pix of the same size as the input Pix, with | |
| 403 * the data array allocated but not initialized to 0. | |
| 404 * (2) Copies the other fields, including colormap if it exists. | |
| 405 * (3) Pad bits are set to avoid reading uninitialized data, because | |
| 406 * some optimized routines read from pad bits. | |
| 407 * (4) Initializing memory is very fast, so this optimization is | |
| 408 * not used in the library. | |
| 409 * </pre> | |
| 410 */ | |
| 411 PIX * | |
| 412 pixCreateTemplateNoInit(const PIX *pixs) | |
| 413 { | |
| 414 l_int32 w, h, d; | |
| 415 PIX *pixd; | |
| 416 | |
| 417 if (!pixs) | |
| 418 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL); | |
| 419 | |
| 420 pixGetDimensions(pixs, &w, &h, &d); | |
| 421 if ((pixd = pixCreateNoInit(w, h, d)) == NULL) | |
| 422 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); | |
| 423 pixCopySpp(pixd, pixs); | |
| 424 pixCopyResolution(pixd, pixs); | |
| 425 pixCopyColormap(pixd, pixs); | |
| 426 pixCopyText(pixd, pixs); | |
| 427 pixCopyInputFormat(pixd, pixs); | |
| 428 pixSetPadBits(pixd, 0); | |
| 429 return pixd; | |
| 430 } | |
| 431 | |
| 432 | |
| 433 /*! | |
| 434 * \brief pixCreateWithCmap() | |
| 435 * | |
| 436 * \param[in] width | |
| 437 * \param[in] height | |
| 438 * \param[in] depth 2, 4 or 8 bpp | |
| 439 * \param[in] initcolor L_SET_BLACK, L_SET_WHITE | |
| 440 * \return pixd with the initialization color assigned to all pixels, | |
| 441 * or NULL on error. | |
| 442 * | |
| 443 * <pre> | |
| 444 * Notes: | |
| 445 * (1) Creates a pix with a cmap, initialized to value 0. | |
| 446 * (2) Initializes the pix black or white by adding that color | |
| 447 * to the cmap at index 0. | |
| 448 * </pre> | |
| 449 */ | |
| 450 PIX * | |
| 451 pixCreateWithCmap(l_int32 width, | |
| 452 l_int32 height, | |
| 453 l_int32 depth, | |
| 454 l_int32 initcolor) | |
| 455 { | |
| 456 PIX *pix; | |
| 457 PIXCMAP *cmap; | |
| 458 | |
| 459 if (depth != 2 && depth != 4 && depth != 8) | |
| 460 return (PIX *)ERROR_PTR("depth not 2, 4 or 8 bpp", __func__, NULL); | |
| 461 | |
| 462 if ((pix = pixCreate(width, height, depth)) == NULL) | |
| 463 return (PIX *)ERROR_PTR("pix not made", __func__, NULL); | |
| 464 cmap = pixcmapCreate(depth); | |
| 465 pixSetColormap(pix, cmap); | |
| 466 if (initcolor == L_SET_BLACK) | |
| 467 pixcmapAddColor(cmap, 0, 0, 0); | |
| 468 else /* L_SET_WHITE */ | |
| 469 pixcmapAddColor(cmap, 255, 255, 255); | |
| 470 return pix; | |
| 471 } | |
| 472 | |
| 473 | |
| 474 /*! | |
| 475 * \brief pixCreateHeader() | |
| 476 * | |
| 477 * \param[in] width, height, depth | |
| 478 * \return pixd with no data allocated, or NULL on error | |
| 479 * | |
| 480 * <pre> | |
| 481 * Notes: | |
| 482 * (1) It is assumed that all 32 bit pix have 3 spp. If there is | |
| 483 * a valid alpha channel, this will be set to 4 spp later. | |
| 484 * (2) All pixCreate*() functions call pixCreateHeader(). | |
| 485 If the number of bytes to be allocated is larger than the | |
| 486 * maximum value in an int32, we can get overflow, resulting | |
| 487 * in a smaller amount of memory actually being allocated. | |
| 488 * Later, an attempt to access memory that wasn't allocated will | |
| 489 * cause a crash. So to avoid crashing a program (or worse) | |
| 490 * with bad (or malicious) input, we limit the requested | |
| 491 * allocation of image data in a typesafe way. | |
| 492 * </pre> | |
| 493 */ | |
| 494 PIX * | |
| 495 pixCreateHeader(l_int32 width, | |
| 496 l_int32 height, | |
| 497 l_int32 depth) | |
| 498 { | |
| 499 l_int32 wpl; | |
| 500 l_uint64 wpl64, bignum; | |
| 501 PIX *pixd; | |
| 502 | |
| 503 if ((depth != 1) && (depth != 2) && (depth != 4) && (depth != 8) | |
| 504 && (depth != 16) && (depth != 24) && (depth != 32)) | |
| 505 return (PIX *)ERROR_PTR("depth must be {1, 2, 4, 8, 16, 24, 32}", | |
| 506 __func__, NULL); | |
| 507 if (width <= 0) | |
| 508 return (PIX *)ERROR_PTR("width must be > 0", __func__, NULL); | |
| 509 if (height <= 0) | |
| 510 return (PIX *)ERROR_PTR("height must be > 0", __func__, NULL); | |
| 511 | |
| 512 /* Avoid overflow in malloc, malicious or otherwise */ | |
| 513 wpl64 = ((l_uint64)width * (l_uint64)depth + 31) / 32; | |
| 514 if (wpl64 > ((1LL << 24) - 1)) { | |
| 515 L_ERROR("requested w = %d, h = %d, d = %d\n", | |
| 516 __func__, width, height, depth); | |
| 517 return (PIX *)ERROR_PTR("wpl >= 2^24", __func__, NULL); | |
| 518 } | |
| 519 wpl = (l_int32)wpl64; | |
| 520 bignum = 4LL * wpl * height; /* number of bytes to be requested */ | |
| 521 if (bignum > ((1LL << 31) - 1)) { | |
| 522 L_ERROR("requested w = %d, h = %d, d = %d\n", | |
| 523 __func__, width, height, depth); | |
| 524 return (PIX *)ERROR_PTR("requested bytes >= 2^31", __func__, NULL); | |
| 525 } | |
| 526 | |
| 527 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | |
| 528 if (bignum > (1LL << 26)) { | |
| 529 L_ERROR("fuzzer requested > 64 MB; refused\n", __func__); | |
| 530 return NULL; | |
| 531 } | |
| 532 if (width > 20000) { | |
| 533 L_ERROR("fuzzer requested width > 20K; refused\n", __func__); | |
| 534 return NULL; | |
| 535 } | |
| 536 if (height > 20000) { | |
| 537 L_ERROR("fuzzer requested height > 20K; refused\n", __func__); | |
| 538 return NULL; | |
| 539 } | |
| 540 #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ | |
| 541 | |
| 542 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 | |
| 558 /*! | |
| 559 * \brief pixClone() | |
| 560 * | |
| 561 * \param[in] pixs | |
| 562 * \return same pix ptr, or NULL on error | |
| 563 * | |
| 564 * <pre> | |
| 565 * Notes: | |
| 566 * (1) A "clone" is simply a handle (ptr) to an existing pix. | |
| 567 * It is implemented because (a) images can be large and | |
| 568 * hence expensive to copy, and (b) extra handles to a data | |
| 569 * structure need to be made with a simple policy to avoid | |
| 570 * both double frees and memory leaks. Pix are reference | |
| 571 * counted. The side effect of pixClone() is an increase | |
| 572 * by 1 in the ref count. | |
| 573 * (2) The protocol to be used is: | |
| 574 * (a) Whenever you want a new handle to an existing image, | |
| 575 * call pixClone(), which just bumps a ref count. | |
| 576 * (b) Always call pixDestroy() on all handles. This | |
| 577 * decrements the ref count, nulls the handle, and | |
| 578 * only destroys the pix when pixDestroy() has been | |
| 579 * called on all handles. | |
| 580 * </pre> | |
| 581 */ | |
| 582 PIX * | |
| 583 pixClone(PIX *pixs) | |
| 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 *--------------------------------------------------------------------*/ | |
| 596 /*! | |
| 597 * \brief pixDestroy() | |
| 598 * | |
| 599 * \param[in,out] ppix will be set to null before returning | |
| 600 * \return void | |
| 601 * | |
| 602 * <pre> | |
| 603 * Notes: | |
| 604 * (1) Decrements the ref count and, if 0, destroys the pix. | |
| 605 * (2) Always nulls the input ptr. | |
| 606 * </pre> | |
| 607 */ | |
| 608 void | |
| 609 pixDestroy(PIX **ppix) | |
| 610 { | |
| 611 PIX *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 | |
| 625 /*! | |
| 626 * \brief pixFree() | |
| 627 * | |
| 628 * \param[in] pix | |
| 629 * \return void | |
| 630 * | |
| 631 * <pre> | |
| 632 * Notes: | |
| 633 * (1) Decrements the ref count and, if 0, destroys the pix. | |
| 634 * </pre> | |
| 635 */ | |
| 636 static void | |
| 637 pixFree(PIX *pix) | |
| 638 { | |
| 639 l_uint32 *data; | |
| 640 char *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); | |
| 649 pixDestroyColormap(pix); | |
| 650 LEPT_FREE(pix); | |
| 651 } | |
| 652 return; | |
| 653 } | |
| 654 | |
| 655 | |
| 656 /*-------------------------------------------------------------------------* | |
| 657 * Pix Copy * | |
| 658 *-------------------------------------------------------------------------*/ | |
| 659 /*! | |
| 660 * \brief pixCopy() | |
| 661 * | |
| 662 * \param[in] pixd [optional] can be null, equal to pixs, | |
| 663 * different from pixs | |
| 664 * \param[in] pixs | |
| 665 * \return pixd, or NULL on error | |
| 666 * | |
| 667 * <pre> | |
| 668 * Notes: | |
| 669 * (1) There are three cases: | |
| 670 * (a) pixd == null (makes a new pix; refcount = 1) | |
| 671 * (b) pixd == pixs (no-op) | |
| 672 * (c) pixd != pixs (data copy; no change in refcount) | |
| 673 * If the refcount of pixd > 1, case (c) will side-effect | |
| 674 * these handles. | |
| 675 * (2) The general pattern of use is: | |
| 676 * pixd = pixCopy(pixd, pixs); | |
| 677 * This will work for all three cases. | |
| 678 * For clarity when the case is known, you can use: | |
| 679 * (a) pixd = pixCopy(NULL, pixs); | |
| 680 * (c) pixCopy(pixd, pixs); | |
| 681 * (3) For case (c), we check if pixs and pixd are the same | |
| 682 * size (w,h,d). If so, the data is copied directly. | |
| 683 * Otherwise, the data is reallocated to the correct size | |
| 684 * and the copy proceeds. The refcount of pixd is unchanged. | |
| 685 * (4) This operation, like all others that may involve a pre-existing | |
| 686 * pixd, will side-effect any existing clones of pixd. | |
| 687 * </pre> | |
| 688 */ | |
| 689 PIX * | |
| 690 pixCopy(PIX *pixd, /* can be null */ | |
| 691 const PIX *pixs) | |
| 692 { | |
| 693 l_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 | |
| 733 /*! | |
| 734 * \brief pixResizeImageData() | |
| 735 * | |
| 736 * \param[in] pixd gets new uninitialized buffer for image data | |
| 737 * \param[in] pixs determines the size of the buffer; not changed | |
| 738 * \return 0 if OK, 1 on error | |
| 739 * | |
| 740 * <pre> | |
| 741 * Notes: | |
| 742 * (1) If the sizes of data in pixs and pixd are unequal, this | |
| 743 * frees the existing image data in pixd and allocates | |
| 744 * an uninitialized buffer that will hold the required amount | |
| 745 * of image data in pixs. The image data from pixs is not | |
| 746 * copied into the new buffer. | |
| 747 * (2) On failure to allocate, pixd is unchanged. | |
| 748 * </pre> | |
| 749 */ | |
| 750 l_ok | |
| 751 pixResizeImageData(PIX *pixd, | |
| 752 const PIX *pixs) | |
| 753 { | |
| 754 l_int32 w, h, d, wpl, bytes; | |
| 755 l_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 | |
| 783 /*! | |
| 784 * \brief pixCopyColormap() | |
| 785 * | |
| 786 * \param[in] pixd | |
| 787 * \param[in] pixs copies the colormap to %pixd | |
| 788 * \return 0 if OK, 1 on error | |
| 789 * | |
| 790 * <pre> | |
| 791 * Notes: | |
| 792 * (1) This destroys the colormap in pixd, unless the operation is a no-op | |
| 793 * </pre> | |
| 794 */ | |
| 795 l_ok | |
| 796 pixCopyColormap(PIX *pixd, | |
| 797 const PIX *pixs) | |
| 798 { | |
| 799 l_int32 valid; | |
| 800 const PIXCMAP *cmaps; | |
| 801 PIXCMAP *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 | |
| 826 /*! | |
| 827 * \brief pixTransferAllData() | |
| 828 * | |
| 829 * \param[in] pixd must be different from pixs | |
| 830 * \param[in,out] ppixs will be nulled if refcount goes to 0 | |
| 831 * \param[in] copytext 1 to copy the text field; 0 to skip | |
| 832 * \param[in] copyformat 1 to copy the informat field; 0 to skip | |
| 833 * \return 0 if OK, 1 on error | |
| 834 * | |
| 835 * <pre> | |
| 836 * Notes: | |
| 837 * (1) This does a complete data transfer from pixs to pixd, | |
| 838 * followed by the destruction of pixs (refcount permitting). | |
| 839 * (2) If the refcount of pixs is 1, pixs is destroyed. Otherwise, | |
| 840 * the data in pixs is copied (rather than transferred) to pixd. | |
| 841 * (3) This operation, like all others with a pre-existing pixd, | |
| 842 * will side-effect any existing clones of pixd. The pixd | |
| 843 * refcount does not change. | |
| 844 * (4) When might you use this? Suppose you have an in-place Pix | |
| 845 * function (returning void) with the typical signature: | |
| 846 * void function-inplace(PIX *pix, ...) | |
| 847 * where "..." are non-pointer input parameters, and suppose | |
| 848 * further that you sometimes want to return an arbitrary Pix | |
| 849 * in place of the input Pix. There are two ways you can do this: | |
| 850 * (a) The straightforward way is to change the function | |
| 851 * signature to take the address of the Pix ptr: | |
| 852 * \code | |
| 853 * void function-inplace(PIX **ppix, ...) { | |
| 854 * PIX *pixt = function-makenew(*ppix); | |
| 855 * pixDestroy(ppix); | |
| 856 * *ppix = pixt; | |
| 857 * return; | |
| 858 * } | |
| 859 * \endcode | |
| 860 * Here, the input and returned pix are different, as viewed | |
| 861 * by the calling function, and the inplace function is | |
| 862 * expected to destroy the input pix to avoid a memory leak. | |
| 863 * (b) Keep the signature the same and use pixTransferAllData() | |
| 864 * to return the new Pix in the input Pix struct: | |
| 865 * \code | |
| 866 * void function-inplace(PIX *pix, ...) { | |
| 867 * PIX *pixt = function-makenew(pix); | |
| 868 * pixTransferAllData(pix, &pixt, 0, 0); | |
| 869 * // pixDestroy() is called on pixt | |
| 870 * return; | |
| 871 * } | |
| 872 * \endcode | |
| 873 * Here, the input and returned pix are the same, as viewed | |
| 874 * by the calling function, and the inplace function must | |
| 875 * never destroy the input pix, because the calling function | |
| 876 * maintains an unchanged handle to it. | |
| 877 * </pre> | |
| 878 */ | |
| 879 l_ok | |
| 880 pixTransferAllData(PIX *pixd, | |
| 881 PIX **ppixs, | |
| 882 l_int32 copytext, | |
| 883 l_int32 copyformat) | |
| 884 { | |
| 885 l_int32 nbytes; | |
| 886 PIX *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 | |
| 930 /*! | |
| 931 * \brief pixSwapAndDestroy() | |
| 932 * | |
| 933 * \param[out] ppixd [optional] input pixd can be null, | |
| 934 * and it must be different from pixs | |
| 935 * \param[in,out] ppixs will be nulled after the swap | |
| 936 * \return 0 if OK, 1 on error | |
| 937 * | |
| 938 * <pre> | |
| 939 * Notes: | |
| 940 * (1) Simple operation to change the handle name safely. | |
| 941 * After this operation, the original image in pixd has | |
| 942 * been destroyed, pixd points to what was pixs, and | |
| 943 * the input pixs ptr has been nulled. | |
| 944 * (2) This works safely whether or not pixs and pixd are cloned. | |
| 945 * If pixs is cloned, the other handles still point to | |
| 946 * the original image, with the ref count reduced by 1. | |
| 947 * (3) Usage example: | |
| 948 * \code | |
| 949 * Pix *pix1 = pixRead("..."); | |
| 950 * Pix *pix2 = function(pix1, ...); | |
| 951 * pixSwapAndDestroy(&pix1, &pix2); | |
| 952 * pixDestroy(&pix1); // holds what was in pix2 | |
| 953 * \endcode | |
| 954 * Example with clones ([] shows ref count of image generated | |
| 955 * by the function): | |
| 956 * \code | |
| 957 * Pix *pixs = pixRead("..."); | |
| 958 * Pix *pix1 = pixClone(pixs); | |
| 959 * Pix *pix2 = function(pix1, ...); [1] | |
| 960 * Pix *pix3 = pixClone(pix2); [1] --> [2] | |
| 961 * pixSwapAndDestroy(&pix1, &pix2); | |
| 962 * pixDestroy(&pixs); // still holds read image | |
| 963 * pixDestroy(&pix1); // holds what was in pix2 [2] --> [1] | |
| 964 * pixDestroy(&pix3); // holds what was in pix2 [1] --> [0] | |
| 965 * \endcode | |
| 966 * </pre> | |
| 967 */ | |
| 968 l_ok | |
| 969 pixSwapAndDestroy(PIX **ppixd, | |
| 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 *--------------------------------------------------------------------*/ | |
| 991 l_int32 | |
| 992 pixGetWidth(const PIX *pix) | |
| 993 { | |
| 994 if (!pix) | |
| 995 return ERROR_INT("pix not defined", __func__, 0); | |
| 996 | |
| 997 return pix->w; | |
| 998 } | |
| 999 | |
| 1000 | |
| 1001 l_int32 | |
| 1002 pixSetWidth(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 | |
| 1017 l_int32 | |
| 1018 pixGetHeight(const PIX *pix) | |
| 1019 { | |
| 1020 if (!pix) | |
| 1021 return ERROR_INT("pix not defined", __func__, 0); | |
| 1022 | |
| 1023 return pix->h; | |
| 1024 } | |
| 1025 | |
| 1026 | |
| 1027 l_int32 | |
| 1028 pixSetHeight(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 | |
| 1043 l_int32 | |
| 1044 pixGetDepth(const PIX *pix) | |
| 1045 { | |
| 1046 if (!pix) | |
| 1047 return ERROR_INT("pix not defined", __func__, 0); | |
| 1048 | |
| 1049 return pix->d; | |
| 1050 } | |
| 1051 | |
| 1052 | |
| 1053 l_int32 | |
| 1054 pixSetDepth(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 | |
| 1067 /*! | |
| 1068 * \brief pixGetDimensions() | |
| 1069 * | |
| 1070 * \param[in] pix | |
| 1071 * \param[out] pw, ph, pd [optional] each can be null | |
| 1072 * \return 0 if OK, 1 on error | |
| 1073 */ | |
| 1074 l_ok | |
| 1075 pixGetDimensions(const PIX *pix, | |
| 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 | |
| 1092 /*! | |
| 1093 * \brief pixSetDimensions() | |
| 1094 * | |
| 1095 * \param[in] pix | |
| 1096 * \param[in] w, h, d use 0 to skip the setting for any of these | |
| 1097 * \return 0 if OK, 1 on error | |
| 1098 */ | |
| 1099 l_ok | |
| 1100 pixSetDimensions(PIX *pix, | |
| 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 | |
| 1114 /*! | |
| 1115 * \brief pixCopyDimensions() | |
| 1116 * | |
| 1117 * \param[in] pixd | |
| 1118 * \param[in] pixs | |
| 1119 * \return 0 if OK, 1 on error | |
| 1120 */ | |
| 1121 l_ok | |
| 1122 pixCopyDimensions(PIX *pixd, | |
| 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 | |
| 1140 l_int32 | |
| 1141 pixGetSpp(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 */ | |
| 1166 l_int32 | |
| 1167 pixSetSpp(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 | |
| 1180 /*! | |
| 1181 * \brief pixCopySpp() | |
| 1182 * | |
| 1183 * \param[in] pixd | |
| 1184 * \param[in] pixs | |
| 1185 * \return 0 if OK, 1 on error | |
| 1186 */ | |
| 1187 l_ok | |
| 1188 pixCopySpp(PIX *pixd, | |
| 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 | |
| 1203 l_int32 | |
| 1204 pixGetWpl(const PIX *pix) | |
| 1205 { | |
| 1206 if (!pix) | |
| 1207 return ERROR_INT("pix not defined", __func__, 0); | |
| 1208 return pix->wpl; | |
| 1209 } | |
| 1210 | |
| 1211 | |
| 1212 l_int32 | |
| 1213 pixSetWpl(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 | |
| 1224 l_int32 | |
| 1225 pixGetXRes(const PIX *pix) | |
| 1226 { | |
| 1227 if (!pix) | |
| 1228 return ERROR_INT("pix not defined", __func__, 0); | |
| 1229 return pix->xres; | |
| 1230 } | |
| 1231 | |
| 1232 | |
| 1233 l_int32 | |
| 1234 pixSetXRes(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 | |
| 1245 l_int32 | |
| 1246 pixGetYRes(const PIX *pix) | |
| 1247 { | |
| 1248 if (!pix) | |
| 1249 return ERROR_INT("pix not defined", __func__, 0); | |
| 1250 return pix->yres; | |
| 1251 } | |
| 1252 | |
| 1253 | |
| 1254 l_int32 | |
| 1255 pixSetYRes(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 | |
| 1266 /*! | |
| 1267 * \brief pixGetResolution() | |
| 1268 * | |
| 1269 * \param[in] pix | |
| 1270 * \param[out] pxres, pyres [optional] each can be null | |
| 1271 * \return 0 if OK, 1 on error | |
| 1272 */ | |
| 1273 l_ok | |
| 1274 pixGetResolution(const PIX *pix, | |
| 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 | |
| 1290 /*! | |
| 1291 * \brief pixSetResolution() | |
| 1292 * | |
| 1293 * \param[in] pix | |
| 1294 * \param[in] xres, yres use 0 to skip setting a value for either of these | |
| 1295 * \return 0 if OK, 1 on error | |
| 1296 */ | |
| 1297 l_ok | |
| 1298 pixSetResolution(PIX *pix, | |
| 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 | |
| 1310 l_int32 | |
| 1311 pixCopyResolution(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 | |
| 1327 l_int32 | |
| 1328 pixScaleResolution(PIX *pix, | |
| 1329 l_float32 xscale, | |
| 1330 l_float32 yscale) | |
| 1331 { | |
| 1332 l_float64 xres, yres; | |
| 1333 l_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 | |
| 1348 l_int32 | |
| 1349 pixGetInputFormat(const PIX *pix) | |
| 1350 { | |
| 1351 if (!pix) | |
| 1352 return ERROR_INT("pix not defined", __func__, 0); | |
| 1353 return pix->informat; | |
| 1354 } | |
| 1355 | |
| 1356 | |
| 1357 l_int32 | |
| 1358 pixSetInputFormat(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 | |
| 1368 l_int32 | |
| 1369 pixCopyInputFormat(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 | |
| 1384 l_int32 | |
| 1385 pixSetSpecial(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 | |
| 1395 /*! | |
| 1396 * \brief pixGetText() | |
| 1397 * | |
| 1398 * \param[in] pix | |
| 1399 * \return ptr to existing text string | |
| 1400 * | |
| 1401 * <pre> | |
| 1402 * Notes: | |
| 1403 * (1) The text string belongs to the pix: | |
| 1404 * * the caller must NOT free it | |
| 1405 * * it must not be used after the pix is destroyed | |
| 1406 * </pre> | |
| 1407 */ | |
| 1408 char * | |
| 1409 pixGetText(PIX *pix) | |
| 1410 { | |
| 1411 if (!pix) | |
| 1412 return (char *)ERROR_PTR("pix not defined", __func__, NULL); | |
| 1413 return pix->text; | |
| 1414 } | |
| 1415 | |
| 1416 | |
| 1417 /*! | |
| 1418 * \brief pixSetText() | |
| 1419 * | |
| 1420 * \param[in] pix | |
| 1421 * \param[in] textstring can be null | |
| 1422 * \return 0 if OK, 1 on error | |
| 1423 * | |
| 1424 * <pre> | |
| 1425 * Notes: | |
| 1426 * (1) This removes any existing textstring and puts a copy of | |
| 1427 * the input textstring there. | |
| 1428 * </pre> | |
| 1429 */ | |
| 1430 l_ok | |
| 1431 pixSetText(PIX *pix, | |
| 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 | |
| 1442 /*! | |
| 1443 * \brief pixAddText() | |
| 1444 * | |
| 1445 * \param[in] pix | |
| 1446 * \param[in] textstring can be null | |
| 1447 * \return 0 if OK, 1 on error | |
| 1448 * | |
| 1449 * <pre> | |
| 1450 * Notes: | |
| 1451 * (1) This adds the new textstring to any existing text. | |
| 1452 * (2) Either or both the existing text and the new text | |
| 1453 * string can be null. | |
| 1454 * </pre> | |
| 1455 */ | |
| 1456 l_ok | |
| 1457 pixAddText(PIX *pix, | |
| 1458 const char *textstring) | |
| 1459 { | |
| 1460 char *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 | |
| 1472 l_int32 | |
| 1473 pixCopyText(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 | |
| 1488 /*! | |
| 1489 * \brief pixGetTextCompNew() | |
| 1490 * | |
| 1491 * \param[in] pix | |
| 1492 * \param[out] psize this number of bytes of returned binary data | |
| 1493 * \return ptr to binary data derived from the text string in the pix, | |
| 1494 * after decoding and uncompressing | |
| 1495 * | |
| 1496 * <pre> | |
| 1497 * Notes: | |
| 1498 * (1) The ascii string in the text field of the input pix was | |
| 1499 * previously stored there using pixSetTextCompNew(). | |
| 1500 * (2) This retrieves the string and performs ascii85 decoding | |
| 1501 * followed by decompression on it. The returned binary data | |
| 1502 * is owned by the caller and must be freed. | |
| 1503 * </pre> | |
| 1504 */ | |
| 1505 l_uint8 * | |
| 1506 pixGetTextCompNew(PIX *pix, | |
| 1507 size_t *psize) | |
| 1508 { | |
| 1509 char *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 | |
| 1518 /*! | |
| 1519 * \brief pixSetTextCompNew() | |
| 1520 * | |
| 1521 * \param[in] pix | |
| 1522 * \param[in] data binary data | |
| 1523 * \param[in] size number of bytes of binary data | |
| 1524 * \return 0 if OK, 1 on error | |
| 1525 * | |
| 1526 * <pre> | |
| 1527 * Notes: | |
| 1528 * (1) This receives binary data and performs compression and ascii85 | |
| 1529 * encoding on it. The ascii result is stored in the input pix, | |
| 1530 * replacing any string that may be there. | |
| 1531 * (2) The input %data can be reconstructed using pixGetTextCompNew(). | |
| 1532 * </pre> | |
| 1533 */ | |
| 1534 l_ok | |
| 1535 pixSetTextCompNew(PIX *pix, | |
| 1536 const l_uint8 *data, | |
| 1537 size_t size) | |
| 1538 { | |
| 1539 size_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 | |
| 1550 PIXCMAP * | |
| 1551 pixGetColormap(PIX *pix) | |
| 1552 { | |
| 1553 if (!pix) | |
| 1554 return (PIXCMAP *)ERROR_PTR("pix not defined", __func__, NULL); | |
| 1555 return pix->colormap; | |
| 1556 } | |
| 1557 | |
| 1558 | |
| 1559 /*! | |
| 1560 * \brief pixSetColormap() | |
| 1561 * | |
| 1562 * \param[in] pix | |
| 1563 * \param[in] colormap optional; can be null. | |
| 1564 * \return 0 if OK, 1 on error. | |
| 1565 * | |
| 1566 * <pre> | |
| 1567 * Notes: | |
| 1568 * (1) If %colormap is not defined, this is a no-op. | |
| 1569 * (2) This destroys any existing colormap before assigning the | |
| 1570 * new %colormap to %pix. | |
| 1571 * (3) If the colormap is not valid, this returns 1. The caller | |
| 1572 * should check if there is a possibility that the pix and | |
| 1573 * colormap depths differ. | |
| 1574 * (4) This does not do the work of checking pixs for a pixel value | |
| 1575 * that is out of bounds for the colormap -- that only needs to | |
| 1576 * be done when reading and writing with an I/O library like | |
| 1577 * png and gif. | |
| 1578 * (5) Because colormaps are not ref counted, the new colormap | |
| 1579 * must not belong to any other pix. | |
| 1580 * </pre> | |
| 1581 */ | |
| 1582 l_ok | |
| 1583 pixSetColormap(PIX *pix, | |
| 1584 PIXCMAP *colormap) | |
| 1585 { | |
| 1586 l_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 | |
| 1603 /*! | |
| 1604 * \brief pixDestroyColormap() | |
| 1605 * | |
| 1606 * \param[in] pix | |
| 1607 * \return 0 if OK, 1 on error | |
| 1608 */ | |
| 1609 l_ok | |
| 1610 pixDestroyColormap(PIX *pix) | |
| 1611 { | |
| 1612 PIXCMAP *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 | |
| 1625 /*! | |
| 1626 * \brief pixGetData() | |
| 1627 * | |
| 1628 * \param[in] pix | |
| 1629 * \return ptr to image data | |
| 1630 * | |
| 1631 * <pre> | |
| 1632 * Notes: | |
| 1633 * (1) This gives a new handle for the data. The data is still | |
| 1634 * owned by the pix, so do not call LEPT_FREE() on it. | |
| 1635 * (2) This cannot guarantee that the pix data returned will not | |
| 1636 * be changed, so %pix cannot be declared const. And because | |
| 1637 * most imaging operations call this for access to the data, | |
| 1638 * this prevents them from declaring %pix to be const, even if | |
| 1639 * they only use the data for inspection. | |
| 1640 * </pre> | |
| 1641 */ | |
| 1642 l_uint32 * | |
| 1643 pixGetData(PIX *pix) | |
| 1644 { | |
| 1645 if (!pix) | |
| 1646 return (l_uint32 *)ERROR_PTR("pix not defined", __func__, NULL); | |
| 1647 return pix->data; | |
| 1648 } | |
| 1649 | |
| 1650 | |
| 1651 /*! | |
| 1652 * \brief pixFreeAndSetData() | |
| 1653 * | |
| 1654 * \param[in] pix | |
| 1655 * \param[in] data | |
| 1656 * \return 0 if OK, 1 on error | |
| 1657 * | |
| 1658 * <pre> | |
| 1659 * Notes: | |
| 1660 * (1) This frees the existing raster data in the pix and assigns %data. | |
| 1661 * </pre> | |
| 1662 */ | |
| 1663 l_int32 | |
| 1664 pixFreeAndSetData(PIX *pix, | |
| 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 | |
| 1676 /*! | |
| 1677 * \brief pixSetData() | |
| 1678 * | |
| 1679 * \param[in] pix | |
| 1680 * \param[in] data | |
| 1681 * \return 0 if OK, 1 on error | |
| 1682 * | |
| 1683 * <pre> | |
| 1684 * Notes: | |
| 1685 * (1) This does not free any existing data. To free existing | |
| 1686 * data, use pixFreeAndSetData() instead. | |
| 1687 * </pre> | |
| 1688 */ | |
| 1689 l_int32 | |
| 1690 pixSetData(PIX *pix, | |
| 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 | |
| 1701 /*! | |
| 1702 * \brief pixFreeData() | |
| 1703 * | |
| 1704 * \param[in] pix | |
| 1705 * \return 0 if OK, 1 on error | |
| 1706 * | |
| 1707 * <pre> | |
| 1708 * Notes: | |
| 1709 * (1) This frees the data and sets the pix data ptr to null. | |
| 1710 * It should be used before pixSetData() in the situation where | |
| 1711 * you want to free any existing data before doing | |
| 1712 * a subsequent assignment with pixSetData(). | |
| 1713 * </pre> | |
| 1714 */ | |
| 1715 l_int32 | |
| 1716 pixFreeData(PIX *pix) | |
| 1717 { | |
| 1718 l_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 | |
| 1731 /*! | |
| 1732 * \brief pixExtractData() | |
| 1733 * | |
| 1734 * \param[in] pix | |
| 1735 * \return ptr to data, or null on error | |
| 1736 * | |
| 1737 * <pre> | |
| 1738 * Notes: | |
| 1739 * (1) This extracts the pix image data for use in another context. | |
| 1740 * The caller still needs to use pixDestroy() on the input pix. | |
| 1741 * (2) If refcount == 1, the data is extracted and the | |
| 1742 * pix->data ptr is set to NULL. | |
| 1743 * (3) If refcount > 1, this simply returns a copy of the data, | |
| 1744 * using the pix allocator, and leaving the input pix unchanged. | |
| 1745 * </pre> | |
| 1746 */ | |
| 1747 l_uint32 * | |
| 1748 pixExtractData(PIX *pixs) | |
| 1749 { | |
| 1750 l_int32 bytes; | |
| 1751 l_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 *--------------------------------------------------------------------*/ | |
| 1774 /*! | |
| 1775 * \brief pixGetLinePtrs() | |
| 1776 * | |
| 1777 * \param[in] pix | |
| 1778 * \param[out] psize [optional] array size, which is the pix height | |
| 1779 * \return array of line ptrs, or NULL on error | |
| 1780 * | |
| 1781 * <pre> | |
| 1782 * Notes: | |
| 1783 * (1) This is intended to be used for fast random pixel access. | |
| 1784 * For example, for an 8 bpp image, | |
| 1785 * val = GET_DATA_BYTE(lines8[i], j); | |
| 1786 * is equivalent to, but much faster than, | |
| 1787 * pixGetPixel(pix, j, i, &val); | |
| 1788 * (2) How much faster? For 1 bpp, it's from 6 to 10x faster. | |
| 1789 * For 8 bpp, it's an amazing 30x faster. So if you are | |
| 1790 * doing random access over a substantial part of the image, | |
| 1791 * use this line ptr array. | |
| 1792 * (3) When random access is used in conjunction with a stack, | |
| 1793 * queue or heap, the overall computation time depends on | |
| 1794 * the operations performed on each struct that is popped | |
| 1795 * or pushed, and whether we are using a priority queue (O(logn)) | |
| 1796 * or a queue or stack (O(1)). For example, for maze search, | |
| 1797 * the overall ratio of time for line ptrs vs. pixGet/Set* is | |
| 1798 * Maze type Type Time ratio | |
| 1799 * binary queue 0.4 | |
| 1800 * gray heap (priority queue) 0.6 | |
| 1801 * (4) Because this returns a void** and the accessors take void*, | |
| 1802 * the compiler cannot check the pointer types. It is | |
| 1803 * strongly recommended that you adopt a naming scheme for | |
| 1804 * the returned ptr arrays that indicates the pixel depth. | |
| 1805 * (This follows the original intent of Simonyi's "Hungarian" | |
| 1806 * application notation, where naming is used proactively | |
| 1807 * to make errors visibly obvious.) By doing this, you can | |
| 1808 * tell by inspection if the correct accessor is used. | |
| 1809 * For example, for an 8 bpp pixg: | |
| 1810 * void **lineg8 = pixGetLinePtrs(pixg, NULL); | |
| 1811 * val = GET_DATA_BYTE(lineg8[i], j); // fast access; BYTE, 8 | |
| 1812 * ... | |
| 1813 * LEPT_FREE(lineg8); // don't forget this | |
| 1814 * (5) These are convenient for accessing bytes sequentially in an | |
| 1815 * 8 bpp grayscale image. People who write image processing code | |
| 1816 * on 8 bpp images are accustomed to grabbing pixels directly out | |
| 1817 * of the raster array. Note that for little endians, you first | |
| 1818 * need to reverse the byte order in each 32-bit word. | |
| 1819 * Here's a typical usage pattern: | |
| 1820 * pixEndianByteSwap(pix); // always safe; no-op on big-endians | |
| 1821 * l_uint8 **lineptrs = (l_uint8 **)pixGetLinePtrs(pix, NULL); | |
| 1822 * pixGetDimensions(pix, &w, &h, NULL); | |
| 1823 * for (i = 0; i < h; i++) { | |
| 1824 * l_uint8 *line = lineptrs[i]; | |
| 1825 * for (j = 0; j < w; j++) { | |
| 1826 * val = line[j]; | |
| 1827 * ... | |
| 1828 * } | |
| 1829 * } | |
| 1830 * pixEndianByteSwap(pix); // restore big-endian order | |
| 1831 * LEPT_FREE(lineptrs); | |
| 1832 * This can be done even more simply as follows: | |
| 1833 * l_uint8 **lineptrs = pixSetupByteProcessing(pix, &w, &h); | |
| 1834 * for (i = 0; i < h; i++) { | |
| 1835 * l_uint8 *line = lineptrs[i]; | |
| 1836 * for (j = 0; j < w; j++) { | |
| 1837 * val = line[j]; | |
| 1838 * ... | |
| 1839 * } | |
| 1840 * } | |
| 1841 * pixCleanupByteProcessing(pix, lineptrs); | |
| 1842 * </pre> | |
| 1843 */ | |
| 1844 void ** | |
| 1845 pixGetLinePtrs(PIX *pix, | |
| 1846 l_int32 *psize) | |
| 1847 { | |
| 1848 l_int32 i, h, wpl; | |
| 1849 l_uint32 *data; | |
| 1850 void **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 *--------------------------------------------------------------------*/ | |
| 1872 /*! | |
| 1873 * \brief pixSizesEqual() | |
| 1874 * | |
| 1875 * \param[in] pix1, pix2 | |
| 1876 * \return 1 if the two pix have same {h, w, d}; 0 otherwise. | |
| 1877 */ | |
| 1878 l_int32 | |
| 1879 pixSizesEqual(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 | |
| 1897 /*! | |
| 1898 * \brief pixMaxAspectRatio() | |
| 1899 * | |
| 1900 * \param[in] pixs 32 bpp rgb | |
| 1901 * \param[out] pratio max aspect ratio, >= 1.0; -1.0 on error | |
| 1902 * \return 0 if OK, 1 on error | |
| 1903 */ | |
| 1904 l_ok | |
| 1905 pixMaxAspectRatio(PIX *pixs, | |
| 1906 l_float32 *pratio) | |
| 1907 { | |
| 1908 l_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 *--------------------------------------------------------------------*/ | |
| 1929 extern const char *ImageFileFormatExtensions[]; | |
| 1930 | |
| 1931 /*! | |
| 1932 * \brief pixPrintStreamInfo() | |
| 1933 * | |
| 1934 * \param[in] fp file stream | |
| 1935 * \param[in] pix | |
| 1936 * \param[in] text [optional] identifying string; can be null | |
| 1937 * \return 0 if OK, 1 on error | |
| 1938 */ | |
| 1939 l_ok | |
| 1940 pixPrintStreamInfo(FILE *fp, | |
| 1941 const PIX *pix, | |
| 1942 const char *text) | |
| 1943 { | |
| 1944 l_int32 informat; | |
| 1945 const 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 } |
