Leptonica  1.73
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 #include <string.h>
60 #include "allheaders.h"
61 
62  /* Image dimension limits */
63 static const l_int32 L_MAX_ALLOWED_WIDTH = 1000000;
64 static const l_int32 L_MAX_ALLOWED_HEIGHT = 1000000;
65 static const l_int64 L_MAX_ALLOWED_AREA = 400000000LL;
66 
67 #ifndef NO_CONSOLE_IO
68 #define DEBUG_SERIALIZE 0
69 #endif /* ~NO_CONSOLE_IO */
70 
71 
72 /*-----------------------------------------------------------------------*
73  * Reading spix from file *
74  *-----------------------------------------------------------------------*/
87 PIX *
89 {
90 size_t nbytes;
91 l_uint8 *data;
92 PIX *pix;
93 
94  PROCNAME("pixReadStreamSpix");
95 
96  if (!fp)
97  return (PIX *)ERROR_PTR("stream not defined", procName, NULL);
98 
99  if ((data = l_binaryReadStream(fp, &nbytes)) == NULL)
100  return (PIX *)ERROR_PTR("data not read", procName, NULL);
101  pix = pixReadMemSpix(data, nbytes);
102  LEPT_FREE(data);
103  if (!pix)
104  return (PIX *)ERROR_PTR("pix not made", procName, NULL);
105  return pix;
106 }
107 
108 
125 l_int32
126 readHeaderSpix(const char *filename,
127  l_int32 *pwidth,
128  l_int32 *pheight,
129  l_int32 *pbps,
130  l_int32 *pspp,
131  l_int32 *piscmap)
132 {
133 l_int32 ret;
134 FILE *fp;
135 
136  PROCNAME("readHeaderSpix");
137 
138  if (!filename)
139  return ERROR_INT("filename not defined", procName, 1);
140  if (!pwidth || !pheight || !pbps || !pspp)
141  return ERROR_INT("input ptr(s) not defined", procName, 1);
142  if ((fp = fopenReadStream(filename)) == NULL)
143  return ERROR_INT("image file not found", procName, 1);
144  ret = freadHeaderSpix(fp, pwidth, pheight, pbps, pspp, piscmap);
145  fclose(fp);
146  return ret;
147 }
148 
149 
166 l_int32
168  l_int32 *pwidth,
169  l_int32 *pheight,
170  l_int32 *pbps,
171  l_int32 *pspp,
172  l_int32 *piscmap)
173 {
174 l_int32 nbytes, ret;
175 l_uint32 data[6];
176 
177  PROCNAME("freadHeaderSpix");
178 
179  if (!fp)
180  return ERROR_INT("stream not defined", procName, 1);
181  if (!pwidth || !pheight || !pbps || !pspp)
182  return ERROR_INT("input ptr(s) not defined", procName, 1);
183 
184  nbytes = fnbytesInFile(fp);
185  if (nbytes < 32)
186  return ERROR_INT("file too small to be spix", procName, 1);
187  if (fread(data, 4, 6, fp) != 6)
188  return ERROR_INT("error reading data", procName, 1);
189  ret = sreadHeaderSpix(data, pwidth, pheight, pbps, pspp, piscmap);
190  return ret;
191 }
192 
193 
210 l_int32
211 sreadHeaderSpix(const l_uint32 *data,
212  l_int32 *pwidth,
213  l_int32 *pheight,
214  l_int32 *pbps,
215  l_int32 *pspp,
216  l_int32 *piscmap)
217 {
218 char *id;
219 l_int32 d, ncolors;
220 
221  PROCNAME("sreadHeaderSpix");
222 
223  if (!data)
224  return ERROR_INT("data not defined", procName, 1);
225  if (!pwidth || !pheight || !pbps || !pspp)
226  return ERROR_INT("input ptr(s) not defined", procName, 1);
227  *pwidth = *pheight = *pbps = *pspp = 0;
228  if (piscmap)
229  *piscmap = 0;
230 
231  /* Check file id */
232  id = (char *)data;
233  if (id[0] != 's' || id[1] != 'p' || id[2] != 'i' || id[3] != 'x')
234  return ERROR_INT("not a valid spix file", procName, 1);
235 
236  *pwidth = data[1];
237  *pheight = data[2];
238  d = data[3];
239  if (d <= 16) {
240  *pbps = d;
241  *pspp = 1;
242  } else {
243  *pbps = 8;
244  *pspp = d / 8; /* if the pix is 32 bpp, call it 4 samples */
245  }
246  ncolors = data[5];
247  if (piscmap)
248  *piscmap = (ncolors == 0) ? 0 : 1;
249 
250  return 0;
251 }
252 
253 
254 /*-----------------------------------------------------------------------*
255  * Writing spix to file *
256  *-----------------------------------------------------------------------*/
264 l_int32
266  PIX *pix)
267 {
268 l_uint8 *data;
269 size_t size;
270 
271  PROCNAME("pixWriteStreamSpix");
272 
273  if (!fp)
274  return ERROR_INT("stream not defined", procName, 1);
275  if (!pix)
276  return ERROR_INT("pix not defined", procName, 1);
277 
278  if (pixWriteMemSpix(&data, &size, pix))
279  return ERROR_INT("failure to write pix to memory", procName, 1);
280  fwrite(data, 1, size, fp);
281  LEPT_FREE(data);
282  return 0;
283 }
284 
285 
286 /*-----------------------------------------------------------------------*
287  * Low-level serialization of pix to/from memory (uncompressed) *
288  *-----------------------------------------------------------------------*/
296 PIX *
297 pixReadMemSpix(const l_uint8 *data,
298  size_t size)
299 {
300  return pixDeserializeFromMemory((l_uint32 *)data, size);
301 }
302 
303 
312 l_int32
313 pixWriteMemSpix(l_uint8 **pdata,
314  size_t *psize,
315  PIX *pix)
316 {
317  return pixSerializeToMemory(pix, (l_uint32 **)pdata, psize);
318 }
319 
320 
345 l_int32
347  l_uint32 **pdata,
348  size_t *pnbytes)
349 {
350 char *id;
351 l_int32 w, h, d, wpl, rdatasize, ncolors, nbytes, index;
352 l_uint8 *cdata; /* data in colormap array (4 bytes/color table entry) */
353 l_uint32 *data;
354 l_uint32 *rdata; /* data in pix raster */
355 PIXCMAP *cmap;
356 
357  PROCNAME("pixSerializeToMemory");
358 
359  if (!pdata || !pnbytes)
360  return ERROR_INT("&data and &nbytes not both defined", procName, 1);
361  *pdata = NULL;
362  *pnbytes = 0;
363  if (!pixs)
364  return ERROR_INT("pixs not defined", procName, 1);
365 
366  pixGetDimensions(pixs, &w, &h, &d);
367  wpl = pixGetWpl(pixs);
368  rdata = pixGetData(pixs);
369  rdatasize = 4 * wpl * h;
370  ncolors = 0;
371  cdata = NULL;
372  if ((cmap = pixGetColormap(pixs)) != NULL)
373  pixcmapSerializeToMemory(cmap, 4, &ncolors, &cdata);
374 
375  nbytes = 24 + 4 * ncolors + 4 + rdatasize;
376  if ((data = (l_uint32 *)LEPT_CALLOC(nbytes / 4, sizeof(l_uint32)))
377  == NULL) {
378  LEPT_FREE(cdata);
379  return ERROR_INT("data not made", procName, 1);
380  }
381  *pdata = data;
382  *pnbytes = nbytes;
383  id = (char *)data;
384  id[0] = 's';
385  id[1] = 'p';
386  id[2] = 'i';
387  id[3] = 'x';
388  data[1] = w;
389  data[2] = h;
390  data[3] = d;
391  data[4] = wpl;
392  data[5] = ncolors;
393  if (ncolors > 0)
394  memcpy((char *)(data + 6), (char *)cdata, 4 * ncolors);
395  index = 6 + ncolors;
396  data[index] = rdatasize;
397  memcpy((char *)(data + index + 1), (char *)rdata, rdatasize);
398 
399 #if DEBUG_SERIALIZE
400  fprintf(stderr, "Serialize: "
401  "raster size = %d, ncolors in cmap = %d, total bytes = %d\n",
402  rdatasize, ncolors, nbytes);
403 #endif /* DEBUG_SERIALIZE */
404 
405  LEPT_FREE(cdata);
406  return 0;
407 }
408 
409 
423 PIX *
424 pixDeserializeFromMemory(const l_uint32 *data,
425  size_t nbytes)
426 {
427 char *id;
428 l_int32 w, h, d, pixdata_size, memdata_size, imdata_size, ncolors;
429 l_uint32 *imdata; /* data in pix raster */
430 PIX *pix1, *pixd;
431 PIXCMAP *cmap;
432 
433  PROCNAME("pixDeserializeFromMemory");
434 
435  if (!data)
436  return (PIX *)ERROR_PTR("data not defined", procName, NULL);
437  if (nbytes < 28)
438  return (PIX *)ERROR_PTR("invalid data", procName, NULL);
439 
440  id = (char *)data;
441  if (id[0] != 's' || id[1] != 'p' || id[2] != 'i' || id[3] != 'x')
442  return (PIX *)ERROR_PTR("invalid id string", procName, NULL);
443  w = data[1];
444  h = data[2];
445  d = data[3];
446  ncolors = data[5];
447  imdata_size = data[6 + ncolors];
448 
449  /* Sanity checks on the amount of image data */
450  if (w < 1 || w > L_MAX_ALLOWED_WIDTH)
451  return (PIX *)ERROR_PTR("invalid width", procName, NULL);
452  if (h < 1 || h > L_MAX_ALLOWED_HEIGHT)
453  return (PIX *)ERROR_PTR("invalid height", procName, NULL);
454  if (1LL * w * h > L_MAX_ALLOWED_AREA)
455  return (PIX *)ERROR_PTR("area too large", procName, NULL);
456  if (ncolors < 0 || ncolors > 256)
457  return (PIX *)ERROR_PTR("invalid ncolors", procName, NULL);
458  if ((pix1 = pixCreateHeader(w, h, d)) == NULL) /* just make the header */
459  return (PIX *)ERROR_PTR("failed to make header", procName, NULL);
460  pixdata_size = 4 * h * pixGetWpl(pix1);
461  memdata_size = nbytes - 24 - 4 * ncolors - 4;
462  imdata_size = data[6 + ncolors];
463  pixDestroy(&pix1);
464  if (pixdata_size != memdata_size || pixdata_size != imdata_size) {
465  L_ERROR("pixdata_size = %d, memdata_size = %d, imdata_size = %d "
466  "not all equal!\n", procName, pixdata_size, memdata_size,
467  imdata_size);
468  return NULL;
469  }
470 
471  if ((pixd = pixCreate(w, h, d)) == NULL)
472  return (PIX *)ERROR_PTR("pix not made", procName, NULL);
473  if (ncolors > 0) {
474  cmap = pixcmapDeserializeFromMemory((l_uint8 *)(&data[6]), 4, ncolors);
475  if (!cmap) {
476  pixDestroy(&pixd);
477  return (PIX *)ERROR_PTR("cmap not made", procName, NULL);
478  }
479  pixSetColormap(pixd, cmap);
480  }
481 
482  imdata = pixGetData(pixd);
483  memcpy((char *)imdata, (char *)(data + 7 + ncolors), imdata_size);
484 
485 #if DEBUG_SERIALIZE
486  fprintf(stderr, "Deserialize: "
487  "raster size = %d, ncolors in cmap = %d, total bytes = %lu\n",
488  imdata_size, ncolors, nbytes);
489 #endif /* DEBUG_SERIALIZE */
490 
491  return pixd;
492 }
PIX * pixReadMemSpix(const l_uint8 *data, size_t size)
pixReadMemSpix()
Definition: spixio.c:297
l_int32 pixWriteMemSpix(l_uint8 **pdata, size_t *psize, PIX *pix)
pixWriteMemSpix()
Definition: spixio.c:313
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1602
PIX * pixDeserializeFromMemory(const l_uint32 *data, size_t nbytes)
pixDeserializeFromMemory()
Definition: spixio.c:424
l_int32 freadHeaderSpix(FILE *fp, l_int32 *pwidth, l_int32 *pheight, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
freadHeaderSpix()
Definition: spixio.c:167
PIX * pixCreateHeader(l_int32 width, l_int32 height, l_int32 depth)
pixCreateHeader()
Definition: pix1.c:439
l_int32 pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1556
size_t fnbytesInFile(FILE *fp)
fnbytesInFile()
Definition: utils2.c:1433
PIX * pixReadStreamSpix(FILE *fp)
pixReadStreamSpix()
Definition: spixio.c:88
l_int32 pixWriteStreamSpix(FILE *fp, PIX *pix)
pixWriteStreamSpix()
Definition: spixio.c:265
l_int32 pixSerializeToMemory(PIX *pixs, l_uint32 **pdata, size_t *pnbytes)
pixSerializeToMemory()
Definition: spixio.c:346
PIXCMAP * pixcmapDeserializeFromMemory(l_uint8 *data, l_int32 cpc, l_int32 ncolors)
pixcmapDeserializeFromMemory()
Definition: colormap.c:1960
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:545
l_int32 readHeaderSpix(const char *filename, l_int32 *pwidth, l_int32 *pheight, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
readHeaderSpix()
Definition: spixio.c:126
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1593
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1200
Definition: pix.h:134
l_int32 sreadHeaderSpix(const l_uint32 *data, l_int32 *pwidth, l_int32 *pheight, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
sreadHeaderSpix()
Definition: spixio.c:211
l_int32 pixcmapSerializeToMemory(PIXCMAP *cmap, l_int32 cpc, l_int32 *pncolors, l_uint8 **pdata)
pixcmapSerializeToMemory()
Definition: colormap.c:1912
l_int32 pixGetDimensions(PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1052