3 * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA.
22 #include "jpeg-data.h"
27 #include <glib/gi18n.h>
29 /* realloc that cleans up on memory failure and returns to caller */
30 #define CLEANUP_REALLOC(p,s) { \
31 unsigned char *cleanup_ptr = realloc((p),(s)); \
32 if (!cleanup_ptr) { free(p); (p) = NULL; return; } \
36 struct _JPEGDataPrivate
38 unsigned int ref_count;
48 data = malloc (sizeof (JPEGData));
51 memset (data, 0, sizeof (JPEGData));
52 data->priv = malloc (sizeof (JPEGDataPrivate));
57 memset (data->priv, 0, sizeof (JPEGDataPrivate));
58 data->priv->ref_count = 1;
64 jpeg_data_append_section (JPEGData *data)
71 s = malloc (sizeof (JPEGSection));
73 s = realloc (data->sections,
74 sizeof (JPEGSection) * (data->count + 1));
76 EXIF_LOG_NO_MEMORY (data->priv->log, "jpeg-data",
77 sizeof (JPEGSection) * (data->count + 1));
80 memset(s + data->count, 0, sizeof (JPEGSection));
85 /*! jpeg_data_save_file returns 1 on success, 0 on failure */
87 jpeg_data_save_file (JPEGData *data, const char *path)
90 unsigned char *d = NULL;
91 unsigned int size = 0, written;
93 jpeg_data_save_data (data, &d, &size);
97 f = fopen (path, "wb");
102 written = fwrite (d, 1, size, f);
105 if (written == size) {
113 jpeg_data_save_data (JPEGData *data, unsigned char **d, unsigned int *ds)
115 unsigned int i, eds = 0;
117 unsigned char *ed = NULL;
126 for (*ds = i = 0; i < data->count; i++) {
127 s = data->sections[i];
129 /* Write the marker */
130 CLEANUP_REALLOC (*d, sizeof (char) * (*ds + 2));
131 (*d)[*ds + 0] = 0xff;
132 (*d)[*ds + 1] = s.marker;
136 case JPEG_MARKER_SOI:
137 case JPEG_MARKER_EOI:
139 case JPEG_MARKER_APP1:
140 exif_data_save_data (s.content.app1, &ed, &eds);
142 CLEANUP_REALLOC (*d, sizeof (char) * (*ds + 2));
143 (*d)[*ds + 0] = (eds + 2) >> 8;
144 (*d)[*ds + 1] = (eds + 2) >> 0;
146 CLEANUP_REALLOC (*d, sizeof (char) * (*ds + eds));
147 memcpy (*d + *ds, ed, eds);
152 CLEANUP_REALLOC (*d, sizeof (char) *
153 (*ds + s.content.generic.size + 2));
154 (*d)[*ds + 0] = (s.content.generic.size + 2) >> 8;
155 (*d)[*ds + 1] = (s.content.generic.size + 2) >> 0;
157 memcpy (*d + *ds, s.content.generic.data,
158 s.content.generic.size);
159 *ds += s.content.generic.size;
161 /* In case of SOS, we need to write the data. */
162 if (s.marker == JPEG_MARKER_SOS) {
163 CLEANUP_REALLOC (*d, *ds + data->size);
164 memcpy (*d + *ds, data->data, data->size);
173 jpeg_data_new_from_data (const unsigned char *d,
178 data = jpeg_data_new ();
179 jpeg_data_load_data (data, d, size);
184 jpeg_data_load_data (JPEGData *data, const unsigned char *d,
187 unsigned int i, o, len;
194 for (o = 0; o < size;) {
197 * JPEG sections start with 0xff. The first byte that is
198 * not 0xff is a marker (hopefully).
200 for (i = 0; i < MIN(7, size - o); i++)
201 if (d[o + i] != 0xff)
203 if ((i >= size - o) || !JPEG_IS_MARKER (d[o + i])) {
204 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "jpeg-data",
205 _("Data does not follow JPEG specification."));
210 /* Append this section */
211 jpeg_data_append_section (data);
212 if (!data->count) return;
213 s = &data->sections[data->count - 1];
218 case JPEG_MARKER_SOI:
219 case JPEG_MARKER_EOI:
223 /* Read the length of the section */
224 if (2 > size - o) { o = size; break; }
225 len = ((d[o] << 8) | d[o + 1]) - 2;
226 if (len > size) { o = size; break; }
228 if (len > size - o) { o = size; break; }
231 case JPEG_MARKER_APP1:
232 s->content.app1 = exif_data_new_from_data (
236 s->content.generic.data =
237 malloc (sizeof (char) * len);
238 if (!s->content.generic.data) {
239 EXIF_LOG_NO_MEMORY (data->priv->log, "jpeg-data", sizeof (char) * len);
242 s->content.generic.size = len;
243 memcpy (s->content.generic.data, &d[o], len);
245 /* In case of SOS, image data will follow. */
246 if (s->marker == JPEG_MARKER_SOS) {
247 data->size = size - o - len;
248 if (data->size >= 2) {
249 /* -2 means 'take all but the last 2 bytes which are
250 hoped to be JPEG_MARKER_EOI */
252 if (d[o + len + data->size] != 0xFF) {
253 /* A truncated file (i.e. w/o JPEG_MARKER_EOI at the end).
254 Instead of trying to use the last two bytes as marker,
255 touching memory beyond allocated memory and posssibly saving
256 back screwed file, we rather take the rest of the file. */
260 data->data = malloc (
261 sizeof (char) * data->size);
263 EXIF_LOG_NO_MEMORY (data->priv->log, "jpeg-data", sizeof (char) * data->size);
267 memcpy (data->data, d + o + len,
280 jpeg_data_new_from_file (const char *path)
284 data = jpeg_data_new ();
285 jpeg_data_load_file (data, path);
290 jpeg_data_load_file (JPEGData *data, const char *path)
299 f = fopen (path, "rb");
301 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "jpeg-data",
302 _("Path '%s' invalid."), path);
306 /* For now, we read the data into memory. Patches welcome... */
307 fseek (f, 0, SEEK_END);
309 fseek (f, 0, SEEK_SET);
312 EXIF_LOG_NO_MEMORY (data->priv->log, "jpeg-data", size);
316 if (fread (d, 1, size, f) != size) {
319 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "jpeg-data",
320 _("Could not read '%s'."), path);
325 jpeg_data_load_data (data, d, size);
330 jpeg_data_ref (JPEGData *data)
335 data->priv->ref_count++;
339 jpeg_data_unref (JPEGData *data)
345 data->priv->ref_count--;
346 if (!data->priv->ref_count)
347 jpeg_data_free (data);
352 jpeg_data_free (JPEGData *data)
361 for (i = 0; i < data->count; i++) {
362 s = data->sections[i];
364 case JPEG_MARKER_SOI:
365 case JPEG_MARKER_EOI:
367 case JPEG_MARKER_APP1:
368 exif_data_unref (s.content.app1);
371 free (s.content.generic.data);
375 free (data->sections);
382 if (data->priv->log) {
383 exif_log_unref (data->priv->log);
384 data->priv->log = NULL;
393 jpeg_data_dump (JPEGData *data)
402 printf ("Dumping JPEG data (%i bytes of data)...\n", data->size);
403 for (i = 0; i < data->count; i++) {
404 marker = data->sections[i].marker;
405 content = data->sections[i].content;
406 printf ("Section %i (marker 0x%x - %s):\n", i, marker,
407 jpeg_marker_get_name (marker));
408 printf (" Description: %s\n",
409 jpeg_marker_get_description (marker));
411 case JPEG_MARKER_SOI:
412 case JPEG_MARKER_EOI:
414 case JPEG_MARKER_APP1:
415 exif_data_dump (content.app1);
418 printf (" Size: %i\n", content.generic.size);
419 printf (" Unknown content.\n");
426 jpeg_data_get_section (JPEGData *data, JPEGMarker marker)
433 for (i = 0; i < data->count; i++)
434 if (data->sections[i].marker == marker)
435 return (&data->sections[i]);
440 jpeg_data_get_exif_data (JPEGData *data)
442 JPEGSection *section;
447 section = jpeg_data_get_section (data, JPEG_MARKER_APP1);
449 exif_data_ref (section->content.app1);
450 return (section->content.app1);
457 jpeg_data_set_exif_data (JPEGData *data, ExifData *exif_data)
459 JPEGSection *section;
463 section = jpeg_data_get_section (data, JPEG_MARKER_APP1);
465 jpeg_data_append_section (data);
466 if (data->count < 2) return;
467 memmove (&data->sections[2], &data->sections[1],
468 sizeof (JPEGSection) * (data->count - 2));
469 section = &data->sections[1];
471 exif_data_unref (section->content.app1);
473 section->marker = JPEG_MARKER_APP1;
474 section->content.app1 = exif_data;
475 exif_data_ref (exif_data);
479 jpeg_data_log (JPEGData *data, ExifLog *log)
481 if (!data || !data->priv) return;
482 if (data->priv->log) exif_log_unref (data->priv->log);
483 data->priv->log = log;