1 #define _XOPEN_SOURCE 600
2 
3 #ifdef HAVE_CONFIG_H
4 # include <config.h>
5 #endif
6 
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <errno.h>
11 
12 #include <math.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 
18 #ifdef HAVE_NETINET_IN_H
19 # include <netinet/in.h>
20 #endif
21 
22 #include "evas_common_private.h"
23 #include "evas_private.h"
24 
25 typedef struct _PSD_Header PSD_Header;
26 
27 typedef enum _PSD_Mode
28   {
29     PSD_GREYSCALE = 1,
30     PSD_INDEXED = 2,
31     PSD_RGB = 3,
32     PSD_CMYK = 4
33   } PSD_Mode;
34 
35 struct _PSD_Header
36 {
37    unsigned char signature[4];
38    unsigned short version;
39    unsigned char reserved[9];
40    unsigned short channels;
41    unsigned int height;
42    unsigned int width;
43    unsigned short depth;
44 
45    unsigned short channel_num;
46 
47    PSD_Mode mode;
48 };
49 
50 enum {
51   READ_COMPRESSED_SUCCESS,
52   READ_COMPRESSED_ERROR_FILE_CORRUPT,
53   READ_COMPRESSED_ERROR_FILE_READ_ERROR
54 };
55 
56 static Eina_Bool get_compressed_channels_length(PSD_Header *Head,
57                                                 const unsigned char *map, size_t length, size_t *position,
58                                                 unsigned short *rle_table,
59                                                 unsigned int *chanlen);
60 
61 static int
read_ushort(const unsigned char * map,size_t length,size_t * position,unsigned short * ret)62 read_ushort(const unsigned char *map, size_t length, size_t *position, unsigned short *ret)
63 {
64    if (((*position) + 2) > length) return 0;
65    // FIXME: need to check order
66    *ret = (map[(*position) + 0] << 8) | map[(*position) + 1];
67    *position += 2;
68    return 1;
69 }
70 
71 static int
read_uint(const unsigned char * map,size_t length,size_t * position,unsigned int * ret)72 read_uint(const unsigned char *map, size_t length, size_t *position, unsigned int *ret)
73 {
74    if (((*position) + 4) > length) return 0;
75    // FIXME: need to check order
76    *ret = ARGB_JOIN(map[(*position) + 0], map[(*position) + 1], map[(*position) + 2], map[(*position) + 3]);
77    *position += 4;
78    return 1;
79 }
80 
81 static int
read_block(const unsigned char * map,size_t length,size_t * position,void * target,size_t size)82 read_block(const unsigned char *map, size_t length, size_t *position, void *target, size_t size)
83 {
84    if (((*position) + size) > length) return 0;
85    memcpy(target, map + *position, size);
86    *position += size;
87    return 1;
88 }
89 
90 // Internal function used to get the Psd header from the current file.
91 static Eina_Bool
psd_get_header(PSD_Header * header,const unsigned char * map,size_t length,size_t * position)92 psd_get_header(PSD_Header *header, const unsigned char *map, size_t length, size_t *position)
93 {
94    unsigned short tmp;
95 
96 #define CHECK_RET(Call)                         \
97    if (!Call) return EINA_FALSE;
98 
99    CHECK_RET(read_block(map, length, position, header->signature, 4));
100    CHECK_RET(read_ushort(map, length, position, &header->version));
101    CHECK_RET(read_block(map, length, position, header->reserved, 6));
102    CHECK_RET(read_ushort(map, length, position, &header->channels));
103    CHECK_RET(read_uint(map, length, position, &header->height));
104    CHECK_RET(read_uint(map, length, position, &header->width));
105    CHECK_RET(read_ushort(map, length, position, &header->depth));
106 
107    CHECK_RET(read_ushort(map, length, position, &tmp));
108    header->mode = tmp;
109 
110 #undef CHECK_RET
111 
112    return EINA_TRUE;
113 }
114 
115 
116 // Internal function used to check if the HEADER is a valid Psd header.
117 static Eina_Bool
is_psd(PSD_Header * header)118 is_psd(PSD_Header *header)
119 {
120    if (strncmp((char*)header->signature, "8BPS", 4))
121      return EINA_FALSE;
122    if (header->version != 1)
123      return EINA_FALSE;
124    if (header->channels < 1 || header->channels > 24)
125      return EINA_FALSE;
126    if (header->height < 1 || header->width < 1)
127      return EINA_FALSE;
128    if (header->depth != 1 && header->depth != 8 && header->depth != 16)
129      return EINA_FALSE;
130 
131    return EINA_TRUE;
132 }
133 
134 static void *
evas_image_load_file_open_psd(Eina_File * f,Eina_Stringshare * key EINA_UNUSED,Evas_Image_Load_Opts * opts EINA_UNUSED,Evas_Image_Animated * animated EINA_UNUSED,int * error EINA_UNUSED)135 evas_image_load_file_open_psd(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
136 			      Evas_Image_Load_Opts *opts EINA_UNUSED,
137 			      Evas_Image_Animated *animated EINA_UNUSED,
138 			      int *error EINA_UNUSED)
139 {
140    return f;
141 }
142 
143 static void
evas_image_load_file_close_psd(void * loader_data EINA_UNUSED)144 evas_image_load_file_close_psd(void *loader_data EINA_UNUSED)
145 {
146 }
147 
148 static Eina_Bool
evas_image_load_file_head_psd(void * loader_data,Emile_Image_Property * prop,int * error)149 evas_image_load_file_head_psd(void *loader_data,
150 			      Emile_Image_Property *prop,
151 			      int *error)
152 {
153    Eina_File *f = loader_data;
154    void *map;
155    size_t length;
156    size_t position;
157    PSD_Header header;
158    Eina_Bool correct;
159    Eina_Bool r = EINA_FALSE;
160 
161    *error = EVAS_LOAD_ERROR_NONE;
162 
163    map = eina_file_map_all(f, EINA_FILE_RANDOM);
164    length = eina_file_size_get(f);
165    position = 0;
166    if (!map || length < 1)
167      {
168         *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
169 	goto on_error;
170      }
171 
172    correct = psd_get_header(&header, map, length, &position);
173    if (!correct || !is_psd(&header))
174      {
175         *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
176 	goto on_error;
177      }
178 
179    prop->w = header.width;
180    prop->h = header.height;
181    if (header.channels != 3)
182      prop->alpha = 1;
183 
184    r = EINA_TRUE;
185 
186  on_error:
187    eina_file_map_free(f, map);
188    return r;
189 }
190 
191 static unsigned int
read_compressed_channel(const unsigned char * map,size_t length,size_t * position,const unsigned int channel_length EINA_UNUSED,unsigned int size,unsigned char * channel)192 read_compressed_channel(const unsigned char *map, size_t length, size_t *position,
193 			const unsigned int channel_length EINA_UNUSED,
194                         unsigned int size,
195 			unsigned char* channel)
196 {
197    // FIXME: what does channel_length means, and why is it not used
198    unsigned int i;
199    signed char headbyte;
200    unsigned char c;
201 
202 #define CHECK_RET(Call)                                         \
203    if (!Call) return READ_COMPRESSED_ERROR_FILE_READ_ERROR;	\
204 
205    for (i = 0; i < size; )
206      {
207         CHECK_RET(read_block(map, length, position, &headbyte, 1));
208 
209         if (headbyte >= 0)
210           {
211              if (i + headbyte > size)
212                return READ_COMPRESSED_ERROR_FILE_CORRUPT;
213 	     CHECK_RET(read_block(map, length, position, channel + i, headbyte + 1));
214 
215              i += headbyte + 1;
216           }
217         else if (headbyte >= -127)
218           {
219              int run;
220 
221 	     CHECK_RET(read_block(map, length, position, &c, 1));
222 
223              run = c;
224              /* if (run == -1) */
225 	     /*   return READ_COMPRESSED_ERROR_FILE_READ_ERROR; */
226 
227              if (i + (-headbyte + 1) > size)
228                return READ_COMPRESSED_ERROR_FILE_CORRUPT;
229 
230              memset(channel + i, run, -headbyte + 1);
231              i += -headbyte + 1;
232           }
233      }
234 
235 #undef CHECK_RET
236 
237    return READ_COMPRESSED_SUCCESS;
238 }
239 
240 
241 static Eina_Bool
psd_get_data(PSD_Header * head,const unsigned char * map,size_t length,size_t * position,unsigned char * buffer,Eina_Bool compressed,int * error)242 psd_get_data(PSD_Header *head,
243              const unsigned char *map, size_t length, size_t *position,
244 	     unsigned char *buffer, Eina_Bool compressed,
245 	     int *error)
246 {
247    unsigned int c, x, y, numchan, bps, bpc, bpp;
248    unsigned int pixels_count;
249    unsigned char *channel = NULL;
250    unsigned char *data = NULL;
251 
252    // Added 01-07-2009: This is needed to correctly load greyscale and
253    //  paletted images.
254    switch (head->mode)
255      {
256       case PSD_GREYSCALE:
257       case PSD_INDEXED:
258          numchan = 1;
259          break;
260       default:
261          numchan = 3;
262      }
263 
264    bpp = head->channels;
265    bpc = head->depth / 8;
266    pixels_count = head->width * head->height;
267 
268    data = malloc(sizeof (unsigned char) * pixels_count * bpp);
269    if (!data) return EINA_FALSE;
270 
271    channel = malloc(sizeof (unsigned char) * pixels_count * bpc);
272    if (!channel)
273      {
274         free(data);
275         return EINA_FALSE;
276      }
277 
278    bps = head->width * head->channels * bpc;
279    // @TODO: Add support for this in, though I have yet to run across a .psd
280    //	file that uses this.
281    if (compressed && bpc == 2)
282      {
283         free(data);
284 	free(channel);
285         *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
286         return EINA_FALSE;
287      }
288 
289 #define CHECK_RET(Call)                         \
290    if (!Call)                                   \
291      {						\
292         free(data);				\
293         free(channel);				\
294         return EINA_FALSE;			\
295      }
296 
297    if (!compressed)
298      {
299         if (bpc == 1)
300           {
301              for (c = 0; c < numchan; c++)
302                {
303                   unsigned char *tmp = channel;
304 
305                   CHECK_RET(read_block(map, length, position, tmp, pixels_count));
306 
307                   for (y = 0; y < head->height * bps; y += bps)
308                     {
309                        for (x = 0; x < bps; x += bpp, tmp++)
310                          {
311                             data[y + x + c] = *tmp;
312                          }
313                     }
314                }
315 
316              // Accumulate any remaining channels into a single alpha channel
317              //@TODO: This needs to be changed for greyscale images.
318              for (; c < head->channels; c++)
319                {
320                   unsigned char *tmp = channel;
321 
322                   CHECK_RET(read_block(map, length, position, channel, pixels_count));
323 
324                   for (y = 0; y < head->height * bps; y += bps)
325                     {
326                        for (x = 0; x < bps; x += bpp, tmp++)
327                          {
328                             unsigned short newval;
329 
330                             // previous formula was : (old / 255 * new / 255) * 255
331                             newval = (*tmp) * data[y + x + 3];
332 
333                             data[y + x + 3] = newval >> 8;
334                          }
335                     }
336                }
337           }
338         else
339           {
340              int bps2;
341 
342              bps2 = bps / 2;
343 
344              // iCurImage->Bpc == 2
345              for (c = 0; c < numchan; c++)
346                {
347                   unsigned short *shortptr = (unsigned short*) channel;
348 
349                   CHECK_RET(read_block(map, length, position, channel, pixels_count * 2));
350 
351                   for (y = 0; y < head->height * bps2; y += bps2)
352                     {
353                        for (x = 0; x < (unsigned int)bps2; x += bpp, shortptr++)
354                          {
355                             ((unsigned short*)data)[y + x + c] = *shortptr;
356                          }
357                     }
358                }
359 
360              // Accumulate any remaining channels into a single alpha channel
361              //@TODO: This needs to be changed for greyscale images.
362              for (; c < head->channels; c++)
363                {
364 		  unsigned short *shortptr = (unsigned short*) channel;
365 
366 		  CHECK_RET(read_block(map, length, position, channel, pixels_count * 2));
367 
368 		  for (y = 0; y < head->height * bps2; y += bps2)
369                     {
370                        for (x = 0; x < (unsigned int)bps2; x += bpp, shortptr++)
371                          {
372                             unsigned int newval;
373 
374                             newval = *shortptr * ((unsigned short*)data)[y + x + 3];
375 
376                             ((unsigned short*)data)[y + x + 3] = newval >> 16;
377                          }
378                     }
379                }
380           }
381      }
382    else
383      {
384         unsigned short *rle_table;
385 	unsigned int *chanlen;
386 
387 	rle_table = alloca(head->height * head->channel_num * sizeof (unsigned short));
388 	chanlen = alloca(head->channel_num * sizeof (unsigned int));
389         if (!get_compressed_channels_length(head, map, length, position, rle_table, chanlen))
390 	  goto file_read_error;
391 
392         for (c = 0; c < numchan; c++)
393           {
394 	     unsigned char *tmp = channel;
395 	     int err;
396 
397 	     err = read_compressed_channel(map, length, position,
398 					   chanlen[c],
399 					   pixels_count,
400 					   channel);
401              if (err == READ_COMPRESSED_ERROR_FILE_CORRUPT)
402                goto file_corrupt;
403              else if (err == READ_COMPRESSED_ERROR_FILE_READ_ERROR)
404                goto file_read_error;
405 
406              for (y = 0; y < head->height * bps; y += bps)
407                {
408 		  for (x = 0; x < bps; x += bpp, tmp++)
409                     {
410                        data[y + x + c] = *tmp;
411                     }
412                }
413           }
414 
415         // Initialize the alpha channel to solid
416         //@TODO: This needs to be changed for greyscale images.
417         if (head->channels >= 4)
418           {
419 	     for (y = 0; y < head->height * bps; y += bps)
420                {
421                   for (x = 0; x < bps; x += bpp)
422 		    {
423                        data[y + x + 3] = 255;
424 		    }
425                }
426 
427              for (; c < head->channels; c++)
428                {
429 		  unsigned char *tmp = channel;
430 		  int err;
431 
432                   err = read_compressed_channel(map, length, position,
433 						chanlen[c],
434 						pixels_count,
435 						channel);
436                   if (err == READ_COMPRESSED_ERROR_FILE_CORRUPT)
437                     goto file_corrupt;
438                   else if (err == READ_COMPRESSED_ERROR_FILE_READ_ERROR)
439                     goto file_read_error;
440 
441                   for (y = 0; y < head->height * bps; y += bps)
442                     {
443 		       for (x = 0; x < bps; x += bpp, tmp++)
444                          {
445 			    unsigned short newval;
446 
447 			    newval = *tmp * data[y + x + 3];
448 
449 			    data[y + x + 3] = newval >> 8;
450                          }
451                     }
452                }
453           }
454      }
455 
456    if (bpp == 3)
457      {
458         for (x = 0; x < pixels_count; x++)
459           {
460              buffer[x * 4 + 0] = data[x * 3 + 2];
461              buffer[x * 4 + 1] = data[x * 3 + 1];
462              buffer[x * 4 + 2] = data[x * 3 + 0];
463              buffer[x * 4 + 3] = 255;
464           }
465      }
466    else
467      {
468         // BRGA to RGBA
469         for (x= 0; x < pixels_count; x++)
470           {
471              buffer[x * 4 + 0] = data[x * 4 + 2];
472              buffer[x * 4 + 1] = data[x * 4 + 1];
473              buffer[x * 4 + 2] = data[x * 4 + 0];
474              buffer[x * 4 + 3] = data[x * 4 + 3];
475           }
476      }
477 
478    free(channel);
479    free(data);
480    return EINA_TRUE;
481 
482 #undef CHECK_RET
483 
484  file_corrupt:
485    *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
486 
487  file_read_error:
488    free(channel);
489    free(data);
490 
491    return EINA_FALSE;
492 }
493 
494 
495 static Eina_Bool
get_single_channel(PSD_Header * head,const unsigned char * map,size_t length,size_t * position,unsigned char * buffer,Eina_Bool compressed)496 get_single_channel(PSD_Header *head,
497 		   const unsigned char *map, size_t length, size_t *position,
498 		   unsigned char *buffer,
499 		   Eina_Bool compressed)
500 {
501    unsigned int i, bpc;
502    signed char headbyte;
503    int c;
504    int pixels_count;
505 
506    bpc = (head->depth / 8);
507    pixels_count = head->width * head->height;
508 
509 #define CHECK_RET(Call)                  \
510    if (!Call) return EINA_FALSE;
511 
512    if (!compressed)
513      {
514         if (bpc == 1)
515           {
516              CHECK_RET(read_block(map, length, position, buffer, pixels_count));
517           }
518         else
519           {  // Bpc == 2
520              CHECK_RET(read_block(map, length, position, buffer, pixels_count * 2));
521           }
522      }
523    else
524      {
525         for (i = 0; i < (unsigned int)pixels_count; )
526           {
527              CHECK_RET(read_block(map, length, position, &headbyte, 1));
528 
529              if (headbyte >= 0)
530                {  //  && HeadByte <= 127
531                   CHECK_RET(read_block(map, length, position, buffer + i, headbyte + 1));
532 
533                   i += headbyte + 1;
534                }
535              if (headbyte >= -127 && headbyte <= -1)
536                {
537                   int run;
538 
539                   CHECK_RET(read_block(map, length, position, &c, 1));
540 
541                   run = c;
542                   if (run == -1) return EINA_FALSE;
543 
544                   memset(buffer + i, run, -headbyte + 1);
545                   i += -headbyte + 1;
546                }
547           }
548      }
549 
550 #undef CHECK_RET
551 
552    return EINA_TRUE;
553 }
554 
555 static Eina_Bool
read_psd_grey(void * pixels,PSD_Header * head,const unsigned char * map,size_t length,size_t * position,int * error)556 read_psd_grey(void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error)
557 {
558    unsigned int color_mode, resource_size, misc_info;
559    unsigned short compressed;
560 
561    *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
562 
563 #define CHECK_RET(Call)                  \
564    if (!Call) return EINA_FALSE;
565 
566    CHECK_RET(read_uint(map, length, position, &color_mode));
567    // Skip over the 'color mode data section'
568    *position += color_mode;
569    if ((*position) >= length) return EINA_FALSE;
570 
571    CHECK_RET(read_uint(map, length, position, &resource_size));
572    // Read the 'image resources section'
573    *position += resource_size;
574    if ((*position) >= length) return EINA_FALSE;
575 
576    CHECK_RET(read_uint(map, length, position, &misc_info));
577    *position += misc_info;
578    if ((*position) >= length) return EINA_FALSE;
579 
580    CHECK_RET(read_ushort(map, length, position, &compressed));
581    if (compressed != 0) compressed = EINA_TRUE;
582 
583    head->channel_num = head->channels;
584    // Temporary to read only one channel...some greyscale .psd files have 2.
585    head->channels = 1;
586 
587    switch (head->depth)
588      {
589       case 8:
590       case 16:
591          break;
592       default:
593          *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
594          return EINA_FALSE;
595      }
596 
597    if (!psd_get_data(head, map, length, position, pixels, compressed, error))
598      goto cleanup_error;
599 
600    return EINA_TRUE;
601 
602 #undef CHECK_RET
603 
604  cleanup_error:
605    return EINA_FALSE;
606 }
607 
608 
609 static Eina_Bool
read_psd_indexed(void * pixels,PSD_Header * head,const unsigned char * map,size_t length,size_t * position,int * error)610 read_psd_indexed(void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error)
611 {
612    unsigned int color_mode, resource_size, misc_info;
613    unsigned short compressed;
614 
615    *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
616 
617 #define CHECK_RET(Call)                  \
618    if (!(Call)) return EINA_FALSE;
619 
620    CHECK_RET(read_uint(map, length, position, &color_mode));
621    CHECK_RET(!(color_mode % 3));
622    /*
623      Palette = (unsigned char*)malloc(Colormode);
624      if (Palette == NULL)
625      return EINA_FALSE;
626      if (fread(&Palette, 1, Colormode, file) != Colormode)
627      goto cleanup_error;
628    */
629    // Skip over the 'color mode data section'
630    *position += color_mode;
631    if ((*position) >= length) return EINA_FALSE;
632 
633    // Read the 'image resources section'
634    CHECK_RET(read_uint(map, length, position, &resource_size));
635    *position += resource_size;
636    if ((*position) >= length) return EINA_FALSE;
637 
638    CHECK_RET(read_uint(map, length, position, &misc_info));
639    *position += misc_info;
640    if ((*position) >= length) return EINA_FALSE;
641 
642    CHECK_RET(read_ushort(map, length, position, &compressed));
643    if (compressed != 0) compressed = EINA_TRUE;
644 
645    if (head->channels != 1 || head->depth != 8)
646      {
647         *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
648         return EINA_FALSE;
649      }
650    head->channel_num = head->channels;
651 
652    if (!psd_get_data(head, map, length, position, pixels, compressed, error))
653      return EINA_FALSE;
654    return EINA_TRUE;
655 
656 #undef CHECK_RET
657 }
658 
659 static Eina_Bool
read_psd_rgb(void * pixels,PSD_Header * head,const unsigned char * map,size_t length,size_t * position,int * error)660 read_psd_rgb(void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error)
661 {
662    unsigned int color_mode, resource_size, misc_info;
663    unsigned short compressed;
664 
665 #define CHECK_RET(Call)                  \
666    if (!Call) return EINA_FALSE;
667 
668    CHECK_RET(read_uint(map, length, position, &color_mode));
669    // Skip over the 'color mode data section'
670    *position += color_mode;
671    if ((*position) >= length) return EINA_FALSE;
672 
673    // Read the 'image resources section'
674    CHECK_RET(read_uint(map, length, position, &resource_size));
675    *position += resource_size;
676    if ((*position) >= length) return EINA_FALSE;
677 
678    CHECK_RET(read_uint(map, length, position, &misc_info));
679    *position += misc_info;
680    if ((*position) >= length) return EINA_FALSE;
681 
682    CHECK_RET(read_ushort(map, length, position, &compressed));
683    if (compressed != 0) compressed = EINA_TRUE;
684 
685    head->channel_num = head->channels;
686 
687    switch (head->depth)
688      {
689       case 8:
690       case 16:
691          break;
692       default:
693          *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
694          return EINA_FALSE;
695      }
696 
697    if (!psd_get_data(head, map, length, position, pixels, compressed, error))
698      return EINA_FALSE;
699 
700    return EINA_TRUE;
701 
702 #undef CHECK_RET
703 }
704 
705 static Eina_Bool
read_psd_cmyk(Emile_Image_Property * prop,void * pixels,PSD_Header * head,const unsigned char * map,size_t length,size_t * position,int * error)706 read_psd_cmyk(Emile_Image_Property *prop, void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error)
707 {
708    unsigned int color_mode, resource_size, misc_info, size, j, data_size;
709    unsigned short compressed;
710    unsigned int format, type;
711    unsigned char *kchannel = NULL;
712    Eina_Bool r = EINA_FALSE;
713 
714    *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
715 
716 #define CHECK_RET(Call)                  \
717    if (!Call) return EINA_FALSE;
718 
719    CHECK_RET(read_uint(map, length, position, &color_mode));
720    // Skip over the 'color mode data section'
721    *position += color_mode;
722    if ((*position) >= length) return EINA_FALSE;
723 
724    CHECK_RET(read_uint(map, length, position, &resource_size));
725    // Read the 'image resources section'
726    *position += resource_size;
727    if ((*position) >= length) return EINA_FALSE;
728 
729    CHECK_RET(read_uint(map, length, position, &misc_info));
730    *position += misc_info;
731    if ((*position) >= length) return EINA_FALSE;
732 
733    CHECK_RET(read_ushort(map, length, position, &compressed));
734    if (compressed != 0) compressed = EINA_TRUE;
735 
736    switch (head->channels)
737      {
738       case 4:
739          format = 0x1907;
740          head->channel_num = 4;
741          head->channels = 3;
742          break;
743       case 5:
744          format = 0x1908;
745          head->channel_num = 5;
746          head->channels = 4;
747          break;
748       default:
749          *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
750          return EINA_FALSE;
751      }
752 
753    switch (head->depth)
754      {
755       case 8:
756          type = 1;
757          break;
758       case 16:
759          type = 2;
760          break;
761       default:
762          *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
763          return EINA_FALSE;
764      }
765 
766    if (!psd_get_data(head, map, length, position, pixels, compressed, error))
767      goto cleanup_error;
768 
769    size = type * prop->w * prop->h;
770    kchannel = malloc(size);
771    if (kchannel == NULL)
772      goto cleanup_error;
773    if (!get_single_channel(head, map, length, position, kchannel, compressed))
774      goto cleanup_error;
775 
776    data_size = head->channels * type * prop->w * prop->h;
777    if (format == 0x1907)
778      {
779         unsigned char *tmp = pixels;
780         const unsigned char *limit = tmp + data_size;
781 
782         for (j = 0; tmp < limit; tmp++, j++)
783           {
784              int k;
785 
786              for (k = 0; k < 3; k++)
787                *tmp = (*tmp * kchannel[j]) >> 8;
788 
789              // FIXME: tmp[i+3] = 255;
790           }
791      }
792    else
793      {  // RGBA
794         unsigned char *tmp = pixels;
795         const unsigned char *limit = tmp + data_size;
796 
797         // The KChannel array really holds the alpha channel on this one.
798         for (j = 0; tmp < limit; tmp += 4, j++)
799           {
800              tmp[0] = (tmp[0] * tmp[3]) >> 8;
801              tmp[1] = (tmp[1] * tmp[3]) >> 8;
802              tmp[2] = (tmp[2] * tmp[3]) >> 8;
803              tmp[3] = kchannel[j];  // Swap 'K' with alpha channel.
804           }
805      }
806 
807    r = EINA_TRUE;
808 
809  cleanup_error:
810    free(kchannel);
811    return r;
812 }
813 
814 static Eina_Bool
evas_image_load_file_data_psd(void * loader_data,Emile_Image_Property * prop,void * pixels,int * error)815 evas_image_load_file_data_psd(void *loader_data,
816 			      Emile_Image_Property *prop,
817 			      void *pixels,
818 			      int *error)
819 {
820    Eina_File *f = loader_data;
821 
822    void *map;
823    size_t length;
824    size_t position;
825    PSD_Header header;
826    Eina_Bool bpsd = EINA_FALSE;
827 
828    map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
829    length = eina_file_size_get(f);
830    position = 0;
831    *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
832    if (!map || length < 1)
833      goto on_error;
834 
835    *error = EVAS_LOAD_ERROR_GENERIC;
836    if (!psd_get_header(&header, map, length, &position) || !is_psd(&header))
837      goto on_error;
838 
839    if (header.width != prop->w ||
840        header.height != prop->h)
841      goto on_error;
842 
843    *error = EVAS_LOAD_ERROR_NONE;
844 
845    switch (header.mode)
846      {
847       case PSD_GREYSCALE:  // Greyscale
848          bpsd = read_psd_grey(pixels, &header, map, length, &position, error);
849          break;
850       case PSD_INDEXED:  // Indexed
851          bpsd = read_psd_indexed(pixels, &header, map, length, &position, error);
852          break;
853       case PSD_RGB:  // RGB
854          bpsd = read_psd_rgb(pixels, &header, map, length, &position, error);
855 	 prop->premul = EINA_TRUE;
856          break;
857       case PSD_CMYK:  // CMYK
858          bpsd = read_psd_cmyk(prop, pixels, &header, map, length, &position, error);
859          prop->premul = EINA_TRUE;
860          break;
861       default :
862          *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
863          bpsd = EINA_FALSE;
864      }
865 
866  on_error:
867    if (map) eina_file_map_free(f, map);
868 
869    return bpsd;
870 }
871 
872 static Eina_Bool
get_compressed_channels_length(PSD_Header * head,const unsigned char * map,size_t length,size_t * position,unsigned short * rle_table,unsigned int * chanlen)873 get_compressed_channels_length(PSD_Header *head,
874                                const unsigned char *map, size_t length, size_t *position,
875 			       unsigned short *rle_table,
876 			       unsigned int *chanlen)
877 {
878    unsigned int j;
879    unsigned int c;
880 
881    if (!read_block(map, length, position, rle_table,
882                    sizeof (unsigned short) * head->height * head->channel_num))
883      return EINA_FALSE;
884 
885    memset(chanlen, 0, head->channel_num * sizeof(unsigned int));
886    for (c = 0; c < head->channel_num; c++)
887      {
888         unsigned int i;
889 
890         j = c * head->height;
891         for (i = 0; i < head->height; i++)
892           {
893 	     chanlen[c] += rle_table[i + j];
894           }
895      }
896 
897    return EINA_TRUE;
898 }
899 
900 static const Evas_Image_Load_Func evas_image_load_psd_func = {
901   EVAS_IMAGE_LOAD_VERSION,
902   evas_image_load_file_open_psd,
903   evas_image_load_file_close_psd,
904   (void*) evas_image_load_file_head_psd,
905   NULL,
906   (void*) evas_image_load_file_data_psd,
907   NULL,
908   EINA_TRUE,
909   EINA_FALSE
910 };
911 
912 static int
module_open(Evas_Module * em)913 module_open(Evas_Module *em)
914 {
915    if (!em) return 0;
916    em->functions = (void *)(&evas_image_load_psd_func);
917    return 1;
918 }
919 
920 static void
module_close(Evas_Module * em EINA_UNUSED)921 module_close(Evas_Module *em EINA_UNUSED)
922 {
923 }
924 
925 static Evas_Module_Api evas_modapi =
926   {
927     EVAS_MODULE_API_VERSION,
928     "psd",
929     "none",
930     {
931       module_open,
932       module_close
933     }
934   };
935 
936 EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, psd);
937 
938 
939 #ifndef EVAS_STATIC_BUILD_PSD
940 EVAS_EINA_MODULE_DEFINE(image_loader, psd);
941 #endif
942