a89f3ff59288cfcd4a45c47e6f3c825c83c35560
[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 }
60
61 _ImageImpl::~_ImageImpl(void)
62 {
63 }
64
65 _ImageImpl*
66 _ImageImpl::GetInstance(Image* pImage)
67 {
68         if (pImage != null)
69         {
70                 return pImage->__pImageImpl;
71         }
72
73         return null;
74 }
75
76 const _ImageImpl*
77 _ImageImpl::GetInstance(const Image* pImage)
78 {
79         if (pImage != null)
80         {
81                 return pImage->__pImageImpl;
82         }
83
84         return null;
85 }
86
87 result
88 _ImageImpl::Construct(void)
89 {
90         return E_SUCCESS;
91 }
92
93 Bitmap* 
94 _ImageImpl::DecodeToBitmapN(const Tizen::Base::String& srcImagePath, Tizen::Graphics::BitmapPixelFormat pixelFormat)
95 {
96         std::unique_ptr<ByteBuffer> pBuf;
97         Bitmap* pBmp = null;
98
99         pBuf.reset(_MediaUtil::FileToBufferN(srcImagePath));
100         SysTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
101                            "[%s] FileToBufferN %S", GetErrorMessage(GetLastResult()), srcImagePath.GetPointer());
102
103         pBmp = DecodeToBitmapN(*pBuf.get(), pixelFormat);
104         return pBmp;
105 }
106
107 Bitmap* 
108 _ImageImpl::DecodeToBitmapN(const Tizen::Base::ByteBuffer& srcImageBuf, Tizen::Graphics::BitmapPixelFormat pixelFormat)
109 {
110         result r = E_SUCCESS;
111         std::unique_ptr<ByteBuffer> pBuf;
112         std::unique_ptr<Bitmap> pBmp;
113         Dimension outDim;
114
115         _ImageDecoder dec;
116
117         r = dec.Construct(srcImageBuf, _ImageUtilImpl::ToMediaPixelFormat(pixelFormat));
118         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Decoder construct failed.", GetErrorMessage(r));
119
120         pBuf.reset(dec.DecodeN());
121         SysTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
122                            "[%s] Propagated", GetErrorMessage(GetLastResult()));
123         r = GetLastResult();
124         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
125
126         r = dec.GetDimension(outDim.width, outDim.height);
127         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
128
129         pBmp.reset(new (std::nothrow) Bitmap);
130         SysTryReturn(NID_MEDIA, pBmp != null, null, E_OUT_OF_MEMORY,
131                            "[%s] new Bitmap", GetErrorMessage(GetLastResult()));
132         r = pBmp->Construct(*pBuf.get(), outDim, pixelFormat, BUFFER_SCALING_AUTO);
133         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
134
135         SetLastResult(E_SUCCESS);
136         return pBmp.release();
137 }
138
139 Bitmap*
140 _ImageImpl::DecodeToBitmapN(const Tizen::Base::String& srcImagePath, Tizen::Graphics::BitmapPixelFormat pixelFormat, const Tizen::Graphics::Dimension &destDim,
141                                                         Tizen::Graphics::BufferScaling bufferScaling)
142 {
143         std::unique_ptr<ByteBuffer> pBuf;
144         Bitmap* pBmp = null;
145
146         pBuf.reset(_MediaUtil::FileToBufferN(srcImagePath));
147         SysTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
148                            "[%s] FileToBufferN %S", GetErrorMessage(GetLastResult()), srcImagePath.GetPointer());
149
150         pBmp = DecodeToBitmapN(*pBuf.get(), pixelFormat, destDim, bufferScaling);
151         return pBmp;
152 }
153
154 Bitmap*
155 _ImageImpl::DecodeToBitmapN(const Tizen::Base::ByteBuffer& srcImageBuf, Tizen::Graphics::BitmapPixelFormat pixelFormat, const Tizen::Graphics::Dimension &destDim,
156                                                         Tizen::Graphics::BufferScaling bufferScaling)
157 {
158         result r = E_SUCCESS;
159         std::unique_ptr<ByteBuffer> pBuf;
160         std::unique_ptr<Bitmap> pBmp;
161         Dimension outDim;
162
163         _ImageDecoder dec;
164
165         r = dec.Construct(srcImageBuf, _ImageUtilImpl::ToMediaPixelFormat(pixelFormat));
166         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Decoder construct failed.", GetErrorMessage(r));
167
168         // Reset decoder output demension
169         dec.SetOutputDimension(destDim.width, destDim.height, true);
170
171         pBuf.reset(dec.DecodeN());
172         SysTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
173                            "[%s] Propagated", GetErrorMessage(GetLastResult()));
174         r = GetLastResult();
175         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
176
177         r = dec.GetDimension(outDim.width, outDim.height);
178         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
179
180         pBmp.reset(new (std::nothrow) Bitmap);
181         SysTryReturn(NID_MEDIA, pBmp != null, null, E_OUT_OF_MEMORY,
182                            "[%s] new Bitmap", GetErrorMessage(GetLastResult()));
183         r = pBmp->Construct(*pBuf.get(), outDim, pixelFormat, bufferScaling);
184         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
185
186         SetLastResult(E_SUCCESS);
187         return pBmp.release();
188 }
189
190 Bitmap*
191 _ImageImpl::DecodeToBitmapN(const Tizen::Base::ByteBuffer& srcImageBuf, Tizen::Graphics::BitmapPixelFormat pixelFormat,
192                                                         const Tizen::Graphics::FloatDimension &destDim)
193 {
194         result r = E_SUCCESS;
195         std::unique_ptr<ByteBuffer> pBuf;
196         std::unique_ptr<Bitmap> pBmp;
197         Dimension orgDim, tmpDim;
198         FloatDimension outDim;
199         BufferInfo bufInfo;
200
201         _ImageDecoder dec;
202
203         r = dec.Construct(srcImageBuf, _ImageUtilImpl::ToMediaPixelFormat(pixelFormat));
204         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Decoder construct failed.", GetErrorMessage(r));
205
206         r = dec.GetDimension(orgDim.width, orgDim.height);
207         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
208
209         // Reset decoder output demension
210         dec.SetOutputDimension(_CoordinateSystemUtils::ConvertToInteger(destDim.width),
211                                                    _CoordinateSystemUtils::ConvertToInteger(destDim.height),
212                                                    true);
213
214         pBuf.reset(dec.DecodeN());
215         SysTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
216                            "[%s] Propagated", GetErrorMessage(GetLastResult()));
217
218         r = dec.GetDimension(tmpDim.width, tmpDim.height);
219         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
220
221         r = _ImageUtil::GetResizedDimension(orgDim.width, orgDim.height, destDim.width, destDim.height, outDim.width, outDim.height);
222         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
223
224         pBmp.reset(new (std::nothrow) Bitmap);
225         SysTryReturn(NID_MEDIA, pBmp.get() != null, null, E_OUT_OF_MEMORY,
226                            "[%s] new Bitmap", GetErrorMessage(GetLastResult()));
227
228         pBmp.reset(_BitmapImpl::GetNonScaledBitmapN(*pBuf.get(), tmpDim, pixelFormat, destDim));
229         SetLastResult(E_SUCCESS);
230         return pBmp.release();
231 }
232
233 Bitmap*
234 _ImageImpl::DecodeToBitmapN(const Tizen::Base::String& srcImagePath, Tizen::Graphics::BitmapPixelFormat pixelFormat,
235                                                         const Tizen::Graphics::FloatDimension &destDim)
236 {
237         std::unique_ptr<ByteBuffer> pBuf;
238         Bitmap* pBmp = null;
239
240         pBuf.reset(_MediaUtil::FileToBufferN(srcImagePath));
241         SysTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
242                            "[%s] FileToBufferN %S", GetErrorMessage(GetLastResult()), srcImagePath.GetPointer());
243
244         pBmp = DecodeToBitmapN(*pBuf.get(), pixelFormat, destDim);
245         return pBmp;
246 }
247
248 Tizen::Base::ByteBuffer*
249 _ImageImpl::DecodeToBufferN(const Tizen::Base::String& srcImagePath,
250                                                         Tizen::Graphics::Dimension &restDim,
251                                                         const Tizen::Graphics::Dimension &dstDim,
252                                                         Tizen::Graphics::BitmapPixelFormat pixelFormat,
253                                                         ImageFormat imgFormat, bool keepAspectRatio)
254 {
255         std::unique_ptr<ByteBuffer> pBuf;
256         ByteBuffer* pRetBuf = null;
257
258         //SysTryCatch(NID_MEDIA, IS_VALID_DIMENSION(dstDim), , E_OUT_OF_RANGE,
259         //"[E_OUT_OF_RANGE] dest dimension:%d,%d", dstDim.width, dstDim.height);
260
261         pBuf.reset(_MediaUtil::FileToBufferN(srcImagePath));
262         SysTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(),
263                            "[%s] FileToBufferN %S", GetErrorMessage(GetLastResult()), srcImagePath.GetPointer());
264
265         pRetBuf = DecodeToBufferN(*pBuf.get(), restDim, dstDim, pixelFormat, imgFormat, keepAspectRatio);
266         return pRetBuf;
267 }
268
269 Tizen::Base::ByteBuffer*
270 _ImageImpl::DecodeToBufferN(const Tizen::Base::ByteBuffer &srcImageBuf,
271                                                         Tizen::Graphics::Dimension &retDim,
272                                                         const Tizen::Graphics::Dimension &dstDim,
273                                                         Tizen::Graphics::BitmapPixelFormat pixelFormat,
274                                                         ImageFormat imgFormat, bool keepAspectRatio)
275 {
276         result r = E_SUCCESS;
277         std::unique_ptr<ByteBuffer> pBuf;
278         _ImageDecoder dec;
279
280         //SysTryCatch(NID_MEDIA, IS_VALID_BITMAP_PIXEL(pixelFormat), , E_INVALID_ARG,
281         //"[E_INVALID_ARG] pixelFormat:%d", pixelFormat);
282
283         r = dec.Construct(srcImageBuf, _ImageUtilImpl::ToMediaPixelFormat(pixelFormat), imgFormat);
284         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Decoder construct failed.", GetErrorMessage(r));
285
286         // Reset decoder output demension
287         dec.SetOutputDimension(dstDim.width, dstDim.height, keepAspectRatio);
288
289         pBuf.reset(dec.DecodeN());
290         r = GetLastResult();
291         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
292
293         r = dec.GetDimension(retDim.width, retDim.height);
294         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
295
296         SetLastResult(E_SUCCESS);
297         return pBuf.release();
298 }
299
300 Tizen::Base::ByteBuffer*
301 _ImageImpl::DecodeToBufferN(const Tizen::Base::String& srcImagePath,
302                                                         Tizen::Graphics::BitmapPixelFormat pixelFormat,
303                                                         int& imageWidth, int& imageHeight, bool keepAspectRatio)
304 {
305         ByteBuffer *pBuf = null;
306         Dimension dim;
307
308         pBuf = DecodeToBufferN(srcImagePath, dim, Dimension(0, 0), pixelFormat, IMG_FORMAT_NONE, keepAspectRatio);
309         imageWidth = dim.width;
310         imageHeight = dim.height;
311         return pBuf;
312 }
313
314
315 Tizen::Base::ByteBuffer*
316 _ImageImpl::DecodeN(const Tizen::Base::String& srcImagePath,
317                                         Tizen::Graphics::BitmapPixelFormat pixelFormat,
318                                         int destWidth, int destHeight, bool keepAspectRatio)
319 {
320         Dimension dim;
321
322         return DecodeToBufferN(srcImagePath, dim, Dimension(destWidth, destHeight), pixelFormat, IMG_FORMAT_NONE, keepAspectRatio);
323 }
324
325 result
326 _ImageImpl::DecodeUrl(const Tizen::Base::Utility::Uri& srcImageUrl,
327                                           Tizen::Graphics::BitmapPixelFormat colorFormat,
328                                           int destWidth, int destHeight, RequestId& reqId,
329                                           const IImageDecodeUrlEventListener& listener, long timeout)
330 {
331         result r = E_SUCCESS;
332
333         _ImageUriDataFactory *pFactory = null;
334
335         SysTryCatch(NID_MEDIA, (colorFormat > Tizen::Graphics::BITMAP_PIXEL_FORMAT_MIN)
336         && colorFormat < Tizen::Graphics::BITMAP_PIXEL_FORMAT_MAX, , E_INVALID_ARG,
337         "[E_INVALID_ARG] Wrong color format.");
338
339         SysTryCatch(NID_MEDIA, destWidth > 0 && destHeight > 0, , E_OUT_OF_RANGE,
340         "[E_OUT_OF_RANGE] The designated width and height SHOUL be greater than 0.");
341
342         SysTryCatch(NID_MEDIA, timeout == _TIMEOUT_INFINITE || timeout > 0 ,
343         r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
344         "[E_OUT_OF_RANGE] The designated timeout SHOUL be greater than 0");
345
346         pFactory = _ImageUriDataFactory::GetInstance();
347         SysTryCatch(NID_MEDIA, pFactory != null, r = GetLastResult(), r,
348         "[%s] Failed to GetInstance().", GetErrorMessage(r));
349
350         r = pFactory->DecodeUrl(srcImageUrl, colorFormat, destWidth,destHeight, reqId, listener, timeout);
351         SysTryCatch(NID_MEDIA, r == E_SUCCESS , , r,"[%s] Propagated.", GetErrorMessage(r));
352
353         return r;
354
355 CATCH:
356         return r;
357 }
358
359 ByteBuffer*
360 _ImageImpl::EncodeToBufferN(const Bitmap& srcBmp, ImageFormat dstFormat)
361 {
362         std::unique_ptr<ByteBuffer> pBuf;
363         BufferInfo bmpInfo;
364         Dimension dim;
365
366         // ClearLastResult();
367
368         Tizen::Graphics::Bitmap& tmpBmp = const_cast<Tizen::Graphics::Bitmap&>(srcBmp);
369
370         // Create src buf
371         tmpBmp.Lock(bmpInfo);
372
373         dim.SetSize(bmpInfo.width, bmpInfo.height);
374
375         // TODO: handle case that pitch != width * bpp/8
376         SysTryReturn(NID_MEDIA, bmpInfo.pitch == bmpInfo.width*bmpInfo.bitsPerPixel/8, null, E_SYSTEM,
377                            "[E_SYSTEM] pitch=%d bpp=%d", bmpInfo.pitch, bmpInfo.bitsPerPixel);
378
379         pBuf.reset(_ImageEncoder::EncodeN(dstFormat, (const byte*)bmpInfo.pPixels, bmpInfo.pitch * bmpInfo.height,
380                                                            dim.width, dim.height,
381                                                            _ImageUtilImpl::ToMediaPixelFormat(srcBmp.GetPixelColorFormat()),
382                                                            _DEFAULT_ENCODE_QUALITY));
383         SysTryReturn(NID_MEDIA, pBuf.get() != null, null, GetLastResult(), "[%s] Propagated. ", GetErrorMessage(GetLastResult()));
384
385         return pBuf.release();
386 }
387
388 result
389 _ImageImpl::EncodeToFile(const Bitmap& srcBmp, ImageFormat dstFormat,
390                                                  const String& dstPath, bool overwrite)
391 {
392         result r = E_SUCCESS;
393         std::unique_ptr<ByteBuffer> pBuf;
394
395         pBuf.reset(EncodeToBufferN(srcBmp, dstFormat));
396         SysTryReturn(NID_MEDIA, pBuf.get() != null, GetLastResult(), GetLastResult(),
397                            "[%s] Propagated.", GetErrorMessage(GetLastResult()));
398
399         r = _MediaUtil::BufferToFile(*pBuf.get(), dstPath, overwrite);
400         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagated. ", GetErrorMessage(r));
401
402         SetLastResult(r);
403         return r;
404 }
405
406 Tizen::Base::ByteBuffer*
407 _ImageImpl::CompressJpegN(const Tizen::Base::ByteBuffer& srcImageBuf, int limitSize)
408 {
409         result r = E_SUCCESS;
410         std::unique_ptr<ByteBuffer> pDecBuf;
411         std::unique_ptr<ByteBuffer> pEncBuf;
412         Dimension srcDim;
413         _ImageDecoder dec;
414         volatile int limit = limitSize;
415         MediaPixelFormat pixelFormat = MEDIA_PIXEL_FORMAT_BGRA8888;
416
417         // TODO : use yuv pixel format
418
419         r = dec.Construct(srcImageBuf, pixelFormat);
420         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Decoder construct failed.", GetErrorMessage(r));
421
422         pDecBuf.reset(dec.DecodeN());
423         r = GetLastResult();
424         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
425         SysTryReturn(NID_MEDIA, pDecBuf.get() != null, null, E_SYSTEM, "[E_SYSTEM] Propagated.");
426
427         r = dec.GetDimension(srcDim.width, srcDim.height);
428         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ", GetErrorMessage(r));
429
430         for (int i = 0; i < _MAX_ENCODE_RESIZE_LOOP; i++)
431         {
432                 Dimension dstDim;
433                 ByteBuffer *pTmpBuf = null;
434
435                 pEncBuf.reset(EncodeToBufferLimitN(*pDecBuf.get(), srcDim, pixelFormat, IMG_FORMAT_JPG, limit));
436
437                 if (pEncBuf.get() != null)
438                 {
439                         break;
440                 }
441
442                 // halve and make even number
443                 dstDim.width = srcDim.width >> 2;
444                 dstDim.height = srcDim.height >> 2;
445
446                 dstDim.width = dstDim.width << 1;
447                 dstDim.height = dstDim.height << 1;
448
449                 SysTryReturn(NID_MEDIA, srcDim != dstDim && dstDim.width > 0 && dstDim.height > 0, null, E_SYSTEM,
450                                    "[E_SYSTEM] Resize failed:src:%dx%d dst:%dx%d, %d %d, %d",
451                                    srcDim.width, srcDim.height, dstDim.width, dstDim.height, i, _SCALE_DOWN_RATIO,
452                                    limit);
453
454                 pTmpBuf = _ImageUtilImpl::ResizeN(*pDecBuf.get(), srcDim, pixelFormat, dstDim);
455                 SysTryReturn(NID_MEDIA, pTmpBuf != null, null, GetLastResult(),
456                                    "[%s] ResizeN: %dx%d->%dx%d", GetErrorMessage(GetLastResult()),
457                                    srcDim.width, srcDim.height, dstDim.width, dstDim.height);
458
459                 srcDim = dstDim;
460                 pDecBuf.reset(pTmpBuf);
461         }
462         SysTryReturn(NID_MEDIA, pEncBuf.get() != null, null, E_SYSTEM, "[E_SYSTEM] Compress failed");
463         SetLastResult(E_SUCCESS);
464         return pEncBuf.release();
465 }
466
467 result
468 _ImageImpl::CompressJpeg(const Tizen::Base::String& srcImagePath,
469                                                  const Tizen::Base::String& dstImagePath, int limitSize)
470 {
471         File file;
472         result r = E_SUCCESS;
473         std::unique_ptr<ByteBuffer> pSrcBuf;
474         std::unique_ptr<ByteBuffer> pEncBuf;
475
476         pSrcBuf.reset(_MediaUtil::FileToBufferN(srcImagePath));
477         SysTryReturn(NID_MEDIA, pSrcBuf.get() != null, GetLastResult(), GetLastResult(),
478                            "[%s] Propagated. ", GetErrorMessage(GetLastResult()));
479
480 //      SysTryCatch(NID_MEDIA, pSrcBuf->GetCapacity() < MAX_IMGFILE_SIZE, r = E_OVERFLOW, E_OVERFLOW,
481 //                         "[E_OUT_OF_RANGE] Input file size is smaller than limitSize.");
482
483         SysTryReturn(NID_MEDIA, pSrcBuf.get()->GetCapacity() > limitSize, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
484                            "[E_OUT_OF_RANGE] Input file size is smaller than limitSize.");
485
486         pEncBuf.reset(CompressJpegN(*pSrcBuf, limitSize));
487         SysTryReturn(NID_MEDIA, pEncBuf != null, GetLastResult(), GetLastResult(),
488                            "[%s] Propagated. ", GetErrorMessage(GetLastResult()));
489
490         if (File::IsFileExist(dstImagePath))
491         {
492                 File::Remove(dstImagePath);
493         }
494
495         r = file.Construct(dstImagePath, "wb", true);
496         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagated. ", GetErrorMessage(r));
497         r = file.Write(*pEncBuf);
498         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagated. ", GetErrorMessage(r));
499
500         return r;
501 }
502
503 Tizen::Base::ByteBuffer*
504 _ImageImpl::ConvertToBufferN(const Tizen::Base::String& srcImagePath, ImageFormat destImageFormat)
505 {
506         std::unique_ptr<Bitmap> pBmp;
507         ByteBuffer* pBuf = null;
508
509         pBmp.reset(DecodeToBitmapN(srcImagePath, BITMAP_PIXEL_FORMAT_ARGB8888, Dimension(0, 0),
510                                                    BUFFER_SCALING_NONE));
511         SysTryReturn(NID_MEDIA, pBmp.get(), null, GetLastResult(),
512                            "[%s] Propagated. ", GetErrorMessage(GetLastResult()));
513
514         pBuf = EncodeToBufferN(*pBmp.get(), destImageFormat);
515         SysTryReturn(NID_MEDIA, pBuf != null, null, GetLastResult(),
516                            "[%s] Propagated.", GetErrorMessage(GetLastResult()));
517
518         SetLastResult(E_SUCCESS);
519         return pBuf;
520 }
521
522 Tizen::Base::ByteBuffer*
523 _ImageImpl::EncodeToBufferLimitN(const Tizen::Base::ByteBuffer &srcBuf,
524                                                                  const Tizen::Graphics::Dimension& dim,
525                                                                  MediaPixelFormat pixelFormat, ImageFormat imgFormat, int limit)
526 {
527         int minQuality = _MIN_ENCODE_QUALITY;
528         int maxQuality = _MAX_ENCODE_QUALITY;
529         int curQuality = 0;
530         int minDiff = 0;
531         int maxDiff = 0;
532
533         std::unique_ptr<ByteBuffer> pMaxBuf;
534         std::unique_ptr<ByteBuffer> pMinBuf;
535
536         pMaxBuf.reset(EncodeToBufferQualityN(srcBuf, dim, pixelFormat, imgFormat, maxQuality));
537         SysTryReturn(NID_MEDIA, pMaxBuf.get() != null, pMinBuf.get(), E_SYSTEM, "[E_SYSTEM] maxBuf is null");
538         maxDiff = pMaxBuf->GetLimit() - limit;
539         SysLog(NID_MEDIA, "maxDiff:%d buf:%d limit:%d q:%d",
540                                 maxDiff, pMaxBuf->GetLimit(), limit, maxQuality);
541         if (maxDiff <= 0)
542         {
543                 SetLastResult(E_SUCCESS);
544                 return pMaxBuf.release();
545         }
546         pMinBuf.reset(EncodeToBufferQualityN(srcBuf, dim, pixelFormat, imgFormat, minQuality));
547         SysTryReturn(NID_MEDIA, pMinBuf.get() != null, pMinBuf.release(), E_SYSTEM, "[E_SYSTEM] minBuf is null");
548         minDiff = pMinBuf->GetLimit() - limit;
549         SysLog(NID_MEDIA, "minDiff:%d buf:%d limit:%d q:%d",
550                                         minDiff, pMinBuf->GetLimit(), limit, minQuality);
551         if (minDiff > 0)
552         {
553                 SetLastResult(E_OVERFLOW);
554                 return null;
555         }
556         if (minDiff == 0)
557         {
558                 SetLastResult(E_SUCCESS);
559                 return pMinBuf.release();
560         }
561
562         for (int i = 0; i < _MAX_ENCODE_LOOP; i++)
563         {
564                 int prevQuality = curQuality;
565                 int curDiff = 0;
566                 ByteBuffer *pCurBuf = null;
567
568                 curQuality = (minQuality + maxQuality) / 2;
569                 if (prevQuality == curQuality)
570                 {
571                         break;
572                 }
573                 pCurBuf = EncodeToBufferQualityN(srcBuf, dim, pixelFormat, imgFormat, curQuality);
574                 if (pCurBuf == null && pMinBuf.get() != null)
575                 {
576                         break;
577                 }
578                 SysTryReturn(NID_MEDIA, pCurBuf != null, pMinBuf.release(), E_SYSTEM,
579                                    "[E_SYSTEM] curBuf is null : %d %d %d", dim.width, dim.height, curQuality);
580                 curDiff = pCurBuf->GetLimit() - limit;
581                 SysLog(NID_MEDIA, "curDiff:%d buf:%d limit:%d q:%d",
582                                         curDiff, pCurBuf->GetLimit(), limit, curQuality);
583                 if (curDiff == 0)
584                 {
585                         SetLastResult(E_SUCCESS);
586                         return pCurBuf;
587                 }
588                 else if (curDiff > 0)
589                 {
590                         maxDiff = curDiff;
591                         maxQuality = curQuality;
592                         pMaxBuf.reset(pCurBuf);
593                 }
594                 else if (curDiff < 0)
595                 {
596                         pMinBuf.reset(pCurBuf);
597                         minDiff = curDiff;
598                         minQuality = curQuality;
599                 }
600         }
601         if (pMinBuf.get())
602         {
603                 SetLastResult(E_SUCCESS);
604         }
605         else
606         {
607                 // should not come here.
608                 SetLastResult(E_SYSTEM);
609         }
610         return pMinBuf.release();
611 }
612
613 Tizen::Base::ByteBuffer*
614 _ImageImpl::EncodeToBufferQualityN(const Tizen::Base::ByteBuffer &srcBuf,
615                                                                    const Tizen::Graphics::Dimension& dim,
616                                                                    MediaPixelFormat pixelFormat, ImageFormat imgFormat, int quality)
617 {
618         ByteBuffer* pBuf = null;
619
620         pBuf = _ImageEncoder::EncodeN(imgFormat, srcBuf.GetPointer(), srcBuf.GetLimit(),
621                                                            dim.width, dim.height, pixelFormat, quality);
622         SysTryReturn(NID_MEDIA, pBuf != null, pBuf, GetLastResult(),
623                 "[%s] enc.EncodeN. ", GetErrorMessage(GetLastResult()));
624
625         return pBuf;
626 }
627
628 result
629 _ImageImpl::GetImageInfo(const Tizen::Base::String& path, ImageFormat &imgFormat,
630                                                  Tizen::Graphics::Dimension &dim)
631 {
632         return _ImageDecoder::GetImageInfo(path, imgFormat, dim.width, dim.height);
633 }
634
635 }} // Tizen::Media