#include <unique_ptr.h>
#include <FBaseColArrayListT.h>
#include <FBaseSysLog.h>
-#include <FMediaImageTypes.h>
#include <FBaseInteger.h>
#include <FIoFile.h>
#include <FMediaImageTypes.h>
#include "FMedia_TiffDecoder.h"
#include "FMedia_WbmpDecoder.h"
#include "FMedia_ImageUtil.h"
+#include "FMedia_ExifUtil.h"
using namespace Tizen::Base;
using namespace Tizen::Io;
((x == MEDIA_PIXEL_FORMAT_RGB565LE) || (x == MEDIA_PIXEL_FORMAT_BGRA8888) \
|| (x == MEDIA_PIXEL_FORMAT_RGBA8888))
+typedef struct {
+ ImageRotationType rotateType;
+ ImageFlipType flipType;
+ bool dimensionSwitch;
+} _ImageExifInfo;
+
+static const _ImageExifInfo _IMAGE_ROTATE_FLIP_MAP[] = {
+ { IMAGE_ROTATION_0, IMAGE_FLIP_NONE, false }, /* NONE */
+ { IMAGE_ROTATION_0, IMAGE_FLIP_NONE, false }, /* TOP_LEFT */
+ { IMAGE_ROTATION_0, IMAGE_FLIP_VERTICAL, false }, /* TOP_RIGHT */
+ { IMAGE_ROTATION_180, IMAGE_FLIP_NONE, false }, /* BOTTOM_RIGHT */
+ { IMAGE_ROTATION_0, IMAGE_FLIP_HORIZONTAL, false }, /* BOTTOM_LEFT */
+ { IMAGE_ROTATION_90, IMAGE_FLIP_VERTICAL, true }, /* LEFT_TOP */
+ { IMAGE_ROTATION_90, IMAGE_FLIP_NONE, true }, /* RIGHT_TOP */
+ { IMAGE_ROTATION_90, IMAGE_FLIP_HORIZONTAL, true }, /* RIGHT_BOTTOM */
+ { IMAGE_ROTATION_270, IMAGE_FLIP_NONE, true } /* LEFT_BOTTOM */
+};
+
Tizen::Base::ByteBuffer*
_ImageDecoder::DecodeToBufferN(const Tizen::Base::String& filePath,
- MediaPixelFormat pixelFormat, int &width, int &height)
+ MediaPixelFormat pixelFormat, int &width, int &height, bool autoRotate)
{
result r = E_SUCCESS;
+
std::unique_ptr<ByteBuffer> pBuf;
_ImageDecoder dec;
SysTryReturn(NID_MEDIA, File::IsFileExist(filePath), null, E_FILE_NOT_FOUND,
"[E_FILE_NOT_FOUND] filePath:%ls", filePath.GetPointer());
- r = dec.Construct(filePath, pixelFormat);
+ r = dec.Construct(filePath, pixelFormat, IMG_FORMAT_NONE, autoRotate);
SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
"[%s] Decoder construct failed.", GetErrorMessage(r));
__outDim.width = 0;
__outDim.height = 0;
__pSrcBuf = null;
+ __autoRotate = false;
+ __orientationInfo = 0;
}
_ImageDecoder::~_ImageDecoder(void)
result
_ImageDecoder::Construct(const Tizen::Base::String& srcPath,
MediaPixelFormat pixelFormat,
- ImageFormat imgFormat)
+ ImageFormat imgFormat, bool autoRotate)
{
result r = E_SUCCESS;
std::unique_ptr<ByteBuffer> pBuf;
r = Construct(*pBuf.get(), pixelFormat, imgFormat);
SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagated.", GetErrorMessage(r));
+
+ if (autoRotate == true)
+ {
+ __autoRotate = true;
+ _ExifUtil imgExif;
+ imgExif.Construct(pBuf->GetPointer(), pBuf->GetCapacity());
+ imgExif.GetValue(EXIF_TAG_IMAGE_ORIENTATION, __orientationInfo);
+ // imgExif.GetValue() will return "r = E_OBJ_NOT_FOUND" if it could not be found exif infomation.
+ // However, the result should be decided by result of construct in this function.
+ SetLastResult(E_SUCCESS);
+ }
return r;
}
result r = E_SUCCESS;
SysTryReturnResult(NID_MEDIA, __pDec.get() == null, E_INVALID_STATE, "Already constructed");
- SysTryCatch(NID_MEDIA,
+ SysTryCatch(NID_MEDIA,
(pixelFormat == MEDIA_PIXEL_FORMAT_RGB565LE)|| (pixelFormat == MEDIA_PIXEL_FORMAT_BGRA8888) ||
(pixelFormat == MEDIA_PIXEL_FORMAT_RGBA8888), r = E_INVALID_ARG, E_INVALID_ARG,
"[E_INVALID_ARG] pixelFormat:%d", pixelFormat);
}
byte*
-_ImageDecoder::DecodeN(int& outLength)
+_ImageDecoder::DecodeN(int& outLength, ImageScalingMethod scalingMethod)
{
result r = E_SUCCESS;
int rawLength = 0;
- byte* outBuf = null;
+ std::unique_ptr<byte[]> pOutBuf;
std::unique_ptr<byte[]> pRawBuf;
+ std::unique_ptr<byte[]> pDstBuf;
SysTryReturn(NID_MEDIA, __pDec.get() != null, null, E_INVALID_STATE, "Not yet constructed");
// Decode
pRawBuf.reset(__pDec->DecodeN(rawLength));
SysTryReturn(NID_MEDIA, pRawBuf.get() != null, null, GetLastResult(),
- "[%s] buffer is null (%x), buffer length is %d.",
+ "[%s] buffer is null (%x), buffer length is %d.",
GetErrorMessage(GetLastResult()),pRawBuf.get(), rawLength);
// Get working dimension
&& (__orgDim.width == __outDim.width)
&& (__orgDim.height == __outDim.height))
{
- outBuf = pRawBuf.release();
+ pOutBuf.swap(pRawBuf);
outLength = rawLength;
}
else
// Converter construction
r = cvt.Construct(__pDec->GetPixelFormat(), __orgDim.width, __orgDim.height,
- __pixelFormat, __outDim.width, __outDim.height);
+ __pixelFormat, __outDim.width, __outDim.height, scalingMethod);
SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
// Convert to output format
- outBuf = cvt.ConvertN(pRawBuf.get(), rawLength, outLength);
+ pOutBuf.reset(cvt.ConvertN(pRawBuf.get(), rawLength, outLength));
r = GetLastResult();
SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
}
+
+ if (__autoRotate == true)
+ {
+ int dstWidth = 0;
+ int dstHeight = 0;
+
+ if (__orientationInfo == EXIF_ORIENTATION_TOP_LEFT || __orientationInfo == 0)
+ {
+ SetLastResult(E_SUCCESS);
+ return pOutBuf.release();
+ }
+
+ if (__orientationInfo > EXIF_ORIENTATION_LEFT_BOTTOM || __orientationInfo < EXIF_ORIENTATION_TOP_LEFT)
+ {
+ SetLastResult(E_SUCCESS);
+ return pOutBuf.release();
+ }
+
+ pDstBuf.reset(new (std::nothrow) byte[outLength]);
+ SysTryReturn(NID_MEDIA, pDstBuf.get() != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]");
+
+ ImageRotationType rotateType = _IMAGE_ROTATE_FLIP_MAP[__orientationInfo].rotateType;
+ ImageFlipType flipType = _IMAGE_ROTATE_FLIP_MAP[__orientationInfo].flipType;
+
+ pDstBuf.reset(_ImageUtil::RotateN(pOutBuf.get(), __pixelFormat, __outDim.width, __outDim.height, rotateType, dstWidth, dstHeight));
+ r = GetLastResult();
+ SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] _ImageUtil:Resize", GetErrorMessage(r));
+
+ __outDim.width = dstWidth;
+ __outDim.height = dstHeight;
+
+ pOutBuf.swap(pDstBuf);
+ if (flipType != IMAGE_FLIP_NONE)
+ {
+ pDstBuf.reset(_ImageUtil::FlipN(pOutBuf.get(), __pixelFormat, __outDim.width, __outDim.height, flipType));
+ r = GetLastResult();
+ SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] _ImageUtil:Flip", GetErrorMessage(r));
+
+ pOutBuf.swap(pDstBuf);
+ }
+ }
SetLastResult(E_SUCCESS);
- return outBuf;
+ return pOutBuf.release();
}
// TODO: Change return type to ByteBuffer*