move around - flatter.
[profile/ivi/evas.git] / src / modules / loaders / tiff / evas_image_load_tiff.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3
4 #include <stdio.h>
5 #include <tiffio.h>
6
7
8 int evas_image_load_file_head_tiff(Image_Entry *ie, const char *file, const char *key);
9 int evas_image_load_file_data_tiff(Image_Entry *ie, const char *file, const char *key);
10
11 Evas_Image_Load_Func evas_image_load_tiff_func =
12 {
13   evas_image_load_file_head_tiff,
14   evas_image_load_file_data_tiff
15 };
16
17 typedef struct TIFFRGBAImage_Extra TIFFRGBAImage_Extra;
18
19 struct TIFFRGBAImage_Extra {
20    TIFFRGBAImage       rgba;
21    tileContigRoutine   put_contig;
22    tileSeparateRoutine put_separate;
23    Image_Entry        *image;
24    char                pper;
25    uint32              num_pixels;
26    uint32              py;
27 };
28
29 static void put_contig_and_raster(TIFFRGBAImage *, uint32 *,
30                                   uint32, uint32, uint32, uint32, int32,
31                                   int32, unsigned char *);
32 static void put_separate_and_raster(TIFFRGBAImage *, uint32 *, uint32,
33                                     uint32, uint32, uint32, int32,
34                                     int32, unsigned char *,
35                                     unsigned char *, unsigned char *,
36                                     unsigned char *);
37 static void raster(TIFFRGBAImage_Extra * img, uint32 * raster, uint32 x,
38                    uint32 y, uint32 w, uint32 h);
39
40
41 static void
42 put_contig_and_raster(TIFFRGBAImage * img, uint32 * rast,
43                       uint32 x, uint32 y, uint32 w, uint32 h,
44                       int32 fromskew, int32 toskew, unsigned char *cp)
45 {
46    (*(((TIFFRGBAImage_Extra *) img)->put_contig)) (img, rast, x, y, w, h,
47                                                    fromskew, toskew, cp);
48    raster((TIFFRGBAImage_Extra *) img, rast, x, y, w, h);
49 }
50
51 static void
52 put_separate_and_raster(TIFFRGBAImage * img, uint32 * rast,
53                         uint32 x, uint32 y, uint32 w, uint32 h,
54                         int32 fromskew, int32 toskew,
55                         unsigned char *r, unsigned char *g, unsigned char *b,
56                         unsigned char *a)
57 {
58    (*(((TIFFRGBAImage_Extra *) img)->put_separate))
59        (img, rast, x, y, w, h, fromskew, toskew, r, g, b, a);
60    raster((TIFFRGBAImage_Extra *) img, rast, x, y, w, h);
61 }
62
63 /* needs orientation code */
64
65 static void
66 raster(TIFFRGBAImage_Extra * img, uint32 * rast,
67        uint32 x, uint32 y, uint32 w, uint32 h)
68 {
69    int                 image_width, image_height;
70    uint32             *pixel, pixel_value;
71    int                 i, j, dy, rast_offset;
72    DATA32             *buffer_pixel, *buffer = evas_cache_image_pixels(img->image);
73    int                 alpha_premult;
74
75    image_width = img->image->w;
76    image_height = img->image->h;
77
78    dy = h > y ? -1 : y - h;
79
80    /* rast seems to point to the beginning of the last strip processed */
81    /* so you need use negative offsets. Bizzare. Someone please check this */
82    /* I don't understand why, but that seems to be what's going on. */
83    /* libtiff needs better docs! */
84
85    if (img->rgba.alpha == EXTRASAMPLE_UNASSALPHA)
86      alpha_premult = 1;
87    for (i = y, rast_offset = 0; i > dy; i--, rast_offset--)
88      {
89         pixel = rast + (rast_offset * image_width);
90         buffer_pixel = buffer + ((((image_height - 1) - i) * image_width) + x);
91
92         for (j = 0; j < w; j++)
93           {
94              int a, r, g, b;
95
96              pixel_value = (*(pixel++));
97              a = TIFFGetA(pixel_value);
98              r = TIFFGetR(pixel_value);
99              g = TIFFGetG(pixel_value);
100              b = TIFFGetB(pixel_value);
101              if (!alpha_premult && (a < 255))
102                {
103                   r = (r * (a + 1)) >> 8;
104                   g = (g * (a + 1)) >> 8;
105                   b = (b * (a + 1)) >> 8;
106                }
107              (*(buffer_pixel++)) = (a << 24) | (r << 16) | (g << 8) | b;
108           }
109      }
110 }
111
112 int
113 evas_image_load_file_head_tiff(Image_Entry *ie, const char *file, const char *key)
114 {
115    char                txt[1024];
116    TIFFRGBAImage       tiff_image;
117    TIFF               *tif = NULL;
118    FILE               *ffile;
119    int                 fd;
120    uint16              magic_number;
121
122    if (!file)
123       return 0;
124
125    ffile = fopen(file, "rb");
126    if (!ffile)
127       return 0;
128
129    if (fread(&magic_number, sizeof(uint16), 1, ffile) != 1)
130      {
131         fclose(ffile);
132         return 0;
133      }
134    /* Apparently rewind(f) isn't sufficient */
135    fseek(ffile, (long)0, SEEK_SET);
136
137    if ((magic_number != TIFF_BIGENDIAN) /* Checks if actually tiff file */
138        && (magic_number != TIFF_LITTLEENDIAN))
139      {
140         fclose(ffile);
141         return 0;
142      }
143
144    fd = fileno(ffile);
145    fd = dup(fd);
146    lseek(fd, (long)0, SEEK_SET);
147    fclose(ffile);
148
149    tif = TIFFFdOpen(fd, file, "r");
150    if (!tif)
151       return 0;
152
153    strcpy(txt, "Evas Tiff loader: cannot be processed by libtiff");
154    if (!TIFFRGBAImageOK(tif, txt))
155      {
156         TIFFClose(tif);
157         return 0;
158      }
159    strcpy(txt, "Evas Tiff loader: cannot begin reading tiff");
160    if (!TIFFRGBAImageBegin(& tiff_image, tif, 1, txt))
161      {
162         TIFFClose(tif);
163         return 0;
164      }
165
166    if (tiff_image.alpha != EXTRASAMPLE_UNSPECIFIED)
167      ie->flags.alpha = 1;
168    if ((tiff_image.width < 1) || (tiff_image.height < 1) ||
169        (tiff_image.width > 8192) || (tiff_image.height > 8192))
170      {
171         TIFFClose(tif);
172         return 0;
173      }
174    ie->w = tiff_image.width;
175    ie->h = tiff_image.height;
176
177    TIFFClose(tif);
178    return 1;
179 }
180
181 int
182 evas_image_load_file_data_tiff(Image_Entry *ie, const char *file, const char *key)
183 {
184    char                txt[1024];
185    TIFFRGBAImage_Extra rgba_image;
186    TIFF               *tif = NULL;
187    FILE               *ffile;
188    uint32             *rast = NULL;
189    uint32              num_pixels;
190    int                 fd;
191    uint16              magic_number;
192
193    if (!file)
194       return 0;
195
196    ffile = fopen(file, "rb");
197    if (!ffile)
198       return 0;
199
200    fread(&magic_number, sizeof(uint16), 1, ffile);
201    /* Apparently rewind(f) isn't sufficient */
202    fseek(ffile, (long)0, SEEK_SET);
203
204    if ((magic_number != TIFF_BIGENDIAN) /* Checks if actually tiff file */
205        && (magic_number != TIFF_LITTLEENDIAN))
206      {
207         fclose(ffile);
208         return 0;
209      }
210
211    fd = fileno(ffile);
212    fd = dup(fd);
213    lseek(fd, (long)0, SEEK_SET);
214    fclose(ffile);
215
216    tif = TIFFFdOpen(fd, file, "r");
217    if (!tif)
218       return 0;
219
220    strcpy(txt, "Evas Tiff loader: cannot be processed by libtiff");
221    if (!TIFFRGBAImageOK(tif, txt))
222      {
223         TIFFClose(tif);
224         return 0;
225      }
226    strcpy(txt, "Evas Tiff loader: cannot begin reading tiff");
227    if (!TIFFRGBAImageBegin((TIFFRGBAImage *) & rgba_image, tif, 0, txt))
228      {
229         TIFFClose(tif);
230         return 0;
231      }
232    rgba_image.image = ie;
233
234    if (rgba_image.rgba.alpha != EXTRASAMPLE_UNSPECIFIED)
235      ie->flags.alpha = 1;
236    if ((rgba_image.rgba.width != ie->w) ||
237        (rgba_image.rgba.height != ie->h))
238      {
239         TIFFClose(tif);
240         return 0;
241      }
242
243    evas_cache_image_surface_alloc(ie, rgba_image.rgba.width, rgba_image.rgba.height);
244    if (!evas_cache_image_pixels(ie))
245      {
246         TIFFRGBAImageEnd((TIFFRGBAImage *) & rgba_image);
247         TIFFClose(tif);
248
249         return 0;
250      }
251
252    rgba_image.num_pixels = num_pixels = ie->w * ie->h;
253
254    rgba_image.pper = rgba_image.py = 0;
255    rast = (uint32 *) _TIFFmalloc(sizeof(uint32) * num_pixels);
256
257    if (!rast)
258      {
259         fprintf(stderr, "Evas Tiff loader: out of memory\n");
260
261         TIFFRGBAImageEnd((TIFFRGBAImage *) & rgba_image);
262         TIFFClose(tif);
263
264         return 0;
265      }
266
267    if (rgba_image.rgba.put.any == NULL)
268      {
269         fprintf(stderr, "Evas Tiff loader: no put function");
270
271         _TIFFfree(rast);
272         TIFFRGBAImageEnd((TIFFRGBAImage *) & rgba_image);
273         TIFFClose(tif);
274
275         return 0;
276      }
277    else
278      {
279        if (rgba_image.rgba.isContig)
280          {
281             rgba_image.put_contig = rgba_image.rgba.put.contig;
282             rgba_image.rgba.put.contig = put_contig_and_raster;
283          }
284        else
285          {
286             rgba_image.put_separate = rgba_image.rgba.put.separate;
287             rgba_image.rgba.put.separate = put_separate_and_raster;
288          }
289      }
290
291    /*   if (rgba_image.rgba.samplesperpixel == 8)*/
292    if (rgba_image.rgba.bitspersample == 8)
293      {
294         if (!TIFFRGBAImageGet((TIFFRGBAImage *) &rgba_image, rast,
295                               rgba_image.rgba.width, rgba_image.rgba.height))
296           {
297              _TIFFfree(rast);
298              TIFFRGBAImageEnd((TIFFRGBAImage *) & rgba_image);
299              TIFFClose(tif);
300              return 0;
301           }
302      }
303    else
304      {
305         printf("channel bits == %i\n", (int)rgba_image.rgba.samplesperpixel);
306      }
307
308    _TIFFfree(rast);
309
310    TIFFRGBAImageEnd((TIFFRGBAImage *) & rgba_image);
311
312    TIFFClose(tif);
313
314    evas_common_image_set_alpha_sparse(ie);
315    return 1;
316 }
317
318 EAPI int
319 module_open(Evas_Module *em)
320 {
321    if (!em) return 0;
322    em->functions = (void *)(&evas_image_load_tiff_func);
323    return 1;
324 }
325
326 EAPI void
327 module_close(void)
328 {
329
330 }
331
332 EAPI Evas_Module_Api evas_modapi =
333 {
334    EVAS_MODULE_API_VERSION,
335      EVAS_MODULE_TYPE_IMAGE_LOADER,
336      "tiff",
337      "none"
338 };