Merge "Fixed a result when decodeUrl() isn't connect correct url" into tizen_2.2
[platform/framework/native/image.git] / src / FMedia_ImageImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file   FMedia_ImageImpl.cpp
20  * @brief  This file contains the implementation of subsystem's Image.
21  */
22
23 #include <unique_ptr.h>
24 #include <FIoFile.h>
25 #include <FMediaImage.h>
26 #include <FMediaImageUtil.h>
27 #include <FMediaIImageEventListener.h>
28 #include <FBaseSysLog.h>
29 #include "FMedia_MediaUtil.h"
30 #include "FMedia_ImageImpl.h"
31 #include "FMedia_ImageUtil.h"
32 #include "FMedia_ImageUtilImpl.h"
33 #include "FMedia_ImageDecoder.h"
34 #include "FMedia_ImageEncoder.h"
35 #include "FMedia_ImageUriDataFactory.h"
36 #include "FGrp_BitmapImpl.h"
37 #include "FUi_CoordinateSystemUtils.h"
38
39
40 using namespace Tizen::Graphics;
41 using namespace Tizen::Base;
42 using namespace Tizen::Io;
43 using namespace Tizen::Ui;
44
45 namespace Tizen { namespace Media
46 {
47
48 static const float _SCALE_DOWN_RATIO = 0.5;
49 static const int _RGB565_PIXEL_DEPTH = 2;
50 static const int _MIN_ENCODE_QUALITY = 20; // Changed from 50 to 20 to allow greater compression.
51 static const int _MAX_ENCODE_QUALITY = 99;
52 static const int _DEFAULT_ENCODE_QUALITY = 50;
53 static const int _MAX_ENCODE_LOOP = 2;
54 static const int _MAX_ENCODE_RESIZE_LOOP = 2;
55 //static const int MAX_IMGFILE_SIZE = 4096000;
56
57 _ImageImpl::_ImageImpl(void)
58 {
59         __pUrlReqIDList.reset(null);
60 }
61
62 _ImageImpl::~_ImageImpl(void)
63 {
64         if (__pUrlReqIDList.get() != null)
65         {
66                 int num = 0;
67                 Object* pObj = null;
68                 _ImageUriDataFactory *pFactory = null;
69
70                 pFactory = _ImageUriDataFactory::GetInstance();
71                 SysTryReturn(NID_MEDIA, pFactory != null, , GetLastResult(), "[%s] Failed to get Factory instance.",
72                         GetErrorMessage(GetLastResult()));
73
74                 // free the memory
75                 num = __pUrlReqIDList->GetCount();
76                 for (int i = 0; i < num; i++)
77                 {
78                         pObj = __pUrlReqIDList->GetAt(i);
79                         if (pObj != null)
80                         {
81                                 Integer *pValue = dynamic_cast<Integer*>(pObj);
82                                 if (pValue == null)
83                                 {
84                                         continue;
85                                 }
86
87                                 RequestId reqId = (RequestId)(pValue->ToInt());
88
89                                 pFactory->Remove(reqId);
90                         }
91                 }
92                 __pUrlReqIDList->RemoveAll(true);
93         }
94 }
95
96 _ImageImpl*
97 _ImageImpl::GetInstance(Image* pImage)
98 {
99         if (pImage != null)
100         {
101                 return pImage->__pImageImpl;
102         }
103
104         return null;
105 }
106
107 const _ImageImpl*
108 _ImageImpl::GetInstance(const Image* pImage)
109 {
110         if (pImage != null)
111         {
112                 return pImage->__pImageImpl;
113         }
114
115         return null;
116 }
117
118 result
119 _ImageImpl::Construct(void)
120 {
121         return E_SUCCESS;
122 }
123
124 Bitmap* 
125 _ImageImpl::DecodeToBitmapN(const Tizen::Base::String& srcImagePath, Tizen::Graphics::BitmapPixelFormat pixelFormat)
126 {
127         std::unique_ptr<ByteBuffer> pBuf;
128         Bitmap* pBmp = null;
129
130         pBuf.reset(_MediaUtil::FileToBufferN(srcImagePath));
131         SysSecureTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
132                            "[%s] FileToBufferN %ls", GetErrorMessage(GetLastResult()), srcImagePath.GetPointer());
133
134         pBmp = DecodeToBitmapN(*pBuf.get(), pixelFormat);
135         return pBmp;
136 }
137
138 Bitmap* 
139 _ImageImpl::DecodeToBitmapN(const Tizen::Base::ByteBuffer& srcImageBuf, Tizen::Graphics::BitmapPixelFormat pixelFormat)
140 {
141         result r = E_SUCCESS;
142         std::unique_ptr<ByteBuffer> pBuf;
143         std::unique_ptr<Bitmap> pBmp;
144         Dimension outDim;
145
146         _ImageDecoder dec;
147
148         r = dec.Construct(srcImageBuf, _ImageUtilImpl::ToMediaPixelFormat(pixelFormat));
149         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Decoder construct failed.", GetErrorMessage(r));
150
151         pBuf.reset(dec.DecodeN());
152         SysTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
153                            "[%s] Propagated", GetErrorMessage(GetLastResult()));
154         r = GetLastResult();
155         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
156
157         r = dec.GetDimension(outDim.width, outDim.height);
158         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
159
160         pBmp.reset(new (std::nothrow) Bitmap);
161         SysTryReturn(NID_MEDIA, pBmp != null, null, E_OUT_OF_MEMORY,
162                            "[%s] new Bitmap", GetErrorMessage(GetLastResult()));
163         r = pBmp->Construct(*pBuf.get(), outDim, pixelFormat, BUFFER_SCALING_AUTO);
164         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
165
166         // Set transparency in case of rgb565 format
167         if (pixelFormat == BITMAP_PIXEL_FORMAT_RGB565)
168         {
169                 short rgb565Chroma = 0;
170                 Boolean transparency(false);
171                 Integer chromaKey(0);
172                 byte red = 0;
173                 byte green = 0;
174                 byte blue = 0;
175                 Color *pMaskingColor = null;
176
177                 r = dec.GetValue(L"transparency", transparency);
178                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, pBmp.release(), E_SUCCESS, "[%s] Propagated.", GetErrorMessage(r));
179                 if (transparency.ToBool() == true)
180                 {
181                         r = dec.GetValue(L"chromaKey", chromaKey);
182                         SysTryReturn(NID_MEDIA, r == E_SUCCESS, pBmp.release(), E_SUCCESS, "[%s] Propagated.", GetErrorMessage(r));
183
184                         rgb565Chroma = chromaKey.ToShort();
185                         red = (rgb565Chroma & 0xf800) >> 8;
186                         red = red | (red >> 5);
187                         green = (rgb565Chroma & 0x07e0) >> 3;
188                         green = green | (green >> 6);
189                         blue = (rgb565Chroma & 0x001f) << 3;
190                         blue = blue | (blue >> 5);
191
192                         pMaskingColor = new Color(red, green, blue);
193                         SysTryReturn(NID_MEDIA, pMaskingColor != null, pBmp.release(), E_SUCCESS,
194                                 "[%s] Could not apply masking color.", GetErrorMessage(r));
195                         r = pBmp->SetMaskingColor(pMaskingColor);
196                         delete pMaskingColor;
197                         SysTryReturn(NID_MEDIA, r == E_SUCCESS, pBmp.release(), E_SUCCESS,
198                                 "[%s] Could not set masking color.", GetErrorMessage(r));
199                 }
200         }
201
202         SetLastResult(E_SUCCESS);
203         return pBmp.release();
204 }
205
206 Bitmap*
207 _ImageImpl::DecodeToBitmapN(const Tizen::Base::String& srcImagePath, Tizen::Graphics::BitmapPixelFormat pixelFormat, const Tizen::Graphics::Dimension &destDim,
208                                                         Tizen::Graphics::BufferScaling bufferScaling)
209 {
210         std::unique_ptr<ByteBuffer> pBuf;
211         Bitmap* pBmp = null;
212
213         pBuf.reset(_MediaUtil::FileToBufferN(srcImagePath));
214         SysSecureTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
215                            "[%s] FileToBufferN %ls", GetErrorMessage(GetLastResult()), srcImagePath.GetPointer());
216
217         pBmp = DecodeToBitmapN(*pBuf.get(), pixelFormat, destDim, bufferScaling);
218         return pBmp;
219 }
220
221 Bitmap*
222 _ImageImpl::DecodeToBitmapN(const Tizen::Base::ByteBuffer& srcImageBuf, Tizen::Graphics::BitmapPixelFormat pixelFormat, const Tizen::Graphics::Dimension &destDim,
223                                                         Tizen::Graphics::BufferScaling bufferScaling)
224 {
225         result r = E_SUCCESS;
226         std::unique_ptr<ByteBuffer> pBuf;
227         std::unique_ptr<Bitmap> pBmp;
228         Dimension outDim;
229
230         _ImageDecoder dec;
231
232         r = dec.Construct(srcImageBuf, _ImageUtilImpl::ToMediaPixelFormat(pixelFormat));
233         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Decoder construct failed.", GetErrorMessage(r));
234
235         // Reset decoder output demension
236         dec.SetOutputDimension(destDim.width, destDim.height, true);
237
238         pBuf.reset(dec.DecodeN());
239         SysTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
240                            "[%s] Propagated", GetErrorMessage(GetLastResult()));
241         r = GetLastResult();
242         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
243
244         r = dec.GetDimension(outDim.width, outDim.height);
245         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
246
247         pBmp.reset(new (std::nothrow) Bitmap);
248         SysTryReturn(NID_MEDIA, pBmp != null, null, E_OUT_OF_MEMORY,
249                            "[%s] new Bitmap", GetErrorMessage(GetLastResult()));
250         r = pBmp->Construct(*pBuf.get(), outDim, pixelFormat, bufferScaling);
251         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
252
253         // Set transparency in case of rgb565 format
254         if (pixelFormat == BITMAP_PIXEL_FORMAT_RGB565)
255         {
256                 short rgb565Chroma = 0;
257                 Boolean transparency(false);
258                 Integer chromaKey(0);
259                 byte red = 0;
260                 byte green = 0;
261                 byte blue = 0;
262                 Color *pMaskingColor = null;
263
264                 r = dec.GetValue(L"transparency", transparency);
265                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, pBmp.release(), E_SUCCESS, "[%s] Propagated.", GetErrorMessage(r));
266                 if (transparency.ToBool() == true)
267                 {
268                         r = dec.GetValue(L"chromaKey", chromaKey);
269                         SysTryReturn(NID_MEDIA, r == E_SUCCESS, pBmp.release(), E_SUCCESS, "[%s] Propagated.", GetErrorMessage(r));
270
271                         rgb565Chroma = chromaKey.ToShort();
272                         red = (rgb565Chroma & 0xf800) >> 8;
273                         red = red | (red >> 5);
274                         green = (rgb565Chroma & 0x07e0) >> 3;
275                         green = green | (green >> 6);
276                         blue = (rgb565Chroma & 0x001f) << 3;
277                         blue = blue | (blue >> 5);
278
279                         pMaskingColor = new Color(red, green, blue);
280                         SysTryReturn(NID_MEDIA, pMaskingColor != null, pBmp.release(), E_SUCCESS,
281                                 "[%s] Could not apply masking color.", GetErrorMessage(r));
282                         r = pBmp->SetMaskingColor(pMaskingColor);
283                         delete pMaskingColor;
284                         SysTryReturn(NID_MEDIA, r == E_SUCCESS, pBmp.release(), E_SUCCESS,
285                                 "[%s] Could not set masking color.", GetErrorMessage(r));
286                 }
287         }
288
289         SetLastResult(E_SUCCESS);
290         return pBmp.release();
291 }
292
293 Bitmap*
294 _ImageImpl::DecodeToBitmapN(const Tizen::Base::ByteBuffer& srcImageBuf, Tizen::Graphics::BitmapPixelFormat pixelFormat,
295                                                         const Tizen::Graphics::FloatDimension &destDim)
296 {
297         result r = E_SUCCESS;
298         std::unique_ptr<ByteBuffer> pBuf;
299         std::unique_ptr<Bitmap> pBmp;
300         Dimension orgDim, tmpDim;
301         FloatDimension outDim;
302         BufferInfo bufInfo;
303
304         _ImageDecoder dec;
305
306         r = dec.Construct(srcImageBuf, _ImageUtilImpl::ToMediaPixelFormat(pixelFormat));
307         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Decoder construct failed.", GetErrorMessage(r));
308
309         r = dec.GetDimension(orgDim.width, orgDim.height);
310         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
311
312         // Reset decoder output demension
313         dec.SetOutputDimension(_CoordinateSystemUtils::ConvertToInteger(destDim.width),
314                                                    _CoordinateSystemUtils::ConvertToInteger(destDim.height),
315                                                    true);
316
317         pBuf.reset(dec.DecodeN());
318         SysTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
319                            "[%s] Propagated", GetErrorMessage(GetLastResult()));
320
321         r = dec.GetDimension(tmpDim.width, tmpDim.height);
322         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
323
324         r = _ImageUtil::GetResizedDimension(orgDim.width, orgDim.height, destDim.width, destDim.height, outDim.width, outDim.height);
325         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
326
327         pBmp.reset(new (std::nothrow) Bitmap);
328         SysTryReturn(NID_MEDIA, pBmp.get() != null, null, E_OUT_OF_MEMORY,
329                            "[%s] new Bitmap", GetErrorMessage(GetLastResult()));
330
331         pBmp.reset(_BitmapImpl::GetNonScaledBitmapN(*pBuf.get(), tmpDim, pixelFormat, destDim));
332
333         // Set transparency in case of rgb565 format
334         if (pixelFormat == BITMAP_PIXEL_FORMAT_RGB565)
335         {
336                 short rgb565Chroma = 0;
337                 Boolean transparency(false);
338                 Integer chromaKey(0);
339                 byte red = 0;
340                 byte green = 0;
341                 byte blue = 0;
342                 Color *pMaskingColor = null;
343
344                 r = dec.GetValue(L"transparency", transparency);
345                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, pBmp.release(), E_SUCCESS, "[%s] Propagated.", GetErrorMessage(r));
346                 if (transparency.ToBool() == true)
347                 {
348                         r = dec.GetValue(L"chromaKey", chromaKey);
349                         SysTryReturn(NID_MEDIA, r == E_SUCCESS, pBmp.release(), E_SUCCESS, "[%s] Propagated.", GetErrorMessage(r));
350
351                         rgb565Chroma = chromaKey.ToShort();
352                         red = (rgb565Chroma & 0xf800) >> 8;
353                         red = red | (red >> 5);
354                         green = (rgb565Chroma & 0x07e0) >> 3;
355                         green = green | (green >> 6);
356                         blue = (rgb565Chroma & 0x001f) << 3;
357                         blue = blue | (blue >> 5);
358
359                         pMaskingColor = new Color(red, green, blue);
360                         SysTryReturn(NID_MEDIA, pMaskingColor != null, pBmp.release(), E_SUCCESS,
361                                 "[%s] Could not apply masking color.", GetErrorMessage(r));
362                         r = pBmp->SetMaskingColor(pMaskingColor);
363                         delete pMaskingColor;
364                         SysTryReturn(NID_MEDIA, r == E_SUCCESS, pBmp.release(), E_SUCCESS,
365                                 "[%s] Could not set masking color.", GetErrorMessage(r));
366                 }
367         }
368
369         SetLastResult(E_SUCCESS);
370         return pBmp.release();
371 }
372
373 Bitmap*
374 _ImageImpl::DecodeToBitmapN(const Tizen::Base::String& srcImagePath, Tizen::Graphics::BitmapPixelFormat pixelFormat,
375                                                         const Tizen::Graphics::FloatDimension &destDim)
376 {
377         std::unique_ptr<ByteBuffer> pBuf;
378         Bitmap* pBmp = null;
379
380         pBuf.reset(_MediaUtil::FileToBufferN(srcImagePath));
381         SysSecureTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
382                            "[%s] FileToBufferN %ls", GetErrorMessage(GetLastResult()), srcImagePath.GetPointer());
383
384         pBmp = DecodeToBitmapN(*pBuf.get(), pixelFormat, destDim);
385         return pBmp;
386 }
387
388 Tizen::Base::ByteBuffer*
389 _ImageImpl::DecodeToBufferN(const Tizen::Base::String& srcImagePath,
390                                                         Tizen::Graphics::Dimension &restDim,
391                                                         const Tizen::Graphics::Dimension &dstDim,
392                                                         Tizen::Graphics::BitmapPixelFormat pixelFormat,
393                                                         ImageFormat imgFormat, bool keepAspectRatio)
394 {
395         std::unique_ptr<ByteBuffer> pBuf;
396         ByteBuffer* pRetBuf = null;
397
398         //SysTryCatch(NID_MEDIA, IS_VALID_DIMENSION(dstDim), , E_OUT_OF_RANGE,
399         //"[E_OUT_OF_RANGE] dest dimension:%d,%d", dstDim.width, dstDim.height);
400
401         pBuf.reset(_MediaUtil::FileToBufferN(srcImagePath));
402         SysSecureTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
403                            "[%s] FileToBufferN %ls", GetErrorMessage(GetLastResult()), srcImagePath.GetPointer());
404
405         pRetBuf = DecodeToBufferN(*pBuf.get(), restDim, dstDim, pixelFormat, imgFormat, keepAspectRatio);
406         return pRetBuf;
407 }
408
409 Tizen::Base::ByteBuffer*
410 _ImageImpl::DecodeToBufferN(const Tizen::Base::ByteBuffer &srcImageBuf,
411                                                         Tizen::Graphics::Dimension &retDim,
412                                                         const Tizen::Graphics::Dimension &dstDim,
413                                                         Tizen::Graphics::BitmapPixelFormat pixelFormat,
414                                                         ImageFormat imgFormat, bool keepAspectRatio)
415 {
416         result r = E_SUCCESS;
417         std::unique_ptr<ByteBuffer> pBuf;
418         _ImageDecoder dec;
419
420         //SysTryCatch(NID_MEDIA, IS_VALID_BITMAP_PIXEL(pixelFormat), , E_INVALID_ARG,
421         //"[E_INVALID_ARG] pixelFormat:%d", pixelFormat);
422
423         r = dec.Construct(srcImageBuf, _ImageUtilImpl::ToMediaPixelFormat(pixelFormat), imgFormat);
424         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Decoder construct failed.", GetErrorMessage(r));
425
426         // Reset decoder output demension
427         dec.SetOutputDimension(dstDim.width, dstDim.height, keepAspectRatio);
428
429         pBuf.reset(dec.DecodeN());
430         r = GetLastResult();
431         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
432
433         r = dec.GetDimension(retDim.width, retDim.height);
434         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
435
436         SetLastResult(E_SUCCESS);
437         return pBuf.release();
438 }
439
440 Tizen::Base::ByteBuffer*
441 _ImageImpl::DecodeToBufferN(const Tizen::Base::String& srcImagePath,
442                                                         Tizen::Graphics::BitmapPixelFormat pixelFormat,
443                                                         int& imageWidth, int& imageHeight, bool keepAspectRatio)
444 {
445         ByteBuffer *pBuf = null;
446         Dimension dim;
447
448         pBuf = DecodeToBufferN(srcImagePath, dim, Dimension(0, 0), pixelFormat, IMG_FORMAT_NONE, keepAspectRatio);
449         imageWidth = dim.width;
450         imageHeight = dim.height;
451         return pBuf;
452 }
453
454
455 Tizen::Base::ByteBuffer*
456 _ImageImpl::DecodeN(const Tizen::Base::String& srcImagePath,
457                                         Tizen::Graphics::BitmapPixelFormat pixelFormat,
458                                         int destWidth, int destHeight, bool keepAspectRatio)
459 {
460         Dimension dim;
461
462         return DecodeToBufferN(srcImagePath, dim, Dimension(destWidth, destHeight), pixelFormat, IMG_FORMAT_NONE, keepAspectRatio);
463 }
464
465 result
466 _ImageImpl::DecodeUrl(const Tizen::Base::Utility::Uri& srcImageUrl,
467                                           Tizen::Graphics::BitmapPixelFormat colorFormat,
468                                           int destWidth, int destHeight, RequestId& reqId,
469                                           const IImageDecodeUrlEventListener& listener, long timeout)
470 {
471         result r = E_SUCCESS;
472
473         _ImageUriDataFactory *pFactory = null;
474
475         SysTryCatch(NID_MEDIA, (colorFormat > Tizen::Graphics::BITMAP_PIXEL_FORMAT_MIN)
476         && colorFormat < Tizen::Graphics::BITMAP_PIXEL_FORMAT_MAX, , E_INVALID_ARG,
477         "[E_INVALID_ARG] Wrong color format.");
478
479         SysTryCatch(NID_MEDIA, destWidth > 0 && destHeight > 0, , E_OUT_OF_RANGE,
480         "[E_OUT_OF_RANGE] The designated width and height SHOUL be greater than 0.");
481
482         SysTryCatch(NID_MEDIA, timeout == _TIMEOUT_INFINITE || timeout > 0 ,
483         r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
484         "[E_OUT_OF_RANGE] The designated timeout SHOUL be greater than 0");
485
486         pFactory = _ImageUriDataFactory::GetInstance();
487         SysTryCatch(NID_MEDIA, pFactory != null, r = GetLastResult(), r,
488         "[%s] Failed to GetInstance().", GetErrorMessage(r));
489
490         r = pFactory->DecodeUrl(srcImageUrl, colorFormat, destWidth,destHeight, reqId, listener, timeout);
491         SysTryCatch(NID_MEDIA, r == E_SUCCESS , , r,"[%s] Propagated.", GetErrorMessage(r));
492
493         if (__pUrlReqIDList.get() == null)
494         {
495                 __pUrlReqIDList.reset(new (std::nothrow)Collection::LinkedList());
496                 SysTryCatch(NID_MEDIA, __pUrlReqIDList.get() != null, r = E_OUT_OF_MEMORY, r,
497                         "[E_OUT_OF_MEMORY] Propagated. Failed to allocate a LinkedList.", GetErrorMessage(r));
498         }
499         __pUrlReqIDList->Add(new (std::nothrow) Integer(reqId));
500
501         return r;
502
503 CATCH:
504         return r;
505 }
506
507 ByteBuffer*
508 _ImageImpl::EncodeToBufferN(const Bitmap& srcBmp, ImageFormat dstFormat)
509 {
510         std::unique_ptr<ByteBuffer> pBuf;
511         BufferInfo bmpInfo;
512         Dimension dim;
513
514         // ClearLastResult();
515
516         Tizen::Graphics::Bitmap& tmpBmp = const_cast<Tizen::Graphics::Bitmap&>(srcBmp);
517
518         // Create src buf
519         tmpBmp.Lock(bmpInfo);
520
521         dim.SetSize(bmpInfo.width, bmpInfo.height);
522
523         // TODO: handle case that pitch != width * bpp/8
524         SysTryReturn(NID_MEDIA, bmpInfo.pitch == bmpInfo.width*bmpInfo.bitsPerPixel/8, null, E_SYSTEM,
525                            "[E_SYSTEM] pitch=%d bpp=%d", bmpInfo.pitch, bmpInfo.bitsPerPixel);
526
527         pBuf.reset(_ImageEncoder::EncodeN(dstFormat, (const byte*)bmpInfo.pPixels, bmpInfo.pitch * bmpInfo.height,
528                                                            dim.width, dim.height,
529                                                            _ImageUtilImpl::ToMediaPixelFormat(srcBmp.GetPixelColorFormat()),
530                                                            _DEFAULT_ENCODE_QUALITY));
531         SysTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(), "[%s] Propagated. ", GetErrorMessage(GetLastResult()));
532
533         return pBuf.release();
534 }
535
536 result
537 _ImageImpl::EncodeToFile(const Bitmap& srcBmp, ImageFormat dstFormat,
538                                                  const String& dstPath, bool overwrite)
539 {
540         result r = E_SUCCESS;
541         std::unique_ptr<ByteBuffer> pBuf;
542
543         pBuf.reset(EncodeToBufferN(srcBmp, dstFormat));
544         SysTryReturn(NID_MEDIA, pBuf.get() != null, GetLastResult(), GetLastResult(),
545                            "[%s] Propagated.", GetErrorMessage(GetLastResult()));
546
547         r = _MediaUtil::BufferToFile(*pBuf.get(), dstPath, overwrite);
548         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagated. ", GetErrorMessage(r));
549
550         SetLastResult(r);
551         return r;
552 }
553
554 Tizen::Base::ByteBuffer*
555 _ImageImpl::CompressJpegN(const Tizen::Base::ByteBuffer& srcImageBuf, int limitSize)
556 {
557         result r = E_SUCCESS;
558         std::unique_ptr<ByteBuffer> pDecBuf;
559         std::unique_ptr<ByteBuffer> pEncBuf;
560         Dimension srcDim;
561         _ImageDecoder dec;
562         volatile int limit = limitSize;
563         MediaPixelFormat pixelFormat = MEDIA_PIXEL_FORMAT_BGRA8888;
564
565         // TODO : use yuv pixel format
566
567         r = dec.Construct(srcImageBuf, pixelFormat);
568         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Decoder construct failed.", GetErrorMessage(r));
569
570         pDecBuf.reset(dec.DecodeN());
571         r = GetLastResult();
572         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
573         SysTryReturn(NID_MEDIA, pDecBuf.get() != null, null, E_SYSTEM, "[E_SYSTEM] Propagated.");
574
575         r = dec.GetDimension(srcDim.width, srcDim.height);
576         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
577
578         for (int i = 0; i < _MAX_ENCODE_RESIZE_LOOP; i++)
579         {
580                 Dimension dstDim;
581                 ByteBuffer *pTmpBuf = null;
582
583                 pEncBuf.reset(EncodeToBufferLimitN(*pDecBuf.get(), srcDim, pixelFormat, IMG_FORMAT_JPG, limit));
584
585                 if (pEncBuf.get() != null)
586                 {
587                         break;
588                 }
589
590                 // halve and make even number
591                 dstDim.width = srcDim.width >> 2;
592                 dstDim.height = srcDim.height >> 2;
593
594                 dstDim.width = dstDim.width << 1;
595                 dstDim.height = dstDim.height << 1;
596
597                 SysTryReturn(NID_MEDIA, srcDim != dstDim && dstDim.width > 0 && dstDim.height > 0, null, E_SYSTEM,
598                                    "[E_SYSTEM] Resize failed:src:%dx%d dst:%dx%d, %d %d, %d",
599                                    srcDim.width, srcDim.height, dstDim.width, dstDim.height, i, _SCALE_DOWN_RATIO,
600                                    limit);
601
602                 pTmpBuf = _ImageUtilImpl::ResizeN(*pDecBuf.get(), srcDim, pixelFormat, dstDim);
603                 SysTryReturn(NID_MEDIA, pTmpBuf != null, null, GetLastResult(),
604                                    "[%s] ResizeN: %dx%d->%dx%d", GetErrorMessage(GetLastResult()),
605                                    srcDim.width, srcDim.height, dstDim.width, dstDim.height);
606
607                 srcDim = dstDim;
608                 pDecBuf.reset(pTmpBuf);
609         }
610         SysTryReturn(NID_MEDIA, pEncBuf.get() != null, null, E_SYSTEM, "[E_SYSTEM] Compress failed");
611         SetLastResult(E_SUCCESS);
612         return pEncBuf.release();
613 }
614
615 result
616 _ImageImpl::CompressJpeg(const Tizen::Base::String& srcImagePath,
617                                                  const Tizen::Base::String& dstImagePath, int limitSize)
618 {
619         File file;
620         result r = E_SUCCESS;
621         std::unique_ptr<ByteBuffer> pSrcBuf;
622         std::unique_ptr<ByteBuffer> pEncBuf;
623
624         pSrcBuf.reset(_MediaUtil::FileToBufferN(srcImagePath));
625         SysTryReturn(NID_MEDIA, pSrcBuf.get() != null, GetLastResult(), GetLastResult(),
626                            "[%s] Propagated. ", GetErrorMessage(GetLastResult()));
627
628 //      SysTryCatch(NID_MEDIA, pSrcBuf->GetCapacity() < MAX_IMGFILE_SIZE, r = E_OVERFLOW, E_OVERFLOW,
629 //                         "[E_OUT_OF_RANGE] Input file size is smaller than limitSize.");
630
631         SysTryReturn(NID_MEDIA, pSrcBuf.get()->GetCapacity() > limitSize, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
632                            "[E_OUT_OF_RANGE] Input file size is smaller than limitSize.");
633
634         pEncBuf.reset(CompressJpegN(*pSrcBuf, limitSize));
635         SysTryReturn(NID_MEDIA, pEncBuf != null, GetLastResult(), GetLastResult(),
636                            "[%s] Propagated. ", GetErrorMessage(GetLastResult()));
637
638         if (File::IsFileExist(dstImagePath))
639         {
640                 File::Remove(dstImagePath);
641         }
642
643         r = file.Construct(dstImagePath, "wb", true);
644         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagated. ", GetErrorMessage(r));
645         r = file.Write(*pEncBuf);
646         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagated. ", GetErrorMessage(r));
647
648         return r;
649 }
650
651 Tizen::Base::ByteBuffer*
652 _ImageImpl::ConvertToBufferN(const Tizen::Base::String& srcImagePath, ImageFormat destImageFormat)
653 {
654         std::unique_ptr<Bitmap> pBmp;
655         ByteBuffer* pBuf = null;
656
657         pBmp.reset(DecodeToBitmapN(srcImagePath, BITMAP_PIXEL_FORMAT_ARGB8888, Dimension(0, 0),
658                                                    BUFFER_SCALING_NONE));
659         SysTryReturn(NID_MEDIA, pBmp.get(), null, GetLastResult(),
660                            "[%s] Propagated. ", GetErrorMessage(GetLastResult()));
661
662         pBuf = EncodeToBufferN(*pBmp.get(), destImageFormat);
663         SysTryReturn(NID_MEDIA, pBuf != null, null, GetLastResult(),
664                            "[%s] Propagated.", GetErrorMessage(GetLastResult()));
665
666         SetLastResult(E_SUCCESS);
667         return pBuf;
668 }
669
670 Tizen::Base::ByteBuffer*
671 _ImageImpl::EncodeToBufferLimitN(const Tizen::Base::ByteBuffer &srcBuf,
672                                                                  const Tizen::Graphics::Dimension& dim,
673                                                                  MediaPixelFormat pixelFormat, ImageFormat imgFormat, int limit)
674 {
675         int minQuality = _MIN_ENCODE_QUALITY;
676         int maxQuality = _MAX_ENCODE_QUALITY;
677         int curQuality = 0;
678         int minDiff = 0;
679         int maxDiff = 0;
680
681         std::unique_ptr<ByteBuffer> pMaxBuf;
682         std::unique_ptr<ByteBuffer> pMinBuf;
683
684         pMaxBuf.reset(EncodeToBufferQualityN(srcBuf, dim, pixelFormat, imgFormat, maxQuality));
685         SysTryReturn(NID_MEDIA, pMaxBuf.get() != null, pMinBuf.get(), E_SYSTEM, "[E_SYSTEM] maxBuf is null");
686         maxDiff = pMaxBuf->GetLimit() - limit;
687         SysLog(NID_MEDIA, "maxDiff:%d buf:%d limit:%d q:%d",
688                                 maxDiff, pMaxBuf->GetLimit(), limit, maxQuality);
689         if (maxDiff <= 0)
690         {
691                 SetLastResult(E_SUCCESS);
692                 return pMaxBuf.release();
693         }
694         pMinBuf.reset(EncodeToBufferQualityN(srcBuf, dim, pixelFormat, imgFormat, minQuality));
695         SysTryReturn(NID_MEDIA, pMinBuf.get() != null, pMinBuf.release(), E_SYSTEM, "[E_SYSTEM] minBuf is null");
696         minDiff = pMinBuf->GetLimit() - limit;
697         SysLog(NID_MEDIA, "minDiff:%d buf:%d limit:%d q:%d",
698                                         minDiff, pMinBuf->GetLimit(), limit, minQuality);
699         if (minDiff > 0)
700         {
701                 SetLastResult(E_OVERFLOW);
702                 return null;
703         }
704         if (minDiff == 0)
705         {
706                 SetLastResult(E_SUCCESS);
707                 return pMinBuf.release();
708         }
709
710         for (int i = 0; i < _MAX_ENCODE_LOOP; i++)
711         {
712                 int prevQuality = curQuality;
713                 int curDiff = 0;
714                 ByteBuffer *pCurBuf = null;
715
716                 curQuality = (minQuality + maxQuality) / 2;
717                 if (prevQuality == curQuality)
718                 {
719                         break;
720                 }
721                 pCurBuf = EncodeToBufferQualityN(srcBuf, dim, pixelFormat, imgFormat, curQuality);
722                 if (pCurBuf == null && pMinBuf.get() != null)
723                 {
724                         break;
725                 }
726                 SysTryReturn(NID_MEDIA, pCurBuf != null, pMinBuf.release(), E_SYSTEM,
727                                    "[E_SYSTEM] curBuf is null : %d %d %d", dim.width, dim.height, curQuality);
728                 curDiff = pCurBuf->GetLimit() - limit;
729                 SysLog(NID_MEDIA, "curDiff:%d buf:%d limit:%d q:%d",
730                                         curDiff, pCurBuf->GetLimit(), limit, curQuality);
731                 if (curDiff == 0)
732                 {
733                         SetLastResult(E_SUCCESS);
734                         return pCurBuf;
735                 }
736                 else if (curDiff > 0)
737                 {
738                         maxDiff = curDiff;
739                         maxQuality = curQuality;
740                         pMaxBuf.reset(pCurBuf);
741                 }
742                 else if (curDiff < 0)
743                 {
744                         pMinBuf.reset(pCurBuf);
745                         minDiff = curDiff;
746                         minQuality = curQuality;
747                 }
748         }
749         if (pMinBuf.get())
750         {
751                 SetLastResult(E_SUCCESS);
752         }
753         else
754         {
755                 // should not come here.
756                 SetLastResult(E_SYSTEM);
757         }
758         return pMinBuf.release();
759 }
760
761 Tizen::Base::ByteBuffer*
762 _ImageImpl::EncodeToBufferQualityN(const Tizen::Base::ByteBuffer &srcBuf,
763                                                                    const Tizen::Graphics::Dimension& dim,
764                                                                    MediaPixelFormat pixelFormat, ImageFormat imgFormat, int quality)
765 {
766         ByteBuffer* pBuf = null;
767
768         pBuf = _ImageEncoder::EncodeN(imgFormat, srcBuf.GetPointer(), srcBuf.GetLimit(),
769                                                            dim.width, dim.height, pixelFormat, quality);
770         SysTryReturn(NID_MEDIA, pBuf != null, pBuf, GetLastResult(),
771                 "[%s] enc.EncodeN. ", GetErrorMessage(GetLastResult()));
772
773         return pBuf;
774 }
775
776 result
777 _ImageImpl::GetImageInfo(const Tizen::Base::String& path, ImageFormat &imgFormat,
778                                                  Tizen::Graphics::Dimension &dim)
779 {
780         return _ImageDecoder::GetImageInfo(path, imgFormat, dim.width, dim.height);
781 }
782
783 }} // Tizen::Media