Leptonica  1.82.0
Image processing and image analysis suite
gifio.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 
69 #ifdef HAVE_CONFIG_H
70 #include <config_auto.h>
71 #endif /* HAVE_CONFIG_H */
72 
73 #include <string.h>
74 #include "allheaders.h"
75 
76 /* --------------------------------------------------------------------*/
77 #if HAVE_LIBGIF || HAVE_LIBUNGIF /* defined in environ.h */
78 /* --------------------------------------------------------------------*/
79 
80 #include "gif_lib.h"
81 
82  /* Interface that enables low-level GIF support for reading from memory */
83 static PIX * gifToPix(GifFileType *gif);
84  /* Interface that enables low-level GIF support for writing to memory */
85 static l_int32 pixToGif(PIX *pix, GifFileType *gif);
86 
88 typedef struct GifReadBuffer
89 {
90  size_t size;
91  size_t pos;
92  const l_uint8 *cdata;
93 } GifReadBuffer;
94 
96 static l_int32 gifReadFunc(GifFileType *gif, GifByteType *dest,
97  l_int32 bytesToRead);
99 static l_int32 gifWriteFunc(GifFileType *gif, const GifByteType *src,
100  l_int32 bytesToWrite);
101 
102 
103 /*---------------------------------------------------------------------*
104  * Reading gif *
105  *---------------------------------------------------------------------*/
112 PIX *
113 pixReadStreamGif(FILE *fp)
114 {
115 l_uint8 *filedata;
116 size_t filesize;
117 PIX *pix;
118 
119  PROCNAME("pixReadStreamGif");
120 
121  if (!fp)
122  return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
123 
124  /* Read data into memory from file */
125  rewind(fp);
126  if ((filedata = l_binaryReadStream(fp, &filesize)) == NULL)
127  return (PIX *)ERROR_PTR("filedata not read", procName, NULL);
128 
129  /* Uncompress from memory */
130  pix = pixReadMemGif(filedata, filesize);
131  LEPT_FREE(filedata);
132  if (!pix)
133  L_ERROR("failed to read gif from file data\n", procName);
134  return pix;
135 }
136 
137 
155 PIX *
156 pixReadMemGif(const l_uint8 *cdata,
157  size_t size)
158 {
159 GifFileType *gif;
160 GifReadBuffer buffer;
161 
162  PROCNAME("pixReadMemGif");
163 
164  /* 5.1+ and not 5.1.2 */
165 #if (GIFLIB_MAJOR < 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 0))
166  L_ERROR("Require giflib-5.1 or later\n", procName);
167  return NULL;
168 #endif /* < 5.1 */
169 #if GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 1 && GIFLIB_RELEASE == 2 /* 5.1.2 */
170  L_ERROR("Can't use giflib-5.1.2; suggest 5.1.3 or later\n", procName);
171  return NULL;
172 #endif /* 5.1.2 */
173 
174  if (!cdata)
175  return (PIX *)ERROR_PTR("cdata not defined", procName, NULL);
176 
177  buffer.cdata = cdata;
178  buffer.size = size;
179  buffer.pos = 0;
180  if ((gif = DGifOpen((void*)&buffer, gifReadFunc, NULL)) == NULL)
181  return (PIX *)ERROR_PTR("could not open gif stream from memory",
182  procName, NULL);
183 
184  return gifToPix(gif);
185 }
186 
187 
188 static l_int32
189 gifReadFunc(GifFileType *gif,
190  GifByteType *dest,
191  l_int32 bytesToRead)
192 {
193 GifReadBuffer *buffer;
194 l_int32 bytesRead;
195 
196  PROCNAME("gifReadFunc");
197 
198  if ((buffer = (GifReadBuffer*)gif->UserData) == NULL)
199  return ERROR_INT("UserData not set", procName, -1);
200 
201  if(buffer->pos >= buffer->size || bytesToRead > buffer->size)
202  return -1;
203 
204  bytesRead = (buffer->pos < buffer->size - bytesToRead)
205  ? bytesToRead : buffer->size - buffer->pos;
206  memcpy(dest, buffer->cdata + buffer->pos, bytesRead);
207  buffer->pos += bytesRead;
208  return bytesRead;
209 }
210 
211 
225 static PIX *
226 gifToPix(GifFileType *gif)
227 {
228 l_int32 wpl, i, j, w, h, d, cindex, ncolors, valid, nimages;
229 l_int32 rval, gval, bval;
230 l_uint32 *data, *line;
231 PIX *pixd;
232 PIXCMAP *cmap;
233 ColorMapObject *gif_cmap;
234 SavedImage si;
235 int giferr;
236 
237  PROCNAME("gifToPix");
238 
239  /* Read all the data, but use only the first image found */
240  if (DGifSlurp(gif) != GIF_OK) {
241  DGifCloseFile(gif, &giferr);
242  return (PIX *)ERROR_PTR("failed to read GIF data", procName, NULL);
243  }
244 
245  if (gif->SavedImages == NULL) {
246  DGifCloseFile(gif, &giferr);
247  return (PIX *)ERROR_PTR("no images found in GIF", procName, NULL);
248  }
249 
250  nimages = gif->ImageCount;
251  if (nimages > 1)
252  L_WARNING("There are %d images in the file; we only read the first\n",
253  procName, nimages);
254 
255  si = gif->SavedImages[0];
256  w = si.ImageDesc.Width;
257  h = si.ImageDesc.Height;
258  if (w <= 0 || h <= 0) {
259  DGifCloseFile(gif, &giferr);
260  return (PIX *)ERROR_PTR("invalid image dimensions", procName, NULL);
261  }
262 
263  if (si.RasterBits == NULL) {
264  DGifCloseFile(gif, &giferr);
265  return (PIX *)ERROR_PTR("no raster data in GIF", procName, NULL);
266  }
267 
268  if (si.ImageDesc.ColorMap) {
269  /* private cmap for this image */
270  gif_cmap = si.ImageDesc.ColorMap;
271  } else if (gif->SColorMap) {
272  /* global cmap for whole picture */
273  gif_cmap = gif->SColorMap;
274  } else {
275  /* don't know where to take cmap from */
276  DGifCloseFile(gif, &giferr);
277  return (PIX *)ERROR_PTR("color map is missing", procName, NULL);
278  }
279 
280  ncolors = gif_cmap->ColorCount;
281  if (ncolors <= 0 || ncolors > 256) {
282  DGifCloseFile(gif, &giferr);
283  return (PIX *)ERROR_PTR("ncolors is invalid", procName, NULL);
284  }
285  if (ncolors <= 2)
286  d = 1;
287  else if (ncolors <= 4)
288  d = 2;
289  else if (ncolors <= 16)
290  d = 4;
291  else /* [17 ... 256] */
292  d = 8;
293  cmap = pixcmapCreate(d);
294  for (cindex = 0; cindex < ncolors; cindex++) {
295  rval = gif_cmap->Colors[cindex].Red;
296  gval = gif_cmap->Colors[cindex].Green;
297  bval = gif_cmap->Colors[cindex].Blue;
298  pixcmapAddColor(cmap, rval, gval, bval);
299  }
300 
301  if ((pixd = pixCreate(w, h, d)) == NULL) {
302  DGifCloseFile(gif, &giferr);
303  pixcmapDestroy(&cmap);
304  return (PIX *)ERROR_PTR("failed to allocate pixd", procName, NULL);
305  }
306  pixSetInputFormat(pixd, IFF_GIF);
307  pixSetColormap(pixd, cmap);
308  pixcmapIsValid(cmap, pixd, &valid);
309  if (!valid) {
310  DGifCloseFile(gif, &giferr);
311  pixDestroy(&pixd);
312  pixcmapDestroy(&cmap);
313  return (PIX *)ERROR_PTR("colormap is invalid", procName, NULL);
314  }
315 
316  wpl = pixGetWpl(pixd);
317  data = pixGetData(pixd);
318  for (i = 0; i < h; i++) {
319  line = data + i * wpl;
320  if (d == 1) {
321  for (j = 0; j < w; j++) {
322  if (si.RasterBits[i * w + j])
323  SET_DATA_BIT(line, j);
324  }
325  } else if (d == 2) {
326  for (j = 0; j < w; j++)
327  SET_DATA_DIBIT(line, j, si.RasterBits[i * w + j]);
328  } else if (d == 4) {
329  for (j = 0; j < w; j++)
330  SET_DATA_QBIT(line, j, si.RasterBits[i * w + j]);
331  } else { /* d == 8 */
332  for (j = 0; j < w; j++)
333  SET_DATA_BYTE(line, j, si.RasterBits[i * w + j]);
334  }
335  }
336 
337  /* Versions before 5.0 required un-interlacing to restore
338  * the raster lines to normal order if the image
339  * had been interlaced (for viewing in a browser):
340  if (gif->Image.Interlace) {
341  PIX *pixdi = pixUninterlaceGIF(pixd);
342  pixTransferAllData(pixd, &pixdi, 0, 0);
343  }
344  * This is no longer required. */
345 
346  DGifCloseFile(gif, &giferr);
347  return pixd;
348 }
349 
350 
351 /*---------------------------------------------------------------------*
352  * Writing gif *
353  *---------------------------------------------------------------------*/
368 l_ok
369 pixWriteStreamGif(FILE *fp,
370  PIX *pix)
371 {
372 l_uint8 *filedata;
373 size_t filebytes, nbytes;
374 
375  PROCNAME("pixWriteStreamGif");
376 
377  if (!fp)
378  return ERROR_INT("stream not open", procName, 1);
379  if (!pix)
380  return ERROR_INT("pix not defined", procName, 1);
381 
382  pixSetPadBits(pix, 0);
383  if (pixWriteMemGif(&filedata, &filebytes, pix) != 0) {
384  LEPT_FREE(filedata);
385  return ERROR_INT("failure to gif encode pix", procName, 1);
386  }
387 
388  rewind(fp);
389  nbytes = fwrite(filedata, 1, filebytes, fp);
390  LEPT_FREE(filedata);
391  if (nbytes != filebytes)
392  return ERROR_INT("write error", procName, 1);
393  return 0;
394 }
395 
396 
410 l_ok
411 pixWriteMemGif(l_uint8 **pdata,
412  size_t *psize,
413  PIX *pix)
414 {
415 int giferr;
416 l_int32 result;
417 GifFileType *gif;
418 L_BBUFFER *buffer;
419 
420  PROCNAME("pixWriteMemGif");
421 
422  /* 5.1+ and not 5.1.2 */
423 #if (GIFLIB_MAJOR < 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 0))
424  L_ERROR("Require giflib-5.1 or later\n", procName);
425  return 1;
426 #endif /* < 5.1 */
427 #if GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 1 && GIFLIB_RELEASE == 2 /* 5.1.2 */
428  L_ERROR("Can't use giflib-5.1.2; suggest 5.1.3 or later\n", procName);
429  return 1;
430 #endif /* 5.1.2 */
431 
432  if (!pdata)
433  return ERROR_INT("&data not defined", procName, 1 );
434  *pdata = NULL;
435  if (!psize)
436  return ERROR_INT("&size not defined", procName, 1 );
437  *psize = 0;
438  if (!pix)
439  return ERROR_INT("&pix not defined", procName, 1 );
440 
441  if ((buffer = bbufferCreate(NULL, 0)) == NULL)
442  return ERROR_INT("failed to create buffer", procName, 1);
443 
444  if ((gif = EGifOpen((void*)buffer, gifWriteFunc, NULL)) == NULL) {
445  bbufferDestroy(&buffer);
446  return ERROR_INT("failed to create GIF image handle", procName, 1);
447  }
448 
449  result = pixToGif(pix, gif);
450  EGifCloseFile(gif, &giferr);
451 
452  if (result == 0) {
453  *pdata = bbufferDestroyAndSaveData(&buffer, psize);
454  } else {
455  bbufferDestroy(&buffer);
456  }
457  return result;
458 }
459 
460 
461 static l_int32
462 gifWriteFunc(GifFileType *gif,
463  const GifByteType *src,
464  l_int32 bytesToWrite)
465 {
466 L_BBUFFER *buffer;
467 
468  PROCNAME("gifWriteFunc");
469 
470  if ((buffer = (L_BBUFFER*)gif->UserData) == NULL)
471  return ERROR_INT("UserData not set", procName, -1);
472 
473  if(bbufferRead(buffer, (l_uint8*)src, bytesToWrite) == 0)
474  return bytesToWrite;
475  return 0;
476 }
477 
478 
493 static l_int32
494 pixToGif(PIX *pix,
495  GifFileType *gif)
496 {
497 char *text;
498 l_int32 wpl, i, j, w, h, d, ncolor, rval, gval, bval, valid;
499 l_int32 gif_ncolor = 0;
500 l_uint32 *data, *line;
501 PIX *pixd;
502 PIXCMAP *cmap;
503 ColorMapObject *gif_cmap;
504 GifByteType *gif_line;
505 
506  PROCNAME("pixToGif");
507 
508  if (!pix)
509  return ERROR_INT("pix not defined", procName, 1);
510  if (!gif)
511  return ERROR_INT("gif not defined", procName, 1);
512 
513  d = pixGetDepth(pix);
514  if (d == 32) {
515  pixd = pixConvertRGBToColormap(pix, 1);
516  } else if (d > 1) {
517  pixd = pixConvertTo8(pix, TRUE);
518  } else { /* d == 1; make sure there's a colormap */
519  pixd = pixClone(pix);
520  if (!pixGetColormap(pixd)) {
521  cmap = pixcmapCreate(1);
522  pixcmapAddColor(cmap, 255, 255, 255);
523  pixcmapAddColor(cmap, 0, 0, 0);
524  pixSetColormap(pixd, cmap);
525  }
526  }
527 
528  if (!pixd)
529  return ERROR_INT("failed to convert to colormapped pix", procName, 1);
530  d = pixGetDepth(pixd);
531  cmap = pixGetColormap(pixd);
532  if (!cmap) {
533  pixDestroy(&pixd);
534  return ERROR_INT("cmap is missing", procName, 1);
535  }
536  pixcmapIsValid(cmap, pixd, &valid);
537  if (!valid) {
538  pixDestroy(&pixd);
539  return ERROR_INT("colormap is not valid", procName, 1);
540  }
541 
542  /* 'Round' the number of gif colors up to a power of 2 */
543  ncolor = pixcmapGetCount(cmap);
544  for (i = 0; i <= 8; i++) {
545  if ((1 << i) >= ncolor) {
546  gif_ncolor = (1 << i);
547  break;
548  }
549  }
550  if (gif_ncolor < 1) {
551  pixDestroy(&pixd);
552  return ERROR_INT("number of colors is invalid", procName, 1);
553  }
554 
555  /* Save the cmap colors in a gif_cmap */
556  if ((gif_cmap = GifMakeMapObject(gif_ncolor, NULL)) == NULL) {
557  pixDestroy(&pixd);
558  return ERROR_INT("failed to create GIF color map", procName, 1);
559  }
560  for (i = 0; i < gif_ncolor; i++) {
561  rval = gval = bval = 0;
562  if (ncolor > 0) {
563  if (pixcmapGetColor(cmap, i, &rval, &gval, &bval) != 0) {
564  pixDestroy(&pixd);
565  GifFreeMapObject(gif_cmap);
566  return ERROR_INT("failed to get color from color map",
567  procName, 1);
568  }
569  ncolor--;
570  }
571  gif_cmap->Colors[i].Red = rval;
572  gif_cmap->Colors[i].Green = gval;
573  gif_cmap->Colors[i].Blue = bval;
574  }
575 
576  pixGetDimensions(pixd, &w, &h, NULL);
577  if (EGifPutScreenDesc(gif, w, h, gif_cmap->BitsPerPixel, 0, gif_cmap)
578  != GIF_OK) {
579  pixDestroy(&pixd);
580  GifFreeMapObject(gif_cmap);
581  return ERROR_INT("failed to write screen description", procName, 1);
582  }
583  GifFreeMapObject(gif_cmap); /* not needed after this point */
584 
585  if (EGifPutImageDesc(gif, 0, 0, w, h, FALSE, NULL) != GIF_OK) {
586  pixDestroy(&pixd);
587  return ERROR_INT("failed to image screen description", procName, 1);
588  }
589 
590  data = pixGetData(pixd);
591  wpl = pixGetWpl(pixd);
592  if (d != 1 && d != 2 && d != 4 && d != 8) {
593  pixDestroy(&pixd);
594  return ERROR_INT("image depth is not in {1, 2, 4, 8}", procName, 1);
595  }
596 
597  if ((gif_line = (GifByteType *)LEPT_CALLOC(sizeof(GifByteType), w))
598  == NULL) {
599  pixDestroy(&pixd);
600  return ERROR_INT("mem alloc fail for data line", procName, 1);
601  }
602 
603  for (i = 0; i < h; i++) {
604  line = data + i * wpl;
605  /* Gif's way of setting the raster line up for compression */
606  for (j = 0; j < w; j++) {
607  switch(d)
608  {
609  case 8:
610  gif_line[j] = GET_DATA_BYTE(line, j);
611  break;
612  case 4:
613  gif_line[j] = GET_DATA_QBIT(line, j);
614  break;
615  case 2:
616  gif_line[j] = GET_DATA_DIBIT(line, j);
617  break;
618  case 1:
619  gif_line[j] = GET_DATA_BIT(line, j);
620  break;
621  }
622  }
623 
624  /* Compress and save the line */
625  if (EGifPutLine(gif, gif_line, w) != GIF_OK) {
626  LEPT_FREE(gif_line);
627  pixDestroy(&pixd);
628  return ERROR_INT("failed to write data line into GIF", procName, 1);
629  }
630  }
631 
632  /* Write a text comment. This must be placed after writing the
633  * data (!!) Note that because libgif does not provide a function
634  * for reading comments from file, you will need another way
635  * to read comments. */
636  if ((text = pixGetText(pix)) != NULL) {
637  if (EGifPutComment(gif, text) != GIF_OK)
638  L_WARNING("gif comment not written\n", procName);
639  }
640 
641  LEPT_FREE(gif_line);
642  pixDestroy(&pixd);
643  return 0;
644 }
645 
646 
647 #if 0
648 /*---------------------------------------------------------------------*
649  * Removing interlacing (reference only; not used) *
650  *---------------------------------------------------------------------*/
651  /* GIF supports 4-way interlacing by raster lines.
652  * Before 5.0, it was necessary for leptonica to restore interlaced
653  * data to normal raster order when reading to a pix. With 5.0,
654  * the de-interlacing is done by the library read function.
655  * It is here only as a reference. */
656 static const l_int32 InterlacedOffset[] = {0, 4, 2, 1};
657 static const l_int32 InterlacedJumps[] = {8, 8, 4, 2};
658 
659 static PIX *
660 pixUninterlaceGIF(PIX *pixs)
661 {
662 l_int32 w, h, d, wpl, j, k, srow, drow;
663 l_uint32 *datas, *datad, *lines, *lined;
664 PIX *pixd;
665 
666  PROCNAME("pixUninterlaceGIF");
667 
668  if (!pixs)
669  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
670 
671  pixGetDimensions(pixs, &w, &h, &d);
672  wpl = pixGetWpl(pixs);
673  pixd = pixCreateTemplate(pixs);
674  datas = pixGetData(pixs);
675  datad = pixGetData(pixd);
676  for (k = 0, srow = 0; k < 4; k++) {
677  for (drow = InterlacedOffset[k]; drow < h;
678  drow += InterlacedJumps[k], srow++) {
679  lines = datas + srow * wpl;
680  lined = datad + drow * wpl;
681  for (j = 0; j < w; j++)
682  memcpy(lined, lines, 4 * wpl);
683  }
684  }
685 
686  return pixd;
687 }
688 #endif
689 
690 
691 /* -----------------------------------------------------------------*/
692 #endif /* HAVE_LIBGIF || HAVE_LIBUNGIF */
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:164
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:149
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:145
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
l_ok bbufferRead(L_BBUFFER *bb, l_uint8 *src, l_int32 nbytes)
bbufferRead()
Definition: bbuffer.c:265
L_BBUFFER * bbufferCreate(const l_uint8 *indata, l_int32 nalloc)
bbufferCreate()
Definition: bbuffer.c:130
l_uint8 * bbufferDestroyAndSaveData(L_BBUFFER **pbb, size_t *pnbytes)
bbufferDestroyAndSaveData()
Definition: bbuffer.c:206
void bbufferDestroy(L_BBUFFER **pbb)
bbufferDestroy()
Definition: bbuffer.c:172
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
Definition: colormap.c:279
l_int32 pixcmapGetCount(const PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:708
l_ok pixcmapIsValid(const PIXCMAP *cmap, PIX *pix, l_int32 *pvalid)
pixcmapIsValid()
Definition: colormap.c:317
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:125
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:824
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:414
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
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
char * pixGetText(PIX *pix)
pixGetText()
Definition: pix1.c:1512
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
Definition: pix2.c:1382
PIX * pixConvertRGBToColormap(PIX *pixs, l_int32 ditherflag)
pixConvertRGBToColormap()
Definition: pixconv.c:1486
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3133
Definition: pix.h:139
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1402