4 * Copyright (C) 2014 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "bcsignals.h"
27 #include "mainerror.h"
32 static int gif_err = 0;
33 #define GIF_ERR ,&gif_err
34 #define GifErrorString(s) Gif##ErrorString(gif_err)
35 #define GifLastError(s) gif_err
37 const char *gifErrorString()
40 snprintf(msg, sizeof(msg), "Gif Error %d", GifLastError());
44 FileGIF::FileGIF(Asset *asset, File *file)
45 : FileList(asset, file, "GIFLIST", ".gif", FILE_GIF, FILE_GIF_LIST)
53 int FileGIF::check_sig(Asset *asset)
55 FILE *stream = fopen(asset->path, "rb");
60 int ret = fread(test, 1, 6, stream);
64 test[0] == 'G' && test[1] == 'I' && test[2] == 'F' &&
65 test[3] == '8' && test[4] == '7' && test[5] == 'A')
71 if(strlen(asset->path) > 4)
73 int len = strlen(asset->path);
74 if(!strncasecmp(asset->path + len - 4, ".gif", 4)) return 1;
79 int FileGIF::colormodel_supported(int colormodel)
84 int FileGIF::get_best_colormodel(Asset *asset, int driver)
90 int FileGIF::read_frame_header(char *path)
92 FILE *stream = fopen(path, "rb");
96 unsigned char test[16];
97 int ret = fread(test, 16, 1, stream);
99 if( ret < 1 ) return 1;
100 asset->width = test[6] | (test[7] << 8);
101 asset->height = test[8] | (test[9] << 8);
102 //printf("FileGIF::read_frame_header %d %d %d\n", __LINE__, asset->width, asset->height);
111 static int input_func(GifFileType *gif_file, GifByteType *buffer, int bytes)
113 FileGIF *file = (FileGIF*)gif_file->UserData;
114 if(file->offset + bytes > file->size) bytes = file->size - file->offset;
117 memcpy(buffer, file->data + file->offset, bytes);
118 file->offset += bytes;
123 int FileGIF::read_frame(VFrame *output, VFrame *input)
125 data = input->get_data();
127 size = input->get_compressed_size();
129 GifFileType *gif_file;
130 GifRowType *gif_buffer;
131 gif_file = DGifOpen(this, input_func GIF_ERR);
136 eprintf("FileGIF::read_frame %d: %s\n", __LINE__, GifErrorString());
139 gif_buffer = (GifRowType*)malloc(sizeof(GifRowType) * gif_file->SHeight);
140 int row_size = gif_file->SWidth * sizeof(GifPixelType);
141 gif_buffer[0] = (GifRowType)malloc(row_size);
143 for(int i = 0; i < gif_file->SWidth; i++)
145 gif_buffer[0][i] = gif_file->SBackGroundColor;
148 for(int i = 0; i < gif_file->SHeight; i++)
150 gif_buffer[i] = (GifRowType)malloc(row_size);
151 memcpy(gif_buffer[i], gif_buffer[0], row_size);
154 GifRecordType record_type;
157 if(DGifGetRecordType(gif_file, &record_type) == GIF_ERROR)
159 eprintf("FileGIF::read_frame %d: %s\n", __LINE__, GifErrorString());
165 case IMAGE_DESC_RECORD_TYPE:
167 if(DGifGetImageDesc(gif_file) == GIF_ERROR)
169 eprintf("FileGIF::read_frame %d: %s\n", __LINE__, GifErrorString());
173 int row = gif_file->Image.Top;
174 int col = gif_file->Image.Left;
175 int width = gif_file->Image.Width;
176 int height = gif_file->Image.Height;
177 if(gif_file->Image.Left + gif_file->Image.Width > gif_file->SWidth ||
178 gif_file->Image.Top + gif_file->Image.Height > gif_file->SHeight)
180 DGifCloseFile(gif_file GIF_ERR);
181 for(int k = 0; k < gif_file->SHeight; k++)
189 if (gif_file->Image.Interlace)
191 static int InterlacedOffset[] = { 0, 4, 2, 1 };
192 static int InterlacedJumps[] = { 8, 8, 4, 2 };
193 /* Need to perform 4 passes on the images: */
194 for (int i = 0; i < 4; i++)
196 for (int j = row + InterlacedOffset[i];
198 j += InterlacedJumps[i])
200 if (DGifGetLine(gif_file,
204 DGifCloseFile(gif_file GIF_ERR);
205 for(int k = 0; k < gif_file->SHeight; k++)
217 for (int i = 0; i < height; i++)
219 if (DGifGetLine(gif_file, &gif_buffer[row++][col],
222 DGifCloseFile(gif_file GIF_ERR);
223 for(int k = 0; k < gif_file->SHeight; k++)
239 } while(record_type != TERMINATE_RECORD_TYPE);
242 //int background = gif_file->SBackGroundColor;
243 ColorMapObject *color_map = (gif_file->Image.ColorMap
244 ? gif_file->Image.ColorMap
245 : gif_file->SColorMap);
248 DGifCloseFile(gif_file GIF_ERR);
249 for(int k = 0; k < gif_file->SHeight; k++)
257 int screen_width = gif_file->SWidth;
258 int screen_height = gif_file->SHeight;
259 for(int i = 0; i < screen_height; i++)
261 GifRowType gif_row = gif_buffer[i];
262 unsigned char *out_ptr = output->get_rows()[i];
263 for(int j = 0; j < screen_width; j++)
265 GifColorType *color_map_entry = &color_map->Colors[gif_row[j]];
266 *out_ptr++ = color_map_entry->Red;
267 *out_ptr++ = color_map_entry->Green;
268 *out_ptr++ = color_map_entry->Blue;
273 for(int k = 0; k < gif_file->SHeight; k++)
278 DGifCloseFile(gif_file GIF_ERR);