diff options
author | Bert <ber.t@gmx.com> | 2011-08-17 18:01:21 +0200 |
---|---|---|
committer | Bert <ber.t@gmx.com> | 2011-08-19 15:12:30 +0200 |
commit | 79bd86defb5c86a50e2def4c03129c4215c07ca5 (patch) | |
tree | 900376bba22d82a349b3ad5f0d94f936f86e7938 | |
parent | 86a6f00112576f3fc1ca565c2b5ad11d784cab8d (diff) |
Refactored img_load_gif()
- Corrected handling of transparency settings for individual frames
- Corrected handling of different frame dimensions & offsets
-rw-r--r-- | image.c | 100 | ||||
-rw-r--r-- | image.h | 2 | ||||
-rw-r--r-- | main.c | 2 |
3 files changed, 63 insertions, 41 deletions
@@ -56,20 +56,18 @@ void img_init(img_t *img, win_t *win) { } int img_load_gif(img_t *img, const fileinfo_t *file) { - DATA32 *data, *ptr; - DATA32 *prev_frame = NULL; - Imlib_Image *im; GifFileType *gif; GifRowType *rows = NULL; GifRecordType rec; ColorMapObject *cmap; - int i, j; - int bg, r, g, b; - int w = 0, h = 0; + DATA32 bgpixel, *data, *ptr; + DATA32 *prev_frame = NULL; + Imlib_Image *im; + int i, j, bg, r, g, b; + int x, y, w, h, sw, sh; int intoffset[] = { 0, 4, 2, 1 }; int intjump[] = { 8, 8, 4, 2 }; - int transp = -1; - int err = 0; + int err = 0, transp = -1; if (img->multi.cap == 0) { img->multi.cap = 8; @@ -77,13 +75,16 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { s_malloc(sizeof(Imlib_Image*) * img->multi.cap); } img->multi.cnt = 0; - img->multi.cur = 0; + img->multi.sel = 0; gif = DGifOpenFileName(file->path); if (!gif) { warn("could not open gif file: %s", file->name); return 0; } + bg = gif->SBackGroundColor; + sw = gif->SWidth; + sh = gif->SHeight; do { if (DGifGetRecordType(gif, &rec) == GIF_ERROR) { @@ -97,8 +98,12 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { DGifGetExtension(gif, &ext_code, &ext); while (ext) { - if ((ext_code == 0xf9) && (ext[1] & 1) && (transp < 0)) - transp = (int) ext[4]; + if (ext_code == 0xf9) { + if (ext[1] & 1) + transp = (int) ext[4]; + else + transp = -1; + } ext = NULL; DGifGetExtensionNext(gif, &ext); } @@ -108,8 +113,11 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { err = 1; break; } + x = gif->Image.Left; + y = gif->Image.Top; w = gif->Image.Width; h = gif->Image.Height; + rows = (GifRowType*) s_malloc(h * sizeof(GifRowType)); for (i = 0; i < h; i++) rows[i] = (GifRowType) s_malloc(w * sizeof(GifPixelType)); @@ -123,36 +131,36 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { DGifGetLine(gif, rows[i], w); } - bg = gif->SBackGroundColor; + ptr = data = (DATA32*) s_malloc(sizeof(DATA32) * sw * sh); cmap = gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap; - ptr = data = (DATA32*) s_malloc(sizeof(DATA32) * w * h); - - if (img->multi.cnt) { - imlib_context_set_image(img->multi.frames[img->multi.cnt - 1]); - prev_frame = imlib_image_get_data_for_reading_only(); - } - - for (i = 0; i < h; i++) { - for (j = 0; j < w; j++) { - if (rows[i][j] == transp) { - if (prev_frame) { - *ptr++ = prev_frame[i * w + j]; - } else { - r = cmap->Colors[bg].Red; - g = cmap->Colors[bg].Green; - b = cmap->Colors[bg].Blue; - *ptr++ = 0x00ffffff & ((r << 16) | (g << 8) | b); - } + r = cmap->Colors[bg].Red; + g = cmap->Colors[bg].Green; + b = cmap->Colors[bg].Blue; + bgpixel = 0x00ffffff & (r << 16 | g << 8 | b); + + for (i = 0; i < sh; i++) { + for (j = 0; j < sw; j++) { + if (i < y || i >= y + h || j < x || j >= x + w) { + if (transp >= 0 && prev_frame) + *ptr = prev_frame[i * sw + j]; + else + *ptr = bgpixel; + } else if (rows[i-y][j-x] == transp) { + if (prev_frame) + *ptr = prev_frame[i * sw + j]; + else + *ptr = bgpixel; } else { - r = cmap->Colors[rows[i][j]].Red; - g = cmap->Colors[rows[i][j]].Green; - b = cmap->Colors[rows[i][j]].Blue; - *ptr++ = (0xff << 24) | (r << 16) | (g << 8) | b; + r = cmap->Colors[rows[i-y][j-x]].Red; + g = cmap->Colors[rows[i-y][j-x]].Green; + b = cmap->Colors[rows[i-y][j-x]].Blue; + *ptr = 0xff << 24 | r << 16 | g << 8 | b; } + ptr++; } } - im = imlib_create_image_using_copied_data(w, h, data); + im = imlib_create_image_using_copied_data(sw, sh, data); for (i = 0; i < h; i++) free(rows[i]); @@ -166,6 +174,8 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { } imlib_context_set_image(im); + prev_frame = imlib_image_get_data_for_reading_only(); + imlib_image_set_format("gif"); if (transp >= 0) imlib_image_set_has_alpha(1); @@ -200,7 +210,7 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { } int img_load(img_t *img, const fileinfo_t *file) { - char *fmt; + const char *fmt; if (!img || !file || !file->name || !file->path) return 0; @@ -229,7 +239,19 @@ int img_load(img_t *img, const fileinfo_t *file) { } void img_close(img_t *img, int decache) { - if (img && img->im) { + int i; + + if (!img) + return; + + if (img->multi.cnt) { + for (i = 0; i < img->multi.cnt; i++) { + imlib_context_set_image(img->multi.frames[i]); + imlib_free_image(); + } + img->multi.cnt = 0; + img->im = NULL; + } else if (img->im) { imlib_context_set_image(img->im); if (decache) imlib_free_image_and_decache(); @@ -350,13 +372,13 @@ int img_change_frame(img_t *img, int d) { if (!img || !img->multi.cnt || !d) return 0; - d += img->multi.cur; + d += img->multi.sel; if (d < 0) d = 0; else if (d >= img->multi.cnt) d = img->multi.cnt - 1; - img->multi.cur = d; + img->multi.sel = d; img->im = img->multi.frames[d]; imlib_context_set_image(img->im); @@ -27,7 +27,7 @@ typedef struct { int cap; int cnt; - int cur; + int sel; Imlib_Image **frames; } multi_img_t; @@ -158,7 +158,7 @@ void update_title() { n = snprintf(win_title, TITLE_LEN, "sxiv: [%d/%d] <%d%%> <%dx%d> (%.2f%s) {%d/%d} %s", fileidx + 1, filecnt, (int) (img.zoom * 100.0), img.w, - img.h, size, unit, img.multi.cur + 1, img.multi.cnt, + img.h, size, unit, img.multi.sel + 1, img.multi.cnt, files[fileidx].name); else n = snprintf(win_title, TITLE_LEN, |