4a176ef3b1c3055b75fb08f3eb6192e17db79c79
[platform/core/uifw/dali-adaptor.git] / platform-abstractions / tizen / image-loaders / loader-wbmp.cpp
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // HEADER
19 #include "loader-wbmp.h"
20
21 // EXTERNAL INCLUDES
22 #include <cstdio>
23 #include <cstdlib>
24 #include <cstring>
25
26 // INTERNAL INCLUDES
27 #include <dali/integration-api/debug.h>
28 #include <dali/integration-api/bitmap.h>
29 #include <dali/public-api/common/dali-vector.h>
30
31 namespace Dali
32 {
33 using Integration::Bitmap;
34 using Dali::Integration::PixelBuffer;
35 namespace TizenPlatform
36 {
37
38 namespace
39 {
40
41 #if defined(DEBUG_ENABLED)
42 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_LOADER_WBMP");
43 #endif
44
45 #define IMG_MAX_SIZE 65536
46
47 #define IMG_TOO_BIG(w, h) \
48         ((((unsigned long long)w) * ((unsigned long long)h)) >= \
49            ((1ULL << (29)) - 2048))
50
51
52 //extract multiple bytes integer , and saved in *data
53 int extractMultiByteInteger(unsigned int *data, void *map, size_t length, size_t *position)
54 {
55   // the header field contains an image type indentifier of multi-byte length(TypeField), an octet of general header info(FixHeaderField)
56   //,  a multi-byte width field(Width) and a multi-byte height field(Height) and so on.
57   // The actual organisation of the image data depends on the image type
58   // for Ext Headers flag (7th bit), 1 = More will follow, 0 = Last octet
59   // so in the for loop, if(buf & 0x80 == 0), loop will be exited
60   int targetMultiByteInteger = 0, readBufCount;
61   unsigned char buf;
62
63   for (readBufCount = 0;;)
64   {
65     // readBufCount means the count that fetched data from map
66     // extractMultiByteInteger() is to fetch wbmp type , width, and height
67     // for wbmp type, when readBufCount == 1, buf = 0x00, it will exit the loop
68     // for width, it have 4 bytes, so when readBufCount == 4, it must exit the loop
69     // for general width and height, if(buf & 0x80) == 0, then the next byte does not need to fetch again
70     // first step, readBufCount = 1 , read int(4 bytes) to buf, if buf & 0x80 !=0, the buf need to continue to fetch
71     // second step, readBufCount = 2, read next( 4 bytes) to buf, if buf & 0x80 == 0, then assigned the buf to target
72     if ((readBufCount ++) == 4)
73     {
74       return -1;
75     }
76     if (*position > length)
77     {
78       return -1;
79     }
80     buf = reinterpret_cast< unsigned char * >( map )[(*position)++];
81     targetMultiByteInteger = (targetMultiByteInteger << 7) | (buf & 0x7f);
82
83     if ((buf & 0x80) == 0)
84     {
85       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "position: %d, readBufCount: %d\n", *position, readBufCount);
86       break;
87     }
88   }
89   *data = targetMultiByteInteger;
90   return 0;
91 }
92
93 }// end unnamed namespace
94
95 bool LoadBitmapFromWbmp( const ImageLoader::Input& input, Integration::Bitmap& bitmap )
96 {
97   FILE* const fp = input.file;
98   if(fp == NULL)
99   {
100     DALI_LOG_ERROR("Error loading bitmap\n");
101     return false;
102   }
103   Dali::Vector<unsigned char> map;
104   Dali::Vector<unsigned char> surface;//unsigned int
105   PixelBuffer* pixels = NULL;
106   size_t position = 0;
107
108   unsigned int w, h;
109   unsigned int type;
110   unsigned int line_length;
111   unsigned char *line = NULL;
112   unsigned int cur = 0, x, y;
113
114   if( fseek(fp,0,SEEK_END) )
115   {
116     DALI_LOG_ERROR("Error seeking WBMP data\n");
117     return false;
118   }
119   long positionIndicator = ftell(fp);
120
121   unsigned int fsize( 0u );
122   if( positionIndicator > -1L )
123   {
124     fsize = static_cast<unsigned int>(positionIndicator);
125   }
126
127   if( 0u == fsize )
128   {
129     DALI_LOG_ERROR("Error: filesize is 0!\n");
130     return false;
131   }
132
133   if( fseek(fp, 0, SEEK_SET) )
134   {
135     DALI_LOG_ERROR("Error seeking WBMP data\n");
136     return false;
137   }
138   if(fsize <= 4)
139   {
140     DALI_LOG_ERROR("Error: WBMP Raw Data Not Found!\n");
141     return false;
142   }
143   if(fsize > 4096 * 4096 * 4)
144   {
145     DALI_LOG_ERROR("Error: WBMP size is too large!\n");
146     return false;
147   }
148   map.Resize(fsize);
149
150   if(fread(&map[0], 1, fsize, fp) != fsize)
151   {
152     DALI_LOG_WARNING("image file read opeation error!\n");
153     return false;
154   }
155
156   if (extractMultiByteInteger(&type, &map[0], fsize, &position) < 0)
157   {
158     return false;
159   }
160
161   position++; /* skipping one byte */
162
163   if (extractMultiByteInteger(&w, &map[0], fsize, &position) < 0)
164   {
165     return false;
166   }
167   if (extractMultiByteInteger(&h, &map[0], fsize, &position) < 0)
168   {
169     return false;
170   }
171   if(type != 0)
172   {
173     DALI_LOG_ERROR("Unknown Format!\n");
174     return false;
175   }
176
177   if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE))
178   {
179     return false;
180   }
181
182   surface.Resize(w* h );//(w * h * 4);
183   memset(&surface[0], 0, w * h ); // w * h * 4
184
185   line_length = (w + 7) >> 3;
186   for (y = 0; y < h; y ++)
187   {
188     if (position + line_length > fsize)
189     {
190       return false;
191     }
192     line = &map[0] + position;
193     position += line_length;
194     for (x = 0; x < w; x++)
195     {
196       int idx = x >> 3;
197       int offset = 1 << (0x07 - (x & 0x07));
198       if (line[idx] & offset)
199       {
200         surface[cur] = 0xff;//0xffffffff;
201       }
202       else
203       {
204         surface[cur] = 0x00;//0xff000000;
205       }
206       cur++;
207     }
208   }
209   pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::L8, w, h);//Pixel::RGBA8888
210
211   memcpy( pixels, &surface[0], w * h ); //w * h * 4
212
213   return true;
214 }
215
216
217 bool LoadWbmpHeader( const ImageLoader::Input& input, unsigned int& width, unsigned int& height )
218 {
219   FILE* const fp = input.file;
220   if(fp == NULL)
221   {
222     DALI_LOG_ERROR("Error loading bitmap\n");
223     return false;
224   }
225   Dali::Vector<unsigned char> map;
226   size_t position = 0;
227
228   unsigned int  w, h;
229   unsigned int type;
230   if( fseek(fp,0,SEEK_END) )
231   {
232     DALI_LOG_ERROR("Error seeking WBMP data\n");
233     return false;
234   }
235   long positionIndicator = ftell(fp);
236
237   unsigned int fsize( 0u );
238   if( positionIndicator > -1L )
239   {
240     fsize = static_cast<unsigned int>(positionIndicator);
241   }
242
243   if( 0u == fsize )
244   {
245     return false;
246   }
247
248   if( fseek(fp, 0, SEEK_SET) )
249   {
250     DALI_LOG_ERROR("Error seeking WBMP data\n");
251     return false;
252   }
253   if(fsize <= 4)
254   {
255     DALI_LOG_ERROR("Error: WBMP Raw Data Not Found!\n");
256     return false;
257   }
258
259   // type(1 byte) + fixedheader(1 byte) + width(uint) + height(uint)
260   unsigned int headerSize = 1 + 1 + 4 + 4;// 8 + 8 + 32 + 32;
261   headerSize = std::min(headerSize, fsize);
262
263   map.Resize(headerSize);
264   if(fread(&map[0], 1, headerSize, fp) != headerSize)
265   {
266     DALI_LOG_WARNING("image file read opeation error!\n");
267     return false;
268   }
269
270   if (extractMultiByteInteger(&type, &map[0], headerSize, &position) < 0)
271   {
272     DALI_LOG_ERROR("Error: unable to read type!\n");
273     return false;
274   }
275   position++; /* skipping one byte */
276   if(type != 0)
277   {
278     DALI_LOG_ERROR("Error: unknown format!\n");
279     return false;
280   }
281   if (extractMultiByteInteger(&w, &map[0], headerSize, &position) < 0)
282   {
283     DALI_LOG_ERROR("Error: can not read width!\n");
284     return false;
285   }
286   if (extractMultiByteInteger(&h, &map[0], headerSize, &position) < 0)
287   {
288     DALI_LOG_ERROR("Error: can not read height!\n");
289     return false;
290   }
291
292   if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) )
293   {
294     DALI_LOG_ERROR("Error: file size is not supported!\n");
295     return false;
296   }
297
298   width = w;
299   height = h;
300   return true;
301 }
302
303 }
304 }