camera zoom fix, upgrade giflib, configure.ac ix86 probe tweaks, any python
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / filegif.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2014 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "asset.h"
23 #include "bcsignals.h"
24 #include "file.h"
25 #include "filegif.h"
26 #include "gif_lib.h"
27 #include "mainerror.h"
28 #include "interlacemodes.h"
29 #include "vframe.h"
30 #include <string.h>
31
32
33 static int gif_err = 0;
34
35 FileGIF::FileGIF(Asset *asset, File *file)
36  : FileList(asset, file, "GIFLIST", ".gif", FILE_GIF, FILE_GIF_LIST)
37 {
38 }
39
40 FileGIF::~FileGIF()
41 {
42 }
43
44 int FileGIF::check_sig(Asset *asset)
45 {
46         FILE *stream = fopen(asset->path, "rb");
47
48         if(stream)
49         {
50                 char test[8];
51                 int ret = fread(test, 1, 6, stream);
52                 fclose(stream);
53
54                 if( ret >= 6 &&
55                         test[0] == 'G' && test[1] == 'I' && test[2] == 'F' &&
56                         test[3] == '8' && test[4] == '7' && test[5] == 'A')
57                 {
58                         eprintf("FileGIFF: version error (87A): \"%s\".\n", asset->path);
59                         return 1;
60                 }
61         }
62
63         if(strlen(asset->path) > 4)
64         {
65                 int len = strlen(asset->path);
66                 if(!strncasecmp(asset->path + len - 4, ".gif", 4)) return 1;
67         }
68         return 0;
69 }
70
71 int FileGIF::colormodel_supported(int colormodel)
72 {
73         return BC_RGB888;
74 }
75
76 int FileGIF::get_best_colormodel(Asset *asset, int driver)
77 {
78         return BC_RGB888;
79 }
80
81
82 int FileGIF::read_frame_header(char *path)
83 {
84         FILE *stream = fopen(path, "rb");
85
86         if(stream)
87         {
88                 unsigned char test[16];
89                 int ret = fread(test, 16, 1, stream);
90                 fclose(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);
95                 return 0;
96         }
97
98         perror(path);
99         return 1;
100 }
101
102
103 static int input_func(GifFileType *gif_file, GifByteType *buffer, int bytes)
104 {
105         FileGIF *file = (FileGIF*)gif_file->UserData;
106         if( file->offset + bytes > file->size )
107                 bytes = file->size - file->offset;
108         if( bytes > 0 ) {
109                 memcpy(buffer, file->data + file->offset, bytes);
110                 file->offset += bytes;
111         }
112         return bytes;
113 }
114
115 int FileGIF::read_frame(VFrame *output, VFrame *input)
116 {
117         data = input->get_data();
118         offset = 0;
119         size = input->get_compressed_size();
120
121         GifFileType *gif_file = DGifOpen(this, input_func, &gif_err);
122         if( !gif_file ) {
123                 eprintf("FileGIF::read_frame %d: %s\n", __LINE__, GifErrorString(gif_err));
124                 return 1;
125         }
126
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);
130
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);
136         }
137
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));
143                         ret = 1;
144                         break;
145                 }
146
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));
151                                 break;
152                         }
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;
157                         int ret = 0;
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 )
160                                 ret = 1;
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 )
169                                                         ret = 1;
170                                         }
171                                 }
172                         }
173                         else {
174                                 for( int i=0; !ret && i<height; ++i ) {
175                                         if (DGifGetLine(gif_file, &gif_buffer[row++][col], width) == GIF_ERROR)
176                                                 ret = 1;
177                                 }
178                         }
179                         break; }
180                 case EXTENSION_RECORD_TYPE: {
181                         int ExtFunction = 0;
182                         GifByteType *ExtData = 0;
183                         if( DGifGetExtension(gif_file, &ExtFunction, &ExtData) == GIF_ERROR )
184                                 ret = 1;
185                         while( !ret && ExtData ) {
186                                 if( DGifGetExtensionNext(gif_file, &ExtData) == GIF_ERROR )
187                                         ret = 1;
188                         }
189                         break; }
190                 case TERMINATE_RECORD_TYPE:
191                         done = 1;
192                         break;
193                 default:
194                         break;
195                 }
196         }
197
198         ColorMapObject *color_map = 0;
199         if( !ret ) {
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;
204         }
205         if( !ret ) {
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;
216                         }
217                 }
218         }
219         for( int k=0; k<gif_file->SHeight; ++k )
220                 free(gif_buffer[k]);
221         free(gif_buffer);
222         DGifCloseFile(gif_file, &gif_err);
223         return ret;
224 }
225