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