1 // This file is part of Deark.
2 // Copyright (C) 2017 Jason Summers
3 // See the file COPYING for terms of use.
7 #include <deark-config.h>
8 #include <deark-private.h>
9 DE_DECLARE_MODULE(de_module_flif
);
11 typedef struct localctx_struct
{
15 i64 bytes_per_channel
;
20 static int read_varint(deark
*c
, i64 pos1
, i64
*result
, i64
*bytes_consumed
)
30 b
= de_getbyte(pos
++);
31 val
= (val
<<7)|(b
&0x7f);
32 if((b
&0x80)==0) break;
34 // We allow varints up to 8 bytes (8*7=56 bits).
35 // If we've read 8 bytes without finding the terminating byte,
37 // (Note that if we were to allow 63 bits, we could have int64
38 // overflow when we convert from a physical value to a logical
40 de_err(c
, "Excessively large varint at %d", (int)pos1
);
48 *bytes_consumed
= pos
- pos1
;
52 static int do_read_header(deark
*c
, lctx
*d
, i64 pos1
,
58 u8 bytes_per_channel_code
;
64 de_dbg(c
, "header at %d", (int)pos1
);
69 b
= de_getbyte(pos
++);
71 intl_anim_code
= (b
&0xf0)>>4;
72 switch(intl_anim_code
) {
74 case 4: d
->is_interlaced
= 1; break;
75 case 5: d
->is_animated
= 1; break;
76 case 6: d
->is_interlaced
= 1; d
->is_animated
= 1; break;
78 de_warn(c
, "Unknown interlace/animation code: %d", (int)intl_anim_code
);
80 de_dbg(c
, "interlaced: %d", d
->is_interlaced
);
81 de_dbg(c
, "animated: %d", d
->is_animated
);
83 d
->num_channels
= (i64
)(b
&0x0f);
84 de_dbg(c
, "number of channels: %d", (int)d
->num_channels
);
86 bytes_per_channel_code
= de_getbyte(pos
++);
87 if(bytes_per_channel_code
=='0') {
88 de_strlcpy(tmps
, "custom", sizeof(tmps
));
90 else if(bytes_per_channel_code
=='1' || bytes_per_channel_code
=='2') {
91 d
->bytes_per_channel
= (i64
)(bytes_per_channel_code
-'0');
92 de_snprintf(tmps
, sizeof(tmps
), "%d", (int)(d
->bytes_per_channel
));
95 de_strlcpy(tmps
, "?", sizeof(tmps
));
97 de_dbg(c
, "bytes per channel: 0x%02x (%s)",
98 (unsigned int)bytes_per_channel_code
, tmps
);
100 if(!read_varint(c
, pos
, &tmpcode
, &bytes_consumed2
)) goto done
;
101 d
->width
= tmpcode
+1;
102 pos
+= bytes_consumed2
;
104 if(!read_varint(c
, pos
, &tmpcode
, &bytes_consumed2
)) goto done
;
105 d
->height
= tmpcode
+1;
106 pos
+= bytes_consumed2
;
108 de_dbg_dimensions(c
, d
->width
, d
->height
);
111 if(!read_varint(c
, pos
, &tmpcode
, &bytes_consumed2
)) goto done
;
112 d
->nb_frames
= tmpcode
+2;
113 pos
+= bytes_consumed2
;
114 de_dbg(c
, "number of frames: %d", (int)d
->nb_frames
);
122 *bytes_consumed
= pos
- pos1
;
123 de_dbg_indent(c
, -1);
127 static int do_read_metadata(deark
*c
, lctx
*d
, i64 pos1
,
132 int saved_indent_level
;
135 de_dbg_indent_save(c
, &saved_indent_level
);
138 // peek at the next byte, to see if there is a metadata segment.
141 de_dbg(c
, "[metadata segment not present]");
146 de_dbg(c
, "metadata segment at %d", (int)pos1
);
147 de_err(c
, "not implemented");
149 // TODO (need samples)
152 de_dbg_indent_restore(c
, saved_indent_level
);
156 static int do_second_header(deark
*c
, lctx
*d
, i64 pos1
,
162 de_dbg(c
, "second header segment at %d", (int)pos1
);
165 ct
= de_getbyte(pos
++);
166 de_dbg(c
, "chunk type: 0x%02x", (unsigned int)ct
);
169 de_err(c
, "unsupported chunk type: 0x%02x", (unsigned int)ct
);
174 de_dbg_indent(c
, -1);
178 static void de_run_flif(deark
*c
, de_module_params
*mparams
)
184 d
= de_malloc(c
, sizeof(lctx
));
188 if(!do_read_header(c
, d
, pos
, &bytes_consumed
)) goto done
;
189 pos
+= bytes_consumed
;
192 if(!do_read_metadata(c
, d
, pos
, &bytes_consumed
)) goto done
;
193 pos
+= bytes_consumed
;
195 if(!do_second_header(c
, d
, pos
, &bytes_consumed
)) goto done
;
201 static int de_identify_flif(deark
*c
)
203 if(!dbuf_memcmp(c
->infile
, 0, "FLIF", 4))
208 void de_module_flif(deark
*c
, struct deark_module_info
*mi
)
211 mi
->desc
= "FLIF image format";
212 mi
->run_fn
= de_run_flif
;
213 mi
->identify_fn
= de_identify_flif
;
214 mi
->flags
|= DE_MODFLAG_NONWORKING
;