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);
98 f = fopen (path, "wb");
103 written = fwrite (d, 1, size, f);
106 if (written == size) {
114 jpeg_data_save_data (JPEGData *data, unsigned char **d, unsigned int *ds)
116 unsigned int i, eds = 0;
118 unsigned char *ed = NULL;
127 for (*ds = i = 0; i < data->count; i++) {
128 s = data->sections[i];
130 /* Write the marker */
131 CLEANUP_REALLOC (*d, sizeof (char) * (*ds + 2));
132 (*d)[*ds + 0] = 0xff;
133 (*d)[*ds + 1] = s.marker;
137 case JPEG_MARKER_SOI:
138 case JPEG_MARKER_EOI:
140 case JPEG_MARKER_APP1:
141 exif_data_save_data (s.content.app1, &ed, &eds);
143 CLEANUP_REALLOC (*d, sizeof (char) * (*ds + 2));
144 (*d)[*ds + 0] = (eds + 2) >> 8;
145 (*d)[*ds + 1] = (eds + 2) >> 0;
147 CLEANUP_REALLOC (*d, sizeof (char) * (*ds + eds));
148 memcpy (*d + *ds, ed, eds);
153 CLEANUP_REALLOC (*d, sizeof (char) *
154 (*ds + s.content.generic.size + 2));
155 (*d)[*ds + 0] = (s.content.generic.size + 2) >> 8;
156 (*d)[*ds + 1] = (s.content.generic.size + 2) >> 0;
158 memcpy (*d + *ds, s.content.generic.data,
159 s.content.generic.size);
160 *ds += s.content.generic.size;
162 /* In case of SOS, we need to write the data. */
163 if (s.marker == JPEG_MARKER_SOS) {
164 CLEANUP_REALLOC (*d, *ds + data->size);
165 memcpy (*d + *ds, data->data, data->size);
174 jpeg_data_new_from_data (const unsigned char *d,
179 data = jpeg_data_new ();
180 jpeg_data_load_data (data, d, size);
185 jpeg_data_load_data (JPEGData *data, const unsigned char *d,
188 unsigned int i, o, len;
195 for (o = 0; o < size;) {
198 * JPEG sections start with 0xff. The first byte that is
199 * not 0xff is a marker (hopefully).
201 for (i = 0; i < MIN(7, size - o); i++)
202 if (d[o + i] != 0xff)
204 if (!JPEG_IS_MARKER (d[o + i])) {
205 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "jpeg-data",
206 _("Data does not follow JPEG specification."));
211 /* Append this section */
212 jpeg_data_append_section (data);
213 if (!data->count) return;
214 s = &data->sections[data->count - 1];
219 case JPEG_MARKER_SOI:
220 case JPEG_MARKER_EOI:
224 /* Read the length of the section */
225 len = ((d[o] << 8) | d[o + 1]) - 2;
226 if (len > size) { o = size; break; }
228 if (o + len > size) { 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) return;
239 s->content.generic.size = len;
240 memcpy (s->content.generic.data, &d[o], len);
242 /* In case of SOS, image data will follow. */
243 if (s->marker == JPEG_MARKER_SOS) {
244 /* -2 means 'take all but the last 2 bytes which are hoped to be JPEG_MARKER_EOI */
245 data->size = size - 2 - o - len;
246 if (d[o + len + data->size] != 0xFF) {
247 /* A truncated file (i.e. w/o JPEG_MARKER_EOI at the end).
248 Instead of trying to use the last two bytes as marker,
249 touching memory beyond allocated memory and posssibly saving
250 back screwed file, we rather take the rest of the file. */
253 data->data = malloc (
254 sizeof (char) * data->size);
255 if (!data->data) return;
256 memcpy (data->data, d + o + len,
269 jpeg_data_new_from_file (const char *path)
273 data = jpeg_data_new ();
274 jpeg_data_load_file (data, path);
279 jpeg_data_load_file (JPEGData *data, const char *path)
288 f = fopen (path, "rb");
290 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "jpeg-data",
291 _("Path '%s' invalid."), path);
295 /* For now, we read the data into memory. Patches welcome... */
296 fseek (f, 0, SEEK_END);
298 fseek (f, 0, SEEK_SET);
301 EXIF_LOG_NO_MEMORY (data->priv->log, "jpeg-data", size);
305 if (fread (d, 1, size, f) != size) {
308 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "jpeg-data",
309 _("Could not read '%s'."), path);
314 jpeg_data_load_data (data, d, size);
319 jpeg_data_ref (JPEGData *data)
324 data->priv->ref_count++;
328 jpeg_data_unref (JPEGData *data)
334 data->priv->ref_count--;
335 if (!data->priv->ref_count)
336 jpeg_data_free (data);
341 jpeg_data_free (JPEGData *data)
350 for (i = 0; i < data->count; i++) {
351 s = data->sections[i];
353 case JPEG_MARKER_SOI:
354 case JPEG_MARKER_EOI:
356 case JPEG_MARKER_APP1:
357 exif_data_unref (s.content.app1);
360 free (s.content.generic.data);
364 free (data->sections);
371 if (data->priv->log) {
372 exif_log_unref (data->priv->log);
373 data->priv->log = NULL;
382 jpeg_data_dump (JPEGData *data)
391 printf ("Dumping JPEG data (%i bytes of data)...\n", data->size);
392 for (i = 0; i < data->count; i++) {
393 marker = data->sections[i].marker;
394 content = data->sections[i].content;
395 printf ("Section %i (marker 0x%x - %s):\n", i, marker,
396 jpeg_marker_get_name (marker));
397 printf (" Description: %s\n",
398 jpeg_marker_get_description (marker));
400 case JPEG_MARKER_SOI:
401 case JPEG_MARKER_EOI:
403 case JPEG_MARKER_APP1:
404 exif_data_dump (content.app1);
407 printf (" Size: %i\n", content.generic.size);
408 printf (" Unknown content.\n");
415 jpeg_data_get_section (JPEGData *data, JPEGMarker marker)
422 for (i = 0; i < data->count; i++)
423 if (data->sections[i].marker == marker)
424 return (&data->sections[i]);
429 jpeg_data_get_exif_data (JPEGData *data)
431 JPEGSection *section;
436 section = jpeg_data_get_section (data, JPEG_MARKER_APP1);
438 exif_data_ref (section->content.app1);
439 return (section->content.app1);
446 jpeg_data_set_exif_data (JPEGData *data, ExifData *exif_data)
448 JPEGSection *section;
452 section = jpeg_data_get_section (data, JPEG_MARKER_APP1);
454 jpeg_data_append_section (data);
455 if (data->count < 2) return;
456 memmove (&data->sections[2], &data->sections[1],
457 sizeof (JPEGSection) * (data->count - 2));
458 section = &data->sections[1];
460 exif_data_unref (section->content.app1);
462 section->marker = JPEG_MARKER_APP1;
463 section->content.app1 = exif_data;
464 exif_data_ref (exif_data);
468 jpeg_data_log (JPEGData *data, ExifLog *log)
470 if (!data || !data->priv) return;
471 if (data->priv->log) exif_log_unref (data->priv->log);
472 data->priv->log = log;