Fix FLIPH, FLIPV, TRANSPOSE, TRANSVERSE, ROT_180 transforms exif issues in loader... 69/143369/2
authorgreynaga <g.reynaga@samsung.com>
Wed, 9 Aug 2017 11:00:44 +0000 (12:00 +0100)
committergreynaga <g.reynaga@samsung.com>
Wed, 9 Aug 2017 13:24:17 +0000 (14:24 +0100)
Change-Id: Ibab0a890daa7f58aed3abb6fe2f930e5c593ed62

platform-abstractions/tizen/image-loaders/loader-jpeg-turbo.cpp

index 254e604..e4362b5 100755 (executable)
@@ -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<RGB888Type*>( 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<unsigned char*>( 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<unsigned char> 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<RGB888Type*>(buffer) + iw - 1;
-      RGB888Type* from = reinterpret_cast<RGB888Type*>( 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<RGB888Type*>(buffer) ;
-      RGB888Type* from = reinterpret_cast<RGB888Type*>( 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<RGB888Type> 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<RGB888Type> 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<unsigned char> 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<RGB888Type*>(buffer) + hw  - iw;
-      RGB888Type* from = reinterpret_cast<RGB888Type*>( 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<RGB888Type> 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<RGB888Type> 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 );