73 #include "config_auto.h" 77 #include "allheaders.h" 80 #if HAVE_LIBGIF || HAVE_LIBUNGIF 86 static PIX * gifToPix(GifFileType *gif);
88 static l_int32 pixToGif(
PIX *pix, GifFileType *gif);
91 typedef struct GifReadBuffer
99 static l_int32 gifReadFunc(GifFileType *gif, GifByteType *dest,
100 l_int32 bytesToRead);
102 static l_int32 gifWriteFunc(GifFileType *gif,
const GifByteType *src,
103 l_int32 bytesToWrite);
109 static PIX * pixUninterlaceGIF(
PIX *pixs);
110 static const l_int32 InterlacedOffset[] = {0, 4, 2, 1};
111 static const l_int32 InterlacedJumps[] = {8, 8, 4, 2};
124 pixReadStreamGif(FILE *fp)
130 PROCNAME(
"pixReadStreamGif");
133 return (
PIX *)ERROR_PTR(
"fp not defined", procName, NULL);
138 return (
PIX *)ERROR_PTR(
"filedata not read", procName, NULL);
141 pix = pixReadMemGif(filedata, filesize);
144 L_ERROR(
"failed to read gif from file data\n", procName);
167 pixReadMemGif(
const l_uint8 *cdata,
171 GifReadBuffer buffer;
173 PROCNAME(
"pixReadMemGif");
176 #if (GIFLIB_MAJOR < 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 0)) 177 L_ERROR(
"Require giflib-5.1 or later\n", procName);
180 #if GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 1 && GIFLIB_RELEASE == 2 181 L_ERROR(
"Can't use giflib-5.1.2; suggest 5.1.3 or later\n", procName);
186 return (
PIX *)ERROR_PTR(
"cdata not defined", procName, NULL);
188 buffer.cdata = cdata;
191 if ((gif = DGifOpen((
void*)&buffer, gifReadFunc, NULL)) == NULL)
192 return (
PIX *)ERROR_PTR(
"could not open gif stream from memory",
195 return gifToPix(gif);
200 gifReadFunc(GifFileType *gif,
204 GifReadBuffer *buffer;
207 PROCNAME(
"gifReadFunc");
209 if ((buffer = (GifReadBuffer*)gif->UserData) == NULL)
210 return ERROR_INT(
"UserData not set", procName, -1);
212 if(buffer->pos >= buffer->size)
215 bytesRead = (buffer->pos < buffer->size - bytesToRead)
216 ? bytesToRead : buffer->size - buffer->pos;
217 memcpy(dest, buffer->cdata + buffer->pos, bytesRead);
218 buffer->pos += bytesRead;
237 gifToPix(GifFileType *gif)
239 l_int32 wpl, i, j, w, h, d, cindex, ncolors;
240 l_int32 rval, gval, bval;
241 l_uint32 *data, *line;
244 ColorMapObject *gif_cmap;
248 PROCNAME(
"gifToPix");
251 if (DGifSlurp(gif) != GIF_OK) {
252 DGifCloseFile(gif, &giferr);
253 return (
PIX *)ERROR_PTR(
"failed to read GIF data", procName, NULL);
256 if (gif->SavedImages == NULL) {
257 DGifCloseFile(gif, &giferr);
258 return (
PIX *)ERROR_PTR(
"no images found in GIF", procName, NULL);
261 si = gif->SavedImages[0];
262 w = si.ImageDesc.Width;
263 h = si.ImageDesc.Height;
264 if (w <= 0 || h <= 0) {
265 DGifCloseFile(gif, &giferr);
266 return (
PIX *)ERROR_PTR(
"invalid image dimensions", procName, NULL);
269 if (si.RasterBits == NULL) {
270 DGifCloseFile(gif, &giferr);
271 return (
PIX *)ERROR_PTR(
"no raster data in GIF", procName, NULL);
274 if (si.ImageDesc.ColorMap) {
276 gif_cmap = si.ImageDesc.ColorMap;
277 }
else if (gif->SColorMap) {
279 gif_cmap = gif->SColorMap;
282 DGifCloseFile(gif, &giferr);
283 return (
PIX *)ERROR_PTR(
"color map is missing", procName, NULL);
286 ncolors = gif_cmap->ColorCount;
289 else if (ncolors <= 4)
291 else if (ncolors <= 16)
296 DGifCloseFile(gif, &giferr);
297 return (
PIX *)ERROR_PTR(
"cmap creation failed", procName, NULL);
300 for (cindex = 0; cindex < ncolors; cindex++) {
301 rval = gif_cmap->Colors[cindex].Red;
302 gval = gif_cmap->Colors[cindex].Green;
303 bval = gif_cmap->Colors[cindex].Blue;
307 if ((pixd =
pixCreate(w, h, d)) == NULL) {
308 DGifCloseFile(gif, &giferr);
310 return (
PIX *)ERROR_PTR(
"failed to allocate pixd", procName, NULL);
312 pixSetInputFormat(pixd, IFF_GIF);
315 wpl = pixGetWpl(pixd);
317 for (i = 0; i < h; i++) {
318 line = data + i * wpl;
320 for (j = 0; j < w; j++) {
321 if (si.RasterBits[i * w + j])
325 for (j = 0; j < w; j++)
328 for (j = 0; j < w; j++)
331 for (j = 0; j < w; j++)
345 DGifCloseFile(gif, &giferr);
368 pixWriteStreamGif(FILE *fp,
372 size_t filebytes, nbytes;
374 PROCNAME(
"pixWriteStreamGif");
377 return ERROR_INT(
"stream not open", procName, 1);
379 return ERROR_INT(
"pix not defined", procName, 1);
382 if (pixWriteMemGif(&filedata, &filebytes, pix) != 0) {
384 return ERROR_INT(
"failure to gif encode pix", procName, 1);
388 nbytes = fwrite(filedata, 1, filebytes, fp);
390 if (nbytes != filebytes)
391 return ERROR_INT(
"write error", procName, 1);
410 pixWriteMemGif(l_uint8 **pdata,
419 PROCNAME(
"pixWriteMemGif");
422 #if (GIFLIB_MAJOR < 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 0)) 423 L_ERROR(
"Require giflib-5.1 or later\n", procName);
426 #if GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 1 && GIFLIB_RELEASE == 2 427 L_ERROR(
"Can't use giflib-5.1.2; suggest 5.1.3 or later\n", procName);
432 return ERROR_INT(
"&data not defined", procName, 1 );
435 return ERROR_INT(
"&size not defined", procName, 1 );
438 return ERROR_INT(
"&pix not defined", procName, 1 );
441 return ERROR_INT(
"failed to create buffer", procName, 1);
443 if ((gif = EGifOpen((
void*)buffer, gifWriteFunc, NULL)) == NULL) {
445 return ERROR_INT(
"failed to create GIF image handle", procName, 1);
448 result = pixToGif(pix, gif);
449 EGifCloseFile(gif, &giferr);
461 gifWriteFunc(GifFileType *gif,
462 const GifByteType *src,
463 l_int32 bytesToWrite)
467 PROCNAME(
"gifWriteFunc");
469 if ((buffer = (
L_BBUFFER*)gif->UserData) == NULL)
470 return ERROR_INT(
"UserData not set", procName, -1);
472 if(
bbufferRead(buffer, (l_uint8*)src, bytesToWrite) == 0)
497 l_int32 wpl, i, j, w, h, d, ncolor, rval, gval, bval;
498 l_int32 gif_ncolor = 0;
499 l_uint32 *data, *line;
502 ColorMapObject *gif_cmap;
503 GifByteType *gif_line;
505 PROCNAME(
"pixToGif");
508 return ERROR_INT(
"pix not defined", procName, 1);
510 return ERROR_INT(
"gif not defined", procName, 1);
512 d = pixGetDepth(pix);
519 if (!pixGetColormap(pixd)) {
528 return ERROR_INT(
"failed to convert image to indexed", procName, 1);
529 d = pixGetDepth(pixd);
531 if ((cmap = pixGetColormap(pixd)) == NULL) {
533 return ERROR_INT(
"cmap is missing", procName, 1);
538 for (i = 0; i <= 8; i++) {
539 if ((1 << i) >= ncolor) {
540 gif_ncolor = (1 << i);
544 if (gif_ncolor < 1) {
546 return ERROR_INT(
"number of colors is invalid", procName, 1);
550 if ((gif_cmap = GifMakeMapObject(gif_ncolor, NULL)) == NULL) {
552 return ERROR_INT(
"failed to create GIF color map", procName, 1);
554 for (i = 0; i < gif_ncolor; i++) {
555 rval = gval = bval = 0;
559 GifFreeMapObject(gif_cmap);
560 return ERROR_INT(
"failed to get color from color map",
565 gif_cmap->Colors[i].Red = rval;
566 gif_cmap->Colors[i].Green = gval;
567 gif_cmap->Colors[i].Blue = bval;
571 if (EGifPutScreenDesc(gif, w, h, gif_cmap->BitsPerPixel, 0, gif_cmap)
574 GifFreeMapObject(gif_cmap);
575 return ERROR_INT(
"failed to write screen description", procName, 1);
577 GifFreeMapObject(gif_cmap);
579 if (EGifPutImageDesc(gif, 0, 0, w, h, FALSE, NULL) != GIF_OK) {
581 return ERROR_INT(
"failed to image screen description", procName, 1);
585 wpl = pixGetWpl(pixd);
586 if (d != 1 && d != 2 && d != 4 && d != 8) {
588 return ERROR_INT(
"image depth is not in {1, 2, 4, 8}", procName, 1);
591 if ((gif_line = (GifByteType *)LEPT_CALLOC(
sizeof(GifByteType), w))
594 return ERROR_INT(
"mem alloc fail for data line", procName, 1);
597 for (i = 0; i < h; i++) {
598 line = data + i * wpl;
600 for (j = 0; j < w; j++) {
619 if (EGifPutLine(gif, gif_line, w) != GIF_OK) {
622 return ERROR_INT(
"failed to write data line into GIF", procName, 1);
631 if (EGifPutComment(gif, text) != GIF_OK)
632 L_WARNING(
"gif comment not written\n", procName);
645 pixUninterlaceGIF(
PIX *pixs)
647 l_int32 w, h, d, wpl, j, k, srow, drow;
648 l_uint32 *datas, *datad, *lines, *lined;
651 PROCNAME(
"pixUninterlaceGIF");
654 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
657 wpl = pixGetWpl(pixs);
661 for (k = 0, srow = 0; k < 4; k++) {
662 for (drow = InterlacedOffset[k]; drow < h;
663 drow += InterlacedJumps[k], srow++) {
664 lines = datas + srow * wpl;
665 lined = datad + drow * wpl;
666 for (j = 0; j < w; j++)
667 memcpy(lined, lines, 4 * wpl);
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
#define SET_DATA_QBIT(pdata, n, val)
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
l_uint32 * pixGetData(PIX *pix)
pixGetData()
l_int32 pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
#define GET_DATA_BIT(pdata, n)
PIX * pixCreateTemplate(PIX *pixs)
pixCreateTemplate()
l_uint8 * bbufferDestroyAndSaveData(L_BBUFFER **pbb, size_t *pnbytes)
bbufferDestroyAndSaveData()
#define SET_DATA_DIBIT(pdata, n, val)
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
l_int32 pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
l_int32 pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
#define SET_DATA_BYTE(pdata, n, val)
l_int32 pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
#define GET_DATA_QBIT(pdata, n)
#define GET_DATA_BYTE(pdata, n)
PIX * pixClone(PIX *pixs)
pixClone()
void pixDestroy(PIX **ppix)
pixDestroy()
void bbufferDestroy(L_BBUFFER **pbb)
bbufferDestroy()
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
char * pixGetText(PIX *pix)
pixGetText()
#define GET_DATA_DIBIT(pdata, n)
l_int32 bbufferRead(L_BBUFFER *bb, l_uint8 *src, l_int32 nbytes)
bbufferRead()
PIX * pixConvertRGBToColormap(PIX *pixs, l_int32 ditherflag)
pixConvertRGBToColormap()
l_int32 pixcmapGetCount(PIXCMAP *cmap)
pixcmapGetCount()
l_int32 pixGetDimensions(PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
L_BBUFFER * bbufferCreate(l_uint8 *indata, l_int32 nalloc)
bbufferCreate()
#define SET_DATA_BIT(pdata, n)