Leptonica 1.68
C Image Processing Library
|
00001 /*====================================================================* 00002 - Copyright (C) 2001 Leptonica. All rights reserved. 00003 - This software is distributed in the hope that it will be 00004 - useful, but with NO WARRANTY OF ANY KIND. 00005 - No author or distributor accepts responsibility to anyone for the 00006 - consequences of using this software, or for whether it serves any 00007 - particular purpose or works at all, unless he or she says so in 00008 - writing. Everyone is granted permission to copy, modify and 00009 - redistribute this source code, for commercial or non-commercial 00010 - purposes, with the following restrictions: (1) the origin of this 00011 - source code must not be misrepresented; (2) modified versions must 00012 - be plainly marked as such; and (3) this notice may not be removed 00013 - or altered from any source or modified source distribution. 00014 *====================================================================*/ 00015 00016 /* 00017 * spixio.c 00018 * 00019 * This does fast serialization of a pix in memory to file, 00020 * copying the raw data for maximum speed. The underlying 00021 * function serializes it to memory, and it is wrapped to be 00022 * callable from standard pixRead and pixWrite functions. 00023 * 00024 * Reading spix from file 00025 * PIX *pixReadStreamSpix() 00026 * l_int32 readHeaderSpix() 00027 * l_int32 freadHeaderSpix() 00028 * l_int32 sreadHeaderSpix() 00029 * 00030 * Writing spix to file 00031 * l_int32 pixWriteStreamSpix() 00032 * 00033 * Low-level serialization of pix to/from memory (uncompressed) 00034 * PIX *pixReadMemSpix() 00035 * l_int32 pixWriteMemSpix() 00036 * l_int32 pixSerializeToMemory() 00037 * PIX *pixDeserializeFromMemory() 00038 * 00039 */ 00040 00041 #include <string.h> 00042 #include "allheaders.h" 00043 00044 00045 /*-----------------------------------------------------------------------* 00046 * Reading spix from file * 00047 *-----------------------------------------------------------------------*/ 00048 /*! 00049 * pixReadStreamSpix() 00050 * 00051 * Input: stream 00052 * Return: pix, or null on error. 00053 * 00054 * Notes: 00055 * (1) If called from pixReadStream(), the stream is positioned 00056 * at the beginning of the file. 00057 */ 00058 PIX * 00059 pixReadStreamSpix(FILE *fp) 00060 { 00061 size_t nbytes; 00062 l_uint8 *data; 00063 PIX *pix; 00064 00065 PROCNAME("pixReadStreamSpix"); 00066 00067 if (!fp) 00068 return (PIX *)ERROR_PTR("stream not defined", procName, NULL); 00069 00070 if ((data = l_binaryReadStream(fp, &nbytes)) == NULL) 00071 return (PIX *)ERROR_PTR("data not read", procName, NULL); 00072 if ((pix = pixReadMemSpix(data, nbytes)) == NULL) { 00073 FREE(data); 00074 return (PIX *)ERROR_PTR("pix not made", procName, NULL); 00075 } 00076 00077 FREE(data); 00078 return pix; 00079 } 00080 00081 00082 /*! 00083 * readHeaderSpix() 00084 * 00085 * Input: filename 00086 * &width (<return>) 00087 * &height (<return>) 00088 * &bps (<return>, bits/sample) 00089 * &spp (<return>, samples/pixel) 00090 * &iscmap (<optional return>; input NULL to ignore) 00091 * Return: 0 if OK, 1 on error 00092 * 00093 * Notes: 00094 * (1) If there is a colormap, iscmap is returned as 1; else 0. 00095 */ 00096 l_int32 00097 readHeaderSpix(const char *filename, 00098 l_int32 *pwidth, 00099 l_int32 *pheight, 00100 l_int32 *pbps, 00101 l_int32 *pspp, 00102 l_int32 *piscmap) 00103 { 00104 l_int32 ret; 00105 FILE *fp; 00106 00107 PROCNAME("readHeaderSpix"); 00108 00109 if (!filename) 00110 return ERROR_INT("filename not defined", procName, 1); 00111 if (!pwidth || !pheight || !pbps || !pspp) 00112 return ERROR_INT("input ptr(s) not defined", procName, 1); 00113 if ((fp = fopenReadStream(filename)) == NULL) 00114 return ERROR_INT("image file not found", procName, 1); 00115 ret = freadHeaderSpix(fp, pwidth, pheight, pbps, pspp, piscmap); 00116 fclose(fp); 00117 return ret; 00118 } 00119 00120 00121 /*! 00122 * freadHeaderSpix() 00123 * 00124 * Input: stream 00125 * &width (<return>) 00126 * &height (<return>) 00127 * &bps (<return>, bits/sample) 00128 * &spp (<return>, samples/pixel) 00129 * &iscmap (<optional return>; input NULL to ignore) 00130 * Return: 0 if OK, 1 on error 00131 * 00132 * Notes: 00133 * (1) If there is a colormap, iscmap is returned as 1; else 0. 00134 */ 00135 l_int32 00136 freadHeaderSpix(FILE *fp, 00137 l_int32 *pwidth, 00138 l_int32 *pheight, 00139 l_int32 *pbps, 00140 l_int32 *pspp, 00141 l_int32 *piscmap) 00142 { 00143 l_int32 nbytes, ret; 00144 l_uint32 *data; 00145 00146 PROCNAME("freadHeaderSpix"); 00147 00148 if (!fp) 00149 return ERROR_INT("stream not defined", procName, 1); 00150 if (!pwidth || !pheight || !pbps || !pspp) 00151 return ERROR_INT("input ptr(s) not defined", procName, 1); 00152 00153 nbytes = fnbytesInFile(fp); 00154 if (nbytes < 32) 00155 return ERROR_INT("file too small to be spix", procName, 1); 00156 if ((data = (l_uint32 *)CALLOC(6, sizeof(l_uint32))) == NULL) 00157 return ERROR_INT("CALLOC fail for data", procName, 1); 00158 if (fread(data, 4, 6, fp) != 6) 00159 return ERROR_INT("error reading data", procName, 1); 00160 ret = sreadHeaderSpix(data, pwidth, pheight, pbps, pspp, piscmap); 00161 FREE(data); 00162 return ret; 00163 } 00164 00165 00166 /*! 00167 * sreadHeaderSpix() 00168 * 00169 * Input: data 00170 * &width (<return>) 00171 * &height (<return>) 00172 * &bps (<return>, bits/sample) 00173 * &spp (<return>, samples/pixel) 00174 * &iscmap (<optional return>; input NULL to ignore) 00175 * Return: 0 if OK, 1 on error 00176 * 00177 * Notes: 00178 * (1) If there is a colormap, iscmap is returned as 1; else 0. 00179 */ 00180 l_int32 00181 sreadHeaderSpix(const l_uint32 *data, 00182 l_int32 *pwidth, 00183 l_int32 *pheight, 00184 l_int32 *pbps, 00185 l_int32 *pspp, 00186 l_int32 *piscmap) 00187 { 00188 char *id; 00189 l_int32 d, ncolors; 00190 00191 PROCNAME("sreadHeaderSpix"); 00192 00193 if (!data) 00194 return ERROR_INT("data not defined", procName, 1); 00195 if (!pwidth || !pheight || !pbps || !pspp) 00196 return ERROR_INT("input ptr(s) not defined", procName, 1); 00197 *pwidth = *pheight = *pbps = *pspp = 0; 00198 if (piscmap) 00199 *piscmap = 0; 00200 00201 /* Check file id */ 00202 id = (char *)data; 00203 if (id[0] != 's' || id[1] != 'p' || id[2] != 'i' || id[3] != 'x') 00204 return ERROR_INT("not a valid spix file", procName, 1); 00205 00206 *pwidth = data[1]; 00207 *pheight = data[2]; 00208 d = data[3]; 00209 if (d <= 16) { 00210 *pbps = d; 00211 *pspp = 1; 00212 } 00213 else { 00214 *pbps = 8; 00215 *pspp = d / 8; /* if the pix is 32 bpp, call it 4 samples */ 00216 } 00217 ncolors = data[5]; 00218 if (piscmap) 00219 *piscmap = (ncolors == 0) ? 0 : 1; 00220 00221 return 0; 00222 } 00223 00224 00225 /*-----------------------------------------------------------------------* 00226 * Writing spix to file * 00227 *-----------------------------------------------------------------------*/ 00228 /*! 00229 * pixWriteStreamSpix() 00230 * 00231 * Input: stream 00232 * pix 00233 * Return: 0 if OK; 1 on error 00234 */ 00235 l_int32 00236 pixWriteStreamSpix(FILE *fp, 00237 PIX *pix) 00238 { 00239 l_uint8 *data; 00240 size_t size; 00241 00242 PROCNAME("pixWriteStreamSpix"); 00243 00244 if (!fp) 00245 return ERROR_INT("stream not defined", procName, 1); 00246 if (!pix) 00247 return ERROR_INT("pix not defined", procName, 1); 00248 00249 if (pixWriteMemSpix(&data, &size, pix)) 00250 return ERROR_INT("failure to write pix to memory", procName, 1); 00251 fwrite(data, 1, size, fp); 00252 FREE(data); 00253 return 0; 00254 } 00255 00256 00257 /*-----------------------------------------------------------------------* 00258 * Low-level serialization of pix to/from memory (uncompressed) * 00259 *-----------------------------------------------------------------------*/ 00260 /*! 00261 * pixReadMemSpix() 00262 * 00263 * Input: data (const; uncompressed) 00264 * size (of data) 00265 * Return: pix, or null on error 00266 */ 00267 PIX * 00268 pixReadMemSpix(const l_uint8 *data, 00269 size_t size) 00270 { 00271 return pixDeserializeFromMemory((l_uint32 *)data, size); 00272 } 00273 00274 00275 /*! 00276 * pixWriteMemSpix() 00277 * 00278 * Input: &data (<return> data of serialized, uncompressed pix) 00279 * &size (<return> size of returned data) 00280 * pix (all depths; colormap OK) 00281 * Return: 0 if OK, 1 on error 00282 */ 00283 l_int32 00284 pixWriteMemSpix(l_uint8 **pdata, 00285 size_t *psize, 00286 PIX *pix) 00287 { 00288 return pixSerializeToMemory(pix, (l_uint32 **)pdata, psize); 00289 } 00290 00291 00292 /*! 00293 * pixSerializeToMemory() 00294 * 00295 * Input: pixs (all depths, colormap OK) 00296 * &data (<return> serialized data in memory) 00297 * &nbytes (<return> number of bytes in data string) 00298 * Return: 0 if OK, 1 on error 00299 * 00300 * Notes: 00301 * (1) This does a fast serialization of the principal elements 00302 * of the pix, as follows: 00303 * "spix" (4 bytes) -- ID for file type 00304 * w (4 bytes) 00305 * h (4 bytes) 00306 * d (4 bytes) 00307 * wpl (4 bytes) 00308 * ncolors (4 bytes) -- in colormap; 0 if there is no colormap 00309 * cdatasize (4 bytes) -- size of serialized colormap 00310 * = 4 * (num colors) 00311 * cdata (cdatasize) 00312 * rdatasize (4 bytes) -- size of serialized raster data 00313 * = 4 * wpl * h 00314 * rdata (rdatasize) 00315 */ 00316 l_int32 00317 pixSerializeToMemory(PIX *pixs, 00318 l_uint32 **pdata, 00319 size_t *pnbytes) 00320 { 00321 char *id; 00322 l_int32 w, h, d, wpl, rdatasize, cdatasize, ncolors, nbytes, index; 00323 l_uint8 *cdata; /* data in colormap (4 bytes/color table entry) */ 00324 l_uint32 *data; 00325 l_uint32 *rdata; /* data in pix raster */ 00326 PIXCMAP *cmap; 00327 00328 PROCNAME("pixSerializeToMemory"); 00329 00330 if (!pdata || !pnbytes) 00331 return ERROR_INT("&data and &nbytes not both defined", procName, 1); 00332 *pdata = NULL; 00333 *pnbytes = 0; 00334 if (!pixs) 00335 return ERROR_INT("pixs not defined", procName, 1); 00336 00337 pixGetDimensions(pixs, &w, &h, &d); 00338 wpl = pixGetWpl(pixs); 00339 rdata = pixGetData(pixs); 00340 rdatasize = 4 * wpl * h; 00341 cdatasize = 0; 00342 ncolors = 0; 00343 cdata = NULL; 00344 if ((cmap = pixGetColormap(pixs)) != NULL) 00345 pixcmapSerializeToMemory(cmap, 4, &ncolors, &cdata, &cdatasize); 00346 00347 nbytes = 32 + cdatasize + rdatasize; 00348 if ((data = (l_uint32 *)CALLOC(nbytes / 4, sizeof(l_uint32))) == NULL) 00349 return ERROR_INT("data not made", procName, 1); 00350 *pdata = data; 00351 *pnbytes = nbytes; 00352 id = (char *)data; 00353 id[0] = 's'; 00354 id[1] = 'p'; 00355 id[2] = 'i'; 00356 id[3] = 'x'; 00357 data[1] = w; 00358 data[2] = h; 00359 data[3] = d; 00360 data[4] = wpl; 00361 data[5] = ncolors; 00362 data[6] = cdatasize; 00363 if (cdatasize > 0) 00364 memcpy((char *)(data + 7), (char *)cdata, cdatasize); 00365 index = 7 + cdatasize / 4; 00366 data[index] = rdatasize; 00367 memcpy((char *)(data + index + 1), (char *)rdata, rdatasize); 00368 00369 #if DEBUG_SERIALIZE 00370 fprintf(stderr, "Serialize: " 00371 "raster size = %d, ncolors in cmap = %d, total bytes = %d\n", 00372 rdatasize, ncolors, nbytes); 00373 #endif /* DEBUG_SERIALIZE */ 00374 00375 FREE(cdata); 00376 return 0; 00377 } 00378 00379 00380 /*! 00381 * pixDeserializeFromMemory() 00382 * 00383 * Input: data (serialized data in memory) 00384 * nbytes (number of bytes in data string) 00385 * Return: pix, or NULL on error 00386 * 00387 * Notes: 00388 * (1) See pixSerializeToMemory() for the binary format. 00389 */ 00390 PIX * 00391 pixDeserializeFromMemory(const l_uint32 *data, 00392 size_t nbytes) 00393 { 00394 char *id; 00395 l_int32 w, h, d, wpl, imdatasize, cdatasize, ncolors; 00396 l_uint32 *imdata; /* data in pix raster */ 00397 PIX *pixd; 00398 PIXCMAP *cmap; 00399 00400 PROCNAME("pixDeserializeFromMemory"); 00401 00402 if (!data) 00403 return (PIX *)ERROR_PTR("data not defined", procName, NULL); 00404 if (nbytes < 32) 00405 return (PIX *)ERROR_PTR("invalid data", procName, NULL); 00406 00407 id = (char *)data; 00408 if (id[0] != 's' || id[1] != 'p' || id[2] != 'i' || id[3] != 'x') 00409 return (PIX *)ERROR_PTR("invalid id string", procName, NULL); 00410 w = data[1]; 00411 h = data[2]; 00412 d = data[3]; 00413 if ((pixd = pixCreate(w, h, d)) == NULL) 00414 return (PIX *)ERROR_PTR("pix not made", procName, NULL); 00415 00416 wpl = data[4]; 00417 ncolors = data[5]; 00418 if ((cdatasize = data[6]) > 0) { 00419 cmap = pixcmapDeserializeFromMemory((l_uint8 *)(&data[7]), ncolors, 00420 cdatasize); 00421 if (!cmap) 00422 return (PIX *)ERROR_PTR("cmap not made", procName, NULL); 00423 pixSetColormap(pixd, cmap); 00424 } 00425 00426 imdata = pixGetData(pixd); 00427 imdatasize = nbytes - 32 - cdatasize; 00428 memcpy((char *)imdata, (char *)(data + 8 + cdatasize / 4), imdatasize); 00429 00430 #if DEBUG_SERIALIZE 00431 fprintf(stderr, "Deserialize: " 00432 "raster size = %d, ncolors in cmap = %d, total bytes = %d\n", 00433 imdatasize, ncolors, nbytes); 00434 #endif /* DEBUG_SERIALIZE */ 00435 00436 return pixd; 00437 } 00438 00439