1 /*
2 * Copyright (c) 2000 Fabrice Bellard
3 * Copyright (c) 2002 Francois Revol
4 * Copyright (c) 2006 Baptiste Coudurier
5 *
6 * first version by Francois Revol <revol@free.fr>
7 *
8 * This file is part of FFmpeg.
9 *
10 * FFmpeg is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * FFmpeg is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with FFmpeg; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 /**
26 * @file
27 * GIF encoder
28 * @see http://www.w3.org/Graphics/GIF/spec-gif89a.txt
29 */
30
38
39 #define BITSTREAM_WRITER_LE
41
51
52 enum {
55 };
56
58 {
61
62 for (y = 0; y < h; y++) {
63 for (x = 0; x < w; x++)
64 histogram[buf[x]]++;
65 buf += linesize;
66 }
68 if (!histogram[i])
69 return i;
70 return -1;
71 }
72
78 {
81 int x_start = 0, y_start = 0, trans = -1;
83
84 /* Crop image */
85 // TODO support with palette change
89 int x_end = avctx->
width - 1,
91
92 /* skip common lines */
93 while (y_start < y_end) {
94 if (memcmp(ref + y_start*ref_linesize, buf + y_start*linesize,
width))
95 break;
96 y_start++;
97 }
98 while (y_end > y_start) {
99 if (memcmp(ref + y_end*ref_linesize, buf + y_end*linesize,
width))
100 break;
101 y_end--;
102 }
103 height = y_end + 1 - y_start;
104
105 /* skip common columns */
106 while (x_start < x_end) {
107 int same_column = 1;
108 for (y = y_start; y < y_end; y++) {
109 if (ref[y*ref_linesize + x_start] != buf[y*linesize + x_start]) {
110 same_column = 0;
111 break;
112 }
113 }
114 if (!same_column)
115 break;
116 x_start++;
117 }
118 while (x_end > x_start) {
119 int same_column = 1;
120 for (y = y_start; y < y_end; y++) {
121 if (ref[y*ref_linesize + x_end] != buf[y*linesize + x_end]) {
122 same_column = 0;
123 break;
124 }
125 }
126 if (!same_column)
127 break;
128 x_end--;
129 }
130 width = x_end + 1 - x_start;
131
134 }
135
136 /* image block */
138 bytestream_put_le16(bytestream, x_start);
139 bytestream_put_le16(bytestream, y_start);
140 bytestream_put_le16(bytestream,
width);
141 bytestream_put_le16(bytestream,
height);
142
143 if (!palette) {
144 bytestream_put_byte(bytestream, 0x00); /* flags */
145 } else {
146 unsigned i;
147 bytestream_put_byte(bytestream, 1<<7 | 0x7); /* flags */
149 const uint32_t
v = palette[i];
150 bytestream_put_be24(bytestream, v);
151 }
152 }
153
154 /* TODO: support with palette change (pal8) */
158 if (trans < 0) { // TODO, patch welcome
160 } else {
162 if (!pal_exdata)
165 pal_exdata[trans*4 + 3*!HAVE_BIGENDIAN] = 0x00;
166 }
167 }
168
169 bytestream_put_byte(bytestream, 0x08);
170
173
174 ptr = buf + y_start*linesize + x_start;
175 if (trans >= 0) {
178
179 for (y = 0; y <
height; y++) {
181 for (x = 0; x <
width; x++)
182 if (ref[x] == ptr[x])
185 ptr += linesize;
186 ref += ref_linesize;
187 }
188 } else {
189 for (y = 0; y <
height; y++) {
191 ptr += linesize;
192 }
193 }
195
197 while (len > 0) {
199 bytestream_put_byte(bytestream, size);
200 if (end - *bytestream < size)
201 return -1;
205 }
206 bytestream_put_byte(bytestream, 0x00); /* end of image block */
207 return 0;
208 }
209
211 {
213
214 if (avctx->
width > 65535 || avctx->
height > 65535) {
217 }
218
224
227
228 return 0;
229 }
230
232 const AVFrame *pict,
int *got_packet)
233 {
237 const uint32_t *
palette = NULL;
239
241 return ret;
242 outbuf_ptr = pkt->
data;
244
247
250 if (!pal_exdata)
253 palette = (uint32_t*)p->
data[1];
254 }
255
262 }
265 if (ret < 0)
267
270 *got_packet = 1;
271
272 return 0;
273 }
274
276 {
278
283 return 0;
284 }
285
286 #define OFFSET(x) offsetof(GIFContext, x)
287 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
292 { NULL }
293 };
294
300 };
301
313 },
316 };