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"
28 #include "interlacemodes.h"
33 static int gif_err = 0;
34 #define GIF_ERR ,&gif_err
35 #define GifErrorString(s) Gif##ErrorString(gif_err)
36 #define GifLastError(s) gif_err
38 const char *gifErrorString()
41 snprintf(msg, sizeof(msg), "Gif Error %d", GifLastError());
45 FileGIF::FileGIF(Asset *asset, File *file)
46 : FileList(asset, file, "GIFLIST", ".gif", FILE_GIF, FILE_GIF_LIST)
54 int FileGIF::check_sig(Asset *asset)
56 FILE *stream = fopen(asset->path, "rb");
61 int ret = fread(test, 1, 6, stream);
65 test[0] == 'G' && test[1] == 'I' && test[2] == 'F' &&
66 test[3] == '8' && test[4] == '7' && test[5] == 'A')
68 eprintf("FileGIFF: version error (87A): \"%s\".\n", asset->path);
73 if(strlen(asset->path) > 4)
75 int len = strlen(asset->path);
76 if(!strncasecmp(asset->path + len - 4, ".gif", 4)) return 1;
81 int FileGIF::colormodel_supported(int colormodel)
86 int FileGIF::get_best_colormodel(Asset *asset, int driver)
92 int FileGIF::read_frame_header(char *path)
94 FILE *stream = fopen(path, "rb");
98 unsigned char test[16];
99 int ret = fread(test, 16, 1, stream);
101 if( ret < 1 ) return 1;
102 asset->width = test[6] | (test[7] << 8);
103 asset->height = test[8] | (test[9] << 8);
104 //printf("FileGIF::read_frame_header %d %d %d\n", __LINE__, asset->width, asset->height);
113 static int input_func(GifFileType *gif_file, GifByteType *buffer, int bytes)
115 FileGIF *file = (FileGIF*)gif_file->UserData;
116 if(file->offset + bytes > file->size) bytes = file->size - file->offset;
119 memcpy(buffer, file->data + file->offset, bytes);
120 file->offset += bytes;
125 int FileGIF::read_frame(VFrame *output, VFrame *input)
127 data = input->get_data();
129 size = input->get_compressed_size();
131 GifFileType *gif_file;
132 GifRowType *gif_buffer;
133 gif_file = DGifOpen(this, input_func GIF_ERR);
138 eprintf("FileGIF::read_frame %d: %s\n", __LINE__, GifErrorString());
141 gif_buffer = (GifRowType*)malloc(sizeof(GifRowType) * gif_file->SHeight);
142 int row_size = gif_file->SWidth * sizeof(GifPixelType);
143 gif_buffer[0] = (GifRowType)malloc(row_size);
145 for(int i = 0; i < gif_file->SWidth; i++)
147 gif_buffer[0][i] = gif_file->SBackGroundColor;
150 for(int i = 0; i < gif_file->SHeight; i++)
152 gif_buffer[i] = (GifRowType)malloc(row_size);
153 memcpy(gif_buffer[i], gif_buffer[0], row_size);
156 GifRecordType record_type;
159 if(DGifGetRecordType(gif_file, &record_type) == GIF_ERROR)
161 eprintf("FileGIF::read_frame %d: %s\n", __LINE__, GifErrorString());
167 case IMAGE_DESC_RECORD_TYPE:
169 if(DGifGetImageDesc(gif_file) == GIF_ERROR)
171 eprintf("FileGIF::read_frame %d: %s\n", __LINE__, GifErrorString());
175 int row = gif_file->Image.Top;
176 int col = gif_file->Image.Left;
177 int width = gif_file->Image.Width;
178 int height = gif_file->Image.Height;
179 if(gif_file->Image.Left + gif_file->Image.Width > gif_file->SWidth ||
180 gif_file->Image.Top + gif_file->Image.Height > gif_file->SHeight)
182 DGifCloseFile(gif_file GIF_ERR);
183 for(int k = 0; k < gif_file->SHeight; k++)
191 if (gif_file->Image.Interlace)
193 static int InterlacedOffset[] = { 0, 4, 2, 1 };
194 static int InterlacedJumps[] = { 8, 8, 4, 2 };
195 /* Need to perform 4 passes on the images: */
196 for (int i = 0; i < 4; i++)
198 for (int j = row + InterlacedOffset[i];
200 j += InterlacedJumps[i])
202 if (DGifGetLine(gif_file,
206 DGifCloseFile(gif_file GIF_ERR);
207 for(int k = 0; k < gif_file->SHeight; k++)
219 for (int i = 0; i < height; i++)
221 if (DGifGetLine(gif_file, &gif_buffer[row++][col],
224 DGifCloseFile(gif_file GIF_ERR);
225 for(int k = 0; k < gif_file->SHeight; k++)
241 } while(record_type != TERMINATE_RECORD_TYPE);
244 //int background = gif_file->SBackGroundColor;
245 ColorMapObject *color_map = (gif_file->Image.ColorMap
246 ? gif_file->Image.ColorMap
247 : gif_file->SColorMap);
250 DGifCloseFile(gif_file GIF_ERR);
251 for(int k = 0; k < gif_file->SHeight; k++)
259 int screen_width = gif_file->SWidth;
260 int screen_height = gif_file->SHeight;
261 for(int i = 0; i < screen_height; i++)
263 GifRowType gif_row = gif_buffer[i];
264 unsigned char *out_ptr = output->get_rows()[i];
265 for(int j = 0; j < screen_width; j++)
267 GifColorType *color_map_entry = &color_map->Colors[gif_row[j]];
268 *out_ptr++ = color_map_entry->Red;
269 *out_ptr++ = color_map_entry->Green;
270 *out_ptr++ = color_map_entry->Blue;
275 for(int k = 0; k < gif_file->SHeight; k++)
280 DGifCloseFile(gif_file GIF_ERR);