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>
63 using Integration::Bitmap;
64 using Dali::Integration::PixelBuffer;
66 namespace TizenPlatform
71 //reserved 2 bytes + type 2 bytes + count 2 bytes + count * 16 bytes
72 const unsigned char ICO_FILE_HEADER = 22;
73 // info header 40 bytes = size 4 bytes + width 4 bytes + height 4 bytes + planes 2 bytes + bitcount 2 bytes
74 // + compression 4 bytes + imagesize 4 bytes + xpixelsPerM 4 bytes + ypixelsPerM 4 bytes + colorsUsed 4 bytes + colorImportant 4 bytes
75 // besides, there are rgba color data = numberOfColors * 4 bytes
76 const unsigned char ICO_IMAGE_INFO_HEADER = 40;
78 typedef unsigned char DATA8;
79 #define A_VAL(p) (((DATA8 *)(p))[3])
81 #define RGB_JOIN(r,g,b) \
82 (((r) << 16) + ((g) << 8) + (b))
84 #define ARGB_JOIN(a,r,g,b) \
85 (((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
86 #define IMG_TOO_BIG(w, h) \
87 ((((unsigned long long)w) * ((unsigned long long)h)) >= \
88 ((1ULL << (29 * (sizeof(void *) / 4))) - 2048))
90 bool read_ushort(unsigned char *map, size_t length, size_t *position, unsigned short *ret)
94 if (*position + 2 > length)
98 b[0] = map[(*position)++];
99 b[1] = map[(*position)++];
100 *ret = (b[1] << 8) | b[0];
104 bool read_uint(unsigned char *map, size_t length, size_t *position, unsigned int *ret)
109 if (*position + 4 > length)
113 for (i = 0; i < 4; i++)
115 b[i] = map[(*position)++];
117 *ret = ARGB_JOIN(b[3], b[2], b[1], b[0]);
121 bool read_uchar(unsigned char *map, size_t length, size_t *position, unsigned char *ret)
123 if (*position + 1 > length)
127 *ret = map[(*position)++];
131 bool read_mem(unsigned char *map, size_t length, size_t *position, void *buffer, int size)
133 if (*position + size > length)
137 memcpy(buffer, map + *position, size);
163 unsigned int bmoffset, bmsize;
166 bool LoadIcoHeaderHelper( FILE* fp,
168 Dali::Vector<unsigned char>& map,
169 unsigned int& fsize )
171 memset( &chosen, 0, sizeof(chosen) );
175 DALI_LOG_ERROR("Error loading bitmap\n");
182 if( fseek(fp,0,SEEK_END) )
184 DALI_LOG_ERROR("Error seeking ICO data\n");
188 long positionIndicator = ftell(fp);
191 if( positionIndicator > -1L )
193 fsize = static_cast<unsigned int>(positionIndicator);
201 if( fseek(fp, 0, SEEK_SET) )
203 DALI_LOG_ERROR("Error seeking ICO data\n");
207 if (fsize < (ICO_FILE_HEADER + ICO_IMAGE_INFO_HEADER)) //6 + 16 + 40
213 if(fread(&map[0], 1, fsize, fp) != fsize)
215 DALI_LOG_WARNING("image file read opeation error!");
219 int search = BIGGEST;
220 unsigned short reserved, type, count;
221 if (!read_ushort(&map[0], fsize, &position, &reserved))
225 if (!read_ushort(&map[0], fsize, &position, &type))
229 if (!read_ushort(&map[0], fsize, &position, &count))
233 if (!((reserved == 0) &&
234 ((type == ICON) || (type == CURSOR)) && (count != 0)))
240 bool have_choice = false;
242 for (unsigned short i = 0; i < count; i++)
244 unsigned char tw = 0, th = 0, tcols = 0;
245 if (!read_uchar(&map[0], fsize, &position, &tw))
254 if (!read_uchar(&map[0], fsize, &position, &th))
264 if (!read_uchar(&map[0], fsize, &position, &tcols))
273 if (!read_uchar(&map[0], fsize, &position, &byte))
277 if (!read_ushort(&map[0], fsize, &position, &word))
287 if (!read_ushort(&map[0], fsize, &position, &word))
297 unsigned int bmoffset, bmsize;
298 if (!read_uint(&map[0], fsize, &position, &bmsize))
302 if (!read_uint(&map[0], fsize, &position, &bmoffset))
306 if ((bmsize <= 0) || (bmoffset <= 0) || (bmoffset >= fsize))
310 if (search == BIGGEST)
313 if ((!have_choice) ||
314 ((pdelta >= chosen.pdelta) &&
315 (((bpp >= 3) && (bpp >= chosen.bpp)) ||
316 ((bpp < 3) && (cols >= chosen.cols)))))
319 chosen.pdelta = pdelta;
324 chosen.planes = planes;
325 chosen.bmsize = bmsize;
326 chosen.bmoffset = bmoffset;
331 if (chosen.bmoffset == 0)
341 bool LoadIcoHeader( const ImageLoader::Input& input, unsigned int& width, unsigned int& height )
344 Dali::Vector<unsigned char> map;
346 FILE* const fp = input.file;
348 if ( false == LoadIcoHeaderHelper(fp, chosen, map, fsize) )
359 bool LoadBitmapFromIco( const ResourceLoadingClient& client, const ImageLoader::Input& input, Integration::Bitmap& bitmap )
362 Dali::Vector<unsigned char> map;
364 FILE* const fp = input.file;
366 if ( false == LoadIcoHeaderHelper(fp, chosen, map, fsize) )
371 Dali::Vector<unsigned int> pal;
372 Dali::Vector<unsigned int> surface;
373 Dali::Vector<unsigned char> maskbuf;
374 Dali::Vector<unsigned char> pixbuf;
382 PixelBuffer* pixels = NULL;
384 size_t position = chosen.bmoffset;//22 == position
388 int cols = chosen.cols;
390 // read bmp header time... let's do some checking
391 if (!read_uint(&map[0], fsize, &position, &dword))
393 return false; // headersize - dont care
395 if (!read_uint(&map[0], fsize, &position, &dword))
397 return false; // width
407 if (!read_uint(&map[0], fsize, &position, &dword))
409 return false; // height
413 if ((int)dword != (h * 2))
421 DALI_LOG_WARNING("Broken ICO file!");
423 if (!read_ushort(&map[0], fsize, &position, &word))
425 return false; // planes
428 if (!read_ushort(&map[0], fsize, &position, &word))
430 return false; // bitcount
432 unsigned int bitcount = word;
433 if (!read_uint(&map[0], fsize, &position, &dword))
435 return false; // compression
437 //compression = dword;
438 if (!read_uint(&map[0], fsize, &position, &dword))
440 return false; // imagesize
443 if (!read_uint(&map[0], fsize, &position, &dword))
445 return false; // z pixels per m
447 if (!read_uint(&map[0], fsize, &position, &dword))
449 return false; // y pizels per m
451 if (!read_uint(&map[0], fsize, &position, &dword))
453 return false; // colors used
455 //colorsused = dword;
456 if (!read_uint(&map[0], fsize, &position, &dword))
458 return false; // colors important
460 //colorsimportant = dword;
461 surface.Resize(w * h * 4);
463 memset(&surface[0], 0, w * h * 4);
465 for(int i = 0; i < cols ; i ++)
467 unsigned char a, r, g, b;
469 if (!read_uchar(&map[0], fsize, &position, &b))
473 if (!read_uchar(&map[0], fsize, &position, &g))
477 if (!read_uchar(&map[0], fsize, &position, &r))
481 if (!read_uchar(&map[0], fsize, &position, &a))
486 pal[i] = ARGB_JOIN(a, r, g, b);
489 if (!((bitcount == 1) || (bitcount == 4) || (bitcount == 8) ||
490 (bitcount == 24) || (bitcount == 32)))
494 int stride = ((w + 31) / 32);
496 maskbuf.Resize(stride * h);
497 pixbuf.Resize(stride * 32 * 4); // more than enough
499 unsigned int none_zero_alpha = 0;
502 int pstride = stride * 4;
503 for (int i = 0; i < h; i++)
505 pix = &surface[0] + ((h - 1 - i) * w);
507 if (!read_mem(&map[0], fsize, &position, &pixbuf[0], pstride))
511 unsigned char* p = &pixbuf[0];
516 for (int j = 0; j < w; j++)
522 if ((j & 0x7) == 0x0)
526 else if ((j & 0x7) == 0x1)
528 *pix = pal[(*p >> 6) & 0x1];
530 else if ((j & 0x7) == 0x2)
532 *pix = pal[(*p >> 5) & 0x1];
534 else if ((j & 0x7) == 0x3)
536 *pix = pal[(*p >> 4) & 0x1];
538 else if ((j & 0x7) == 0x4)
540 *pix = pal[(*p >> 3) & 0x1];
542 else if ((j & 0x7) == 0x5)
544 *pix = pal[(*p >> 2) & 0x1];
546 else if ((j & 0x7) == 0x6)
548 *pix = pal[(*p >> 1) & 0x1];
552 *pix = pal[*p & 0x1];
559 else if (bitcount == 4)
561 int pstride = ((w + 7) / 8) * 4;
562 for (int i = 0; i < h; i++)
564 pix = &surface[0] + ((h - 1 - i) * w);
566 if (!read_mem(&map[0], fsize, &position, &pixbuf[0], pstride))
570 unsigned char* p = &pixbuf[0];
575 for (int j = 0; j < w; j++)
581 if ((j & 0x1) == 0x1)
583 *pix = pal[*p & 0x0f];
594 else if (bitcount == 8)
596 int pstride = ((w + 3) / 4) * 4;
597 for (int i = 0; i < h; i++)
599 pix = &surface[0] + ((h - 1 - i) * w);
601 if (!read_mem(&map[0], fsize, &position, &pixbuf[0], pstride))
605 unsigned char* p = &pixbuf[0];
610 for (int j = 0; j < w; j++)
622 else if (bitcount == 24)
625 for (int i = 0; i < h; i++)
627 pix = &surface[0] + ((h - 1 - i) * w);
629 if (!read_mem(&map[0], fsize, &position, &pixbuf[0], pstride))
633 unsigned char* p = &pixbuf[0];
638 for (int j = 0; j < w; j++)
640 unsigned char a, r, g, b;
651 *pix = ARGB_JOIN(a, r, g, b);
656 else if (bitcount == 32)
659 for (int i = 0; i < h; i++)
661 pix = &surface[0] + ((h - 1 - i) * w);
663 if (!read_mem(&map[0], fsize, &position, &pixbuf[0], pstride))
667 unsigned char* p = &pixbuf[0];
672 for (int j = 0; j < w; j++)
674 unsigned char a, r, g, b;
688 *pix = ARGB_JOIN(a, r, g, b);
693 if (!none_zero_alpha)
695 if (!read_mem(&map[0], fsize, &position, &maskbuf[0], stride * 4 * h))
700 for (int i = 0; i < h; i++)
704 pix = &surface[0] + ((h - 1 - i) * w);
706 m = &maskbuf[0] + (stride * i * 4);
711 for (int j = 0; j < w; j++)
717 if (*m & (1 << (7 - (j & 0x7))))
725 if ((j & 0x7) == 0x7)
733 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, w, h);
734 memset(pixels, 0, w * h * 4);
735 memcpy(pixels, (unsigned char*)&surface[0], w * h * 4);