Leptonica 1.82.0
Image processing and image analysis suite
spixio.c
Go to the documentation of this file.
1/*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
59#ifdef HAVE_CONFIG_H
60#include <config_auto.h>
61#endif /* HAVE_CONFIG_H */
62
63#include <string.h>
64#include "allheaders.h"
65
66 /* Image dimension limits */
67static const l_int32 MaxAllowedWidth = 1000000;
68static const l_int32 MaxAllowedHeight = 1000000;
69static const l_int64 MaxAllowedArea = 400000000LL;
70
71#ifndef NO_CONSOLE_IO
72#define DEBUG_SERIALIZE 0
73#endif /* ~NO_CONSOLE_IO */
74
75
76/*-----------------------------------------------------------------------*
77 * Reading spix from file *
78 *-----------------------------------------------------------------------*/
91PIX *
93{
94size_t nbytes;
95l_uint8 *data;
96PIX *pix;
97
98 PROCNAME("pixReadStreamSpix");
99
100 if (!fp)
101 return (PIX *)ERROR_PTR("stream not defined", procName, NULL);
102
103 if ((data = l_binaryReadStream(fp, &nbytes)) == NULL)
104 return (PIX *)ERROR_PTR("data not read", procName, NULL);
105 pix = pixReadMemSpix(data, nbytes);
106 LEPT_FREE(data);
107 if (!pix)
108 return (PIX *)ERROR_PTR("pix not made", procName, NULL);
109 return pix;
110}
111
112
129l_ok
130readHeaderSpix(const char *filename,
131 l_int32 *pwidth,
132 l_int32 *pheight,
133 l_int32 *pbps,
134 l_int32 *pspp,
135 l_int32 *piscmap)
136{
137l_int32 ret;
138FILE *fp;
139
140 PROCNAME("readHeaderSpix");
141
142 if (!filename)
143 return ERROR_INT("filename not defined", procName, 1);
144 if (!pwidth || !pheight || !pbps || !pspp)
145 return ERROR_INT("input ptr(s) not defined", procName, 1);
146 if ((fp = fopenReadStream(filename)) == NULL)
147 return ERROR_INT("image file not found", procName, 1);
148 ret = freadHeaderSpix(fp, pwidth, pheight, pbps, pspp, piscmap);
149 fclose(fp);
150 return ret;
151}
152
153
170l_ok
172 l_int32 *pwidth,
173 l_int32 *pheight,
174 l_int32 *pbps,
175 l_int32 *pspp,
176 l_int32 *piscmap)
177{
178l_int32 nbytes, ret;
179l_uint32 data[6];
180
181 PROCNAME("freadHeaderSpix");
182
183 if (!fp)
184 return ERROR_INT("stream not defined", procName, 1);
185 if (!pwidth || !pheight || !pbps || !pspp)
186 return ERROR_INT("input ptr(s) not defined", procName, 1);
187
188 nbytes = fnbytesInFile(fp);
189 if (nbytes < 32)
190 return ERROR_INT("file too small to be spix", procName, 1);
191 if (fread(data, 4, 6, fp) != 6)
192 return ERROR_INT("error reading data", procName, 1);
193 ret = sreadHeaderSpix(data, nbytes, pwidth, pheight, pbps, pspp, piscmap);
194 return ret;
195}
196
197
215l_ok
216sreadHeaderSpix(const l_uint32 *data,
217 size_t size,
218 l_int32 *pwidth,
219 l_int32 *pheight,
220 l_int32 *pbps,
221 l_int32 *pspp,
222 l_int32 *piscmap)
223{
224char *id;
225l_int32 d, ncolors;
226
227 PROCNAME("sreadHeaderSpix");
228
229 if (!data)
230 return ERROR_INT("data not defined", procName, 1);
231 if (!pwidth || !pheight || !pbps || !pspp)
232 return ERROR_INT("input ptr(s) not defined", procName, 1);
233 *pwidth = *pheight = *pbps = *pspp = 0;
234 if (piscmap)
235 *piscmap = 0;
236 if (size < 28)
237 return ERROR_INT("size too small", procName, 1);
238
239 /* Check file id */
240 id = (char *)data;
241 if (id[0] != 's' || id[1] != 'p' || id[2] != 'i' || id[3] != 'x')
242 return ERROR_INT("not a valid spix file", procName, 1);
243
244 *pwidth = data[1];
245 *pheight = data[2];
246 d = data[3];
247 if (d <= 16) {
248 *pbps = d;
249 *pspp = 1;
250 } else {
251 *pbps = 8;
252 *pspp = d / 8; /* if the pix is 32 bpp, call it 4 samples */
253 }
254 ncolors = data[5];
255 if (piscmap)
256 *piscmap = (ncolors == 0) ? 0 : 1;
257
258 return 0;
259}
260
261
262/*-----------------------------------------------------------------------*
263 * Writing spix to file *
264 *-----------------------------------------------------------------------*/
272l_ok
274 PIX *pix)
275{
276l_uint8 *data;
277size_t size;
278
279 PROCNAME("pixWriteStreamSpix");
280
281 if (!fp)
282 return ERROR_INT("stream not defined", procName, 1);
283 if (!pix)
284 return ERROR_INT("pix not defined", procName, 1);
285
286 if (pixWriteMemSpix(&data, &size, pix))
287 return ERROR_INT("failure to write pix to memory", procName, 1);
288 fwrite(data, 1, size, fp);
289 LEPT_FREE(data);
290 return 0;
291}
292
293
294/*-----------------------------------------------------------------------*
295 * Low-level serialization of pix to/from memory (uncompressed) *
296 *-----------------------------------------------------------------------*/
304PIX *
305pixReadMemSpix(const l_uint8 *data,
306 size_t size)
307{
308 return pixDeserializeFromMemory((l_uint32 *)data, size);
309}
310
311
320l_ok
321pixWriteMemSpix(l_uint8 **pdata,
322 size_t *psize,
323 PIX *pix)
324{
325 return pixSerializeToMemory(pix, (l_uint32 **)pdata, psize);
326}
327
328
353l_ok
355 l_uint32 **pdata,
356 size_t *pnbytes)
357{
358char *id;
359l_int32 w, h, d, wpl, rdatasize, ncolors, nbytes, index, valid;
360l_uint8 *cdata; /* data in colormap array (4 bytes/color table entry) */
361l_uint32 *data;
362l_uint32 *rdata; /* data in pix raster */
363PIXCMAP *cmap;
364
365 PROCNAME("pixSerializeToMemory");
366
367 if (!pdata || !pnbytes)
368 return ERROR_INT("&data and &nbytes not both defined", procName, 1);
369 *pdata = NULL;
370 *pnbytes = 0;
371 if (!pixs)
372 return ERROR_INT("pixs not defined", procName, 1);
373
374 pixGetDimensions(pixs, &w, &h, &d);
375 wpl = pixGetWpl(pixs);
376 rdata = pixGetData(pixs);
377 rdatasize = 4 * wpl * h;
378 ncolors = 0;
379 cdata = NULL;
380 if ((cmap = pixGetColormap(pixs)) != NULL) {
381 pixcmapIsValid(cmap, pixs, &valid);
382 if (!valid)
383 return ERROR_INT("colormap not valid", procName, 1);
384 pixcmapSerializeToMemory(cmap, 4, &ncolors, &cdata);
385 }
386
387 nbytes = 24 + 4 * ncolors + 4 + rdatasize;
388 if ((data = (l_uint32 *)LEPT_CALLOC(nbytes / 4, sizeof(l_uint32)))
389 == NULL) {
390 LEPT_FREE(cdata);
391 return ERROR_INT("data not made", procName, 1);
392 }
393 *pdata = data;
394 *pnbytes = nbytes;
395 id = (char *)data;
396 id[0] = 's';
397 id[1] = 'p';
398 id[2] = 'i';
399 id[3] = 'x';
400 data[1] = w;
401 data[2] = h;
402 data[3] = d;
403 data[4] = wpl;
404 data[5] = ncolors;
405 if (ncolors > 0)
406 memcpy(data + 6, cdata, 4 * ncolors);
407 index = 6 + ncolors;
408 data[index] = rdatasize;
409 memcpy(data + index + 1, rdata, rdatasize);
410
411#if DEBUG_SERIALIZE
412 lept_stderr("Serialize: "
413 "raster size = %d, ncolors in cmap = %d, total bytes = %d\n",
414 rdatasize, ncolors, nbytes);
415#endif /* DEBUG_SERIALIZE */
416
417 LEPT_FREE(cdata);
418 return 0;
419}
420
421
435PIX *
436pixDeserializeFromMemory(const l_uint32 *data,
437 size_t nbytes)
438{
439char *id;
440l_int32 w, h, d, pixdata_size, memdata_size, imdata_size, ncolors, valid;
441l_uint32 *imdata; /* data in pix raster */
442PIX *pix1, *pixd;
443PIXCMAP *cmap;
444
445 PROCNAME("pixDeserializeFromMemory");
446
447 if (!data)
448 return (PIX *)ERROR_PTR("data not defined", procName, NULL);
449 if (nbytes < 28 || nbytes > ((1LL << 31) - 1)) {
450 L_ERROR("invalid nbytes = %zu\n", procName, nbytes);
451 return NULL;
452 }
453
454 id = (char *)data;
455 if (id[0] != 's' || id[1] != 'p' || id[2] != 'i' || id[3] != 'x')
456 return (PIX *)ERROR_PTR("invalid id string", procName, NULL);
457 w = data[1];
458 h = data[2];
459 d = data[3];
460 ncolors = data[5];
461
462 /* Sanity checks on the amount of image data */
463 if (w < 1 || w > MaxAllowedWidth)
464 return (PIX *)ERROR_PTR("invalid width", procName, NULL);
465 if (h < 1 || h > MaxAllowedHeight)
466 return (PIX *)ERROR_PTR("invalid height", procName, NULL);
467 if (1LL * w * h > MaxAllowedArea)
468 return (PIX *)ERROR_PTR("area too large", procName, NULL);
469 if (ncolors < 0 || ncolors > 256 || ncolors + 7 >= nbytes/sizeof(l_int32))
470 return (PIX *)ERROR_PTR("invalid ncolors", procName, NULL);
471 if ((pix1 = pixCreateHeader(w, h, d)) == NULL) /* just make the header */
472 return (PIX *)ERROR_PTR("failed to make header", procName, NULL);
473 pixdata_size = 4 * h * pixGetWpl(pix1);
474 memdata_size = nbytes - 24 - 4 * ncolors - 4;
475 imdata_size = data[6 + ncolors];
476 pixDestroy(&pix1);
477 if (pixdata_size != memdata_size || pixdata_size != imdata_size) {
478 L_ERROR("pixdata_size = %d, memdata_size = %d, imdata_size = %d "
479 "not all equal!\n", procName, pixdata_size, memdata_size,
480 imdata_size);
481 return NULL;
482 }
483
484 if ((pixd = pixCreate(w, h, d)) == NULL)
485 return (PIX *)ERROR_PTR("pix not made", procName, NULL);
486 if (ncolors > 0) {
487 cmap = pixcmapDeserializeFromMemory((l_uint8 *)(&data[6]), 4, ncolors);
488 if (!cmap) {
489 pixDestroy(&pixd);
490 return (PIX *)ERROR_PTR("cmap not made", procName, NULL);
491 }
492 if (pixSetColormap(pixd, cmap)) {
493 pixDestroy(&pixd);
494 return (PIX *)ERROR_PTR("cmap is not valid", procName, NULL);
495 }
496 }
497
498 /* Read the raster data */
499 imdata = pixGetData(pixd);
500 memcpy(imdata, data + 7 + ncolors, imdata_size);
501
502 /* Verify that the colormap is valid with the pix */
503 if (ncolors > 0) {
504 pixcmapIsValid(cmap, pixd, &valid);
505 if (!valid) {
506 pixDestroy(&pixd);
507 return (PIX *)ERROR_PTR("cmap is invalid with pix", procName, NULL);
508 }
509 }
510
511#if DEBUG_SERIALIZE
512 lept_stderr("Deserialize: "
513 "raster size = %d, ncolors in cmap = %d, total bytes = %zu\n",
514 imdata_size, ncolors, nbytes);
515#endif /* DEBUG_SERIALIZE */
516
517 return pixd;
518}
l_ok pixcmapIsValid(const PIXCMAP *cmap, PIX *pix, l_int32 *pvalid)
pixcmapIsValid()
Definition: colormap.c:317
l_ok pixcmapSerializeToMemory(PIXCMAP *cmap, l_int32 cpc, l_int32 *pncolors, l_uint8 **pdata)
pixcmapSerializeToMemory()
Definition: colormap.c:2164
PIXCMAP * pixcmapDeserializeFromMemory(l_uint8 *data, l_int32 cpc, l_int32 ncolors)
pixcmapDeserializeFromMemory()
Definition: colormap.c:2211
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1699
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixCreateHeader(l_int32 width, l_int32 height, l_int32 depth)
pixCreateHeader()
Definition: pix1.c:504
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok freadHeaderSpix(FILE *fp, l_int32 *pwidth, l_int32 *pheight, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
freadHeaderSpix()
Definition: spixio.c:171
PIX * pixDeserializeFromMemory(const l_uint32 *data, size_t nbytes)
pixDeserializeFromMemory()
Definition: spixio.c:436
l_ok pixWriteMemSpix(l_uint8 **pdata, size_t *psize, PIX *pix)
pixWriteMemSpix()
Definition: spixio.c:321
l_ok readHeaderSpix(const char *filename, l_int32 *pwidth, l_int32 *pheight, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
readHeaderSpix()
Definition: spixio.c:130
l_ok pixWriteStreamSpix(FILE *fp, PIX *pix)
pixWriteStreamSpix()
Definition: spixio.c:273
PIX * pixReadStreamSpix(FILE *fp)
pixReadStreamSpix()
Definition: spixio.c:92
PIX * pixReadMemSpix(const l_uint8 *data, size_t size)
pixReadMemSpix()
Definition: spixio.c:305
l_ok pixSerializeToMemory(PIX *pixs, l_uint32 **pdata, size_t *pnbytes)
pixSerializeToMemory()
Definition: spixio.c:354
l_ok sreadHeaderSpix(const l_uint32 *data, size_t size, l_int32 *pwidth, l_int32 *pheight, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
sreadHeaderSpix()
Definition: spixio.c:216
Definition: pix.h:139
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
size_t fnbytesInFile(FILE *fp)
fnbytesInFile()
Definition: utils2.c:1635
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1932
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1402