2 ref code) http://diary.awm.jp/~yoya/data/2008/02/03/jpegdump.phps
4 gcc -W -Wall -D__JPEG_SEGMENT_DEBUG__ jpeg_segment.c bitstream.c
9 #include "swf_define.h"
10 #include "bitstream.h"
11 #include "jpeg_segment.h"
13 typedef struct jpeg_marker_name_ {
18 jpeg_marker_name_t jpeg_marker_name_table[] = {
20 {0xE0, "APP0"}, {0xE1, "APP1"}, {0xE2, "APP2"}, {0xE3, "APP3"},
21 {0xE4, "APP4"}, {0xE5, "APP5"}, {0xE6, "APP6"}, {0xE7, "APP7"},
22 {0xE8, "APP8"}, {0xE9, "APP9"}, {0xEA, "APP10"},{0xEB, "APP11"},
23 {0xEC, "APP12"},{0xED, "APP13"},{0xEE, "APP14"},{0xEF, "APP15"},
26 {0xC0, "SOF0"}, {0xC1, "SOF1"}, {0xC2, "SOF2"}, {0xC3, "SOF3"},
27 {0xC5, "SOF5"}, {0xC6, "SOF6"}, {0xC7, "SOF7"},
28 {0xC8, "JPG"}, {0xC9, "SOF9"}, {0xCA, "SOF10"},{0xCB, "SOF11"},
29 {0xCC, "DAC"}, {0xCD, "SOF13"},{0xCE, "SOF14"},{0xCF, "SOF15"},
32 {0xD0, "RST0"}, {0xD1, "RST1"}, {0xD2, "RST2"}, {0xD3, "RST3"},
33 {0xD4, "RST4"}, {0xD5, "RST5"}, {0xD6, "RST6"}, {0xD7, "RST7"},
36 {0xDC, "DNL"}, {0xDE, "DHP"}, {0xDF, "EXP"},
37 {0xF0, "JPG0"}, {0xF1, "JPG1"}, {0xF2, "JPG2"}, {0xF3, "JPG3"},
38 {0xF4, "JPG4"}, {0xF5, "JPG5"}, {0xF6, "JPG6"}, {0xF7, "JPG7"},
39 {0xF8, "JPG8"}, {0xF9, "JPG9"}, {0xFA, "JPG10"},{0xFB, "JPG11"},
40 {0xFC, "JPG12"},{0xFD, "JPG13"},
43 #define NumOfTable(t) (sizeof(t) / sizeof(*t))
45 char *jpeg_segment_get_marker_name(int marker) {
46 int i, marker_name_num = NumOfTable(jpeg_marker_name_table);
47 for (i=0 ; i < marker_name_num ; i++) {
48 if (marker == jpeg_marker_name_table[i].marker) {
49 return jpeg_marker_name_table[i].name;
55 jpeg_segment_t *jpeg_segment_create(void) {
56 jpeg_segment_t *jpeg_seg = calloc(sizeof(*jpeg_seg), 1);
57 if (jpeg_seg == NULL) {
58 fprintf(stderr, "jpeg_segment_create: Can't alloc memory\n");
61 jpeg_seg->head = NULL;
62 jpeg_seg->tail = NULL;
66 void jpeg_segment_append(jpeg_segment_t *jpeg_seg,
68 unsigned char *data_ref, unsigned long data_len) {
69 jpeg_segment_node_t *node = jpeg_seg->head;
70 jpeg_segment_node_t *new_node;
71 new_node = calloc(sizeof(*node), 1);
72 if (new_node == NULL) {
73 fprintf(stderr, "jpeg_segment_append: jpeg_segment_create failed\n");
76 if (jpeg_seg->head == NULL) {
77 jpeg_seg->head = new_node;
79 jpeg_seg->tail->next = new_node;
81 jpeg_seg->tail = new_node;
82 new_node->marker = marker;
83 new_node->data_ref = data_ref;
84 new_node->data_len = data_len;
88 jpeg_segment_t *jpeg_segment_parse(unsigned char *data,
89 unsigned long data_len,
92 jpeg_segment_t *jpeg_seg;
96 bs = bitstream_open();
97 bitstream_input(bs, data, data_len);
98 jpeg_seg = jpeg_segment_create();
100 while((marker1 = bitstream_getbyte(bs)) >= 0) {
103 if (marker1 != 0xFF) {
107 fprintf(stderr, "jpeg_segment_parse: marker1=0x%02X\n", marker1);
108 jpeg_segment_destroy(jpeg_seg);
112 marker2 = bitstream_getbyte(bs);
114 unsigned long sos_offset;
116 /* removed segment */
118 case 0xD8: // SOI (Start of Image)
119 jpeg_segment_append(jpeg_seg, marker2, NULL, 0);
121 case 0xD9: // EOI (End of Image)
122 jpeg_segment_append(jpeg_seg, marker2, NULL, 0);
126 if ((! rst_scan) && (data[data_len - 2] == 0xFF) &&
127 (data[data_len - 1] == 0xD9)) {
129 sos_offset = bitstream_getbytepos(bs);
130 sos_len = data_len - sos_offset - 2;
131 jpeg_segment_append(jpeg_seg, marker2, data + sos_offset,
133 bitstream_incrpos(bs, sos_len, 0);
134 marker1 = bitstream_getbyte(bs);
135 marker2 = bitstream_getbyte(bs);
136 jpeg_segment_append(jpeg_seg, marker2, NULL, 0); // EOI
140 case 0xD0: case 0xD1: case 0xD2: case 0xD3: // RST
141 case 0xD4: case 0xD5: case 0xD6: case 0xD7: // RST
142 sos_offset = bitstream_getbytepos(bs);
143 while((marker1 = bitstream_getbyte(bs)) >= 0) {
144 if (marker1 != 0xFF) {
147 next_marker2 = bitstream_getbyte(bs);
148 if (next_marker2 == 0x00) {
151 bitstream_incrpos(bs, -2, 0);
152 jpeg_segment_append(jpeg_seg, marker2, data + sos_offset,
153 bitstream_getbytepos(bs) - sos_offset);
158 len = bitstream_getbytesBE(bs, 2) - 2;
159 jpeg_segment_append(jpeg_seg, marker2,
160 data + bitstream_getbytepos(bs),
162 bitstream_incrpos(bs, len, 0);
170 int jpeg_segment_contain(jpeg_segment_t *jpeg_seg, int marker) {
171 jpeg_segment_node_t *node;
172 for (node=jpeg_seg->head ; node ; node=node->next) {
173 if (node->marker == marker) {
180 unsigned char *jpeg_segment_steal_node(jpeg_segment_t *jpeg_seg,
182 unsigned long *length) {
183 jpeg_segment_node_t *node;
186 for (node=jpeg_seg->head ; node ; node=node->next) {
187 if (node->marker == marker) {
188 data = node->data_ref;
189 *length = node->data_len;
190 node->marker = -1; // remove mark;
191 node->data_ref = NULL;
200 jpeg_segment_delete_node(jpeg_segment_t *jpeg_seg, int marker) {
201 jpeg_segment_node_t *node;
203 for (node=jpeg_seg->head ; node ; node=node->next) {
204 if (node->marker == marker) {
205 node->marker = -1; // remove mark;
206 node->data_ref = NULL;
215 jpeg_segment_peek_marker(jpeg_segment_t *jpeg_seg) {
216 jpeg_segment_node_t *node;
217 for (node=jpeg_seg->head ; node ; node=node->next) {
218 if (node->marker != -1) {
226 jpeg_segment_print(jpeg_segment_t *jpeg_seg) {
228 jpeg_segment_node_t *node;
229 if (jpeg_seg == NULL) {
230 fprintf(stderr, "jpeg_segment_print: jpeg_seg == NULL\n");
233 node = jpeg_seg->head;
234 for (i=0 ; node ; i++) {
236 if (node->marker >= 0) {
237 marker_name = jpeg_segment_get_marker_name(node->marker);
238 printf("(%d) marker=%s(FF%02X): length=%lu\n",
239 i, marker_name?marker_name:"Unknown",
240 node->marker, node->data_len);
247 jpeg_segment_output(jpeg_segment_t *jpeg_seg, unsigned long *length) {
250 jpeg_segment_node_t *node;
252 node = jpeg_seg->head;
253 bs = bitstream_open();
254 for (; node ; node=node->next) {
255 int marker2 = node->marker;
259 bitstream_putbyte(bs, 0xFF); // marker1
260 bitstream_putbyte(bs, marker2); // marker2
262 case 0xD8: // SOI (Start of Image)
263 case 0xD9: // EOI (End of Image)
267 bitstream_putbytesBE(bs, node->data_len + 2, 2);
270 case 0xD0: case 0xD1: case 0xD2: case 0xD3: // RST
271 case 0xD4: case 0xD5: case 0xD6: case 0xD7: // RST
272 bitstream_putstring(bs, node->data_ref, node->data_len);
276 data = bitstream_steal(bs, length);
281 void jpeg_segment_destroy(jpeg_segment_t *jpeg_seg) {
282 jpeg_segment_node_t *node, *next_node;
283 if (jpeg_seg == NULL) {
286 node = jpeg_seg->head;
288 next_node = node->next;
289 /* node->data_ref no free!! */
296 #ifdef __JPEG_SEGMENT_DEBUG__ /* for component debug */
298 #include <sys/stat.h>
300 int main(int argc, char **argv) {
303 FILE *fp, *fp_out = NULL;
304 unsigned char *data, *output_data;
305 unsigned long data_len, output_data_len;
306 jpeg_segment_t *jpeg_seg;
307 if ((argc != 2) && (argc != 3)) {
308 fprintf(stderr, "Usage: %s <jpeg_infile> [<jpeg_outfile>]\n", argv[0]);
312 if (stat(filename, &sbuf)) {
313 fprintf(stderr, "Can't stat file(%s)\n", filename);
316 data_len = sbuf.st_size;
317 fp = fopen(filename, "rb");
319 fprintf(stderr, "Can't open infile(%s)\n", filename);
322 data = malloc(data_len);
323 if (fread(data, 1, data_len, fp) != data_len) {
328 jpeg_seg = jpeg_segment_parse(data, data_len, 1);
329 jpeg_segment_print(jpeg_seg);
331 fp_out = fopen(argv[2], "wb");
332 if (fp_out == NULL) {
333 fprintf(stderr, "Can't open outfile(%s)\n", argv[2]);
336 output_data = jpeg_segment_output(jpeg_seg, &output_data_len);
337 fwrite(output_data, output_data_len, 1, fp_out);
341 jpeg_segment_destroy(jpeg_seg);
346 #endif /* __JPEG_SEGMENT_DEBUG__ */