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