2001-12-21 Lutz Müller <urc8@rz.uni-karlsruhe.de>
[platform/upstream/libexif.git] / libexif / exif-data.c
1 /* exif-data.c
2  *
3  * Copyright (C) 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 #include <config.h>
21 #include "exif-data.h"
22
23 #include <stdlib.h>
24 #include <stdio.h>
25
26 #include <libjpeg/jpeg-marker.h>
27
28 static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
29
30 struct _ExifDataPrivate
31 {
32         ExifByteOrder order;
33
34         unsigned int ref_count;
35 };
36
37 ExifData *
38 exif_data_new (void)
39 {
40         ExifData *data;
41
42         data = malloc (sizeof (ExifData));
43         if (!data)
44                 return (NULL);
45         memset (data, 0, sizeof (ExifData));
46         data->priv = malloc (sizeof (ExifDataPrivate));
47         if (!data->priv) {
48                 free (data);
49                 return (NULL);
50         }
51         memset (data->priv, 0, sizeof (ExifDataPrivate));
52         data->priv->ref_count = 1;
53
54         data->content = exif_content_new ();
55         if (!data->content) {
56                 exif_data_free (data);
57                 return (NULL);
58         }
59
60         return (data);
61 }
62
63 ExifData *
64 exif_data_new_from_data (const unsigned char *data, unsigned int size)
65 {
66         ExifData *edata;
67         unsigned int o, len;
68         ExifByteOrder order;
69
70         if (!data)
71                 return (NULL);
72
73         /* Search the exif marker */
74         for (o = 0; o < size; o++)
75                 if (data[o] == JPEG_MARKER_APP1)
76                         break;
77         if (o == size)
78                 return (NULL);
79         o++;
80         data += o;
81         size -= o;
82
83         /* Size of exif data? */
84         if (size < 2)
85                 return (NULL);
86         len = (data[0] << 8) | data[1];
87
88         /*
89          * Verify the exif header
90          * (offset 2, length 6).
91          */
92         if (size < 2 + 6)
93                 return (NULL);
94         if (memcmp (data + 2, ExifHeader, 6))
95                 return (NULL);
96
97         /*
98          * Byte order (offset 8, length 2) plus two values for
99          * correctness check (offset 10, length 2 and 4).
100          */
101         if (size < 16)
102                 return (NULL);
103         if (!memcmp (data + 8, "II", 2))
104                 order = EXIF_BYTE_ORDER_INTEL;
105         else if (!memcmp (data + 8, "MM", 2))
106                 order = EXIF_BYTE_ORDER_MOTOROLA;
107         else
108                 return (NULL);
109
110         edata = exif_data_new ();
111         edata->priv->order = order;
112
113         /* Parse the actual exif data (offset 16) */
114         exif_content_parse (edata->content, data + 8, size - 8, 8, order);
115
116         return (edata);
117 }
118
119 ExifData *
120 exif_data_new_from_file (const char *path)
121 {
122         FILE *f;
123         unsigned int size;
124         unsigned char *data;
125         ExifData *edata;
126
127         f = fopen (path, "r");
128         if (!f)
129                 return (NULL);
130
131         /* For now, we read the data into memory. Patches welcome... */
132         fseek (f, 0, SEEK_END);
133         size = ftell (f);
134         fseek (f, 0, SEEK_SET);
135         data = malloc (sizeof (char) * size);
136         if (!data)
137                 return (NULL);
138         if (fread (data, 1, size, f) != size) {
139                 free (data);
140                 return (NULL);
141         }
142
143         edata = exif_data_new_from_data (data, size);
144         free (data);
145
146         fclose (f);
147
148         return (edata);
149 }
150
151 void
152 exif_data_ref (ExifData *data)
153 {
154         if (!data)
155                 return;
156
157         data->priv->ref_count++;
158 }
159
160 void
161 exif_data_unref (ExifData *data)
162 {
163         if (!data)
164                 return;
165
166         data->priv->ref_count--;
167         if (!data->priv->ref_count)
168                 exif_data_free (data);
169 }
170
171 void
172 exif_data_free (ExifData *data)
173 {
174         if (data->content)
175                 exif_content_unref (data->content);
176         free (data->priv);
177         free (data);
178 }
179
180 void
181 exif_data_dump (ExifData *data)
182 {
183         if (!data)
184                 return;
185
186         printf ("Dumping EXIF data...\n");
187         exif_content_dump (data->content, 0);
188 }