libgphoto2 photo camera library (libgphoto2) Internals  2.5.23
jpeg.c
Go to the documentation of this file.
1 
23 #include "config.h"
24 #include "jpeg.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <gphoto2/gphoto2-file.h>
29 
30 /* call example:nullpictureabort(picture,"Picture",0); */
31 #define nullpointerabort(pointer,name,val) \
32  if (pointer==NULL) { printf(name " does not exist\n"); return val; }
33 
34 /* call example:nullpictureabortvoid(picture,"Picture"); */
35 #define nullpointerabortvoid(pointer,name) \
36  if (pointer==NULL) { printf(name " does not exist\n"); return; }
37 
38 #define CHECK_RESULT(result) {int r = (result); if (r < 0) return (r);}
39 
40 /* Determine the number of elements in an array. */
41 #define countof(array) (sizeof(array) / sizeof((array)[0]))
42 
47 };
48 
49 const char *JPEG_MARKERNAMES[] = {
50  "Start", "Comment", "APPO",
51  "Quantization table", "Huffman table", "SOFC0",
52  "SsSeAhAl", "End of image"
53 };
54 
56 {
57  chunk *mychunk;
58  printf("Entered gpi_jpeg_chunk_new\n");
59  mychunk = (chunk *) malloc(sizeof(chunk));
60  if (mychunk==NULL) {
61  printf("Failed to allocate new chunk!\n");
62  return NULL;
63  }
64  mychunk->size=length;
65 /* printf("New chunk of size %i\n", mychunk->size); */
66  mychunk->data = malloc(length);
67  return mychunk;
68 }
69 
70 chunk *gpi_jpeg_chunk_new_filled(int length, char *data)
71 {
72  chunk *mychunk;
73  printf("Entered gpi_jpeg_chunk_new_filled\n");
74  mychunk = gpi_jpeg_chunk_new(length);
75  if (!mychunk)
76  return NULL;
77  printf("Filling the chunk data via chunk_new_filled\n");
78  memcpy(mychunk->data, data, length);
79  return mychunk;
80 }
81 
83 {
84  nullpointerabortvoid(mychunk, "Chunk");
85  mychunk->size=0;
86  free(mychunk->data);
87  free(mychunk);
88 }
89 
90 
92 {
93  int x;
94 /* printf("Size=%i\n", mychunk->size); */
95  nullpointerabortvoid(mychunk, "Chunk");
96  for (x=0; x<mychunk->size; x++)
97  printf("%hhX ", mychunk->data[x]);
98  printf("\n");
99 }
100 
101 char gpi_jpeg_findff(int *location, chunk *picture)
102 {
103 /* printf("Entered jpeg_findamarker!!!!!!\n"); */
104  nullpointerabort(picture, "Picture",0);
105  while(*location<picture->size)
106  {
107 /* printf("%hX ",picture->data[*location]); */
108  if (picture->data[*location]==0xff)
109  {
110 /* printf("return success!\n"); */
111  return 1;
112  }
113  (*location)++;
114  }
115 /* printf("return failure!\n"); */
116  return 0;
117 }
118 
119 char gpi_jpeg_findactivemarker(char *id, int *location, chunk *picture)
120 {
121 /* printf("Entered gpi_jpeg_findactivemarker!!!!!!!!\n"); */
122  nullpointerabort(picture, "Picture",0);
123  while(gpi_jpeg_findff(location, picture) && ((*location+1)<picture->size))
124  if (picture->data[*location+1]) {
125  *id=picture->data[*location+1];
126  return 1;
127  }
128  return 0;
129 }
130 
131 char *gpi_jpeg_markername(unsigned int c)
132 {
133  unsigned int x;
134 /* printf("searching for marker %X in list\n",c); */
135 /* printf("%i\n", sizeof(markers)); */
136  for (x=0; x<countof(JPEG_MARKERS); x++)
137  {
138 /* printf("checking to see if it is marker %X\n", markers[x]); */
139 
140  if (c==JPEG_MARKERS[x])
141  return (char *)JPEG_MARKERNAMES[x];
142  }
143  return "Undefined marker";
144 }
145 
147 {
148  jpeg *temp;
149  temp=malloc(sizeof(jpeg));
150  temp->count=0;
151  return temp;
152 }
153 
154 void gpi_jpeg_destroy(jpeg *myjpeg)
155 {
156  int count;
157  for (count=0; count<myjpeg->count; count++)
158  gpi_jpeg_chunk_destroy(myjpeg->marker[count]);
159  myjpeg->count=0;
160  free(myjpeg);
161 }
162 
163 void gpi_jpeg_add_marker(jpeg *myjpeg, chunk *picture, int start, int end)
164 {
165  int length;
166  nullpointerabortvoid(picture, "Picture");
167  length=(int)(end-start+1);
168 /* printf("Add marker #%i starting from %i and ending at %i for a length of %i\n", myjpeg->count, start, end, length); */
169  myjpeg->marker[myjpeg->count] = gpi_jpeg_chunk_new(length);
170  if (!myjpeg->marker[myjpeg->count])
171  return;
172 /* printf("Read length is: %i\n", myjpeg->marker[myjpeg->count].size); */
173  memcpy(myjpeg->marker[myjpeg->count]->data, picture->data+start, length);
174  gpi_jpeg_chunk_print(myjpeg->marker[myjpeg->count]);
175  myjpeg->count++;
176 }
177 
178 void gpi_jpeg_add_chunk(jpeg *myjpeg, chunk *source)
179 { /* Warning! This points to the added chunk instead of deleting it! */
180  printf("Entered gpi_jpeg_add_chunk\n");
181  nullpointerabortvoid(source, "Chunk to add");
182  myjpeg->marker[myjpeg->count]=source;
183  myjpeg->count++;
184 }
185 
186 void gpi_jpeg_parse(jpeg *myjpeg, chunk *picture)
187 {
188  int position=0;
189  int lastposition;
190  char id;
191  nullpointerabortvoid(picture,"Picture");
192  if (picture->data[0]!=0xff)
193  {
194  gpi_jpeg_findactivemarker(&id, &position, picture);
195  gpi_jpeg_add_marker(myjpeg,picture,0,position-1);
196  lastposition=position;
197  position++;
198  }
199  else
200  {
201  lastposition=position;
202  position+=2;
203  gpi_jpeg_findactivemarker(&id, &position, picture);
204  gpi_jpeg_add_marker(myjpeg,picture,0,position-1);
205  lastposition=position;
206  position+=2;
207  }
208  while (position<picture->size)
209  {
210  gpi_jpeg_findactivemarker(&id, &position, picture);
211  gpi_jpeg_add_marker(myjpeg,picture,lastposition,position-1);
212  lastposition=position;
213  position+=2;
214  }
215  position-=2;
216  if (position<picture->size)
217  gpi_jpeg_add_marker(myjpeg,picture,lastposition,picture->size-1);
218 }
219 
220 void gpi_jpeg_print(jpeg *myjpeg)
221 {
222  int c;
223  printf("There are %i markers\n", myjpeg->count);
224  for (c=0; c < myjpeg->count; c++)
225  {
226  printf("%s:\n",gpi_jpeg_markername(myjpeg->marker[c]->data[1]));
227  gpi_jpeg_chunk_print(myjpeg->marker[c]);
228  }
229 }
230 
231 chunk *gpi_jpeg_make_start() /* also makes the JFIF marker */
232 {
233  chunk *temp;
234  /* Start marker and
235  JFIF APPO Marker:Version 1.01, density 1x2 (the 00 01 00 02) */
236  temp = gpi_jpeg_chunk_new_filled(20, "\xFF\xD8"
237  "\xFF\xE0\x00\x10\x4A\x46\x49\x46" "\x00\x01\x01\x00\x00\x01\x00\x02" "\x00\x00");
238  return temp;
239 }
240 
241 chunk *gpi_jpeg_make_SOFC (int width, int height, char vh1, char vh2, char vh3, char q1, char q2, char q3)
242 {
243  chunk *target;
244 
245  char sofc_data[]={
246  0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0x80, 0x01,
247  0x40, 0x03, 0x01, 0x11, 0x00, 0x02, 0x21, 0x01, 0x03, 0x11, 0x00
248  };
249  target = gpi_jpeg_chunk_new(sizeof(sofc_data));
250  if (target==NULL) { printf("New SOFC failed allocation\n"); return target; }
251  memcpy(target->data, sofc_data, sizeof(sofc_data));
252  target->data[5] = (height&0xff00) >> 8;
253  target->data[6] = height&0xff;
254  target->data[7] = (width&0xff00) >> 8;
255  target->data[8] = width&0xff;
256  target->data[11]= vh1;
257  target->data[12]= q1;
258  target->data[14]= vh2;
259  target->data[15]= q2;
260  target->data[17]= vh3;
261  target->data[18]= q3;
262  return target;
263 }
264 
265 chunk *gpi_jpeg_makeSsSeAhAl(int huffset1, int huffset2, int huffset3)
266 {
267  chunk *target;
268  printf("About to call gpi_jpeg_chunk_new_filled\n");
269  target= gpi_jpeg_chunk_new_filled(14, "\xFF\xDA\x00\x0C\x03\x01\x00\x02"
270  "\x00\x03\x00\x00\x3F\x00");
271  if (!target) return NULL;
272  target->data[6] = huffset1;
273  target->data[8] = huffset2;
274  target->data[10] = huffset3;
275  return target;
276 }
277 
279 {
280  int x;
281  nullpointerabortvoid(table, "Quantization table");
282  for (x=0; x<64; x++)
283  {
284  if (x && ((x%8)==0))
285  {
286  printf("\n");
287  }
288  printf("%3i ", (*table)[x]);
289  }
290  printf("\n");
291 }
292 
293 
295 {
296  chunk *temp;
297  char x,y,z,c;
298  temp = gpi_jpeg_chunk_new(5+64);
299  if (!temp) return NULL;
300  memcpy(temp->data, "\xFF\xDB\x00\x43\x01", 5);
301  temp->data[4]=number;
302  for (c=z=0; z<8; z++)
303  if (z%2)
304  for (y=0,x=z; y<=z; x--,y++)
305  {
306  temp->data[5+c] = (*table)[x+y*8];
307  temp->data[5+63-c++] = (*table)[63-x-y*8];
308  }
309  else
310  for (x=0,y=z; x<=z; x++,y--)
311  {
312  temp->data[5+c] = (*table)[x+y*8];
313  temp->data[5+63-c++] = (*table)[63-x-y*8];
314  }
315  return temp;
316 }
317 
319 {
320  char x,y,z,c;
322  table = (jpeg_quantization_table *)malloc(64);
323  for (c=z=0; z<8; z++)
324  if (z%2)
325  for (y=0,x=z; y<=z; x--,y++)
326  {
327  (*table)[63-x-y*8] = qmarker->data[5+63-c];
328  (*table)[x+y*8] = qmarker->data[5+c++];
329  }
330  else
331  for (x=0,y=z; x<=z; x++,y--)
332  {
333  (*table)[63-x-y*8] = qmarker->data[5+63-c];
334  (*table)[x+y*8] = qmarker->data[5+c++];
335  }
336  return table;
337 }
338 
339 
340 jpeg *gpi_jpeg_header(int width, int height,
341  char vh1, char vh2, char vh3,
342  char q1, char q2, char q3,
343  const jpeg_quantization_table *quant1, const jpeg_quantization_table *quant2,
344  char huffset1, char huffset2, char huffset3,
345  chunk *huff1, chunk *huff2, chunk *huff3, chunk *huff4)
346 {
347  jpeg *temp;
348  temp = gpi_jpeg_new();
352  gpi_jpeg_add_chunk(temp, gpi_jpeg_make_SOFC(width,height, vh1,vh2,vh3, q1,q2,q3));
353  gpi_jpeg_add_chunk(temp, huff1);
354  gpi_jpeg_add_chunk(temp, huff2);
355  gpi_jpeg_add_chunk(temp, huff3);
356  gpi_jpeg_add_chunk(temp, huff4);
357  printf("About to make and add the SsSeAhAl marker\n");
358  gpi_jpeg_add_chunk(temp, gpi_jpeg_makeSsSeAhAl(huffset1, huffset2, huffset3));
359  return temp;
360 }
361 
362 /*#define TESTING_JPEG_C */
363 
364 #ifndef TESTING_JPEG_C
365 char gpi_jpeg_write(CameraFile *file, const char *filename, jpeg *myjpeg)
366 {
367  int x;
368  CHECK_RESULT (gp_file_set_name (file, filename));
370  for (x=0; x<myjpeg->count; x++)
371  CHECK_RESULT (gp_file_append(file, (char*)myjpeg->marker[x]->data, myjpeg->marker[x]->size));
372  return 1;
373 }
374 #endif
375 
376 #ifdef TESTING_JPEG_C
377 /* TEST CODE SECTION */
378 char testdata[] ={
379  0xFF,0xD8, 0xFF,0xE0, 0xff,0xDB, 0xFF,0xC4, 0xFF,0xDA,
380  0xFF,0xC0, 0xff,0xff};
381 
382 jpeg_quantization_table mytable = {
383  2, 3, 4, 5, 6, 7, 8, 9,
384  3, 4, 5, 6, 7, 8, 9, 10,
385  4, 5, 6, 7, 8, 9, 10, 11,
386  5, 6, 7, 8, 9, 10, 11, 12,
387  6, 7, 8, 9, 10, 11, 12, 13,
388  7, 8, 9, 10, 11, 12, 13, 14,
389  8, 9, 10, 11, 12, 13, 14, 15,
390  9, 10, 11, 12, 13, 14, 15, 16};
391 
392 int main()
393 {
394 chunk *picture;
395 jpeg *myjpeg;
396 char id;
397 int location=0,x;
398 printf("Print the test quantization table\n");
400 myjpeg = gpi_jpeg_new();
401 picture = gpi_jpeg_chunk_new(sizeof(testdata));
402 picture->data=testdata;
403 picture->size=sizeof(testdata);
404 printf("testdata size is %i\n",picture->size);
405 gpi_jpeg_chunk_print(picture);
406 printf("Call jpeg_parse!!!!!!!!!!!!!!!!!!!!!!!\n");
407 gpi_jpeg_parse(myjpeg,picture);
408 
409 printf("\nPrint the jpeg table\n");
410 gpi_jpeg_print(myjpeg);
411 printf("\nCall gpi_jpeg_destroy\n");
412 gpi_jpeg_destroy(myjpeg);
413 /* You can't call gpi_jpeg_chunk_destroy because testdata is a constant.
414  * Since picture->data points to it, it would segfault.
415  */
416 free(picture);
417 printf("gpi_jpeg_chunk_new and gpi_jpeg_chunk_destroy tests\n");
418 picture = gpi_jpeg_chunk_new(10);
419 for (x=0; x<10; x++) picture->data[x]=x;
420 for (x=0; x<10; x++) printf("%hX ",picture->data[x]);
421 gpi_jpeg_chunk_destroy(picture);
422 printf("\n");
423 }
424 #endif
gp_file_set_mime_type
int gp_file_set_mime_type(CameraFile *file, const char *mime_type)
Definition: gphoto2-file.c:1013
gpi_jpeg_destroy
void gpi_jpeg_destroy(jpeg *myjpeg)
Definition: jpeg.c:154
gp_file_append
int gp_file_append(CameraFile *file, const char *data, unsigned long int size)
Definition: gphoto2-file.c:205
gpi_jpeg_make_SOFC
chunk * gpi_jpeg_make_SOFC(int width, int height, char vh1, char vh2, char vh3, char q1, char q2, char q3)
Definition: jpeg.c:241
JPEG_MARKERNAMES
const char * JPEG_MARKERNAMES[]
Definition: jpeg.c:49
gpi_jpeg_makeSsSeAhAl
chunk * gpi_jpeg_makeSsSeAhAl(int huffset1, int huffset2, int huffset3)
Definition: jpeg.c:265
nullpointerabort
#define nullpointerabort(pointer, name, val)
Definition: jpeg.c:31
CameraFile
File structure.
gpi_jpeg_chunk_new
chunk * gpi_jpeg_chunk_new(int length)
Definition: jpeg.c:55
number
unsigned char number
Definition: gphoto2-port.c:668
jpeg::marker
struct chunk * marker[20]
Definition: jpeg.h:44
jpeg_quantization_table
char jpeg_quantization_table[64]
Definition: jpeg.h:40
JPEG_MARKERS
const jpegmarker JPEG_MARKERS[]
Definition: jpeg.c:43
gpi_jpeg_print_quantization_table
void gpi_jpeg_print_quantization_table(jpeg_quantization_table *table)
Definition: jpeg.c:278
chunk::data
unsigned char * data
Definition: jpeg.h:37
gp_file_set_name
int gp_file_set_name(CameraFile *file, const char *name)
Definition: gphoto2-file.c:996
gpi_jpeg_findff
char gpi_jpeg_findff(int *location, chunk *picture)
Definition: jpeg.c:101
nullpointerabortvoid
#define nullpointerabortvoid(pointer, name)
Definition: jpeg.c:35
gpi_jpeg_print
void gpi_jpeg_print(jpeg *myjpeg)
Definition: jpeg.c:220
jpeg
Definition: jpeg.h:42
gpi_jpeg_chunk_print
void gpi_jpeg_chunk_print(chunk *mychunk)
Definition: jpeg.c:91
chunk
Definition: jpeg.h:35
gpi_jpeg_chunk_destroy
void gpi_jpeg_chunk_destroy(chunk *mychunk)
Definition: jpeg.c:82
gpi_jpeg_add_marker
void gpi_jpeg_add_marker(jpeg *myjpeg, chunk *picture, int start, int end)
Definition: jpeg.c:163
JPEG_EOI
@ JPEG_EOI
Definition: jpeg.h:32
gpi_jpeg_write
char gpi_jpeg_write(CameraFile *file, const char *filename, jpeg *myjpeg)
Definition: jpeg.c:365
gpi_jpeg_new
jpeg * gpi_jpeg_new()
Definition: jpeg.c:146
chunk::size
int size
Definition: jpeg.h:36
countof
#define countof(array)
Definition: jpeg.c:41
CHECK_RESULT
#define CHECK_RESULT(result)
Definition: jpeg.c:38
JPEG_APPO
@ JPEG_APPO
Definition: jpeg.h:30
JPEG_START
@ JPEG_START
Definition: jpeg.h:30
gpi_jpeg_findactivemarker
char gpi_jpeg_findactivemarker(char *id, int *location, chunk *picture)
Definition: jpeg.c:119
gpi_jpeg_make_start
chunk * gpi_jpeg_make_start()
Definition: jpeg.c:231
gpi_jpeg_parse
void gpi_jpeg_parse(jpeg *myjpeg, chunk *picture)
Definition: jpeg.c:186
gpi_jpeg_add_chunk
void gpi_jpeg_add_chunk(jpeg *myjpeg, chunk *source)
Definition: jpeg.c:178
jpeg::count
int count
Definition: jpeg.h:43
JPEG_HUFFMAN
@ JPEG_HUFFMAN
Definition: jpeg.h:31
JPEG_SOFC0
@ JPEG_SOFC0
Definition: jpeg.h:31
GP_MIME_JPEG
#define GP_MIME_JPEG
Definition: gphoto2-file.h:43
gpi_jpeg_make_quantization
chunk * gpi_jpeg_make_quantization(const jpeg_quantization_table *table, char number)
Definition: jpeg.c:294
JPEG_QUANTIZATION
@ JPEG_QUANTIZATION
Definition: jpeg.h:31
gpi_jpeg_header
jpeg * gpi_jpeg_header(int width, int height, char vh1, char vh2, char vh3, char q1, char q2, char q3, const jpeg_quantization_table *quant1, const jpeg_quantization_table *quant2, char huffset1, char huffset2, char huffset3, chunk *huff1, chunk *huff2, chunk *huff3, chunk *huff4)
Definition: jpeg.c:340
gpi_jpeg_chunk_new_filled
chunk * gpi_jpeg_chunk_new_filled(int length, char *data)
Definition: jpeg.c:70
gpi_jpeg_quantization2table
jpeg_quantization_table * gpi_jpeg_quantization2table(chunk *qmarker)
Definition: jpeg.c:318
JPEG_COMMENT
@ JPEG_COMMENT
Definition: jpeg.h:30
gphoto2-file.h
Abstracted gphoto2 file operations.
gpi_jpeg_markername
char * gpi_jpeg_markername(unsigned int c)
Definition: jpeg.c:131
JPEG_SSSEAHAL
@ JPEG_SSSEAHAL
Definition: jpeg.h:32
jpeg.h
jpegmarker
jpegmarker
Definition: jpeg.h:29