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;
35 FileGIF::FileGIF(Asset *asset, File *file)
36 : FileList(asset, file, "GIFLIST", ".gif", FILE_GIF, FILE_GIF_LIST)
44 int FileGIF::check_sig(Asset *asset)
46 FILE *stream = fopen(asset->path, "rb");
51 int ret = fread(test, 1, 6, stream);
55 test[0] == 'G' && test[1] == 'I' && test[2] == 'F' &&
56 test[3] == '8' && test[4] == '7' && test[5] == 'A')
58 eprintf("FileGIFF: version error (87A): \"%s\".\n", asset->path);
63 if(strlen(asset->path) > 4)
65 int len = strlen(asset->path);
66 if(!strncasecmp(asset->path + len - 4, ".gif", 4)) return 1;
71 int FileGIF::colormodel_supported(int colormodel)
76 int FileGIF::get_best_colormodel(Asset *asset, int driver)
82 int FileGIF::read_frame_header(char *path)
84 FILE *stream = fopen(path, "rb");
88 unsigned char test[16];
89 int ret = fread(test, 16, 1, stream);
91 if( ret < 1 ) return 1;
92 asset->width = test[6] | (test[7] << 8);
93 asset->height = test[8] | (test[9] << 8);
94 //printf("FileGIF::read_frame_header %d %d %d\n", __LINE__, asset->width, asset->height);
103 static int input_func(GifFileType *gif_file, GifByteType *buffer, int bytes)
105 FileGIF *file = (FileGIF*)gif_file->UserData;
106 if( file->offset + bytes > file->size )
107 bytes = file->size - file->offset;
109 memcpy(buffer, file->data + file->offset, bytes);
110 file->offset += bytes;
115 int FileGIF::read_frame(VFrame *output, VFrame *input)
117 data = input->get_data();
119 size = input->get_compressed_size();
121 GifFileType *gif_file = DGifOpen(this, input_func, &gif_err);
123 eprintf("FileGIF::read_frame %d: %s\n", __LINE__, GifErrorString(gif_err));
127 GifRowType *gif_buffer = (GifRowType*)malloc(sizeof(GifRowType) * gif_file->SHeight);
128 int row_size = gif_file->SWidth * sizeof(GifPixelType);
129 gif_buffer[0] = (GifRowType)malloc(row_size);
131 for( int i=0; i<gif_file->SWidth; ++i )
132 gif_buffer[0][i] = gif_file->SBackGroundColor;
133 for( int i=0; i<gif_file->SHeight; ++i ) {
134 gif_buffer[i] = (GifRowType)malloc(row_size);
135 memcpy(gif_buffer[i], gif_buffer[0], row_size);
138 int ret = 0, done = 0;
139 GifRecordType record_type;
140 while( !ret && !done ) {
141 if( DGifGetRecordType(gif_file, &record_type) == GIF_ERROR ) {
142 eprintf("FileGIF::read_frame %d: %s\n", __LINE__, GifErrorString(gif_err));
147 switch( record_type ) {
148 case IMAGE_DESC_RECORD_TYPE: {
149 if( DGifGetImageDesc(gif_file) == GIF_ERROR ) {
150 eprintf("FileGIF::read_frame %d: %s\n", __LINE__, GifErrorString(gif_err));
153 int row = gif_file->Image.Top;
154 int col = gif_file->Image.Left;
155 int width = gif_file->Image.Width;
156 int height = gif_file->Image.Height;
158 if( gif_file->Image.Left + gif_file->Image.Width > gif_file->SWidth ||
159 gif_file->Image.Top + gif_file->Image.Height > gif_file->SHeight )
161 if( !ret && gif_file->Image.Interlace ) {
162 static int InterlacedOffset[] = { 0, 4, 2, 1 };
163 static int InterlacedJumps[] = { 8, 8, 4, 2 };
164 /* Need to perform 4 passes on the images: */
165 for( int i=0; i<4; ++i ) {
166 int j = row + InterlacedOffset[i];
167 for( ; !ret && j<row + height; j+=InterlacedJumps[i] ) {
168 if( DGifGetLine(gif_file, &gif_buffer[j][col], width) == GIF_ERROR )
174 for( int i=0; !ret && i<height; ++i ) {
175 if (DGifGetLine(gif_file, &gif_buffer[row++][col], width) == GIF_ERROR)
180 case EXTENSION_RECORD_TYPE: {
182 GifByteType *ExtData = 0;
183 if( DGifGetExtension(gif_file, &ExtFunction, &ExtData) == GIF_ERROR )
185 while( !ret && ExtData ) {
186 if( DGifGetExtensionNext(gif_file, &ExtData) == GIF_ERROR )
190 case TERMINATE_RECORD_TYPE:
198 ColorMapObject *color_map = 0;
200 //int background = gif_file->SBackGroundColor;
201 color_map = gif_file->Image.ColorMap;
202 if( !color_map ) color_map = gif_file->SColorMap;
203 if( !color_map ) ret = 1;
206 int screen_width = gif_file->SWidth;
207 int screen_height = gif_file->SHeight;
208 for( int i=0; i<screen_height; ++i ) {
209 GifRowType gif_row = gif_buffer[i];
210 unsigned char *out_ptr = output->get_rows()[i];
211 for( int j=0; j<screen_width; ++j ) {
212 GifColorType *color_map_entry = &color_map->Colors[gif_row[j]];
213 *out_ptr++ = color_map_entry->Red;
214 *out_ptr++ = color_map_entry->Green;
215 *out_ptr++ = color_map_entry->Blue;
219 for( int k=0; k<gif_file->SHeight; ++k )
222 DGifCloseFile(gif_file, &gif_err);