/src/leptonica/src/pix1.c
Line | Count | Source (jump to first uncovered line) |
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 | 3.35M | { |
249 | 3.35M | #ifndef _MSC_VER |
250 | 3.35M | 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 | 3.35M | } |
257 | | |
258 | | static void |
259 | | pixdata_free(void *ptr) |
260 | 3.35M | { |
261 | 3.35M | #ifndef _MSC_VER |
262 | 3.35M | (*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 | 3.35M | } |
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 | 0 | { |
299 | 0 | if (allocator) pix_mem_manager.allocator = allocator; |
300 | 0 | if (deallocator) pix_mem_manager.deallocator = deallocator; |
301 | 0 | } |
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 | 1.34M | { |
319 | 1.34M | PIX *pixd; |
320 | | |
321 | 1.34M | if ((pixd = pixCreateNoInit(width, height, depth)) == NULL) |
322 | 0 | return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); |
323 | 1.34M | memset(pixd->data, 0, 4LL * pixd->wpl * pixd->h); |
324 | 1.34M | return pixd; |
325 | 1.34M | } |
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 | 3.35M | { |
348 | 3.35M | l_int32 wpl; |
349 | 3.35M | PIX *pixd; |
350 | 3.35M | l_uint32 *data; |
351 | | |
352 | 3.35M | if ((pixd = pixCreateHeader(width, height, depth)) == NULL) |
353 | 0 | return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); |
354 | 3.35M | wpl = pixGetWpl(pixd); |
355 | 3.35M | if ((data = (l_uint32 *)pixdata_malloc(4LL * wpl * height)) == NULL) { |
356 | 0 | pixDestroy(&pixd); |
357 | 0 | return (PIX *)ERROR_PTR("pixdata_malloc fail for data", |
358 | 0 | __func__, NULL); |
359 | 0 | } |
360 | 3.35M | pixSetData(pixd, data); |
361 | 3.35M | pixSetPadBits(pixd, 0); |
362 | 3.35M | return pixd; |
363 | 3.35M | } |
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 | 2.01M | { |
382 | 2.01M | PIX *pixd; |
383 | | |
384 | 2.01M | if (!pixs) |
385 | 0 | return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL); |
386 | | |
387 | 2.01M | if ((pixd = pixCreateTemplateNoInit(pixs)) == NULL) |
388 | 0 | return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); |
389 | 2.01M | memset(pixd->data, 0, 4LL * pixd->wpl * pixd->h); |
390 | 2.01M | return pixd; |
391 | 2.01M | } |
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 | 2.01M | { |
414 | 2.01M | l_int32 w, h, d; |
415 | 2.01M | PIX *pixd; |
416 | | |
417 | 2.01M | if (!pixs) |
418 | 0 | return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL); |
419 | | |
420 | 2.01M | pixGetDimensions(pixs, &w, &h, &d); |
421 | 2.01M | if ((pixd = pixCreateNoInit(w, h, d)) == NULL) |
422 | 0 | return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); |
423 | 2.01M | pixCopySpp(pixd, pixs); |
424 | 2.01M | pixCopyResolution(pixd, pixs); |
425 | 2.01M | pixCopyColormap(pixd, pixs); |
426 | 2.01M | pixCopyText(pixd, pixs); |
427 | 2.01M | pixCopyInputFormat(pixd, pixs); |
428 | 2.01M | pixSetPadBits(pixd, 0); |
429 | 2.01M | return pixd; |
430 | 2.01M | } |
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 | 0 | { |
456 | 0 | PIX *pix; |
457 | 0 | PIXCMAP *cmap; |
458 | |
|
459 | 0 | if (depth != 2 && depth != 4 && depth != 8) |
460 | 0 | return (PIX *)ERROR_PTR("depth not 2, 4 or 8 bpp", __func__, NULL); |
461 | | |
462 | 0 | if ((pix = pixCreate(width, height, depth)) == NULL) |
463 | 0 | return (PIX *)ERROR_PTR("pix not made", __func__, NULL); |
464 | 0 | cmap = pixcmapCreate(depth); |
465 | 0 | pixSetColormap(pix, cmap); |
466 | 0 | if (initcolor == L_SET_BLACK) |
467 | 0 | pixcmapAddColor(cmap, 0, 0, 0); |
468 | 0 | else /* L_SET_WHITE */ |
469 | 0 | pixcmapAddColor(cmap, 255, 255, 255); |
470 | 0 | return pix; |
471 | 0 | } |
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 | 3.36M | { |
499 | 3.36M | l_int32 wpl; |
500 | 3.36M | l_uint64 wpl64, bignum; |
501 | 3.36M | PIX *pixd; |
502 | | |
503 | 3.36M | if ((depth != 1) && (depth != 2) && (depth != 4) && (depth != 8) |
504 | 3.36M | && (depth != 16) && (depth != 24) && (depth != 32)) |
505 | 73 | return (PIX *)ERROR_PTR("depth must be {1, 2, 4, 8, 16, 24, 32}", |
506 | 3.35M | __func__, NULL); |
507 | 3.35M | if (width <= 0) |
508 | 0 | return (PIX *)ERROR_PTR("width must be > 0", __func__, NULL); |
509 | 3.35M | if (height <= 0) |
510 | 0 | return (PIX *)ERROR_PTR("height must be > 0", __func__, NULL); |
511 | | |
512 | | /* Avoid overflow in malloc, malicious or otherwise */ |
513 | 3.35M | wpl64 = ((l_uint64)width * (l_uint64)depth + 31) / 32; |
514 | 3.35M | if (wpl64 > ((1LL << 24) - 1)) { |
515 | 0 | L_ERROR("requested w = %d, h = %d, d = %d\n", |
516 | 0 | __func__, width, height, depth); |
517 | 0 | return (PIX *)ERROR_PTR("wpl >= 2^24", __func__, NULL); |
518 | 0 | } |
519 | 3.35M | wpl = (l_int32)wpl64; |
520 | 3.35M | bignum = 4LL * wpl * height; /* number of bytes to be requested */ |
521 | 3.35M | if (bignum > ((1LL << 31) - 1)) { |
522 | 0 | L_ERROR("requested w = %d, h = %d, d = %d\n", |
523 | 0 | __func__, width, height, depth); |
524 | 0 | return (PIX *)ERROR_PTR("requested bytes >= 2^31", __func__, NULL); |
525 | 0 | } |
526 | | |
527 | 3.35M | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
528 | 3.35M | if (bignum > (1LL << 26)) { |
529 | 8 | L_ERROR("fuzzer requested > 64 MB; refused\n", __func__); |
530 | 8 | return NULL; |
531 | 8 | } |
532 | 3.35M | if (width > 20000) { |
533 | 13 | L_ERROR("fuzzer requested width > 20K; refused\n", __func__); |
534 | 13 | return NULL; |
535 | 13 | } |
536 | 3.35M | if (height > 20000) { |
537 | 11 | L_ERROR("fuzzer requested height > 20K; refused\n", __func__); |
538 | 11 | return NULL; |
539 | 11 | } |
540 | 3.35M | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
541 | | |
542 | 3.35M | if ((pixd = (PIX *)LEPT_CALLOC(1, sizeof(PIX))) == NULL) |
543 | 0 | return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); |
544 | 3.35M | pixSetWidth(pixd, width); |
545 | 3.35M | pixSetHeight(pixd, height); |
546 | 3.35M | pixSetDepth(pixd, depth); |
547 | 3.35M | pixSetWpl(pixd, wpl); |
548 | 3.35M | if (depth == 24 || depth == 32) |
549 | 4.14k | pixSetSpp(pixd, 3); |
550 | 3.35M | else |
551 | 3.35M | pixSetSpp(pixd, 1); |
552 | 3.35M | pixd->refcount = 1; |
553 | 3.35M | pixd->informat = IFF_UNKNOWN; |
554 | 3.35M | return pixd; |
555 | 3.35M | } |
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 | 5.91M | { |
585 | 5.91M | if (!pixs) |
586 | 0 | return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL); |
587 | 5.91M | ++pixs->refcount; |
588 | | |
589 | 5.91M | return pixs; |
590 | 5.91M | } |
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 | 9.29M | { |
611 | 9.29M | PIX *pix; |
612 | | |
613 | 9.29M | if (!ppix) { |
614 | 0 | L_WARNING("ptr address is null!\n", __func__); |
615 | 0 | return; |
616 | 0 | } |
617 | | |
618 | 9.29M | if ((pix = *ppix) == NULL) |
619 | 14.8k | return; |
620 | 9.27M | pixFree(pix); |
621 | 9.27M | *ppix = NULL; |
622 | 9.27M | } |
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 | 9.27M | { |
639 | 9.27M | l_uint32 *data; |
640 | 9.27M | char *text; |
641 | | |
642 | 9.27M | if (!pix) return; |
643 | | |
644 | 9.27M | if (--pix->refcount == 0) { |
645 | 3.35M | if ((data = pixGetData(pix)) != NULL) |
646 | 3.35M | pixdata_free(data); |
647 | 3.35M | if ((text = pixGetText(pix)) != NULL) |
648 | 0 | LEPT_FREE(text); |
649 | 3.35M | pixDestroyColormap(pix); |
650 | 3.35M | LEPT_FREE(pix); |
651 | 3.35M | } |
652 | 9.27M | return; |
653 | 9.27M | } |
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 | 4.69M | { |
693 | 4.69M | l_int32 bytes; |
694 | | |
695 | 4.69M | if (!pixs) |
696 | 0 | return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd); |
697 | 4.69M | if (pixs == pixd) |
698 | 2.67M | return pixd; |
699 | | |
700 | | /* Total bytes in image data */ |
701 | 2.01M | bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs); |
702 | | |
703 | | /* If we're making a new pix ... */ |
704 | 2.01M | if (!pixd) { |
705 | 673k | if ((pixd = pixCreateTemplate(pixs)) == NULL) |
706 | 0 | return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); |
707 | 673k | memcpy(pixd->data, pixs->data, bytes); |
708 | 673k | return pixd; |
709 | 673k | } |
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 | 1.34M | if (pixResizeImageData(pixd, pixs) == 1) |
718 | 0 | return (PIX *)ERROR_PTR("reallocation of data failed", __func__, NULL); |
719 | | |
720 | | /* Copy non-image data fields */ |
721 | 1.34M | pixCopyColormap(pixd, pixs); |
722 | 1.34M | pixCopySpp(pixd, pixs); |
723 | 1.34M | pixCopyResolution(pixd, pixs); |
724 | 1.34M | pixCopyInputFormat(pixd, pixs); |
725 | 1.34M | pixCopyText(pixd, pixs); |
726 | | |
727 | | /* Copy image data */ |
728 | 1.34M | memcpy(pixd->data, pixs->data, bytes); |
729 | 1.34M | return pixd; |
730 | 1.34M | } |
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 | 1.34M | { |
754 | 1.34M | l_int32 w, h, d, wpl, bytes; |
755 | 1.34M | l_uint32 *data; |
756 | | |
757 | 1.34M | if (!pixs) |
758 | 0 | return ERROR_INT("pixs not defined", __func__, 1); |
759 | 1.34M | if (!pixd) |
760 | 0 | return ERROR_INT("pixd not defined", __func__, 1); |
761 | | |
762 | 1.34M | if (pixSizesEqual(pixs, pixd)) /* nothing to do */ |
763 | 1.34M | return 0; |
764 | | |
765 | | /* Make sure we can copy the data */ |
766 | 0 | pixGetDimensions(pixs, &w, &h, &d); |
767 | 0 | wpl = pixGetWpl(pixs); |
768 | 0 | bytes = 4 * wpl * h; |
769 | 0 | if ((data = (l_uint32 *)pixdata_malloc(bytes)) == NULL) |
770 | 0 | return ERROR_INT("pixdata_malloc fail for data", __func__, 1); |
771 | | |
772 | | /* OK, do it */ |
773 | 0 | pixSetWidth(pixd, w); |
774 | 0 | pixSetHeight(pixd, h); |
775 | 0 | pixSetDepth(pixd, d); |
776 | 0 | pixSetWpl(pixd, wpl); |
777 | 0 | pixFreeAndSetData(pixd, data); /* free old data and assign new data */ |
778 | 0 | pixCopyResolution(pixd, pixs); |
779 | 0 | return 0; |
780 | 0 | } |
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 | 4.69M | { |
799 | 4.69M | l_int32 valid; |
800 | 4.69M | const PIXCMAP *cmaps; |
801 | 4.69M | PIXCMAP *cmapd; |
802 | | |
803 | 4.69M | if (!pixs) |
804 | 0 | return ERROR_INT("pixs not defined", __func__, 1); |
805 | 4.69M | if (!pixd) |
806 | 0 | return ERROR_INT("pixd not defined", __func__, 1); |
807 | 4.69M | if (pixs == pixd) |
808 | 0 | return 0; /* no-op */ |
809 | 4.69M | if (pixGetDepth(pixs) != pixGetDepth(pixd)) |
810 | 0 | return ERROR_INT("depths of pixs and pixd differ", __func__, 1); |
811 | | |
812 | 4.69M | pixDestroyColormap(pixd); |
813 | 4.69M | if ((cmaps = pixs->colormap) == NULL) /* not an error */ |
814 | 4.59M | return 0; |
815 | 101k | pixcmapIsValid(cmaps, NULL, &valid); |
816 | 101k | if (!valid) |
817 | 0 | return ERROR_INT("cmap not valid", __func__, 1); |
818 | | |
819 | 101k | if ((cmapd = pixcmapCopy(cmaps)) == NULL) |
820 | 0 | return ERROR_INT("cmapd not made", __func__, 1); |
821 | 101k | pixSetColormap(pixd, cmapd); |
822 | 101k | return 0; |
823 | 101k | } |
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 | 0 | { |
885 | 0 | l_int32 nbytes; |
886 | 0 | PIX *pixs; |
887 | |
|
888 | 0 | if (!ppixs) |
889 | 0 | return ERROR_INT("&pixs not defined", __func__, 1); |
890 | 0 | if ((pixs = *ppixs) == NULL) |
891 | 0 | return ERROR_INT("pixs not defined", __func__, 1); |
892 | 0 | if (!pixd) |
893 | 0 | return ERROR_INT("pixd not defined", __func__, 1); |
894 | 0 | if (pixs == pixd) /* no-op */ |
895 | 0 | return ERROR_INT("pixd == pixs", __func__, 1); |
896 | | |
897 | 0 | if (pixs->refcount == 1) { /* transfer the data, cmap, text */ |
898 | 0 | pixFreeData(pixd); /* dealloc any existing data */ |
899 | 0 | pixSetData(pixd, pixGetData(pixs)); /* transfer new data from pixs */ |
900 | 0 | pixs->data = NULL; /* pixs no longer owns data */ |
901 | 0 | pixDestroyColormap(pixd); /* free the old one, if it exists */ |
902 | 0 | pixd->colormap = pixGetColormap(pixs); /* transfer to pixd */ |
903 | 0 | pixs->colormap = NULL; /* pixs no longer owns colormap */ |
904 | 0 | if (copytext) { |
905 | 0 | pixSetText(pixd, pixGetText(pixs)); |
906 | 0 | pixSetText(pixs, NULL); |
907 | 0 | } |
908 | 0 | } else { /* preserve pixs by making a copy of the data, cmap, text */ |
909 | 0 | pixResizeImageData(pixd, pixs); |
910 | 0 | nbytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs); |
911 | 0 | memcpy(pixGetData(pixd), pixGetData(pixs), nbytes); |
912 | 0 | pixCopyColormap(pixd, pixs); |
913 | 0 | if (copytext) |
914 | 0 | pixCopyText(pixd, pixs); |
915 | 0 | } |
916 | |
|
917 | 0 | pixCopySpp(pixd, pixs); |
918 | 0 | pixCopyResolution(pixd, pixs); |
919 | 0 | pixCopyDimensions(pixd, pixs); |
920 | 0 | if (copyformat) |
921 | 0 | pixCopyInputFormat(pixd, pixs); |
922 | | |
923 | | /* This will destroy pixs if data was transferred; |
924 | | * otherwise, it just decrements its refcount. */ |
925 | 0 | pixDestroy(ppixs); |
926 | 0 | return 0; |
927 | 0 | } |
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 | 0 | { |
972 | 0 | if (!ppixd) |
973 | 0 | return ERROR_INT("&pixd not defined", __func__, 1); |
974 | 0 | if (!ppixs) |
975 | 0 | return ERROR_INT("&pixs not defined", __func__, 1); |
976 | 0 | if (*ppixs == NULL) |
977 | 0 | return ERROR_INT("pixs not defined", __func__, 1); |
978 | 0 | if (ppixs == ppixd) /* no-op */ |
979 | 0 | return ERROR_INT("&pixd == &pixs", __func__, 1); |
980 | | |
981 | 0 | pixDestroy(ppixd); |
982 | 0 | *ppixd = pixClone(*ppixs); |
983 | 0 | pixDestroy(ppixs); |
984 | 0 | return 0; |
985 | 0 | } |
986 | | |
987 | | |
988 | | /*--------------------------------------------------------------------* |
989 | | * Pix Accessors * |
990 | | *--------------------------------------------------------------------*/ |
991 | | l_int32 |
992 | | pixGetWidth(const PIX *pix) |
993 | 5.42M | { |
994 | 5.42M | if (!pix) |
995 | 0 | return ERROR_INT("pix not defined", __func__, 0); |
996 | | |
997 | 5.42M | return pix->w; |
998 | 5.42M | } |
999 | | |
1000 | | |
1001 | | l_int32 |
1002 | | pixSetWidth(PIX *pix, |
1003 | | l_int32 width) |
1004 | 3.35M | { |
1005 | 3.35M | if (!pix) |
1006 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1007 | 3.35M | if (width < 0) { |
1008 | 0 | pix->w = 0; |
1009 | 0 | return ERROR_INT("width must be >= 0", __func__, 1); |
1010 | 0 | } |
1011 | | |
1012 | 3.35M | pix->w = width; |
1013 | 3.35M | return 0; |
1014 | 3.35M | } |
1015 | | |
1016 | | |
1017 | | l_int32 |
1018 | | pixGetHeight(const PIX *pix) |
1019 | 8.77M | { |
1020 | 8.77M | if (!pix) |
1021 | 0 | return ERROR_INT("pix not defined", __func__, 0); |
1022 | | |
1023 | 8.77M | return pix->h; |
1024 | 8.77M | } |
1025 | | |
1026 | | |
1027 | | l_int32 |
1028 | | pixSetHeight(PIX *pix, |
1029 | | l_int32 height) |
1030 | 3.35M | { |
1031 | 3.35M | if (!pix) |
1032 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1033 | 3.35M | if (height < 0) { |
1034 | 0 | pix->h = 0; |
1035 | 0 | return ERROR_INT("h must be >= 0", __func__, 1); |
1036 | 0 | } |
1037 | | |
1038 | 3.35M | pix->h = height; |
1039 | 3.35M | return 0; |
1040 | 3.35M | } |
1041 | | |
1042 | | |
1043 | | l_int32 |
1044 | | pixGetDepth(const PIX *pix) |
1045 | 23.4M | { |
1046 | 23.4M | if (!pix) |
1047 | 0 | return ERROR_INT("pix not defined", __func__, 0); |
1048 | | |
1049 | 23.4M | return pix->d; |
1050 | 23.4M | } |
1051 | | |
1052 | | |
1053 | | l_int32 |
1054 | | pixSetDepth(PIX *pix, |
1055 | | l_int32 depth) |
1056 | 3.35M | { |
1057 | 3.35M | if (!pix) |
1058 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1059 | 3.35M | if (depth < 1) |
1060 | 0 | return ERROR_INT("d must be >= 1", __func__, 1); |
1061 | | |
1062 | 3.35M | pix->d = depth; |
1063 | 3.35M | return 0; |
1064 | 3.35M | } |
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 | 26.8M | { |
1080 | 26.8M | if (pw) *pw = 0; |
1081 | 26.8M | if (ph) *ph = 0; |
1082 | 26.8M | if (pd) *pd = 0; |
1083 | 26.8M | if (!pix) |
1084 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1085 | 26.8M | if (pw) *pw = pix->w; |
1086 | 26.8M | if (ph) *ph = pix->h; |
1087 | 26.8M | if (pd) *pd = pix->d; |
1088 | 26.8M | return 0; |
1089 | 26.8M | } |
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 | 0 | { |
1105 | 0 | if (!pix) |
1106 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1107 | 0 | if (w > 0) pixSetWidth(pix, w); |
1108 | 0 | if (h > 0) pixSetHeight(pix, h); |
1109 | 0 | if (d > 0) pixSetDepth(pix, d); |
1110 | 0 | return 0; |
1111 | 0 | } |
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 | 0 | { |
1125 | 0 | if (!pixd) |
1126 | 0 | return ERROR_INT("pixd not defined", __func__, 1); |
1127 | 0 | if (!pixs) |
1128 | 0 | return ERROR_INT("pixs not defined", __func__, 1); |
1129 | 0 | if (pixs == pixd) |
1130 | 0 | return 0; /* no-op */ |
1131 | | |
1132 | 0 | pixSetWidth(pixd, pixGetWidth(pixs)); |
1133 | 0 | pixSetHeight(pixd, pixGetHeight(pixs)); |
1134 | 0 | pixSetDepth(pixd, pixGetDepth(pixs)); |
1135 | 0 | pixSetWpl(pixd, pixGetWpl(pixs)); |
1136 | 0 | return 0; |
1137 | 0 | } |
1138 | | |
1139 | | |
1140 | | l_int32 |
1141 | | pixGetSpp(const PIX *pix) |
1142 | 6.03M | { |
1143 | 6.03M | if (!pix) |
1144 | 0 | return ERROR_INT("pix not defined", __func__, 0); |
1145 | | |
1146 | 6.03M | return pix->spp; |
1147 | 6.03M | } |
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 | 6.71M | { |
1170 | 6.71M | if (!pix) |
1171 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1172 | 6.71M | if (spp < 1) |
1173 | 0 | return ERROR_INT("spp must be >= 1", __func__, 1); |
1174 | | |
1175 | 6.71M | pix->spp = spp; |
1176 | 6.71M | return 0; |
1177 | 6.71M | } |
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 | 3.35M | { |
1191 | 3.35M | if (!pixd) |
1192 | 0 | return ERROR_INT("pixd not defined", __func__, 1); |
1193 | 3.35M | if (!pixs) |
1194 | 0 | return ERROR_INT("pixs not defined", __func__, 1); |
1195 | 3.35M | if (pixs == pixd) |
1196 | 0 | return 0; /* no-op */ |
1197 | | |
1198 | 3.35M | pixSetSpp(pixd, pixGetSpp(pixs)); |
1199 | 3.35M | return 0; |
1200 | 3.35M | } |
1201 | | |
1202 | | |
1203 | | l_int32 |
1204 | | pixGetWpl(const PIX *pix) |
1205 | 29.5M | { |
1206 | 29.5M | if (!pix) |
1207 | 0 | return ERROR_INT("pix not defined", __func__, 0); |
1208 | 29.5M | return pix->wpl; |
1209 | 29.5M | } |
1210 | | |
1211 | | |
1212 | | l_int32 |
1213 | | pixSetWpl(PIX *pix, |
1214 | | l_int32 wpl) |
1215 | 3.35M | { |
1216 | 3.35M | if (!pix) |
1217 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1218 | | |
1219 | 3.35M | pix->wpl = wpl; |
1220 | 3.35M | return 0; |
1221 | 3.35M | } |
1222 | | |
1223 | | |
1224 | | l_int32 |
1225 | | pixGetXRes(const PIX *pix) |
1226 | 4.69M | { |
1227 | 4.69M | if (!pix) |
1228 | 0 | return ERROR_INT("pix not defined", __func__, 0); |
1229 | 4.69M | return pix->xres; |
1230 | 4.69M | } |
1231 | | |
1232 | | |
1233 | | l_int32 |
1234 | | pixSetXRes(PIX *pix, |
1235 | | l_int32 res) |
1236 | 4.69M | { |
1237 | 4.69M | if (!pix) |
1238 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1239 | | |
1240 | 4.69M | pix->xres = res; |
1241 | 4.69M | return 0; |
1242 | 4.69M | } |
1243 | | |
1244 | | |
1245 | | l_int32 |
1246 | | pixGetYRes(const PIX *pix) |
1247 | 4.69M | { |
1248 | 4.69M | if (!pix) |
1249 | 0 | return ERROR_INT("pix not defined", __func__, 0); |
1250 | 4.69M | return pix->yres; |
1251 | 4.69M | } |
1252 | | |
1253 | | |
1254 | | l_int32 |
1255 | | pixSetYRes(PIX *pix, |
1256 | | l_int32 res) |
1257 | 4.69M | { |
1258 | 4.69M | if (!pix) |
1259 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1260 | | |
1261 | 4.69M | pix->yres = res; |
1262 | 4.69M | return 0; |
1263 | 4.69M | } |
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 | 0 | { |
1278 | 0 | if (pxres) *pxres = 0; |
1279 | 0 | if (pyres) *pyres = 0; |
1280 | 0 | if (!pxres && !pyres) |
1281 | 0 | return ERROR_INT("no output requested", __func__, 1); |
1282 | 0 | if (!pix) |
1283 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1284 | 0 | if (pxres) *pxres = pix->xres; |
1285 | 0 | if (pyres) *pyres = pix->yres; |
1286 | 0 | return 0; |
1287 | 0 | } |
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 | 0 | { |
1302 | 0 | if (!pix) |
1303 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1304 | 0 | if (xres > 0) pix->xres = xres; |
1305 | 0 | if (yres > 0) pix->yres = yres; |
1306 | 0 | return 0; |
1307 | 0 | } |
1308 | | |
1309 | | |
1310 | | l_int32 |
1311 | | pixCopyResolution(PIX *pixd, |
1312 | | const PIX *pixs) |
1313 | 4.69M | { |
1314 | 4.69M | if (!pixs) |
1315 | 0 | return ERROR_INT("pixs not defined", __func__, 1); |
1316 | 4.69M | if (!pixd) |
1317 | 0 | return ERROR_INT("pixd not defined", __func__, 1); |
1318 | 4.69M | if (pixs == pixd) |
1319 | 0 | return 0; /* no-op */ |
1320 | | |
1321 | 4.69M | pixSetXRes(pixd, pixGetXRes(pixs)); |
1322 | 4.69M | pixSetYRes(pixd, pixGetYRes(pixs)); |
1323 | 4.69M | return 0; |
1324 | 4.69M | } |
1325 | | |
1326 | | |
1327 | | l_int32 |
1328 | | pixScaleResolution(PIX *pix, |
1329 | | l_float32 xscale, |
1330 | | l_float32 yscale) |
1331 | 321 | { |
1332 | 321 | l_float64 xres, yres; |
1333 | 321 | l_float64 maxres = 100000000.0; |
1334 | | |
1335 | 321 | if (!pix) |
1336 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1337 | 321 | if (xscale <= 0 || yscale <= 0) |
1338 | 0 | return ERROR_INT("invalid scaling ratio", __func__, 1); |
1339 | | |
1340 | 321 | xres = (l_float64)xscale * (l_float32)(pix->xres) + 0.5; |
1341 | 321 | yres = (l_float64)yscale * (l_float32)(pix->yres) + 0.5; |
1342 | 321 | pix->xres = (l_uint32)L_MIN(xres, maxres); |
1343 | 321 | pix->yres = (l_uint32)L_MIN(yres, maxres); |
1344 | 321 | return 0; |
1345 | 321 | } |
1346 | | |
1347 | | |
1348 | | l_int32 |
1349 | | pixGetInputFormat(const PIX *pix) |
1350 | 3.35M | { |
1351 | 3.35M | if (!pix) |
1352 | 0 | return ERROR_INT("pix not defined", __func__, 0); |
1353 | 3.35M | return pix->informat; |
1354 | 3.35M | } |
1355 | | |
1356 | | |
1357 | | l_int32 |
1358 | | pixSetInputFormat(PIX *pix, |
1359 | | l_int32 informat) |
1360 | 3.35M | { |
1361 | 3.35M | if (!pix) |
1362 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1363 | 3.35M | pix->informat = informat; |
1364 | 3.35M | return 0; |
1365 | 3.35M | } |
1366 | | |
1367 | | |
1368 | | l_int32 |
1369 | | pixCopyInputFormat(PIX *pixd, |
1370 | | const PIX *pixs) |
1371 | 3.35M | { |
1372 | 3.35M | if (!pixs) |
1373 | 0 | return ERROR_INT("pixs not defined", __func__, 1); |
1374 | 3.35M | if (!pixd) |
1375 | 0 | return ERROR_INT("pixd not defined", __func__, 1); |
1376 | 3.35M | if (pixs == pixd) |
1377 | 0 | return 0; /* no-op */ |
1378 | | |
1379 | 3.35M | pixSetInputFormat(pixd, pixGetInputFormat(pixs)); |
1380 | 3.35M | return 0; |
1381 | 3.35M | } |
1382 | | |
1383 | | |
1384 | | l_int32 |
1385 | | pixSetSpecial(PIX *pix, |
1386 | | l_int32 special) |
1387 | 0 | { |
1388 | 0 | if (!pix) |
1389 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1390 | 0 | pix->special = special; |
1391 | 0 | return 0; |
1392 | 0 | } |
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 | 3.35M | { |
1411 | 3.35M | if (!pix) |
1412 | 0 | return (char *)ERROR_PTR("pix not defined", __func__, NULL); |
1413 | 3.35M | return pix->text; |
1414 | 3.35M | } |
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 | 4.69M | { |
1434 | 4.69M | if (!pix) |
1435 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1436 | | |
1437 | 4.69M | stringReplace(&pix->text, textstring); |
1438 | 4.69M | return 0; |
1439 | 4.69M | } |
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 | 0 | { |
1460 | 0 | char *newstring; |
1461 | |
|
1462 | 0 | if (!pix) |
1463 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1464 | | |
1465 | 0 | newstring = stringJoin(pixGetText(pix), textstring); |
1466 | 0 | stringReplace(&pix->text, newstring); |
1467 | 0 | LEPT_FREE(newstring); |
1468 | 0 | return 0; |
1469 | 0 | } |
1470 | | |
1471 | | |
1472 | | l_int32 |
1473 | | pixCopyText(PIX *pixd, |
1474 | | const PIX *pixs) |
1475 | 4.69M | { |
1476 | 4.69M | if (!pixs) |
1477 | 0 | return ERROR_INT("pixs not defined", __func__, 1); |
1478 | 4.69M | if (!pixd) |
1479 | 0 | return ERROR_INT("pixd not defined", __func__, 1); |
1480 | 4.69M | if (pixs == pixd) |
1481 | 0 | return 0; /* no-op */ |
1482 | | |
1483 | 4.69M | pixSetText(pixd, pixs->text); |
1484 | 4.69M | return 0; |
1485 | 4.69M | } |
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 | 0 | { |
1509 | 0 | char *str; |
1510 | |
|
1511 | 0 | if (!pix) |
1512 | 0 | return (l_uint8 *)ERROR_PTR("pix not defined", __func__, NULL); |
1513 | 0 | str = pixGetText(pix); |
1514 | 0 | return decodeAscii85WithComp(str, strlen(str), psize); |
1515 | 0 | } |
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 | 0 | { |
1539 | 0 | size_t encodesize; /* ignored */ |
1540 | |
|
1541 | 0 | if (!pix) |
1542 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1543 | | |
1544 | 0 | LEPT_FREE(pix->text); |
1545 | 0 | pix->text = encodeAscii85WithComp(data, size, &encodesize); |
1546 | 0 | return 0; |
1547 | 0 | } |
1548 | | |
1549 | | |
1550 | | PIXCMAP * |
1551 | | pixGetColormap(PIX *pix) |
1552 | 2.74M | { |
1553 | 2.74M | if (!pix) |
1554 | 0 | return (PIXCMAP *)ERROR_PTR("pix not defined", __func__, NULL); |
1555 | 2.74M | return pix->colormap; |
1556 | 2.74M | } |
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 | 101k | { |
1586 | 101k | l_int32 valid; |
1587 | | |
1588 | 101k | if (!pix) |
1589 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1590 | 101k | if (!colormap) return 0; |
1591 | | |
1592 | | /* Make sure the colormap doesn't get lost */ |
1593 | 101k | pixDestroyColormap(pix); |
1594 | 101k | pix->colormap = colormap; |
1595 | | |
1596 | 101k | pixcmapIsValid(colormap, NULL, &valid); |
1597 | 101k | if (!valid) |
1598 | 0 | return ERROR_INT("colormap is not valid", __func__, 1); |
1599 | 101k | return 0; |
1600 | 101k | } |
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 | 8.15M | { |
1612 | 8.15M | PIXCMAP *cmap; |
1613 | | |
1614 | 8.15M | if (!pix) |
1615 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1616 | | |
1617 | 8.15M | if ((cmap = pix->colormap) != NULL) { |
1618 | 101k | pixcmapDestroy(&cmap); |
1619 | 101k | pix->colormap = NULL; |
1620 | 101k | } |
1621 | 8.15M | return 0; |
1622 | 8.15M | } |
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 | 27.4M | { |
1645 | 27.4M | if (!pix) |
1646 | 0 | return (l_uint32 *)ERROR_PTR("pix not defined", __func__, NULL); |
1647 | 27.4M | return pix->data; |
1648 | 27.4M | } |
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 | 0 | { |
1667 | 0 | if (!pix) |
1668 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1669 | | |
1670 | 0 | pixFreeData(pix); |
1671 | 0 | pix->data = data; |
1672 | 0 | return 0; |
1673 | 0 | } |
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 | 3.35M | { |
1693 | 3.35M | if (!pix) |
1694 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1695 | | |
1696 | 3.35M | pix->data = data; |
1697 | 3.35M | return 0; |
1698 | 3.35M | } |
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 | 0 | { |
1718 | 0 | l_uint32 *data; |
1719 | |
|
1720 | 0 | if (!pix) |
1721 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1722 | | |
1723 | 0 | if ((data = pixGetData(pix)) != NULL) { |
1724 | 0 | pixdata_free(data); |
1725 | 0 | pix->data = NULL; |
1726 | 0 | } |
1727 | 0 | return 0; |
1728 | 0 | } |
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 | 0 | { |
1750 | 0 | l_int32 bytes; |
1751 | 0 | l_uint32 *data, *datas; |
1752 | |
|
1753 | 0 | if (!pixs) |
1754 | 0 | return (l_uint32 *)ERROR_PTR("pixs not defined", __func__, NULL); |
1755 | | |
1756 | 0 | if (pixs->refcount == 1) { /* extract */ |
1757 | 0 | data = pixGetData(pixs); |
1758 | 0 | pixSetData(pixs, NULL); |
1759 | 0 | } else { /* refcount > 1; copy */ |
1760 | 0 | bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs); |
1761 | 0 | datas = pixGetData(pixs); |
1762 | 0 | if ((data = (l_uint32 *)pixdata_malloc(bytes)) == NULL) |
1763 | 0 | return (l_uint32 *)ERROR_PTR("data not made", __func__, NULL); |
1764 | 0 | memcpy(data, datas, bytes); |
1765 | 0 | } |
1766 | | |
1767 | 0 | return data; |
1768 | 0 | } |
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 | 0 | { |
1848 | 0 | l_int32 i, h, wpl; |
1849 | 0 | l_uint32 *data; |
1850 | 0 | void **lines; |
1851 | |
|
1852 | 0 | if (psize) *psize = 0; |
1853 | 0 | if (!pix) |
1854 | 0 | return (void **)ERROR_PTR("pix not defined", __func__, NULL); |
1855 | | |
1856 | 0 | h = pixGetHeight(pix); |
1857 | 0 | if (psize) *psize = h; |
1858 | 0 | if ((lines = (void **)LEPT_CALLOC(h, sizeof(void *))) == NULL) |
1859 | 0 | return (void **)ERROR_PTR("lines not made", __func__, NULL); |
1860 | 0 | wpl = pixGetWpl(pix); |
1861 | 0 | data = pixGetData(pix); |
1862 | 0 | for (i = 0; i < h; i++) |
1863 | 0 | lines[i] = (void *)(data + i * wpl); |
1864 | |
|
1865 | 0 | return lines; |
1866 | 0 | } |
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 | 1.37M | { |
1882 | 1.37M | if (!pix1 || !pix2) |
1883 | 0 | return ERROR_INT("pix1 and pix2 not both defined", __func__, 0); |
1884 | | |
1885 | 1.37M | if (pix1 == pix2) |
1886 | 455 | return 1; |
1887 | | |
1888 | 1.37M | if ((pixGetWidth(pix1) != pixGetWidth(pix2)) || |
1889 | 1.37M | (pixGetHeight(pix1) != pixGetHeight(pix2)) || |
1890 | 1.37M | (pixGetDepth(pix1) != pixGetDepth(pix2))) |
1891 | 958 | return 0; |
1892 | 1.37M | else |
1893 | 1.37M | return 1; |
1894 | 1.37M | } |
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 | 0 | { |
1908 | 0 | l_int32 w, h; |
1909 | |
|
1910 | 0 | if (!pratio) |
1911 | 0 | return ERROR_INT("&ratio not defined", __func__, 1); |
1912 | 0 | *pratio = -1.0; |
1913 | 0 | if (!pixs) |
1914 | 0 | return ERROR_INT("pixs not defined", __func__, 1); |
1915 | 0 | pixGetDimensions(pixs, &w, &h, NULL); |
1916 | 0 | if (w == 0 || h == 0) { |
1917 | 0 | L_ERROR("invalid size: w = %d, h = %d\n", __func__, w, h); |
1918 | 0 | return 1; |
1919 | 0 | } |
1920 | | |
1921 | 0 | *pratio = L_MAX((l_float32)h / (l_float32)w, (l_float32)w / (l_float32)h); |
1922 | 0 | return 0; |
1923 | 0 | } |
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 | 0 | { |
1944 | 0 | l_int32 informat; |
1945 | 0 | const PIXCMAP *cmap; |
1946 | |
|
1947 | 0 | if (!fp) |
1948 | 0 | return ERROR_INT("fp not defined", __func__, 1); |
1949 | 0 | if (!pix) |
1950 | 0 | return ERROR_INT("pix not defined", __func__, 1); |
1951 | | |
1952 | 0 | if (text) |
1953 | 0 | fprintf(fp, " Pix Info for %s:\n", text); |
1954 | 0 | fprintf(fp, " width = %d, height = %d, depth = %d, spp = %d\n", |
1955 | 0 | pixGetWidth(pix), pixGetHeight(pix), pixGetDepth(pix), |
1956 | 0 | pixGetSpp(pix)); |
1957 | 0 | fprintf(fp, " wpl = %d, data = %p, refcount = %d\n", |
1958 | 0 | pixGetWpl(pix), pix->data, pix->refcount); |
1959 | 0 | fprintf(fp, " xres = %d, yres = %d\n", pixGetXRes(pix), pixGetYRes(pix)); |
1960 | 0 | if ((cmap = pix->colormap) != NULL) |
1961 | 0 | pixcmapWriteStream(fp, cmap); |
1962 | 0 | else |
1963 | 0 | fprintf(fp, " no colormap\n"); |
1964 | 0 | informat = pixGetInputFormat(pix); |
1965 | 0 | fprintf(fp, " input format: %d (%s)\n", informat, |
1966 | 0 | ImageFileFormatExtensions[informat]); |
1967 | 0 | if (pix->text != NULL) |
1968 | 0 | fprintf(fp, " text: %s\n", pix->text); |
1969 | |
|
1970 | 0 | return 0; |
1971 | 0 | } |