| @@ -56,20 +56,18 @@ void img_init(img_t *img, win_t *win) { |
| 56 | 56 | | } |
| 57 | 57 | | |
| 58 | 58 | | int img_load_gif(img_t *img, const fileinfo_t *file) { |
| 59 | | − | DATA32 *data, *ptr; |
| 60 | | − | DATA32 *prev_frame = NULL; |
| 61 | | − | Imlib_Image *im; |
| 62 | 59 | | GifFileType *gif; |
| 63 | 60 | | GifRowType *rows = NULL; |
| 64 | 61 | | GifRecordType rec; |
| 65 | 62 | | ColorMapObject *cmap; |
| 66 | | − | int i, j; |
| 67 | | − | int bg, r, g, b; |
| 68 | | − | int w = 0, h = 0; |
| 63 | + | DATA32 bgpixel, *data, *ptr; |
| 64 | + | DATA32 *prev_frame = NULL; |
| 65 | + | Imlib_Image *im; |
| 66 | + | int i, j, bg, r, g, b; |
| 67 | + | int x, y, w, h, sw, sh; |
| 69 | 68 | | int intoffset[] = { 0, 4, 2, 1 }; |
| 70 | 69 | | int intjump[] = { 8, 8, 4, 2 }; |
| 71 | | − | int transp = -1; |
| 72 | | − | int err = 0; |
| 70 | + | int err = 0, transp = -1; |
| 73 | 71 | | |
| 74 | 72 | | if (img->multi.cap == 0) { |
| 75 | 73 | | img->multi.cap = 8; |
| @@ -77,13 +75,16 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { |
| 77 | 75 | | s_malloc(sizeof(Imlib_Image*) * img->multi.cap); |
| 78 | 76 | | } |
| 79 | 77 | | img->multi.cnt = 0; |
| 80 | | − | img->multi.cur = 0; |
| 78 | + | img->multi.sel = 0; |
| 81 | 79 | | |
| 82 | 80 | | gif = DGifOpenFileName(file->path); |
| 83 | 81 | | if (!gif) { |
| 84 | 82 | | warn("could not open gif file: %s", file->name); |
| 85 | 83 | | return 0; |
| 86 | 84 | | } |
| 85 | + | bg = gif->SBackGroundColor; |
| 86 | + | sw = gif->SWidth; |
| 87 | + | sh = gif->SHeight; |
| 87 | 88 | | |
| 88 | 89 | | do { |
| 89 | 90 | | if (DGifGetRecordType(gif, &rec) == GIF_ERROR) { |
| @@ -97,8 +98,12 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { |
| 97 | 98 | | |
| 98 | 99 | | DGifGetExtension(gif, &ext_code, &ext); |
| 99 | 100 | | while (ext) { |
| 100 | | − | if ((ext_code == 0xf9) && (ext[1] & 1) && (transp < 0)) |
| 101 | | − | transp = (int) ext[4]; |
| 101 | + | if (ext_code == 0xf9) { |
| 102 | + | if (ext[1] & 1) |
| 103 | + | transp = (int) ext[4]; |
| 104 | + | else |
| 105 | + | transp = -1; |
| 106 | + | } |
| 102 | 107 | | ext = NULL; |
| 103 | 108 | | DGifGetExtensionNext(gif, &ext); |
| 104 | 109 | | } |
| @@ -108,8 +113,11 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { |
| 108 | 113 | | err = 1; |
| 109 | 114 | | break; |
| 110 | 115 | | } |
| 116 | + | x = gif->Image.Left; |
| 117 | + | y = gif->Image.Top; |
| 111 | 118 | | w = gif->Image.Width; |
| 112 | 119 | | h = gif->Image.Height; |
| 120 | + | |
| 113 | 121 | | rows = (GifRowType*) s_malloc(h * sizeof(GifRowType)); |
| 114 | 122 | | for (i = 0; i < h; i++) |
| 115 | 123 | | rows[i] = (GifRowType) s_malloc(w * sizeof(GifPixelType)); |
| @@ -123,36 +131,36 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { |
| 123 | 131 | | DGifGetLine(gif, rows[i], w); |
| 124 | 132 | | } |
| 125 | 133 | | |
| 126 | | − | bg = gif->SBackGroundColor; |
| 134 | + | ptr = data = (DATA32*) s_malloc(sizeof(DATA32) * sw * sh); |
| 127 | 135 | | cmap = gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap; |
| 128 | | − | ptr = data = (DATA32*) s_malloc(sizeof(DATA32) * w * h); |
| 129 | | − | |
| 130 | | − | if (img->multi.cnt) { |
| 131 | | − | imlib_context_set_image(img->multi.frames[img->multi.cnt - 1]); |
| 132 | | − | prev_frame = imlib_image_get_data_for_reading_only(); |
| 133 | | − | } |
| 134 | | − | |
| 135 | | − | for (i = 0; i < h; i++) { |
| 136 | | − | for (j = 0; j < w; j++) { |
| 137 | | − | if (rows[i][j] == transp) { |
| 138 | | − | if (prev_frame) { |
| 139 | | − | *ptr++ = prev_frame[i * w + j]; |
| 140 | | − | } else { |
| 141 | | − | r = cmap->Colors[bg].Red; |
| 142 | | − | g = cmap->Colors[bg].Green; |
| 143 | | − | b = cmap->Colors[bg].Blue; |
| 144 | | − | *ptr++ = 0x00ffffff & ((r << 16) | (g << 8) | b); |
| 145 | | − | } |
| 136 | + | r = cmap->Colors[bg].Red; |
| 137 | + | g = cmap->Colors[bg].Green; |
| 138 | + | b = cmap->Colors[bg].Blue; |
| 139 | + | bgpixel = 0x00ffffff & (r << 16 | g << 8 | b); |
| 140 | + | |
| 141 | + | for (i = 0; i < sh; i++) { |
| 142 | + | for (j = 0; j < sw; j++) { |
| 143 | + | if (i < y || i >= y + h || j < x || j >= x + w) { |
| 144 | + | if (transp >= 0 && prev_frame) |
| 145 | + | *ptr = prev_frame[i * sw + j]; |
| 146 | + | else |
| 147 | + | *ptr = bgpixel; |
| 148 | + | } else if (rows[i-y][j-x] == transp) { |
| 149 | + | if (prev_frame) |
| 150 | + | *ptr = prev_frame[i * sw + j]; |
| 151 | + | else |
| 152 | + | *ptr = bgpixel; |
| 146 | 153 | | } else { |
| 147 | | − | r = cmap->Colors[rows[i][j]].Red; |
| 148 | | − | g = cmap->Colors[rows[i][j]].Green; |
| 149 | | − | b = cmap->Colors[rows[i][j]].Blue; |
| 150 | | − | *ptr++ = (0xff << 24) | (r << 16) | (g << 8) | b; |
| 154 | + | r = cmap->Colors[rows[i-y][j-x]].Red; |
| 155 | + | g = cmap->Colors[rows[i-y][j-x]].Green; |
| 156 | + | b = cmap->Colors[rows[i-y][j-x]].Blue; |
| 157 | + | *ptr = 0xff << 24 | r << 16 | g << 8 | b; |
| 151 | 158 | | } |
| 159 | + | ptr++; |
| 152 | 160 | | } |
| 153 | 161 | | } |
| 154 | 162 | | |
| 155 | | − | im = imlib_create_image_using_copied_data(w, h, data); |
| 163 | + | im = imlib_create_image_using_copied_data(sw, sh, data); |
| 156 | 164 | | |
| 157 | 165 | | for (i = 0; i < h; i++) |
| 158 | 166 | | free(rows[i]); |
| @@ -166,6 +174,8 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { |
| 166 | 174 | | } |
| 167 | 175 | | |
| 168 | 176 | | imlib_context_set_image(im); |
| 177 | + | prev_frame = imlib_image_get_data_for_reading_only(); |
| 178 | + | |
| 169 | 179 | | imlib_image_set_format("gif"); |
| 170 | 180 | | if (transp >= 0) |
| 171 | 181 | | imlib_image_set_has_alpha(1); |
| @@ -200,7 +210,7 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { |
| 200 | 210 | | } |
| 201 | 211 | | |
| 202 | 212 | | int img_load(img_t *img, const fileinfo_t *file) { |
| 203 | | − | char *fmt; |
| 213 | + | const char *fmt; |
| 204 | 214 | | |
| 205 | 215 | | if (!img || !file || !file->name || !file->path) |
| 206 | 216 | | return 0; |
| @@ -229,7 +239,19 @@ int img_load(img_t *img, const fileinfo_t *file) { |
| 229 | 239 | | } |
| 230 | 240 | | |
| 231 | 241 | | void img_close(img_t *img, int decache) { |
| 232 | | − | if (img && img->im) { |
| 242 | + | int i; |
| 243 | + | |
| 244 | + | if (!img) |
| 245 | + | return; |
| 246 | + | |
| 247 | + | if (img->multi.cnt) { |
| 248 | + | for (i = 0; i < img->multi.cnt; i++) { |
| 249 | + | imlib_context_set_image(img->multi.frames[i]); |
| 250 | + | imlib_free_image(); |
| 251 | + | } |
| 252 | + | img->multi.cnt = 0; |
| 253 | + | img->im = NULL; |
| 254 | + | } else if (img->im) { |
| 233 | 255 | | imlib_context_set_image(img->im); |
| 234 | 256 | | if (decache) |
| 235 | 257 | | imlib_free_image_and_decache(); |
| @@ -350,13 +372,13 @@ int img_change_frame(img_t *img, int d) { |
| 350 | 372 | | if (!img || !img->multi.cnt || !d) |
| 351 | 373 | | return 0; |
| 352 | 374 | | |
| 353 | | − | d += img->multi.cur; |
| 375 | + | d += img->multi.sel; |
| 354 | 376 | | if (d < 0) |
| 355 | 377 | | d = 0; |
| 356 | 378 | | else if (d >= img->multi.cnt) |
| 357 | 379 | | d = img->multi.cnt - 1; |
| 358 | 380 | | |
| 359 | | − | img->multi.cur = d; |
| 381 | + | img->multi.sel = d; |
| 360 | 382 | | img->im = img->multi.frames[d]; |
| 361 | 383 | | |
| 362 | 384 | | imlib_context_set_image(img->im); |