2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * Derived from Enlightenment file evas_image_load_ico.c[1] which is licensed
19 * under the BSD 2-clause license[2] reproduced below.
21 * [1][http://web.archive.org/web/20141201151111/http://git.enlightenment.org/core/efl.git/tree/src/modules/evas/loaders/ico/evas_image_load_ico.c]
22 * [2][http://web.archive.org/web/20140717012400/https://git.enlightenment.org/core/efl.git/about/]
24 * Copyright (C) 2002-2012 Carsten Haitzler, Dan Sinclair, Mike Blumenkrantz,
25 * Samsung Electronics and various contributors (see AUTHORS)
27 * All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
38 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
39 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
40 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
41 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
42 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
44 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
45 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
46 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
47 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 #include "loader-ico.h"
55 #include <dali/public-api/common/dali-vector.h>
58 #include <dali/integration-api/debug.h>
59 #include <dali/integration-api/bitmap.h>
60 #include <dali/public-api/images/image-attributes.h>
64 using Integration::Bitmap;
65 using Dali::Integration::PixelBuffer;
67 namespace TizenPlatform
72 //reserved 2 bytes + type 2 bytes + count 2 bytes + count * 16 bytes
73 const unsigned char ICO_FILE_HEADER = 22;
74 // info header 40 bytes = size 4 bytes + width 4 bytes + height 4 bytes + planes 2 bytes + bitcount 2 bytes
75 // + compression 4 bytes + imagesize 4 bytes + xpixelsPerM 4 bytes + ypixelsPerM 4 bytes + colorsUsed 4 bytes + colorImportant 4 bytes
76 // besides, there are rgba color data = numberOfColors * 4 bytes
77 const unsigned char ICO_IMAGE_INFO_HEADER = 40;
79 typedef unsigned char DATA8;
80 #define A_VAL(p) (((DATA8 *)(p))[3])
82 #define RGB_JOIN(r,g,b) \
83 (((r) << 16) + ((g) << 8) + (b))
85 #define ARGB_JOIN(a,r,g,b) \
86 (((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
87 #define IMG_TOO_BIG(w, h) \
88 ((((unsigned long long)w) * ((unsigned long long)h)) >= \
89 ((1ULL << (29 * (sizeof(void *) / 4))) - 2048))
91 bool read_ushort(unsigned char *map, size_t length, size_t *position, unsigned short *ret)
95 if (*position + 2 > length)
99 b[0] = map[(*position)++];
100 b[1] = map[(*position)++];
101 *ret = (b[1] << 8) | b[0];
105 bool read_uint(unsigned char *map, size_t length, size_t *position, unsigned int *ret)
110 if (*position + 4 > length)
114 for (i = 0; i < 4; i++)
116 b[i] = map[(*position)++];
118 *ret = ARGB_JOIN(b[3], b[2], b[1], b[0]);
122 bool read_uchar(unsigned char *map, size_t length, size_t *position, unsigned char *ret)
124 if (*position + 1 > length)
128 *ret = map[(*position)++];
132 bool read_mem(unsigned char *map, size_t length, size_t *position, void *buffer, int size)
134 if (*position + size > length)
138 memcpy(buffer, map + *position, size);
164 unsigned int bmoffset, bmsize;
167 bool LoadIcoHeaderHelper( FILE* fp,
169 Dali::Vector<unsigned char>& map,
170 unsigned int& fsize )
172 memset( &chosen, 0, sizeof(chosen) );
176 DALI_LOG_ERROR("Error loading bitmap\n");
183 if( fseek(fp,0,SEEK_END) )
185 DALI_LOG_ERROR("Error seeking ICO data\n");
189 long positionIndicator = ftell(fp);
192 if( positionIndicator > -1L )
194 fsize = static_cast<unsigned int>(positionIndicator);
202 if( fseek(fp, 0, SEEK_SET) )
204 DALI_LOG_ERROR("Error seeking ICO data\n");
208 if (fsize < (ICO_FILE_HEADER + ICO_IMAGE_INFO_HEADER)) //6 + 16 + 40
214 if(fread(&map[0], 1, fsize, fp) != fsize)
216 DALI_LOG_WARNING("image file read opeation error!");
220 int search = BIGGEST;
221 unsigned short reserved, type, count;
222 if (!read_ushort(&map[0], fsize, &position, &reserved))
226 if (!read_ushort(&map[0], fsize, &position, &type))
230 if (!read_ushort(&map[0], fsize, &position, &count))
234 if (!((reserved == 0) &&
235 ((type == ICON) || (type == CURSOR)) && (count != 0)))
241 bool have_choice = false;
243 for (unsigned short i = 0; i < count; i++)
245 unsigned char tw = 0, th = 0, tcols = 0;
246 if (!read_uchar(&map[0], fsize, &position, &tw))
255 if (!read_uchar(&map[0], fsize, &position, &th))
265 if (!read_uchar(&map[0], fsize, &position, &tcols))
274 if (!read_uchar(&map[0], fsize, &position, &byte))
278 if (!read_ushort(&map[0], fsize, &position, &word))
288 if (!read_ushort(&map[0], fsize, &position, &word))
298 unsigned int bmoffset, bmsize;
299 if (!read_uint(&map[0], fsize, &position, &bmsize))
303 if (!read_uint(&map[0], fsize, &position, &bmoffset))
307 if ((bmsize <= 0) || (bmoffset <= 0) || (bmoffset >= fsize))
311 if (search == BIGGEST)
314 if ((!have_choice) ||
315 ((pdelta >= chosen.pdelta) &&
316 (((bpp >= 3) && (bpp >= chosen.bpp)) ||
317 ((bpp < 3) && (cols >= chosen.cols)))))
320 chosen.pdelta = pdelta;
325 chosen.planes = planes;
326 chosen.bmsize = bmsize;
327 chosen.bmoffset = bmoffset;
332 if (chosen.bmoffset == 0)
342 bool LoadIcoHeader(FILE *fp, const ImageAttributes& attributes, unsigned int &width, unsigned int &height )
345 Dali::Vector<unsigned char> map;
348 if ( false == LoadIcoHeaderHelper(fp, chosen, map, fsize) )
359 bool LoadBitmapFromIco( FILE *fp, Integration::Bitmap& bitmap, ImageAttributes& attributes, const ResourceLoadingClient& client )
362 Dali::Vector<unsigned char> map;
365 if ( false == LoadIcoHeaderHelper(fp, chosen, map, fsize) )
370 Dali::Vector<unsigned int> pal;
371 Dali::Vector<unsigned int> surface;
372 Dali::Vector<unsigned char> maskbuf;
373 Dali::Vector<unsigned char> pixbuf;
381 PixelBuffer* pixels = NULL;
383 size_t position = chosen.bmoffset;//22 == position
387 int cols = chosen.cols;
389 // read bmp header time... let's do some checking
390 if (!read_uint(&map[0], fsize, &position, &dword))
392 return false; // headersize - dont care
394 if (!read_uint(&map[0], fsize, &position, &dword))
396 return false; // width
406 if (!read_uint(&map[0], fsize, &position, &dword))
408 return false; // height
412 if ((int)dword != (h * 2))
420 DALI_LOG_WARNING("Broken ICO file!");
422 if (!read_ushort(&map[0], fsize, &position, &word))
424 return false; // planes
427 if (!read_ushort(&map[0], fsize, &position, &word))
429 return false; // bitcount
431 unsigned int bitcount = word;
432 if (!read_uint(&map[0], fsize, &position, &dword))
434 return false; // compression
436 //compression = dword;
437 if (!read_uint(&map[0], fsize, &position, &dword))
439 return false; // imagesize
442 if (!read_uint(&map[0], fsize, &position, &dword))
444 return false; // z pixels per m
446 if (!read_uint(&map[0], fsize, &position, &dword))
448 return false; // y pizels per m
450 if (!read_uint(&map[0], fsize, &position, &dword))
452 return false; // colors used
454 //colorsused = dword;
455 if (!read_uint(&map[0], fsize, &position, &dword))
457 return false; // colors important
459 //colorsimportant = dword;
460 surface.Resize(w * h * 4);
462 memset(&surface[0], 0, w * h * 4);
464 for(int i = 0; i < cols ; i ++)
466 unsigned char a, r, g, b;
468 if (!read_uchar(&map[0], fsize, &position, &b))
472 if (!read_uchar(&map[0], fsize, &position, &g))
476 if (!read_uchar(&map[0], fsize, &position, &r))
480 if (!read_uchar(&map[0], fsize, &position, &a))
485 pal[i] = ARGB_JOIN(a, r, g, b);
488 if (!((bitcount == 1) || (bitcount == 4) || (bitcount == 8) ||
489 (bitcount == 24) || (bitcount == 32)))
493 int stride = ((w + 31) / 32);
495 maskbuf.Resize(stride * h);
496 pixbuf.Resize(stride * 32 * 4); // more than enough
498 unsigned int none_zero_alpha = 0;
501 int pstride = stride * 4;
502 for (int i = 0; i < h; i++)
504 pix = &surface[0] + ((h - 1 - i) * w);
506 if (!read_mem(&map[0], fsize, &position, &pixbuf[0], pstride))
510 unsigned char* p = &pixbuf[0];
515 for (int j = 0; j < w; j++)
521 if ((j & 0x7) == 0x0)
525 else if ((j & 0x7) == 0x1)
527 *pix = pal[(*p >> 6) & 0x1];
529 else if ((j & 0x7) == 0x2)
531 *pix = pal[(*p >> 5) & 0x1];
533 else if ((j & 0x7) == 0x3)
535 *pix = pal[(*p >> 4) & 0x1];
537 else if ((j & 0x7) == 0x4)
539 *pix = pal[(*p >> 3) & 0x1];
541 else if ((j & 0x7) == 0x5)
543 *pix = pal[(*p >> 2) & 0x1];
545 else if ((j & 0x7) == 0x6)
547 *pix = pal[(*p >> 1) & 0x1];
551 *pix = pal[*p & 0x1];
558 else if (bitcount == 4)
560 int pstride = ((w + 7) / 8) * 4;
561 for (int i = 0; i < h; i++)
563 pix = &surface[0] + ((h - 1 - i) * w);
565 if (!read_mem(&map[0], fsize, &position, &pixbuf[0], pstride))
569 unsigned char* p = &pixbuf[0];
574 for (int j = 0; j < w; j++)
580 if ((j & 0x1) == 0x1)
582 *pix = pal[*p & 0x0f];
593 else if (bitcount == 8)
595 int pstride = ((w + 3) / 4) * 4;
596 for (int i = 0; i < h; i++)
598 pix = &surface[0] + ((h - 1 - i) * w);
600 if (!read_mem(&map[0], fsize, &position, &pixbuf[0], pstride))
604 unsigned char* p = &pixbuf[0];
609 for (int j = 0; j < w; j++)
621 else if (bitcount == 24)
624 for (int i = 0; i < h; i++)
626 pix = &surface[0] + ((h - 1 - i) * w);
628 if (!read_mem(&map[0], fsize, &position, &pixbuf[0], pstride))
632 unsigned char* p = &pixbuf[0];
637 for (int j = 0; j < w; j++)
639 unsigned char a, r, g, b;
650 *pix = ARGB_JOIN(a, r, g, b);
655 else if (bitcount == 32)
658 for (int i = 0; i < h; i++)
660 pix = &surface[0] + ((h - 1 - i) * w);
662 if (!read_mem(&map[0], fsize, &position, &pixbuf[0], pstride))
666 unsigned char* p = &pixbuf[0];
671 for (int j = 0; j < w; j++)
673 unsigned char a, r, g, b;
687 *pix = ARGB_JOIN(a, r, g, b);
692 if (!none_zero_alpha)
694 if (!read_mem(&map[0], fsize, &position, &maskbuf[0], stride * 4 * h))
699 for (int i = 0; i < h; i++)
703 pix = &surface[0] + ((h - 1 - i) * w);
705 m = &maskbuf[0] + (stride * i * 4);
710 for (int j = 0; j < w; j++)
716 if (*m & (1 << (7 - (j & 0x7))))
724 if ((j & 0x7) == 0x7)
732 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, w, h);
733 memset(pixels, 0, w * h * 4);
734 memcpy(pixels, (unsigned char*)&surface[0], w * h * 4);
736 attributes.SetSize(w, h);