From: greynaga Date: Wed, 9 Aug 2017 11:00:44 +0000 (+0100) Subject: Fix FLIPH, FLIPV, TRANSPOSE, TRANSVERSE, ROT_180 transforms exif issues in loader... X-Git-Tag: submit/tizen_3.0/20170811.054953~2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git;a=commitdiff_plain;h=6acb08a6d0f0e9def1c2deed6cd62aaef60ea239 Fix FLIPH, FLIPV, TRANSPOSE, TRANSVERSE, ROT_180 transforms exif issues in loader-jpeg-turbo Change-Id: Ibab0a890daa7f58aed3abb6fe2f930e5c593ed62 --- diff --git a/platform-abstractions/tizen/image-loaders/loader-jpeg-turbo.cpp b/platform-abstractions/tizen/image-loaders/loader-jpeg-turbo.cpp index 254e604..e4362b5 100755 --- a/platform-abstractions/tizen/image-loaders/loader-jpeg-turbo.cpp +++ b/platform-abstractions/tizen/image-loaders/loader-jpeg-turbo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,9 +60,9 @@ namespace struct RGB888Type { - char R; - char G; - char B; + unsigned char R; + unsigned char G; + unsigned char B; }; /** @@ -178,10 +178,13 @@ namespace const int MAX_TEXTURE_HEIGHT = 4096; } // namespace - -bool JpegRotate90 (unsigned char *buffer, int width, int height, int bpp); -bool JpegRotate180(unsigned char *buffer, int width, int height, int bpp); -bool JpegRotate270(unsigned char *buffer, int width, int height, int bpp); +bool JpegFlipV( RGB888Type *buffer, int width, int height ); +bool JpegFlipH( RGB888Type *buffer, int width, int height ); +bool JpegTranspose( RGB888Type *buffer, int width, int height ); +bool JpegTransverse( RGB888Type *buffer, int width, int height ); +bool JpegRotate90 ( RGB888Type *buffer, int width, int height ); +bool JpegRotate180( RGB888Type *buffer, int width, int height ); +bool JpegRotate270( RGB888Type *buffer, int width, int height ); JPGFORM_CODE ConvertExifOrientation(ExifData* exifData); bool TransformSize( int requiredWidth, int requiredHeight, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, @@ -340,12 +343,12 @@ bool LoadBitmapFromJpeg( const ResourceLoadingClient& client, const ImageLoader: // Allocate a bitmap and decompress the jpeg buffer into its pixel buffer: - unsigned char * const bitmapPixelBuffer = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB888, scaledPostXformWidth, scaledPostXformHeight); + RGB888Type * bitmapPixelBuffer = reinterpret_cast( bitmap.GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGB888, scaledPostXformWidth, scaledPostXformHeight ) ); // Allow early cancellation before decoding: client.InterruptionPoint(); - if( tjDecompress2( autoJpg.GetHandle(), jpegBufferPtr, jpegBufferSize, bitmapPixelBuffer, scaledPreXformWidth, 0, scaledPreXformHeight, DECODED_PIXEL_LIBJPEG_TYPE, flags ) == -1 ) + if( tjDecompress2( autoJpg.GetHandle(), jpegBufferPtr, jpegBufferSize, reinterpret_cast( bitmapPixelBuffer ), scaledPreXformWidth, 0, scaledPreXformHeight, DECODED_PIXEL_LIBJPEG_TYPE, flags ) == -1 ) { std::string errorString = tjGetErrorStr(); @@ -380,26 +383,43 @@ bool LoadBitmapFromJpeg( const ResourceLoadingClient& client, const ImageLoader: // 3 orientation changes for a camera held perpendicular to the ground or upside-down: case JPGFORM_ROT_180: { - result = JpegRotate180(bitmapPixelBuffer, bufferWidth, bufferHeight, DECODED_PIXEL_SIZE); + result = JpegRotate180( bitmapPixelBuffer, bufferWidth, bufferHeight ); break; } case JPGFORM_ROT_270: { - result = JpegRotate270(bitmapPixelBuffer, bufferWidth, bufferHeight, DECODED_PIXEL_SIZE); + result = JpegRotate270( bitmapPixelBuffer, bufferWidth, bufferHeight ); break; } case JPGFORM_ROT_90: { - result = JpegRotate90(bitmapPixelBuffer, bufferWidth, bufferHeight, DECODED_PIXEL_SIZE); + result = JpegRotate90( bitmapPixelBuffer, bufferWidth, bufferHeight ); + break; + } + case JPGFORM_FLIP_V: + { + result = JpegFlipV( bitmapPixelBuffer, bufferWidth, bufferHeight ); break; } /// Less-common orientation changes, since they don't correspond to a camera's // physical orientation: case JPGFORM_FLIP_H: - case JPGFORM_FLIP_V: + { + result = JpegFlipH( bitmapPixelBuffer, bufferWidth, bufferHeight ); + break; + } case JPGFORM_TRANSPOSE: + { + result = JpegTranspose( bitmapPixelBuffer, bufferWidth, bufferHeight ); + break; + } case JPGFORM_TRANSVERSE: { + result = JpegTransverse( bitmapPixelBuffer, bufferWidth, bufferHeight ); + break; + } + default: + { DALI_LOG_WARNING( "Unsupported JPEG Orientation transformation: %x.\n", transform ); break; } @@ -407,124 +427,190 @@ bool LoadBitmapFromJpeg( const ResourceLoadingClient& client, const ImageLoader: return result; } -///@Todo: Move all these rotation functions to portable/image-operations and take "Jpeg" out of their names. -bool JpegRotate90(unsigned char *buffer, int width, int height, int bpp) +bool JpegFlipV(RGB888Type *buffer, int width, int height ) { - int w, iw, ih, hw = 0; - int ix, iy = 0; - iw = width; - ih = height; - Vector data; - data.Resize(width * height * bpp); - unsigned char *dataPtr = data.Begin(); - memcpy(dataPtr, buffer, width * height * bpp); - w = ih; - ih = iw; - iw = w; - hw = iw * ih; - hw = - hw - 1; - switch(bpp) + int bwidth = width; + int bheight = height; + //Destination pixel, set as the first pixel of screen + RGB888Type* to = buffer; + //Source pixel, as the image is flipped horizontally and vertically, + //the source pixel is the end of the buffer of size bwidth * bheight + RGB888Type* from = buffer + bwidth * bheight - 1; + RGB888Type temp; + unsigned int endLoop = ( bwidth * bheight ) / 2; + + for(unsigned ix = 0; ix < endLoop; ++ ix, ++ to, -- from ) { - case 3: - { - RGB888Type* to = reinterpret_cast(buffer) + iw - 1; - RGB888Type* from = reinterpret_cast( dataPtr ); + temp = *from; + *from = *to; + *to = temp; + } - for(ix = iw; -- ix >= 0;) - { - for(iy = ih; -- iy >= 0; ++from ) - { - *to = *from; - to += iw; - } - to += hw; - } - break; - } + return true; +} - default: +bool JpegFlipH(RGB888Type *buffer, int width, int height ) +{ + int ix, iy; + int bwidth = width; + int bheight = height; + + RGB888Type* to; + RGB888Type* from; + RGB888Type temp; + + for(iy = 0; iy < bheight; iy ++) + { + //Set the destination pixel as the beginning of the row + to = buffer + bwidth * iy; + //Set the source pixel as the end of the row to flip in X axis + from = buffer + bwidth * (iy + 1) - 1; + for(ix = 0; ix < bwidth / 2; ix ++ , ++ to, -- from ) { - return false; + temp = *from; + *from = *to; + *to = temp; } } - return true; } -bool JpegRotate180(unsigned char *buffer, int width, int height, int bpp) +bool JpegTranspose( RGB888Type *buffer, int width, int height ) { - int ix, iw, ih, hw = 0; - iw = width; - ih = height; - hw = iw * ih; - ix = hw; + int ix, iy; + int bwidth = width; + int bheight = height; - switch(bpp) + RGB888Type* to; + RGB888Type* from; + RGB888Type temp; + //Flip vertically only + for(iy = 0; iy < bheight / 2; iy ++) { - case 3: + for(ix = 0; ix < bwidth; ix ++) { - RGB888Type tmp; - RGB888Type* to = reinterpret_cast(buffer) ; - RGB888Type* from = reinterpret_cast( buffer ) + hw - 1; - for(; --ix >= (hw / 2); ++to, --from) - { - tmp = *to; - *to = *from; - *from = tmp; - } - break; + to = buffer + iy * bwidth + ix; + from = buffer + (bheight - 1 - iy) * bwidth + ix; + temp = *from; + *from = *to; + *to = temp; } + } - default: + return true; +} + +bool JpegTransverse( RGB888Type *buffer, int width, int height ) +{ + int bwidth = width; + int bheight = height; + Vector data; + data.Resize( bwidth * bheight ); + RGB888Type *dataPtr = data.Begin(); + memcpy(dataPtr, buffer, bwidth * bheight * DECODED_PIXEL_SIZE ); + + RGB888Type* to = buffer; + RGB888Type* from; + for( int iy = 0; iy < bwidth; iy++ ) + { + for( int ix = 0; ix < bheight; ix++ ) { - return false; + from = dataPtr + ix * bwidth + iy; + *to = *from; + to ++; } } return true; } -bool JpegRotate270(unsigned char *buffer, int width, int height, int bpp) +///@Todo: Move all these rotation functions to portable/image-operations and take "Jpeg" out of their names. +bool JpegRotate90(RGB888Type *buffer, int width, int height ) { - int w, iw, ih, hw = 0; + int w, hw = 0; int ix, iy = 0; + int bwidth = width; + int bheight = height; + Vector data; + data.Resize(width * height); + RGB888Type *dataPtr = data.Begin(); + memcpy(dataPtr, buffer, width * height * DECODED_PIXEL_SIZE ); + w = bheight; + bheight = bwidth; + bwidth = w; + hw = bwidth * bheight; + hw = - hw - 1; - iw = width; - ih = height; - Vector data; - data.Resize(width * height * bpp); - unsigned char *dataPtr = data.Begin(); - memcpy(dataPtr, buffer, width * height * bpp); - w = ih; - ih = iw; - iw = w; - hw = iw * ih; + RGB888Type* to = buffer + bwidth - 1; + RGB888Type* from = dataPtr; - switch(bpp) + for(ix = bwidth; -- ix >= 0;) { - case 3: + for(iy = bheight; -- iy >= 0; ++from ) { - RGB888Type* to = reinterpret_cast(buffer) + hw - iw; - RGB888Type* from = reinterpret_cast( dataPtr ); + *to = *from; + to += bwidth; + } + to += hw; + } - w = -w; - hw = hw + 1; - for(ix = iw; -- ix >= 0;) - { - for(iy = ih; -- iy >= 0;) - { - *to = *from; - from += 1; - to += w; - } - to += hw; - } - break; + return true; +} + +bool JpegRotate180( RGB888Type *buffer, int width, int height ) +{ + int bwidth = width; + int bheight = height; + Vector data; + data.Resize( bwidth * bheight ); + RGB888Type *dataPtr = data.Begin(); + memcpy(dataPtr, buffer, bwidth * bheight * DECODED_PIXEL_SIZE ); + + RGB888Type* to = buffer; + RGB888Type* from; + for( int iy = 0; iy < bwidth; iy++ ) + { + for( int ix = 0; ix < bheight; ix++ ) + { + from = dataPtr + ( bheight - ix) * bwidth - 1 - iy; + *to = *from; + to ++; } - default: + } + + return true; +} + +bool JpegRotate270( RGB888Type *buffer, int width, int height ) +{ + int w, hw = 0; + int ix, iy = 0; + + int bwidth = width; + int bheight = height; + Vector data; + data.Resize( width * height ); + RGB888Type *dataPtr = data.Begin(); + memcpy(dataPtr, buffer, width * height * DECODED_PIXEL_SIZE ); + w = bheight; + bheight = bwidth; + bwidth = w; + hw = bwidth * bheight; + + RGB888Type* to = buffer + hw - bwidth; + RGB888Type* from = dataPtr; + + w = -w; + hw = hw + 1; + for(ix = bwidth; -- ix >= 0;) + { + for(iy = bheight; -- iy >= 0;) { - return false; + *to = *from; + from ++; + to += w; } + to += hw; } return true; @@ -681,7 +767,7 @@ bool TransformSize( int requiredWidth, int requiredHeight, { bool success = true; - if( transform == JPGFORM_ROT_90 || transform == JPGFORM_ROT_270 ) + if( transform == JPGFORM_ROT_90 || transform == JPGFORM_ROT_270 || transform == JPGFORM_ROT_180 || transform == JPGFORM_TRANSVERSE) { std::swap( requiredWidth, requiredHeight ); std::swap( postXformImageWidth, postXformImageHeight );