[4.0] Exposing Exif Image metadata
[platform/core/uifw/dali-adaptor.git] / platform-abstractions / tizen / image-loaders / loader-gif.cpp
index cac1bff..9bcd17b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 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.
 #include "loader-gif.h"
 
 #include <gif_lib.h>
-#include <cstdlib>
 
 #include <dali/integration-api/debug.h>
-#include <dali/integration-api/bitmap.h>
+#include <adaptors/devel-api/adaptor-framework/pixel-buffer.h>
+#include <memory>
+
+// We need to check if giflib has the new open and close API (including error parameter).
+#ifdef GIFLIB_MAJOR
+#define LIBGIF_VERSION_5_1_OR_ABOVE
+#endif
 
 namespace Dali
 {
-using Integration::Bitmap;
-using Dali::Integration::PixelBuffer;
 
 namespace TizenPlatform
 {
@@ -47,29 +50,23 @@ struct AutoCleanupGif
     if(NULL != gifInfo)
     {
       // clean up GIF resources
-      DGifCloseFile(gifInfo);
+#ifdef LIBGIF_VERSION_5_1_OR_ABOVE
+      int errorCode = 0; //D_GIF_SUCCEEDED is 0
+      DGifCloseFile( gifInfo, &errorCode );
+
+      if( errorCode )
+      {
+        DALI_LOG_ERROR( "GIF Loader: DGifCloseFile Error. Code: %d\n", errorCode );
+      }
+#else
+      DGifCloseFile( gifInfo );
+#endif
     }
   }
 
   GifFileType*& gifInfo;
 };
 
-// Simple class to enforce clean-up of PixelBuffer
-struct AutoDeleteBuffer
-{
-  AutoDeleteBuffer( PixelBuffer* _buffer )
-  : buffer( _buffer )
-  {
-  }
-
-  ~AutoDeleteBuffer()
-  {
-    delete []buffer;
-  }
-
-  PixelBuffer* buffer;
-};
-
 // Used in the GIF interlace algorithm to determine the starting byte and the increment required
 // for each pass.
 struct InterlacePair
