~ubuntu-branches/ubuntu/edgy/gwenview/edgy

« back to all changes in this revision

Viewing changes to libgvexif/jpeg-data.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2005-12-06 17:59:19 UTC
  • mfrom: (1.1.3 upstream) (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20051206175919-8yv9nfmw0pws6p52
Tags: 1.3.1-0ubuntu1
* Sync with Debian
* Edit kde.mk for .pot generation

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* jpeg-data.c
2
 
 *
3
 
 * Copyright � 2001 Lutz M�ller <lutz@users.sourceforge.net>
4
 
 *
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.
9
 
 *
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.
14
 
 *
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., 59 Temple Place - Suite 330,
18
 
 * Boston, MA 02111-1307, USA.
19
 
 */
20
 
 
21
 
#include "jpeg-data.h"
22
 
 
23
 
#include <stdlib.h>
24
 
#include <stdio.h>
25
 
#include <string.h>
26
 
 
27
 
/* #define DEBUG */
28
 
 
29
 
struct _JPEGDataPrivate
30
 
{
31
 
        unsigned int ref_count;
32
 
};
33
 
 
34
 
JPEGData *
35
 
jpeg_data_new (void)
36
 
{
37
 
        JPEGData *data;
38
 
 
39
 
        data = malloc (sizeof (JPEGData));
40
 
        if (!data)
41
 
                return (NULL);
42
 
        memset (data, 0, sizeof (JPEGData));
43
 
        data->priv = malloc (sizeof (JPEGDataPrivate));
44
 
        if (!data->priv) {
45
 
                free (data);
46
 
                return (NULL);
47
 
        }
48
 
        memset (data->priv, 0, sizeof (JPEGDataPrivate));
49
 
        data->priv->ref_count = 1;
50
 
 
51
 
        return (data);
52
 
}
53
 
 
54
 
static void
55
 
jpeg_data_append_section (JPEGData *data)
56
 
{
57
 
        JPEGSection *s;
58
 
 
59
 
        if (!data->count)
60
 
                s = malloc (sizeof (JPEGSection));
61
 
        else
62
 
                s = realloc (data->sections,
63
 
                             sizeof (JPEGSection) * (data->count + 1));
64
 
        if (!s)
65
 
                return;
66
 
 
67
 
        data->sections = s;
68
 
        data->count++;
69
 
}
70
 
 
71
 
void
72
 
jpeg_data_save_file (JPEGData *data, const char *path)
73
 
{
74
 
        FILE *f;
75
 
        unsigned char *d = NULL;
76
 
        unsigned int size = 0;
77
 
 
78
 
        jpeg_data_save_data (data, &d, &size);
79
 
        if (!d)
80
 
                return;
81
 
 
82
 
        remove (path);
83
 
        f = fopen (path, "wb");
84
 
        if (!f) {
85
 
                free (d);
86
 
                return;
87
 
        }
88
 
        fwrite (d, sizeof (char), size, f);
89
 
        fclose (f);
90
 
        free (d);
91
 
}
92
 
 
93
 
void
94
 
jpeg_data_save_data (JPEGData *data, unsigned char **d, unsigned int *ds)
95
 
{
96
 
        unsigned int i, eds = 0;
97
 
        JPEGSection s;
98
 
        unsigned char *ed = NULL;
99
 
 
100
 
        if (!data)
101
 
                return;
102
 
        if (!d)
103
 
                return;
104
 
        if (!ds)
105
 
                return;
106
 
 
107
 
        for (*ds = i = 0; i < data->count; i++) {
108
 
                s = data->sections[i];
109
 
#ifdef DEBUG
110
 
                printf ("Writing marker 0x%x at position %i...\n",
111
 
                        s.marker, *ds);
112
 
#endif
113
 
 
114
 
                /* Write the marker */
115
 
                *d = realloc (*d, sizeof (char) * (*ds + 2));
116
 
                (*d)[*ds + 0] = 0xff;
117
 
                (*d)[*ds + 1] = s.marker;
118
 
                *ds += 2;
119
 
 
120
 
                switch (s.marker) {
121
 
                case JPEG_MARKER_SOI:
122
 
                case JPEG_MARKER_EOI:
123
 
                        break;
124
 
                case JPEG_MARKER_APP1:
125
 
                        exif_data_save_data (s.content.app1, &ed, &eds);
126
 
                        if (!ed) break;
127
 
                        *d = realloc (*d, sizeof (char) * (*ds + 2));
128
 
                        (*d)[*ds + 0] = (eds + 2) >> 8;
129
 
                        (*d)[*ds + 1] = (eds + 2) >> 0;
130
 
                        *ds += 2;
131
 
                        *d = realloc (*d, sizeof (char) * (*ds + eds));
132
 
                        memcpy (*d + *ds, ed, eds);
133
 
                        *ds += eds;
134
 
                        free (ed);
135
 
                        break;
136
 
                default:
137
 
                        *d = realloc (*d, sizeof (char) *
138
 
                                        (*ds + s.content.generic.size + 2));
139
 
                        (*d)[*ds + 0] = (s.content.generic.size + 2) >> 8;
140
 
                        (*d)[*ds + 1] = (s.content.generic.size + 2) >> 0;
141
 
                        *ds += 2;
142
 
                        memcpy (*d + *ds, s.content.generic.data,
143
 
                                s.content.generic.size);
144
 
                        *ds += s.content.generic.size;
145
 
 
146
 
                        /* In case of SOS, we need to write the data. */
147
 
                        if (s.marker == JPEG_MARKER_SOS) {
148
 
                                *d = realloc (*d, *ds + data->size);
149
 
                                memcpy (*d + *ds, data->data, data->size);
150
 
                                *ds += data->size;
151
 
                        }
152
 
                        break;
153
 
                }
154
 
        }
155
 
}
156
 
 
157
 
JPEGData *
158
 
jpeg_data_new_from_data (const unsigned char *d,
159
 
                         unsigned int size)
160
 
{
161
 
        JPEGData *data;
162
 
 
163
 
        data = jpeg_data_new ();
164
 
        jpeg_data_load_data (data, d, size);
165
 
        return (data);
166
 
}
167
 
 
168
 
void
169
 
jpeg_data_load_data (JPEGData *data, const unsigned char *d,
170
 
                     unsigned int size)
171
 
{
172
 
        unsigned int i, o, len;
173
 
        JPEGSection *s;
174
 
        JPEGMarker marker;
175
 
 
176
 
        if (!data)
177
 
                return;
178
 
        if (!d)
179
 
                return;
180
 
 
181
 
#ifdef DEBUG
182
 
        printf ("Parsing %i bytes...\n", size);
183
 
#endif
184
 
 
185
 
        for (o = 0; o < size;) {
186
 
 
187
 
                /*
188
 
                 * JPEG sections start with 0xff. The first byte that is
189
 
                 * not 0xff is a marker (hopefully).
190
 
                 */
191
 
                for (i = 0; i < 7; i++)
192
 
                        if (d[o + i] != 0xff)
193
 
                                break;
194
 
                if (!JPEG_IS_MARKER (d[o + i]))
195
 
                        return;
196
 
                marker = d[o + i];
197
 
 
198
 
#ifdef DEBUG
199
 
                printf ("Found marker 0x%x ('%s') at %i.\n", marker,
200
 
                        jpeg_marker_get_name (marker), o + i);
201
 
#endif
202
 
 
203
 
                /* Append this section */
204
 
                jpeg_data_append_section (data);
205
 
                s = &data->sections[data->count - 1];
206
 
                s->marker = marker;
207
 
                s->content.generic.data = NULL;
208
 
                o += i + 1;
209
 
 
210
 
                switch (s->marker) {
211
 
                case JPEG_MARKER_SOI:
212
 
                case JPEG_MARKER_EOI:
213
 
                        break;
214
 
                default:
215
 
 
216
 
                        /* Read the length of the section */
217
 
                        len = ((d[o] << 8) | d[o + 1]) - 2;
218
 
                        if (len > size) { o = size; break; }
219
 
                        o += 2;
220
 
                        if (o + len > size) { o = size; break; }
221
 
 
222
 
                        switch (s->marker) {
223
 
                        case JPEG_MARKER_APP1:
224
 
                                s->content.app1 = exif_data_new_from_data (
225
 
                                                        d + o - 4, len + 4);
226
 
                                break;
227
 
                        default:
228
 
                                s->content.generic.size = len;
229
 
                                s->content.generic.data =
230
 
                                                malloc (sizeof (char) * len);
231
 
                                memcpy (s->content.generic.data, &d[o], len);
232
 
 
233
 
                                /* In case of SOS, image data will follow. */
234
 
                                if (s->marker == JPEG_MARKER_SOS) {
235
 
                                        data->size = size - 2 - o - len;
236
 
                                        data->data = malloc (
237
 
                                                sizeof (char) * data->size);
238
 
                                        memcpy (data->data, d + o + len,
239
 
                                                data->size);
240
 
                                        o += data->size;
241
 
                                }
242
 
                                break;
243
 
                        }
244
 
                        o += len;
245
 
                        break;
246
 
                }
247
 
        }
248
 
}
249
 
 
250
 
JPEGData *
251
 
jpeg_data_new_from_file (const char *path)
252
 
{
253
 
        JPEGData *data;
254
 
 
255
 
        data = jpeg_data_new ();
256
 
        jpeg_data_load_file (data, path);
257
 
        return (data);
258
 
}
259
 
 
260
 
void
261
 
jpeg_data_load_file (JPEGData *data, const char *path)
262
 
{
263
 
        FILE *f;
264
 
        unsigned char *d;
265
 
        unsigned int size;
266
 
 
267
 
        if (!data)
268
 
                return;
269
 
        if (!path)
270
 
                return;
271
 
 
272
 
        f = fopen (path, "rb");
273
 
        if (!f)
274
 
                return;
275
 
 
276
 
        /* For now, we read the data into memory. Patches welcome... */
277
 
        fseek (f, 0, SEEK_END);
278
 
        size = ftell (f);
279
 
        fseek (f, 0, SEEK_SET);
280
 
        d = malloc (sizeof (char) * size);
281
 
        if (!d) {
282
 
                fclose (f);
283
 
                return;
284
 
        }
285
 
        if (fread (d, 1, size, f) != size) {
286
 
                free (d);
287
 
                fclose (f);
288
 
                return;
289
 
        }
290
 
        fclose (f);
291
 
 
292
 
        jpeg_data_load_data (data, d, size);
293
 
        free (d);
294
 
}
295
 
 
296
 
void
297
 
jpeg_data_ref (JPEGData *data)
298
 
{
299
 
        if (!data)
300
 
                return;
301
 
 
302
 
        data->priv->ref_count++;
303
 
}
304
 
 
305
 
void
306
 
jpeg_data_unref (JPEGData *data)
307
 
{
308
 
        if (!data)
309
 
                return;
310
 
 
311
 
        data->priv->ref_count--;
312
 
        if (!data->priv->ref_count)
313
 
                jpeg_data_free (data);
314
 
}
315
 
 
316
 
void
317
 
jpeg_data_free (JPEGData *data)
318
 
{
319
 
        unsigned int i;
320
 
        JPEGSection s;
321
 
 
322
 
        if (!data)
323
 
                return;
324
 
 
325
 
        if (data->count) {
326
 
                for (i = 0; i < data->count; i++) {
327
 
                        s = data->sections[i];
328
 
                        switch (s.marker) {
329
 
                        case JPEG_MARKER_SOI:
330
 
                        case JPEG_MARKER_EOI:
331
 
                                break;
332
 
                        case JPEG_MARKER_APP1:
333
 
                                exif_data_unref (s.content.app1);
334
 
                                break;
335
 
                        default:
336
 
                                free (s.content.generic.data);
337
 
                                break;
338
 
                        }
339
 
                }
340
 
                free (data->sections);
341
 
        }
342
 
 
343
 
        if (data->data)
344
 
                free (data->data);
345
 
        free (data->priv);
346
 
        free (data);
347
 
}
348
 
 
349
 
void
350
 
jpeg_data_dump (JPEGData *data)
351
 
{
352
 
        unsigned int i;
353
 
        JPEGContent content;
354
 
        JPEGMarker marker;
355
 
 
356
 
        if (!data)
357
 
                return;
358
 
 
359
 
        printf ("Dumping JPEG data (%i bytes of data)...\n", data->size);
360
 
        for (i = 0; i < data->count; i++) {
361
 
                marker = data->sections[i].marker;
362
 
                content = data->sections[i].content;
363
 
                printf ("Section %i (marker 0x%x - %s):\n", i, marker,
364
 
                        jpeg_marker_get_name (marker));
365
 
                printf ("  Description: %s\n",
366
 
                        jpeg_marker_get_description (marker));
367
 
                switch (marker) {
368
 
                case JPEG_MARKER_SOI:
369
 
                case JPEG_MARKER_EOI:
370
 
                        break;
371
 
                case JPEG_MARKER_APP1:
372
 
                        exif_data_dump (content.app1);
373
 
                        break;
374
 
                default:
375
 
                        printf ("  Size: %i\n", content.generic.size);
376
 
                        printf ("  Unknown content.\n");
377
 
                        break;
378
 
                }
379
 
        }
380
 
}
381
 
 
382
 
static JPEGSection *
383
 
jpeg_data_get_section (JPEGData *data, JPEGMarker marker)
384
 
{
385
 
        unsigned int i;
386
 
 
387
 
        if (!data)
388
 
                return (NULL);
389
 
 
390
 
        for (i = 0; i < data->count; i++)
391
 
                if (data->sections[i].marker == marker)
392
 
                        return (&data->sections[i]);
393
 
        return (NULL);
394
 
}
395
 
 
396
 
ExifData *
397
 
jpeg_data_get_exif_data (JPEGData *data)
398
 
{
399
 
        JPEGSection *section;
400
 
 
401
 
        if (!data)
402
 
                return NULL;
403
 
 
404
 
        section = jpeg_data_get_section (data, JPEG_MARKER_APP1);
405
 
        if (section) {
406
 
                exif_data_ref (section->content.app1);
407
 
                return (section->content.app1);
408
 
        }
409
 
 
410
 
        return (NULL);
411
 
}
412
 
 
413
 
void
414
 
jpeg_data_set_exif_data (JPEGData *data, ExifData *exif_data)
415
 
{
416
 
        JPEGSection *section;
417
 
 
418
 
        section = jpeg_data_get_section (data, JPEG_MARKER_APP1);
419
 
        if (!section) {
420
 
                jpeg_data_append_section (data);
421
 
                memmove (&data->sections[2], &data->sections[1],
422
 
                         sizeof (JPEGSection) * (data->count - 2));
423
 
                section = &data->sections[1];
424
 
        }
425
 
        section->marker = JPEG_MARKER_APP1;
426
 
        section->content.app1 = exif_data;
427
 
        exif_data_ref (exif_data);
428
 
}