Leptonica 1.68
C Image Processing Library

spixio.c

Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines