1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "fx_gif.h"
Input(uint8_t * src_buf,FX_DWORD src_size)8 void CGifLZWDecoder::Input(uint8_t* src_buf, FX_DWORD src_size) {
9 next_in = src_buf;
10 avail_in = src_size;
11 }
GetAvailInput()12 FX_DWORD CGifLZWDecoder::GetAvailInput() {
13 return avail_in;
14 }
InitTable(uint8_t code_len)15 void CGifLZWDecoder::InitTable(uint8_t code_len) {
16 code_size = code_len;
17 code_clear = 1 << code_size;
18 code_end = code_clear + 1;
19 bits_left = 0;
20 code_store = 0;
21 next_in = NULL;
22 avail_in = 0;
23 stack_size = 0;
24 code_first = 0;
25 ClearTable();
26 }
ClearTable()27 void CGifLZWDecoder::ClearTable() {
28 code_size_cur = code_size + 1;
29 code_next = code_end + 1;
30 code_old = (FX_WORD)-1;
31 FXSYS_memset(code_table, 0, sizeof(tag_Table) * GIF_MAX_LZW_CODE);
32 FXSYS_memset(stack, 0, GIF_MAX_LZW_CODE);
33 for (FX_WORD i = 0; i < code_clear; i++) {
34 code_table[i].suffix = (uint8_t)i;
35 }
36 }
DecodeString(FX_WORD code)37 void CGifLZWDecoder::DecodeString(FX_WORD code) {
38 stack_size = 0;
39 while (TRUE) {
40 ASSERT(code <= code_next);
41 if (code < code_clear || code > code_next) {
42 break;
43 }
44 stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = code_table[code].suffix;
45 code = code_table[code].prefix;
46 }
47 stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = (uint8_t)code;
48 code_first = (uint8_t)code;
49 }
AddCode(FX_WORD prefix_code,uint8_t append_char)50 void CGifLZWDecoder::AddCode(FX_WORD prefix_code, uint8_t append_char) {
51 if (code_next == GIF_MAX_LZW_CODE) {
52 return;
53 }
54 code_table[code_next].prefix = prefix_code;
55 code_table[code_next].suffix = append_char;
56 if (++code_next < GIF_MAX_LZW_CODE) {
57 if (code_next >> code_size_cur) {
58 code_size_cur++;
59 }
60 }
61 }
Decode(uint8_t * des_buf,FX_DWORD & des_size)62 int32_t CGifLZWDecoder::Decode(uint8_t* des_buf, FX_DWORD& des_size) {
63 if (des_size == 0) {
64 return 3;
65 }
66 FX_DWORD i = 0;
67 if (stack_size != 0) {
68 if (des_size < stack_size) {
69 FXSYS_memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], des_size);
70 stack_size -= (FX_WORD)des_size;
71 return 3;
72 }
73 FXSYS_memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], stack_size);
74 des_buf += stack_size;
75 i += stack_size;
76 stack_size = 0;
77 }
78 FX_WORD code = 0;
79 while (i <= des_size && (avail_in > 0 || bits_left >= code_size_cur)) {
80 if (code_size_cur > 12) {
81 if (err_msg_ptr) {
82 FXSYS_strncpy(err_msg_ptr, "Code Length Out Of Range",
83 GIF_MAX_ERROR_SIZE - 1);
84 }
85 return 0;
86 }
87 if (avail_in > 0) {
88 code_store |= (*next_in++) << bits_left;
89 avail_in--;
90 bits_left += 8;
91 }
92 while (bits_left >= code_size_cur) {
93 code = (FX_WORD)code_store & ((1 << code_size_cur) - 1);
94 code_store >>= code_size_cur;
95 bits_left -= code_size_cur;
96 if (code == code_clear) {
97 ClearTable();
98 continue;
99 } else if (code == code_end) {
100 des_size = i;
101 return 1;
102 } else {
103 if (code_old != (FX_WORD)-1) {
104 if (code_next < GIF_MAX_LZW_CODE) {
105 if (code == code_next) {
106 AddCode(code_old, code_first);
107 DecodeString(code);
108 } else if (code > code_next) {
109 if (err_msg_ptr) {
110 FXSYS_strncpy(err_msg_ptr, "Decode Error, Out Of Range",
111 GIF_MAX_ERROR_SIZE - 1);
112 }
113 return 0;
114 } else {
115 DecodeString(code);
116 uint8_t append_char = stack[GIF_MAX_LZW_CODE - stack_size];
117 AddCode(code_old, append_char);
118 }
119 }
120 } else {
121 DecodeString(code);
122 }
123 code_old = code;
124 if (i + stack_size > des_size) {
125 FXSYS_memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size],
126 des_size - i);
127 stack_size -= (FX_WORD)(des_size - i);
128 return 3;
129 }
130 FXSYS_memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size],
131 stack_size);
132 des_buf += stack_size;
133 i += stack_size;
134 stack_size = 0;
135 }
136 }
137 }
138 if (avail_in == 0) {
139 des_size = i;
140 return 2;
141 }
142 return 0;
143 }
_gif_grow_buf(uint8_t * & dst_buf,FX_DWORD & dst_len,FX_DWORD size)144 static FX_BOOL _gif_grow_buf(uint8_t*& dst_buf,
145 FX_DWORD& dst_len,
146 FX_DWORD size) {
147 if (dst_len < size) {
148 FX_DWORD len_org = dst_len;
149 while (dst_buf && dst_len < size) {
150 dst_len <<= 1;
151 dst_buf = FX_Realloc(uint8_t, dst_buf, dst_len);
152 }
153 if (dst_buf == NULL) {
154 dst_len = size;
155 dst_buf = FX_Realloc(uint8_t, dst_buf, dst_len);
156 if (dst_buf == NULL) {
157 return FALSE;
158 }
159 }
160 FXSYS_memset(dst_buf + len_org, 0, dst_len - len_org);
161 return dst_buf != NULL;
162 }
163 return TRUE;
164 }
_gif_cut_index(uint8_t & val,FX_DWORD index,uint8_t index_bit,uint8_t index_bit_use,uint8_t bit_use)165 static inline void _gif_cut_index(uint8_t& val,
166 FX_DWORD index,
167 uint8_t index_bit,
168 uint8_t index_bit_use,
169 uint8_t bit_use) {
170 FX_DWORD cut = ((1 << (index_bit - index_bit_use)) - 1) << index_bit_use;
171 val |= ((index & cut) >> index_bit_use) << bit_use;
172 }
_gif_cut_buf(const uint8_t * buf,FX_DWORD & offset,uint8_t bit_cut,uint8_t & bit_offset,FX_DWORD & bit_num)173 static inline uint8_t _gif_cut_buf(const uint8_t* buf,
174 FX_DWORD& offset,
175 uint8_t bit_cut,
176 uint8_t& bit_offset,
177 FX_DWORD& bit_num) {
178 if (bit_cut != 8) {
179 FX_WORD index = 0;
180 index |= ((1 << bit_cut) - 1) << (7 - bit_offset);
181 uint8_t ret = ((index & buf[offset]) >> (7 - bit_offset));
182 bit_offset += bit_cut;
183 if (bit_offset >= 8) {
184 if (bit_offset > 8) {
185 ret |= ((index & (buf[offset + 1] << 8)) >> 8);
186 }
187 bit_offset -= 8;
188 offset++;
189 }
190 bit_num += bit_cut;
191 return ret;
192 }
193 bit_num += bit_cut;
194 return buf[offset++];
195 }
CGifLZWEncoder()196 CGifLZWEncoder::CGifLZWEncoder() {
197 FXSYS_memset(this, 0, sizeof(CGifLZWEncoder));
198 }
~CGifLZWEncoder()199 CGifLZWEncoder::~CGifLZWEncoder() {}
ClearTable()200 void CGifLZWEncoder::ClearTable() {
201 index_bit_cur = code_size + 1;
202 index_num = code_end + 1;
203 table_cur = code_end + 1;
204 for (FX_WORD i = 0; i < GIF_MAX_LZW_CODE; i++) {
205 code_table[i].prefix = 0;
206 code_table[i].suffix = 0;
207 }
208 }
Start(uint8_t code_len,const uint8_t * src_buf,uint8_t * & dst_buf,FX_DWORD & offset)209 void CGifLZWEncoder::Start(uint8_t code_len,
210 const uint8_t* src_buf,
211 uint8_t*& dst_buf,
212 FX_DWORD& offset) {
213 code_size = code_len + 1;
214 src_bit_cut = code_size;
215 if (code_len == 0) {
216 src_bit_cut = 1;
217 code_size = 2;
218 }
219 code_clear = 1 << code_size;
220 code_end = code_clear + 1;
221 dst_buf[offset++] = code_size;
222 bit_offset = 0;
223 ClearTable();
224 src_offset = 0;
225 src_bit_offset = 0;
226 src_bit_num = 0;
227 code_table[index_num].prefix = _gif_cut_buf(src_buf, src_offset, src_bit_cut,
228 src_bit_offset, src_bit_num);
229 code_table[index_num].suffix = _gif_cut_buf(src_buf, src_offset, src_bit_cut,
230 src_bit_offset, src_bit_num);
231 }
WriteBlock(uint8_t * & dst_buf,FX_DWORD & dst_len,FX_DWORD & offset)232 void CGifLZWEncoder::WriteBlock(uint8_t*& dst_buf,
233 FX_DWORD& dst_len,
234 FX_DWORD& offset) {
235 if (!_gif_grow_buf(dst_buf, dst_len, offset + GIF_DATA_BLOCK + 1)) {
236 longjmp(jmp, 1);
237 }
238 dst_buf[offset++] = index_buf_len;
239 FXSYS_memcpy(&dst_buf[offset], index_buf, index_buf_len);
240 offset += index_buf_len;
241 FXSYS_memset(index_buf, 0, GIF_DATA_BLOCK);
242 index_buf_len = 0;
243 }
EncodeString(FX_DWORD index,uint8_t * & dst_buf,FX_DWORD & dst_len,FX_DWORD & offset)244 void CGifLZWEncoder::EncodeString(FX_DWORD index,
245 uint8_t*& dst_buf,
246 FX_DWORD& dst_len,
247 FX_DWORD& offset) {
248 uint8_t index_bit_use;
249 index_bit_use = 0;
250 if (index_buf_len == GIF_DATA_BLOCK) {
251 WriteBlock(dst_buf, dst_len, offset);
252 }
253 _gif_cut_index(index_buf[index_buf_len], index, index_bit_cur, index_bit_use,
254 bit_offset);
255 if (index_bit_cur <= (8 - bit_offset)) {
256 bit_offset += index_bit_cur;
257 } else if (index_bit_cur <= (16 - bit_offset)) {
258 index_bit_use += (8 - bit_offset);
259 bit_offset = 0;
260 index_buf_len++;
261 if (index_buf_len == GIF_DATA_BLOCK) {
262 WriteBlock(dst_buf, dst_len, offset);
263 }
264 _gif_cut_index(index_buf[index_buf_len], index, index_bit_cur,
265 index_bit_use, bit_offset);
266 bit_offset = index_bit_cur - index_bit_use;
267 } else {
268 index_bit_use += (8 - bit_offset);
269 bit_offset = 0;
270 index_buf_len++;
271 if (index_buf_len == GIF_DATA_BLOCK) {
272 WriteBlock(dst_buf, dst_len, offset);
273 }
274 _gif_cut_index(index_buf[index_buf_len], index, index_bit_cur,
275 index_bit_use, bit_offset);
276 index_bit_use += 8;
277 bit_offset = 0;
278 index_buf_len++;
279 if (index_buf_len == GIF_DATA_BLOCK) {
280 WriteBlock(dst_buf, dst_len, offset);
281 }
282 _gif_cut_index(index_buf[index_buf_len], index, index_bit_cur,
283 index_bit_use, bit_offset);
284 bit_offset = index_bit_cur - index_bit_use;
285 }
286 if (bit_offset == 8) {
287 bit_offset = 0;
288 index_buf_len++;
289 if (index_buf_len == GIF_DATA_BLOCK) {
290 WriteBlock(dst_buf, dst_len, offset);
291 }
292 }
293 if (index == code_end) {
294 index_buf_len++;
295 WriteBlock(dst_buf, dst_len, offset);
296 }
297 if (index_num++ >> index_bit_cur) {
298 index_bit_cur++;
299 }
300 }
Encode(const uint8_t * src_buf,FX_DWORD src_len,uint8_t * & dst_buf,FX_DWORD & dst_len,FX_DWORD & offset)301 FX_BOOL CGifLZWEncoder::Encode(const uint8_t* src_buf,
302 FX_DWORD src_len,
303 uint8_t*& dst_buf,
304 FX_DWORD& dst_len,
305 FX_DWORD& offset) {
306 uint8_t suffix;
307 if (setjmp(jmp)) {
308 return FALSE;
309 }
310 while (src_bit_num < src_len) {
311 if (!LookUpInTable(src_buf, src_offset, src_bit_offset)) {
312 EncodeString(code_table[index_num].prefix, dst_buf, dst_len, offset);
313 if (index_num == GIF_MAX_LZW_CODE) {
314 suffix = code_table[index_num - 1].suffix;
315 EncodeString(code_clear, dst_buf, dst_len, offset);
316 ClearTable();
317 code_table[index_num].prefix = suffix;
318 code_table[index_num].suffix = _gif_cut_buf(
319 src_buf, src_offset, src_bit_cut, src_bit_offset, src_bit_num);
320 } else {
321 code_table[index_num].prefix = code_table[index_num - 1].suffix;
322 code_table[index_num].suffix = _gif_cut_buf(
323 src_buf, src_offset, src_bit_cut, src_bit_offset, src_bit_num);
324 }
325 }
326 }
327 src_offset = 0;
328 src_bit_offset = 0;
329 src_bit_num = 0;
330 return TRUE;
331 }
LookUpInTable(const uint8_t * buf,FX_DWORD & offset,uint8_t & bit_offset)332 FX_BOOL CGifLZWEncoder::LookUpInTable(const uint8_t* buf,
333 FX_DWORD& offset,
334 uint8_t& bit_offset) {
335 for (FX_WORD i = table_cur; i < index_num; i++) {
336 if (code_table[i].prefix == code_table[index_num].prefix &&
337 code_table[i].suffix == code_table[index_num].suffix) {
338 code_table[index_num].prefix = i;
339 code_table[index_num].suffix =
340 _gif_cut_buf(buf, offset, src_bit_cut, bit_offset, src_bit_num);
341 table_cur = i;
342 return TRUE;
343 }
344 }
345 table_cur = code_end + 1;
346 return FALSE;
347 }
Finish(uint8_t * & dst_buf,FX_DWORD & dst_len,FX_DWORD & offset)348 void CGifLZWEncoder::Finish(uint8_t*& dst_buf,
349 FX_DWORD& dst_len,
350 FX_DWORD& offset) {
351 EncodeString(code_table[index_num].prefix, dst_buf, dst_len, offset);
352 EncodeString(code_end, dst_buf, dst_len, offset);
353 bit_offset = 0;
354 ClearTable();
355 }
_gif_create_decompress()356 gif_decompress_struct_p _gif_create_decompress() {
357 gif_decompress_struct_p gif_ptr =
358 (gif_decompress_struct*)FX_Alloc(uint8_t, sizeof(gif_decompress_struct));
359 if (gif_ptr == NULL) {
360 return NULL;
361 }
362 FXSYS_memset(gif_ptr, 0, sizeof(gif_decompress_struct));
363 gif_ptr->decode_status = GIF_D_STATUS_SIG;
364 gif_ptr->img_ptr_arr_ptr = new CFX_ArrayTemplate<GifImage*>;
365 #ifdef GIF_SUPPORT_COMMENT_EXTENSION
366 gif_ptr->cmt_data_ptr = new CFX_ByteString;
367 #endif
368 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION
369 gif_ptr->pt_ptr_arr_ptr = new CFX_ArrayTemplate<GifPlainText*>;
370 #endif
371 return gif_ptr;
372 }
_gif_destroy_decompress(gif_decompress_struct_pp gif_ptr_ptr)373 void _gif_destroy_decompress(gif_decompress_struct_pp gif_ptr_ptr) {
374 if (gif_ptr_ptr == NULL || *gif_ptr_ptr == NULL) {
375 return;
376 }
377 gif_decompress_struct_p gif_ptr = *gif_ptr_ptr;
378 *gif_ptr_ptr = NULL;
379 if (gif_ptr->global_pal_ptr != NULL) {
380 FX_Free(gif_ptr->global_pal_ptr);
381 }
382 if (gif_ptr->img_decoder_ptr != NULL) {
383 delete gif_ptr->img_decoder_ptr;
384 }
385 if (gif_ptr->img_ptr_arr_ptr != NULL) {
386 int32_t size_img_arr = gif_ptr->img_ptr_arr_ptr->GetSize();
387 for (int32_t i = 0; i < size_img_arr; i++) {
388 GifImage* p = gif_ptr->img_ptr_arr_ptr->GetAt(i);
389 if (p->image_info_ptr != NULL) {
390 FX_Free(p->image_info_ptr);
391 }
392 if (p->image_gce_ptr != NULL) {
393 FX_Free(p->image_gce_ptr);
394 }
395 if (p->image_row_buf != NULL) {
396 FX_Free(p->image_row_buf);
397 }
398 if (p->local_pal_ptr != NULL &&
399 p->local_pal_ptr != gif_ptr->global_pal_ptr) {
400 FX_Free(p->local_pal_ptr);
401 }
402 FX_Free(p);
403 }
404 gif_ptr->img_ptr_arr_ptr->RemoveAll();
405 delete gif_ptr->img_ptr_arr_ptr;
406 }
407 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION
408 if (gif_ptr->app_data != NULL) {
409 FX_Free(gif_ptr->app_data);
410 }
411 #endif
412 #ifdef GIF_SUPPORT_COMMENT_EXTENSION
413 if (gif_ptr->cmt_data_ptr != NULL) {
414 delete gif_ptr->cmt_data_ptr;
415 }
416 #endif
417 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION
418 if (gif_ptr->gce_ptr != NULL) {
419 FX_Free(gif_ptr->gce_ptr);
420 }
421 #endif
422 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION
423 if (gif_ptr->pt_ptr_arr_ptr != NULL) {
424 int32_t size_pt_arr = gif_ptr->pt_ptr_arr_ptr->GetSize();
425 for (int32_t i = 0; i < size_pt_arr; i++) {
426 GifPlainText* p = gif_ptr->pt_ptr_arr_ptr->GetAt(i);
427 if (p->gce_ptr != NULL) {
428 FX_Free(p->gce_ptr);
429 }
430 if (p->pte_ptr != NULL) {
431 FX_Free(p->pte_ptr);
432 }
433 if (p->string_ptr != NULL) {
434 delete p->string_ptr;
435 }
436 }
437 gif_ptr->pt_ptr_arr_ptr->RemoveAll();
438 delete gif_ptr->pt_ptr_arr_ptr;
439 }
440 #endif
441 FX_Free(gif_ptr);
442 }
_gif_create_compress()443 gif_compress_struct_p _gif_create_compress() {
444 gif_compress_struct_p gif_ptr =
445 (gif_compress_struct*)FX_Alloc(uint8_t, sizeof(gif_compress_struct));
446 if (gif_ptr == NULL) {
447 return NULL;
448 }
449 FXSYS_memset(gif_ptr, 0, sizeof(gif_compress_struct));
450 gif_ptr->img_encoder_ptr = new CGifLZWEncoder;
451 gif_ptr->header_ptr = (GifHeader*)FX_Alloc(uint8_t, sizeof(GifHeader));
452 if (gif_ptr->header_ptr == NULL) {
453 delete (gif_ptr->img_encoder_ptr);
454 FX_Free(gif_ptr);
455 return NULL;
456 }
457 FXSYS_memcpy(gif_ptr->header_ptr->signature, GIF_SIGNATURE, 3);
458 FXSYS_memcpy(gif_ptr->header_ptr->version, "89a", 3);
459 gif_ptr->lsd_ptr = (GifLSD*)FX_Alloc(uint8_t, sizeof(GifLSD));
460 if (gif_ptr->lsd_ptr == NULL) {
461 FX_Free(gif_ptr->header_ptr);
462 delete (gif_ptr->img_encoder_ptr);
463 FX_Free(gif_ptr);
464 return NULL;
465 }
466 FXSYS_memset(gif_ptr->lsd_ptr, 0, sizeof(GifLSD));
467 gif_ptr->image_info_ptr =
468 (GifImageInfo*)FX_Alloc(uint8_t, sizeof(GifImageInfo));
469 if (gif_ptr->image_info_ptr == NULL) {
470 FX_Free(gif_ptr->lsd_ptr);
471 FX_Free(gif_ptr->header_ptr);
472 delete (gif_ptr->img_encoder_ptr);
473 FX_Free(gif_ptr);
474 return NULL;
475 }
476 FXSYS_memset(gif_ptr->image_info_ptr, 0, sizeof(GifImageInfo));
477 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION
478 FXSYS_memcpy(gif_ptr->app_identify, "netscape", 8);
479 FXSYS_memcpy(gif_ptr->app_authentication, "2.0", 3);
480 #endif
481 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION
482 gif_ptr->gce_ptr = (GifGCE*)FX_Alloc(uint8_t, sizeof(GifGCE));
483 if (gif_ptr->gce_ptr == NULL) {
484 FX_Free(gif_ptr->image_info_ptr);
485 FX_Free(gif_ptr->lsd_ptr);
486 FX_Free(gif_ptr->header_ptr);
487 delete (gif_ptr->img_encoder_ptr);
488 FX_Free(gif_ptr);
489 return NULL;
490 }
491 #endif
492 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION
493 gif_ptr->pte_ptr = (GifPTE*)FX_Alloc(uint8_t, sizeof(GifPTE));
494 if (gif_ptr->pte_ptr == NULL) {
495 FX_Free(gif_ptr->gce_ptr);
496 FX_Free(gif_ptr->image_info_ptr);
497 FX_Free(gif_ptr->lsd_ptr);
498 FX_Free(gif_ptr->header_ptr);
499 delete (gif_ptr->img_encoder_ptr);
500 FX_Free(gif_ptr);
501 return NULL;
502 }
503 FXSYS_memset(gif_ptr->pte_ptr, 0, sizeof(GifPTE));
504 gif_ptr->pte_ptr->block_size = 12;
505 #endif
506 return gif_ptr;
507 }
_gif_destroy_compress(gif_compress_struct_pp gif_ptr_ptr)508 void _gif_destroy_compress(gif_compress_struct_pp gif_ptr_ptr) {
509 if (gif_ptr_ptr == NULL || *gif_ptr_ptr == NULL) {
510 return;
511 }
512 gif_compress_struct_p gif_ptr = *gif_ptr_ptr;
513 *gif_ptr_ptr = NULL;
514 if (gif_ptr->header_ptr != NULL) {
515 FX_Free(gif_ptr->header_ptr);
516 }
517 if (gif_ptr->lsd_ptr != NULL) {
518 FX_Free(gif_ptr->lsd_ptr);
519 }
520 if (gif_ptr->global_pal != NULL) {
521 FX_Free(gif_ptr->global_pal);
522 }
523 if (gif_ptr->image_info_ptr != NULL) {
524 FX_Free(gif_ptr->image_info_ptr);
525 }
526 if (gif_ptr->local_pal != NULL) {
527 FX_Free(gif_ptr->local_pal);
528 }
529 if (gif_ptr->img_encoder_ptr != NULL) {
530 delete gif_ptr->img_encoder_ptr;
531 }
532 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION
533 if (gif_ptr->app_data != NULL) {
534 FX_Free(gif_ptr->app_data);
535 }
536 #endif
537 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION
538 if (gif_ptr->gce_ptr != NULL) {
539 FX_Free(gif_ptr->gce_ptr);
540 }
541 #endif
542 #ifdef GIF_SUPPORT_COMMENT_EXTENSION
543 if (gif_ptr->cmt_data_ptr != NULL) {
544 FX_Free(gif_ptr->cmt_data_ptr);
545 }
546 #endif
547 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION
548 if (gif_ptr->pte_ptr != NULL) {
549 FX_Free(gif_ptr->pte_ptr);
550 }
551 #endif
552 FX_Free(gif_ptr);
553 }
_gif_error(gif_decompress_struct_p gif_ptr,const FX_CHAR * err_msg)554 void _gif_error(gif_decompress_struct_p gif_ptr, const FX_CHAR* err_msg) {
555 if (gif_ptr != NULL && gif_ptr->_gif_error_fn != NULL) {
556 gif_ptr->_gif_error_fn(gif_ptr, err_msg);
557 }
558 }
_gif_warn(gif_decompress_struct_p gif_ptr,const FX_CHAR * err_msg)559 void _gif_warn(gif_decompress_struct_p gif_ptr, const FX_CHAR* err_msg) {}
_gif_read_header(gif_decompress_struct_p gif_ptr)560 int32_t _gif_read_header(gif_decompress_struct_p gif_ptr) {
561 if (gif_ptr == NULL) {
562 return 0;
563 }
564 FX_DWORD skip_size_org = gif_ptr->skip_size;
565 ASSERT(sizeof(GifHeader) == 6);
566 GifHeader* gif_header_ptr = NULL;
567 if (_gif_read_data(gif_ptr, (uint8_t**)&gif_header_ptr, 6) == NULL) {
568 return 2;
569 }
570 if (FXSYS_strncmp(gif_header_ptr->signature, GIF_SIGNATURE, 3) != 0 ||
571 gif_header_ptr->version[0] != '8' || gif_header_ptr->version[2] != 'a') {
572 _gif_error(gif_ptr, "Not A Gif Image");
573 return 0;
574 }
575 ASSERT(sizeof(GifLSD) == 7);
576 GifLSD* gif_lsd_ptr = NULL;
577 if (_gif_read_data(gif_ptr, (uint8_t**)&gif_lsd_ptr, 7) == NULL) {
578 gif_ptr->skip_size = skip_size_org;
579 return 2;
580 }
581 if (((GifGF*)&gif_lsd_ptr->global_flag)->global_pal) {
582 gif_ptr->global_pal_num = 2
583 << ((GifGF*)&gif_lsd_ptr->global_flag)->pal_bits;
584 ASSERT(sizeof(GifPalette) == 3);
585 int32_t global_pal_size = gif_ptr->global_pal_num * 3;
586 uint8_t* global_pal_ptr = NULL;
587 if (_gif_read_data(gif_ptr, &global_pal_ptr, global_pal_size) == NULL) {
588 gif_ptr->skip_size = skip_size_org;
589 return 2;
590 }
591 gif_ptr->global_sort_flag = ((GifGF*)&gif_lsd_ptr->global_flag)->sort_flag;
592 gif_ptr->global_color_resolution =
593 ((GifGF*)&gif_lsd_ptr->global_flag)->color_resolution;
594 if (gif_ptr->global_pal_ptr != NULL) {
595 FX_Free(gif_ptr->global_pal_ptr);
596 }
597 gif_ptr->global_pal_ptr = NULL;
598 gif_ptr->global_pal_ptr = (GifPalette*)FX_Alloc(uint8_t, global_pal_size);
599 GIF_PTR_NOT_NULL(gif_ptr->global_pal_ptr, gif_ptr);
600 FXSYS_memcpy(gif_ptr->global_pal_ptr, global_pal_ptr, global_pal_size);
601 }
602 gif_ptr->width = (int)_GetWord_LSBFirst((uint8_t*)&gif_lsd_ptr->width);
603 gif_ptr->height = (int)_GetWord_LSBFirst((uint8_t*)&gif_lsd_ptr->height);
604 gif_ptr->bc_index = gif_lsd_ptr->bc_index;
605 gif_ptr->pixel_aspect = gif_lsd_ptr->pixel_aspect;
606 return 1;
607 }
_gif_get_frame(gif_decompress_struct_p gif_ptr)608 int32_t _gif_get_frame(gif_decompress_struct_p gif_ptr) {
609 if (gif_ptr == NULL) {
610 return 0;
611 }
612 int32_t ret = 1;
613 while (TRUE) {
614 switch (gif_ptr->decode_status) {
615 case GIF_D_STATUS_TAIL:
616 return 1;
617 case GIF_D_STATUS_SIG: {
618 uint8_t* sig_ptr = NULL;
619 if (_gif_read_data(gif_ptr, &sig_ptr, 1) == NULL) {
620 return 2;
621 }
622 switch (*sig_ptr) {
623 case GIF_SIG_EXTENSION:
624 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT);
625 continue;
626 case GIF_SIG_IMAGE:
627 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_INFO);
628 continue;
629 case GIF_SIG_TRAILER:
630 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);
631 return 1;
632 default:
633 if (gif_ptr->avail_in) {
634 _gif_warn(gif_ptr, "The Gif File has non_standard Tag!");
635 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG);
636 continue;
637 }
638 _gif_warn(gif_ptr, "The Gif File Doesn't have Trailer Tag!");
639 return 1;
640 }
641 }
642 case GIF_D_STATUS_EXT: {
643 uint8_t* ext_ptr = NULL;
644 if (_gif_read_data(gif_ptr, &ext_ptr, 1) == NULL) {
645 return 2;
646 }
647 switch (*ext_ptr) {
648 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION
649 case GIF_BLOCK_AE:
650 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_AE);
651 continue;
652 #endif
653 #ifdef GIF_SUPPORT_COMMENT_EXTENSION
654 case GIF_BLOCK_CE:
655 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_CE);
656 continue;
657 #endif
658 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION
659 case GIF_BLOCK_GCE:
660 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_GCE);
661 continue;
662 #endif
663 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION
664 case GIF_BLOCK_PTE:
665 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_PTE);
666 continue;
667 #endif
668 default: {
669 int32_t status = GIF_D_STATUS_EXT_UNE;
670 #ifndef GIF_SUPPORT_PLAIN_TEXT_EXTENSION
671 if (*ext_ptr == GIF_BLOCK_PTE) {
672 status = GIF_D_STATUS_EXT_PTE;
673 }
674 #endif
675 _gif_save_decoding_status(gif_ptr, status);
676 continue;
677 }
678 }
679 }
680 case GIF_D_STATUS_IMG_INFO: {
681 ret = _gif_decode_image_info(gif_ptr);
682 if (ret != 1) {
683 return ret;
684 }
685 continue;
686 }
687 case GIF_D_STATUS_IMG_DATA: {
688 uint8_t* data_size_ptr = NULL;
689 uint8_t* data_ptr = NULL;
690 FX_DWORD skip_size_org = gif_ptr->skip_size;
691 if (_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {
692 return 2;
693 }
694 while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
695 if (_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL) {
696 gif_ptr->skip_size = skip_size_org;
697 return 2;
698 }
699 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);
700 skip_size_org = gif_ptr->skip_size;
701 if (_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {
702 return 2;
703 }
704 }
705 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG);
706 continue;
707 }
708 default: {
709 ret = _gif_decode_extension(gif_ptr);
710 if (ret != 1) {
711 return ret;
712 }
713 continue;
714 }
715 }
716 }
717 return 1;
718 }
_gif_takeover_gce_ptr(gif_decompress_struct_p gif_ptr,GifGCE ** gce_ptr_ptr)719 void _gif_takeover_gce_ptr(gif_decompress_struct_p gif_ptr,
720 GifGCE** gce_ptr_ptr) {
721 *gce_ptr_ptr = NULL;
722 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION
723 if (gif_ptr->gce_ptr != NULL && gce_ptr_ptr != NULL) {
724 *gce_ptr_ptr = gif_ptr->gce_ptr;
725 gif_ptr->gce_ptr = NULL;
726 }
727 #endif
728 }
_gif_decode_extension(gif_decompress_struct_p gif_ptr)729 int32_t _gif_decode_extension(gif_decompress_struct_p gif_ptr) {
730 uint8_t* data_size_ptr = NULL;
731 uint8_t* data_ptr = NULL;
732 FX_DWORD skip_size_org = gif_ptr->skip_size;
733 switch (gif_ptr->decode_status) {
734 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION
735 case GIF_D_STATUS_EXT_AE: {
736 ASSERT(sizeof(GifAE) == 12);
737 GifAE* gif_ae_ptr = NULL;
738 if (_gif_read_data(gif_ptr, (uint8_t**)&gif_ae_ptr, 12) == NULL) {
739 return 2;
740 }
741 CFX_ByteString gif_ae_data_str;
742 if (_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {
743 gif_ptr->skip_size = skip_size_org;
744 return 2;
745 }
746 while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
747 uint8_t data_size = *data_size_ptr;
748 if (_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL ||
749 _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {
750 gif_ptr->skip_size = skip_size_org;
751 return 2;
752 }
753 gif_ae_data_str += CFX_ByteString((const uint8_t*)data_ptr, data_size);
754 }
755 FXSYS_memcpy(gif_ptr->app_identify, gif_ae_ptr->app_identify, 8);
756 FXSYS_memcpy(gif_ptr->app_authentication, gif_ae_ptr->app_authentication,
757 3);
758 gif_ptr->app_data_size = gif_ae_data_str.GetLength();
759 if (gif_ptr->app_data != NULL) {
760 FX_Free(gif_ptr->app_data);
761 gif_ptr->app_data = NULL;
762 }
763 gif_ptr->app_data = FX_Alloc(uint8_t, gif_ptr->app_data_size);
764 GIF_PTR_NOT_NULL(gif_ptr->app_data, gif_ptr);
765 FXSYS_memcpy(gif_ptr->app_data, const uint8_t*(gif_ae_data_str),
766 gif_ptr->app_data_size);
767 } break;
768 #endif
769 #ifdef GIF_SUPPORT_COMMENT_EXTENSION
770 case GIF_D_STATUS_EXT_CE: {
771 if (_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {
772 gif_ptr->skip_size = skip_size_org;
773 return 2;
774 }
775 gif_ptr->cmt_data_ptr->Empty();
776 while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
777 uint8_t data_size = *data_size_ptr;
778 if (_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL ||
779 _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {
780 gif_ptr->skip_size = skip_size_org;
781 return 2;
782 }
783 *(gif_ptr->cmt_data_ptr) +=
784 CFX_ByteString((const FX_CHAR*)data_ptr, data_size);
785 }
786 } break;
787 #endif
788 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION
789 case GIF_D_STATUS_EXT_PTE: {
790 ASSERT(sizeof(GifPTE) == 13);
791 GifPTE* gif_pte_ptr = NULL;
792 if (_gif_read_data(gif_ptr, (uint8_t**)&gif_pte_ptr, 13) == NULL) {
793 return 2;
794 }
795 GifPlainText* gif_pt_ptr = FX_Alloc(GifPlainText, 1);
796 GIF_PTR_NOT_NULL(gif_pt_ptr, gif_ptr);
797 FXSYS_memset(gif_pt_ptr, 0, sizeof(GifPlainText));
798 _gif_takeover_gce_ptr(gif_ptr, &gif_pt_ptr->gce_ptr);
799 gif_pt_ptr->pte_ptr = (GifPTE*)FX_Alloc(uint8_t, sizeof(GifPTE));
800 GIF_PTR_NOT_NULL(gif_pt_ptr->pte_ptr, gif_ptr);
801 gif_pt_ptr->string_ptr = new CFX_ByteString;
802 GIF_PTR_NOT_NULL(gif_pt_ptr->string_ptr, gif_ptr);
803 gif_pt_ptr->pte_ptr->block_size = gif_pte_ptr->block_size;
804 gif_pt_ptr->pte_ptr->grid_left =
805 _GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_left);
806 gif_pt_ptr->pte_ptr->grid_top =
807 _GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_top);
808 gif_pt_ptr->pte_ptr->grid_width =
809 _GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_width);
810 gif_pt_ptr->pte_ptr->grid_height =
811 _GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_height);
812 gif_pt_ptr->pte_ptr->char_width = gif_pte_ptr->char_width;
813 gif_pt_ptr->pte_ptr->char_height = gif_pte_ptr->char_height;
814 gif_pt_ptr->pte_ptr->fc_index = gif_pte_ptr->fc_index;
815 gif_pt_ptr->pte_ptr->bc_index = gif_pte_ptr->bc_index;
816 if (_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {
817 gif_ptr->skip_size = skip_size_org;
818 if (gif_pt_ptr != NULL) {
819 if (gif_pt_ptr->gce_ptr != NULL) {
820 FX_Free(gif_pt_ptr->gce_ptr);
821 }
822 if (gif_pt_ptr->pte_ptr != NULL) {
823 FX_Free(gif_pt_ptr->pte_ptr);
824 }
825 if (gif_pt_ptr->string_ptr != NULL) {
826 delete gif_pt_ptr->string_ptr;
827 }
828 FX_Free(gif_pt_ptr);
829 }
830 return 2;
831 }
832 while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
833 uint8_t data_size = *data_size_ptr;
834 if (_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL ||
835 _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {
836 gif_ptr->skip_size = skip_size_org;
837 if (gif_pt_ptr != NULL) {
838 if (gif_pt_ptr->gce_ptr != NULL) {
839 FX_Free(gif_pt_ptr->gce_ptr);
840 }
841 if (gif_pt_ptr->pte_ptr != NULL) {
842 FX_Free(gif_pt_ptr->pte_ptr);
843 }
844 if (gif_pt_ptr->string_ptr != NULL) {
845 delete gif_pt_ptr->string_ptr;
846 }
847 FX_Free(gif_pt_ptr);
848 }
849 return 2;
850 }
851 *(gif_pt_ptr->string_ptr) +=
852 CFX_ByteString((const FX_CHAR*)data_ptr, data_size);
853 }
854 gif_ptr->pt_ptr_arr_ptr->Add(gif_pt_ptr);
855 } break;
856 #endif
857 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION
858 case GIF_D_STATUS_EXT_GCE: {
859 ASSERT(sizeof(GifGCE) == 5);
860 GifGCE* gif_gce_ptr = NULL;
861 if (_gif_read_data(gif_ptr, (uint8_t**)&gif_gce_ptr, 6) == NULL) {
862 return 2;
863 }
864 if (gif_ptr->gce_ptr == NULL) {
865 gif_ptr->gce_ptr = (GifGCE*)FX_Alloc(uint8_t, sizeof(GifGCE));
866 GIF_PTR_NOT_NULL(gif_ptr->gce_ptr, gif_ptr);
867 }
868 gif_ptr->gce_ptr->block_size = gif_gce_ptr->block_size;
869 gif_ptr->gce_ptr->gce_flag = gif_gce_ptr->gce_flag;
870 gif_ptr->gce_ptr->delay_time =
871 _GetWord_LSBFirst((uint8_t*)&gif_gce_ptr->delay_time);
872 gif_ptr->gce_ptr->trans_index = gif_gce_ptr->trans_index;
873 } break;
874 #endif
875 default: {
876 #ifndef GIF_SUPPORT_PLAIN_TEXT_EXTENSION
877 if (gif_ptr->decode_status == GIF_D_STATUS_EXT_PTE) {
878 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION
879 if (gif_ptr->gce_ptr != NULL) {
880 FX_Free(gif_ptr->gce_ptr);
881 gif_ptr->gce_ptr = NULL;
882 }
883 #endif
884 }
885 #endif
886 if (_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {
887 return 2;
888 }
889 while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
890 if (_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL ||
891 _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {
892 gif_ptr->skip_size = skip_size_org;
893 return 2;
894 }
895 }
896 }
897 }
898 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG);
899 return 1;
900 }
_gif_decode_image_info(gif_decompress_struct_p gif_ptr)901 int32_t _gif_decode_image_info(gif_decompress_struct_p gif_ptr) {
902 if (gif_ptr->width == 0 || gif_ptr->height == 0) {
903 _gif_error(gif_ptr, "No Image Header Info");
904 return 0;
905 }
906 FX_DWORD skip_size_org = gif_ptr->skip_size;
907 ASSERT(sizeof(GifImageInfo) == 9);
908 GifImageInfo* gif_img_info_ptr = NULL;
909 if (_gif_read_data(gif_ptr, (uint8_t**)&gif_img_info_ptr, 9) == NULL) {
910 return 2;
911 }
912 GifImage* gif_image_ptr = (GifImage*)FX_Alloc(uint8_t, sizeof(GifImage));
913 GIF_PTR_NOT_NULL(gif_image_ptr, gif_ptr);
914 FXSYS_memset(gif_image_ptr, 0, sizeof(GifImage));
915 gif_image_ptr->image_info_ptr =
916 (GifImageInfo*)FX_Alloc(uint8_t, sizeof(GifImageInfo));
917 GIF_PTR_NOT_NULL(gif_image_ptr->image_info_ptr, gif_ptr);
918 gif_image_ptr->image_info_ptr->left =
919 _GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->left);
920 gif_image_ptr->image_info_ptr->top =
921 _GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->top);
922 gif_image_ptr->image_info_ptr->width =
923 _GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->width);
924 gif_image_ptr->image_info_ptr->height =
925 _GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->height);
926 gif_image_ptr->image_info_ptr->local_flag = gif_img_info_ptr->local_flag;
927 if (gif_image_ptr->image_info_ptr->left +
928 gif_image_ptr->image_info_ptr->width >
929 gif_ptr->width ||
930 gif_image_ptr->image_info_ptr->top +
931 gif_image_ptr->image_info_ptr->height >
932 gif_ptr->height) {
933 if (gif_image_ptr->image_info_ptr != NULL) {
934 FX_Free(gif_image_ptr->image_info_ptr);
935 }
936 if (gif_image_ptr->image_row_buf != NULL) {
937 FX_Free(gif_image_ptr->image_row_buf);
938 }
939 FX_Free(gif_image_ptr);
940 _gif_error(gif_ptr, "Image Data Out Of LSD, The File May Be Corrupt");
941 return 0;
942 }
943 GifLF* gif_img_info_lf_ptr = (GifLF*)&gif_img_info_ptr->local_flag;
944 if (gif_img_info_lf_ptr->local_pal) {
945 ASSERT(sizeof(GifPalette) == 3);
946 int32_t loc_pal_size = (2 << gif_img_info_lf_ptr->pal_bits) * 3;
947 uint8_t* loc_pal_ptr = NULL;
948 if (_gif_read_data(gif_ptr, &loc_pal_ptr, loc_pal_size) == NULL) {
949 gif_ptr->skip_size = skip_size_org;
950 if (gif_image_ptr->image_info_ptr != NULL) {
951 FX_Free(gif_image_ptr->image_info_ptr);
952 }
953 if (gif_image_ptr->image_row_buf != NULL) {
954 FX_Free(gif_image_ptr->image_row_buf);
955 }
956 FX_Free(gif_image_ptr);
957 return 2;
958 }
959 gif_image_ptr->local_pal_ptr =
960 (GifPalette*)gif_ptr->_gif_ask_buf_for_pal_fn(gif_ptr, loc_pal_size);
961 if (gif_image_ptr->local_pal_ptr != NULL) {
962 FXSYS_memcpy((uint8_t*)gif_image_ptr->local_pal_ptr, loc_pal_ptr,
963 loc_pal_size);
964 }
965 }
966 uint8_t* code_size_ptr = NULL;
967 if (_gif_read_data(gif_ptr, &code_size_ptr, 1) == NULL) {
968 gif_ptr->skip_size = skip_size_org;
969 if (gif_image_ptr->image_info_ptr != NULL) {
970 FX_Free(gif_image_ptr->image_info_ptr);
971 }
972 if (gif_image_ptr->local_pal_ptr != NULL) {
973 FX_Free(gif_image_ptr->local_pal_ptr);
974 }
975 if (gif_image_ptr->image_row_buf != NULL) {
976 FX_Free(gif_image_ptr->image_row_buf);
977 }
978 FX_Free(gif_image_ptr);
979 return 2;
980 }
981 gif_image_ptr->image_code_size = *code_size_ptr;
982 gif_ptr->_gif_record_current_position_fn(gif_ptr,
983 &gif_image_ptr->image_data_pos);
984 gif_image_ptr->image_data_pos += gif_ptr->skip_size;
985 _gif_takeover_gce_ptr(gif_ptr, &gif_image_ptr->image_gce_ptr);
986 gif_ptr->img_ptr_arr_ptr->Add(gif_image_ptr);
987 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);
988 return 1;
989 }
_gif_load_frame(gif_decompress_struct_p gif_ptr,int32_t frame_num)990 int32_t _gif_load_frame(gif_decompress_struct_p gif_ptr, int32_t frame_num) {
991 if (gif_ptr == NULL || frame_num < 0 ||
992 frame_num >= gif_ptr->img_ptr_arr_ptr->GetSize()) {
993 return 0;
994 }
995 uint8_t* data_size_ptr = NULL;
996 uint8_t* data_ptr = NULL;
997 FX_DWORD skip_size_org = gif_ptr->skip_size;
998 GifImage* gif_image_ptr = gif_ptr->img_ptr_arr_ptr->GetAt(frame_num);
999 FX_DWORD gif_img_row_bytes = gif_image_ptr->image_info_ptr->width;
1000 if (gif_ptr->decode_status == GIF_D_STATUS_TAIL) {
1001 if (gif_image_ptr->image_row_buf) {
1002 FX_Free(gif_image_ptr->image_row_buf);
1003 gif_image_ptr->image_row_buf = NULL;
1004 }
1005 gif_image_ptr->image_row_buf = FX_Alloc(uint8_t, gif_img_row_bytes);
1006 GIF_PTR_NOT_NULL(gif_image_ptr->image_row_buf, gif_ptr);
1007 GifGCE* gif_img_gce_ptr = gif_image_ptr->image_gce_ptr;
1008 int32_t loc_pal_num =
1009 ((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->local_pal
1010 ? (2 << ((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)
1011 ->pal_bits)
1012 : 0;
1013 gif_ptr->avail_in = 0;
1014 if (gif_img_gce_ptr == NULL) {
1015 FX_BOOL bRes = gif_ptr->_gif_get_record_position_fn(
1016 gif_ptr, gif_image_ptr->image_data_pos,
1017 gif_image_ptr->image_info_ptr->left,
1018 gif_image_ptr->image_info_ptr->top,
1019 gif_image_ptr->image_info_ptr->width,
1020 gif_image_ptr->image_info_ptr->height, loc_pal_num,
1021 gif_image_ptr->local_pal_ptr, 0, 0, -1, 0,
1022 (FX_BOOL)((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)
1023 ->interlace);
1024 if (!bRes) {
1025 FX_Free(gif_image_ptr->image_row_buf);
1026 gif_image_ptr->image_row_buf = NULL;
1027 _gif_error(gif_ptr, "Error Read Record Position Data");
1028 return 0;
1029 }
1030 } else {
1031 FX_BOOL bRes = gif_ptr->_gif_get_record_position_fn(
1032 gif_ptr, gif_image_ptr->image_data_pos,
1033 gif_image_ptr->image_info_ptr->left,
1034 gif_image_ptr->image_info_ptr->top,
1035 gif_image_ptr->image_info_ptr->width,
1036 gif_image_ptr->image_info_ptr->height, loc_pal_num,
1037 gif_image_ptr->local_pal_ptr,
1038 (int32_t)gif_image_ptr->image_gce_ptr->delay_time,
1039 (FX_BOOL)((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)
1040 ->user_input,
1041 ((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->transparency
1042 ? (int32_t)gif_image_ptr->image_gce_ptr->trans_index
1043 : -1,
1044 (int32_t)((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)
1045 ->disposal_method,
1046 (FX_BOOL)((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)
1047 ->interlace);
1048 if (!bRes) {
1049 FX_Free(gif_image_ptr->image_row_buf);
1050 gif_image_ptr->image_row_buf = NULL;
1051 _gif_error(gif_ptr, "Error Read Record Position Data");
1052 return 0;
1053 }
1054 }
1055 if (gif_ptr->img_decoder_ptr == NULL) {
1056 gif_ptr->img_decoder_ptr = new CGifLZWDecoder(gif_ptr->err_ptr);
1057 GIF_PTR_NOT_NULL(gif_ptr->img_decoder_ptr, gif_ptr);
1058 }
1059 gif_ptr->img_decoder_ptr->InitTable(gif_image_ptr->image_code_size);
1060 gif_ptr->img_row_offset = 0;
1061 gif_ptr->img_row_avail_size = 0;
1062 gif_ptr->img_pass_num = 0;
1063 gif_image_ptr->image_row_num = 0;
1064 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);
1065 }
1066 CGifLZWDecoder* img_decoder_ptr = gif_ptr->img_decoder_ptr;
1067 if (gif_ptr->decode_status == GIF_D_STATUS_IMG_DATA) {
1068 if (_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {
1069 return 2;
1070 }
1071 if (*data_size_ptr != GIF_BLOCK_TERMINAL) {
1072 if (_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL) {
1073 gif_ptr->skip_size = skip_size_org;
1074 return 2;
1075 }
1076 img_decoder_ptr->Input(data_ptr, *data_size_ptr);
1077 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);
1078 gif_ptr->img_row_offset += gif_ptr->img_row_avail_size;
1079 gif_ptr->img_row_avail_size = gif_img_row_bytes - gif_ptr->img_row_offset;
1080 int32_t ret = img_decoder_ptr->Decode(
1081 gif_image_ptr->image_row_buf + gif_ptr->img_row_offset,
1082 gif_ptr->img_row_avail_size);
1083 if (ret == 0) {
1084 FX_Free(gif_image_ptr->image_row_buf);
1085 gif_image_ptr->image_row_buf = NULL;
1086 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);
1087 _gif_error(gif_ptr, "Decode Image Data Error");
1088 return 0;
1089 }
1090 while (ret != 0) {
1091 if (ret == 1) {
1092 gif_ptr->_gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num,
1093 gif_image_ptr->image_row_buf);
1094 FX_Free(gif_image_ptr->image_row_buf);
1095 gif_image_ptr->image_row_buf = NULL;
1096 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);
1097 return 1;
1098 }
1099 if (ret == 2) {
1100 ASSERT(img_decoder_ptr->GetAvailInput() == 0);
1101 skip_size_org = gif_ptr->skip_size;
1102 if (_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {
1103 return 2;
1104 }
1105 if (*data_size_ptr != GIF_BLOCK_TERMINAL) {
1106 if (_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL) {
1107 gif_ptr->skip_size = skip_size_org;
1108 return 2;
1109 }
1110 img_decoder_ptr->Input(data_ptr, *data_size_ptr);
1111 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);
1112 gif_ptr->img_row_offset += gif_ptr->img_row_avail_size;
1113 gif_ptr->img_row_avail_size =
1114 gif_img_row_bytes - gif_ptr->img_row_offset;
1115 ret = img_decoder_ptr->Decode(
1116 gif_image_ptr->image_row_buf + gif_ptr->img_row_offset,
1117 gif_ptr->img_row_avail_size);
1118 }
1119 }
1120 if (ret == 3) {
1121 if (((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->interlace) {
1122 gif_ptr->_gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num,
1123 gif_image_ptr->image_row_buf);
1124 gif_image_ptr->image_row_num +=
1125 s_gif_interlace_step[gif_ptr->img_pass_num];
1126 if (gif_image_ptr->image_row_num >=
1127 (int32_t)gif_image_ptr->image_info_ptr->height) {
1128 gif_ptr->img_pass_num++;
1129 gif_image_ptr->image_row_num =
1130 s_gif_interlace_step[gif_ptr->img_pass_num] / 2;
1131 }
1132 } else {
1133 gif_ptr->_gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num++,
1134 gif_image_ptr->image_row_buf);
1135 }
1136 gif_ptr->img_row_offset = 0;
1137 gif_ptr->img_row_avail_size = gif_img_row_bytes;
1138 ret = img_decoder_ptr->Decode(
1139 gif_image_ptr->image_row_buf + gif_ptr->img_row_offset,
1140 gif_ptr->img_row_avail_size);
1141 }
1142 if (ret == 0) {
1143 FX_Free(gif_image_ptr->image_row_buf);
1144 gif_image_ptr->image_row_buf = NULL;
1145 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);
1146 _gif_error(gif_ptr, "Decode Image Data Error");
1147 return 0;
1148 }
1149 }
1150 }
1151 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);
1152 }
1153 _gif_error(gif_ptr, "Decode Image Data Error");
1154 return 0;
1155 }
_gif_save_decoding_status(gif_decompress_struct_p gif_ptr,int32_t status)1156 void _gif_save_decoding_status(gif_decompress_struct_p gif_ptr,
1157 int32_t status) {
1158 gif_ptr->decode_status = status;
1159 gif_ptr->next_in += gif_ptr->skip_size;
1160 gif_ptr->avail_in -= gif_ptr->skip_size;
1161 gif_ptr->skip_size = 0;
1162 }
_gif_read_data(gif_decompress_struct_p gif_ptr,uint8_t ** des_buf_pp,FX_DWORD data_size)1163 uint8_t* _gif_read_data(gif_decompress_struct_p gif_ptr,
1164 uint8_t** des_buf_pp,
1165 FX_DWORD data_size) {
1166 if (gif_ptr == NULL || gif_ptr->avail_in < gif_ptr->skip_size + data_size) {
1167 return NULL;
1168 }
1169 *des_buf_pp = gif_ptr->next_in + gif_ptr->skip_size;
1170 gif_ptr->skip_size += data_size;
1171 return *des_buf_pp;
1172 }
_gif_input_buffer(gif_decompress_struct_p gif_ptr,uint8_t * src_buf,FX_DWORD src_size)1173 void _gif_input_buffer(gif_decompress_struct_p gif_ptr,
1174 uint8_t* src_buf,
1175 FX_DWORD src_size) {
1176 gif_ptr->next_in = src_buf;
1177 gif_ptr->avail_in = src_size;
1178 gif_ptr->skip_size = 0;
1179 }
_gif_get_avail_input(gif_decompress_struct_p gif_ptr,uint8_t ** avial_buf_ptr)1180 FX_DWORD _gif_get_avail_input(gif_decompress_struct_p gif_ptr,
1181 uint8_t** avial_buf_ptr) {
1182 if (avial_buf_ptr != NULL) {
1183 *avial_buf_ptr = NULL;
1184 if (gif_ptr->avail_in > 0) {
1185 *avial_buf_ptr = gif_ptr->next_in;
1186 }
1187 }
1188 return gif_ptr->avail_in;
1189 }
_gif_get_frame_num(gif_decompress_struct_p gif_ptr)1190 int32_t _gif_get_frame_num(gif_decompress_struct_p gif_ptr) {
1191 return gif_ptr->img_ptr_arr_ptr->GetSize();
1192 }
_gif_write_header(gif_compress_struct_p gif_ptr,uint8_t * & dst_buf,FX_DWORD & dst_len)1193 static FX_BOOL _gif_write_header(gif_compress_struct_p gif_ptr,
1194 uint8_t*& dst_buf,
1195 FX_DWORD& dst_len) {
1196 if (gif_ptr->cur_offset) {
1197 return TRUE;
1198 }
1199 dst_len = sizeof(GifHeader) + sizeof(GifLSD) + sizeof(GifGF);
1200 dst_buf = FX_TryAlloc(uint8_t, dst_len);
1201 if (dst_buf == NULL) {
1202 return FALSE;
1203 }
1204 FXSYS_memset(dst_buf, 0, dst_len);
1205 FXSYS_memcpy(dst_buf, gif_ptr->header_ptr, sizeof(GifHeader));
1206 gif_ptr->cur_offset += sizeof(GifHeader);
1207 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->lsd_ptr->width);
1208 gif_ptr->cur_offset += 2;
1209 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->lsd_ptr->height);
1210 gif_ptr->cur_offset += 2;
1211 dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->global_flag;
1212 dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->bc_index;
1213 dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->pixel_aspect;
1214 if (gif_ptr->global_pal) {
1215 FX_WORD size = sizeof(GifPalette) * gif_ptr->gpal_num;
1216 if (!_gif_grow_buf(dst_buf, dst_len, gif_ptr->cur_offset + size)) {
1217 return FALSE;
1218 }
1219 FXSYS_memcpy(&dst_buf[gif_ptr->cur_offset], gif_ptr->global_pal, size);
1220 gif_ptr->cur_offset += size;
1221 }
1222 return TRUE;
1223 }
interlace_buf(const uint8_t * buf,FX_DWORD pitch,FX_DWORD height)1224 void interlace_buf(const uint8_t* buf, FX_DWORD pitch, FX_DWORD height) {
1225 CFX_ArrayTemplate<uint8_t*> pass[4];
1226 int i, j;
1227 FX_DWORD row;
1228 row = 0;
1229 uint8_t* temp;
1230 while (row < height) {
1231 if (row % 8 == 0) {
1232 j = 0;
1233 } else if (row % 4 == 0) {
1234 j = 1;
1235 } else if (row % 2 == 0) {
1236 j = 2;
1237 } else {
1238 j = 3;
1239 }
1240 temp = FX_Alloc(uint8_t, pitch);
1241 if (temp == NULL) {
1242 return;
1243 }
1244 FXSYS_memcpy(temp, &buf[pitch * row], pitch);
1245 pass[j].Add(temp);
1246 row++;
1247 }
1248 for (i = 0, row = 0; i < 4; i++) {
1249 for (j = 0; j < pass[i].GetSize(); j++, row++) {
1250 FXSYS_memcpy((uint8_t*)&buf[pitch * row], pass[i].GetAt(j), pitch);
1251 FX_Free(pass[i].GetAt(j));
1252 }
1253 }
1254 }
_gif_write_block_data(const uint8_t * src_buf,FX_DWORD src_len,uint8_t * & dst_buf,FX_DWORD & dst_len,FX_DWORD & dst_offset)1255 static void _gif_write_block_data(const uint8_t* src_buf,
1256 FX_DWORD src_len,
1257 uint8_t*& dst_buf,
1258 FX_DWORD& dst_len,
1259 FX_DWORD& dst_offset) {
1260 FX_DWORD src_offset = 0;
1261 while (src_len > GIF_DATA_BLOCK) {
1262 dst_buf[dst_offset++] = GIF_DATA_BLOCK;
1263 FXSYS_memcpy(&dst_buf[dst_offset], &src_buf[src_offset], GIF_DATA_BLOCK);
1264 dst_offset += GIF_DATA_BLOCK;
1265 src_offset += GIF_DATA_BLOCK;
1266 src_len -= GIF_DATA_BLOCK;
1267 }
1268 dst_buf[dst_offset++] = (uint8_t)src_len;
1269 FXSYS_memcpy(&dst_buf[dst_offset], &src_buf[src_offset], src_len);
1270 dst_offset += src_len;
1271 }
_gif_write_data(gif_compress_struct_p gif_ptr,uint8_t * & dst_buf,FX_DWORD & dst_len)1272 static FX_BOOL _gif_write_data(gif_compress_struct_p gif_ptr,
1273 uint8_t*& dst_buf,
1274 FX_DWORD& dst_len) {
1275 if (!_gif_grow_buf(dst_buf, dst_len, gif_ptr->cur_offset + GIF_DATA_BLOCK)) {
1276 return FALSE;
1277 }
1278 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION
1279 if (FXSYS_memcmp(gif_ptr->header_ptr->version, "89a", 3) == 0) {
1280 dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION;
1281 dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_GCE;
1282 gif_ptr->gce_ptr->block_size = 4;
1283 dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->block_size;
1284 gif_ptr->gce_ptr->gce_flag = 0;
1285 dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->gce_flag;
1286 gif_ptr->gce_ptr->delay_time = 10;
1287 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset,
1288 gif_ptr->gce_ptr->delay_time);
1289 gif_ptr->cur_offset += 2;
1290 gif_ptr->gce_ptr->trans_index = 0;
1291 dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->trans_index;
1292 dst_buf[gif_ptr->cur_offset++] = 0;
1293 }
1294 #endif
1295 dst_buf[gif_ptr->cur_offset++] = GIF_SIG_IMAGE;
1296 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset,
1297 gif_ptr->image_info_ptr->left);
1298 gif_ptr->cur_offset += 2;
1299 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset,
1300 gif_ptr->image_info_ptr->top);
1301 gif_ptr->cur_offset += 2;
1302 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset,
1303 gif_ptr->image_info_ptr->width);
1304 gif_ptr->cur_offset += 2;
1305 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset,
1306 gif_ptr->image_info_ptr->height);
1307 gif_ptr->cur_offset += 2;
1308 GifLF& lf = (GifLF&)gif_ptr->image_info_ptr->local_flag;
1309 dst_buf[gif_ptr->cur_offset++] = gif_ptr->image_info_ptr->local_flag;
1310 if (gif_ptr->local_pal) {
1311 FX_DWORD pal_size = sizeof(GifPalette) * gif_ptr->lpal_num;
1312 if (!_gif_grow_buf(dst_buf, dst_len, pal_size + gif_ptr->cur_offset)) {
1313 return FALSE;
1314 }
1315 FXSYS_memcpy(&dst_buf[gif_ptr->cur_offset], gif_ptr->local_pal, pal_size);
1316 gif_ptr->cur_offset += pal_size;
1317 }
1318 if (lf.interlace) {
1319 interlace_buf(gif_ptr->src_buf, gif_ptr->src_pitch,
1320 gif_ptr->image_info_ptr->height);
1321 }
1322 uint8_t code_bit = lf.pal_bits;
1323 if (lf.local_pal == 0) {
1324 GifGF& gf = (GifGF&)gif_ptr->lsd_ptr->global_flag;
1325 code_bit = gf.pal_bits;
1326 }
1327 gif_ptr->img_encoder_ptr->Start(code_bit, gif_ptr->src_buf, dst_buf,
1328 gif_ptr->cur_offset);
1329 FX_DWORD i;
1330 for (i = 0; i < gif_ptr->src_row; i++) {
1331 if (!gif_ptr->img_encoder_ptr->Encode(
1332 &gif_ptr->src_buf[i * gif_ptr->src_pitch],
1333 gif_ptr->src_width * (code_bit + 1), dst_buf, dst_len,
1334 gif_ptr->cur_offset)) {
1335 return FALSE;
1336 }
1337 }
1338 gif_ptr->img_encoder_ptr->Finish(dst_buf, dst_len, gif_ptr->cur_offset);
1339 dst_buf[gif_ptr->cur_offset++] = 0;
1340 #ifdef GIF_SUPPORT_COMMENT_EXTENSION
1341 if (FXSYS_memcmp(gif_ptr->header_ptr->version, "89a", 3) == 0 &&
1342 gif_ptr->cmt_data_ptr) {
1343 dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION;
1344 dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_CE;
1345 _gif_write_block_data(gif_ptr->cmt_data_ptr, gif_ptr->cmt_data_len, dst_buf,
1346 dst_len, gif_ptr->cur_offset);
1347 dst_buf[gif_ptr->cur_offset++] = 0;
1348 }
1349 #endif
1350 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION
1351 if (FXSYS_memcmp(gif_ptr->header_ptr->version, "89a", 3) == 0 &&
1352 gif_ptr->pte_data_ptr) {
1353 dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION;
1354 dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_PTE;
1355 dst_buf[gif_ptr->cur_offset++] = gif_ptr->pte_ptr->block_size;
1356 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset,
1357 gif_ptr->pte_ptr->grid_left);
1358 gif_ptr->cur_offset += 2;
1359 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset,
1360 gif_ptr->pte_ptr->grid_top);
1361 gif_ptr->cur_offset += 2;
1362 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset,
1363 gif_ptr->pte_ptr->grid_width);
1364 gif_ptr->cur_offset += 2;
1365 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset,
1366 gif_ptr->pte_ptr->grid_height);
1367 gif_ptr->cur_offset += 2;
1368 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset,
1369 gif_ptr->pte_ptr->char_width);
1370 gif_ptr->cur_offset += 2;
1371 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset,
1372 gif_ptr->pte_ptr->char_height);
1373 gif_ptr->cur_offset += 2;
1374 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset,
1375 gif_ptr->pte_ptr->fc_index);
1376 gif_ptr->cur_offset += 2;
1377 _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset,
1378 gif_ptr->pte_ptr->bc_index);
1379 gif_ptr->cur_offset += 2;
1380 _gif_write_block_data(gif_ptr->pte_data_ptr, gif_ptr->pte_data_len, dst_buf,
1381 dst_len, gif_ptr->cur_offset);
1382 gif_ptr->cur_offset += gif_ptr->pte_data_len;
1383 dst_buf[gif_ptr->cur_offset++] = 0;
1384 }
1385 #endif
1386 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION
1387 if (FXSYS_memcmp(gif_ptr->header_ptr->version, "89a", 3) == 0 &&
1388 gif_ptr->app_data) {
1389 dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION;
1390 dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_AE;
1391 dst_buf[gif_ptr->cur_offset++] = 11;
1392 FXSYS_memcpy(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_identify, 8);
1393 gif_ptr->cur_offset += 8;
1394 FXSYS_memcpy(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_authentication, 8);
1395 gif_ptr->cur_offset += 3;
1396 FXSYS_memcpy(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_data,
1397 gif_ptr->app_data_size);
1398 gif_ptr->cur_offset += gif_ptr->app_data_size;
1399 dst_buf[gif_ptr->cur_offset++] = 0;
1400 }
1401 #endif
1402 dst_buf[gif_ptr->cur_offset++] = GIF_SIG_TRAILER;
1403 return TRUE;
1404 }
_gif_encode(gif_compress_struct_p gif_ptr,uint8_t * & dst_buf,FX_DWORD & dst_len)1405 FX_BOOL _gif_encode(gif_compress_struct_p gif_ptr,
1406 uint8_t*& dst_buf,
1407 FX_DWORD& dst_len) {
1408 if (!_gif_write_header(gif_ptr, dst_buf, dst_len)) {
1409 return FALSE;
1410 }
1411 FX_DWORD cur_offset = gif_ptr->cur_offset;
1412 FX_BOOL res = TRUE;
1413 if (gif_ptr->frames) {
1414 gif_ptr->cur_offset--;
1415 }
1416 if (!_gif_write_data(gif_ptr, dst_buf, dst_len)) {
1417 gif_ptr->cur_offset = cur_offset;
1418 res = FALSE;
1419 }
1420 dst_len = gif_ptr->cur_offset;
1421 dst_buf[dst_len - 1] = GIF_SIG_TRAILER;
1422 if (res) {
1423 gif_ptr->frames++;
1424 }
1425 return res;
1426 }
1427