@@ -98,10 +95,17 @@ int ReadDataFromGif(GifFileType *gifInfo, GifByteType *data, int length)
 /// Loads the GIF Header.
 bool LoadGifHeader(FILE *fp, unsigned int &width, unsigned int &height, GifFileType** gifInfo)
 {
-  *gifInfo = DGifOpen(reinterpret_cast<void*>(fp), ReadDataFromGif);
+  int errorCode = 0; //D_GIF_SUCCEEDED is 0
+
+#ifdef LIBGIF_VERSION_5_1_OR_ABOVE
+  *gifInfo = DGifOpen( reinterpret_cast<void*>(fp), ReadDataFromGif, &errorCode );
+#else
+  *gifInfo = DGifOpen( reinterpret_cast<void*>(fp), ReadDataFromGif );
+#endif
 
-  if ( !(*gifInfo) )
+  if ( !(*gifInfo) || errorCode )
   {
+    DALI_LOG_ERROR( "GIF Loader: DGifOpen Error. Code: %d\n", errorCode );
     return false;
   }
 
@@ -118,7 +122,7 @@ bool LoadGifHeader(FILE *fp, unsigned int &width, unsigned int &height, GifFileT
 }
 
 /// Decode the GIF image.
-bool DecodeImage( GifFileType* gifInfo, PixelBuffer* decodedData, const unsigned int width, const unsigned int height, const unsigned int bytesPerRow )
+bool DecodeImage( GifFileType* gifInfo, unsigned char* decodedData, const unsigned int width, const unsigned int height, const unsigned int bytesPerRow )
 {
   if ( gifInfo->Image.Interlace )
   {
@@ -129,7 +133,7 @@ bool DecodeImage( GifFileType* gifInfo, PixelBuffer* decodedData, const unsigned
     {
       for( unsigned int currentByte = interlacePairPtr->startingByte; currentByte < height; currentByte += interlacePairPtr->incrementalByte )
       {
-        PixelBuffer* row = decodedData + currentByte * bytesPerRow;
+        unsigned char* row = decodedData + currentByte * bytesPerRow;
         if ( DGifGetLine( gifInfo, row, width ) == GIF_ERROR )
         {
           DALI_LOG_ERROR( "GIF Loader: Error reading Interlaced GIF\n" );
@@ -141,7 +145,7 @@ bool DecodeImage( GifFileType* gifInfo, PixelBuffer* decodedData, const unsigned
   else
   {
     // Non-interlace does not require any erratic reading / jumping.
-    PixelBuffer* decodedDataPtr( decodedData );
+    unsigned char* decodedDataPtr( decodedData );
 
     for ( unsigned int row = 0; row < height; ++row )
     {
@@ -173,7 +177,7 @@ GifColorType* GetImageColors( SavedImage* image, GifFileType* gifInfo )
 }
 
 /// Called when we want to handle IMAGE_DESC_RECORD_TYPE
-bool HandleImageDescriptionRecordType( Bitmap& bitmap, GifFileType* gifInfo, unsigned int width, unsigned int height, bool& finished )
+bool HandleImageDescriptionRecordType( Dali::Devel::PixelBuffer& bitmap, GifFileType* gifInfo, unsigned int width, unsigned int height, bool& finished )
 {
   if ( DGifGetImageDesc( gifInfo ) == GIF_ERROR )
   {
@@ -188,17 +192,22 @@ bool HandleImageDescriptionRecordType( Bitmap& bitmap, GifFileType* gifInfo, uns
     return false;
   }
 
+  Pixel::Format pixelFormat( Pixel::RGB888 );
+
   SavedImage* image( &gifInfo->SavedImages[ gifInfo->ImageCount - 1 ] );
   const GifImageDesc& desc( image->ImageDesc );
 
-  // Create a buffer to store the decoded data.
-  PixelBuffer* decodedData( new PixelBuffer[ width * height * sizeof( GifPixelType ) ] );
-  AutoDeleteBuffer autoDeleteBuffer( decodedData );
+  auto decodedData = new unsigned char[ width * height * sizeof( GifPixelType ) ];
+
+  std::unique_ptr<unsigned char[]> ptr{ decodedData };
 
   const unsigned int bytesPerRow( width * sizeof( GifPixelType ) );
   const unsigned int actualWidth( desc.Width );
   const unsigned int actualHeight( desc.Height );
 
+  // Create a buffer to store the decoded data.
+  bitmap = Dali::Devel::PixelBuffer::New( actualWidth, actualHeight, pixelFormat );
+
   // Decode the GIF Image
   if ( !DecodeImage( gifInfo, decodedData, actualWidth, actualHeight, bytesPerRow ) )
   {
@@ -211,10 +220,7 @@ bool HandleImageDescriptionRecordType( Bitmap& bitmap, GifFileType* gifInfo, uns
   // If it's an animated GIF, we still only read the first image
 
   // Create and populate pixel buffer.
-
-  Pixel::Format pixelFormat( Pixel::RGB888 );
-  PixelBuffer *pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer( pixelFormat, actualWidth, actualHeight );
-
+  auto pixels = bitmap.GetBuffer();
   for (unsigned int row = 0; row < actualHeight; ++row)
   {
     for (unsigned int column = 0; column < actualWidth; ++column)
@@ -227,9 +233,7 @@ bool HandleImageDescriptionRecordType( Bitmap& bitmap, GifFileType* gifInfo, uns
       pixels += 3;
     }
   }
-
   finished = true;
-
   return true;
 }
 
@@ -237,12 +241,21 @@ bool HandleImageDescriptionRecordType( Bitmap& bitmap, GifFileType* gifInfo, uns
 bool HandleExtensionRecordType( GifFileType* gifInfo )
 {
   SavedImage image;
+  GifByteType *extensionByte( NULL );
+
+#ifdef LIBGIF_VERSION_5_1_OR_ABOVE
+  ExtensionBlock extensionBlocks;
+  image.ExtensionBlocks          = &extensionBlocks;
+  image.ExtensionBlockCount      = 1;
+  int *extensionBlockTypePointer = &image.ExtensionBlocks->Function;
+#else
   image.ExtensionBlocks     = NULL;
   image.ExtensionBlockCount = 0;
-  GifByteType *extensionByte( NULL );
+  int *extensionBlockTypePointer = &image.Function;
+#endif
 
   // Not really interested in the extensions so just skip them unless there is an error.
-  for ( int extRetCode = DGifGetExtension( gifInfo, &image.Function, &extensionByte );
+  for ( int extRetCode = DGifGetExtension( gifInfo, extensionBlockTypePointer, &extensionByte );
         extensionByte != NULL;
         extRetCode = DGifGetExtensionNext( gifInfo, &extensionByte ) )
   {
@@ -267,7 +280,7 @@ bool LoadGifHeader( const ImageLoader::Input& input, unsigned int& width, unsign
   return LoadGifHeader(fp, width, height, &gifInfo);
 }
 
-bool LoadBitmapFromGif( const ResourceLoadingClient& client, const ImageLoader::Input& input, Integration::Bitmap& bitmap )
+bool LoadBitmapFromGif( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap )
 {
   FILE* const fp = input.file;
   // Load the GIF Header file.