Minor optimization on image loading
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / common / loader-gif.cpp
old mode 100755 (executable)
new mode 100644 (file)
index cf9b010..c8e9091
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -19,8 +19,8 @@
 
 #include <gif_lib.h>
 
-#include <dali/integration-api/debug.h>
 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/integration-api/debug.h>
 #include <memory>
 
 // We need to check if giflib has the new open and close API (including error parameter).
 
 namespace Dali
 {
-
 namespace TizenPlatform
 {
-
 namespace
 {
-
 // simple class to enforce clean-up of GIF structures
 struct AutoCleanupGif
 {
@@ -52,14 +49,14 @@ struct AutoCleanupGif
       // clean up GIF resources
 #ifdef LIBGIF_VERSION_5_1_OR_ABOVE
       int errorCode = 0; //D_GIF_SUCCEEDED is 0
-      DGifCloseFile( gifInfo, &errorCode );
+      DGifCloseFile(gifInfo, &errorCode);
 
-      if( errorCode )
+      if(errorCode)
       {
-        DALI_LOG_ERROR( "GIF Loader: DGifCloseFile Error. Code: %d\n", errorCode );
+        DALI_LOG_ERROR("GIF Loader: DGifCloseFile Error. Code: %d\n", errorCode);
       }
 #else
-      DGifCloseFile( gifInfo );
+      DGifCloseFile(gifInfo);
 #endif
     }
   }
@@ -77,35 +74,35 @@ struct InterlacePair
 
 // Used in the GIF interlace algorithm to determine the order and which location to read data from
 // the file.
-const InterlacePair INTERLACE_PAIR_TABLE [] = {
-  { 0, 8 }, // Starting at 0, read every 8 bytes.
-  { 4, 8 }, // Starting at 4, read every 8 bytes.
-  { 2, 4 }, // Starting at 2, read every 4 bytes.
-  { 1, 2 }, // Starting at 1, read every 2 bytes.
+const InterlacePair INTERLACE_PAIR_TABLE[] = {
+  {0, 8}, // Starting at 0, read every 8 bytes.
+  {4, 8}, // Starting at 4, read every 8 bytes.
+  {2, 4}, // Starting at 2, read every 4 bytes.
+  {1, 2}, // Starting at 1, read every 2 bytes.
 };
-const unsigned int INTERLACE_PAIR_TABLE_SIZE( sizeof( INTERLACE_PAIR_TABLE ) / sizeof( InterlacePair ) );
+const unsigned int INTERLACE_PAIR_TABLE_SIZE(sizeof(INTERLACE_PAIR_TABLE) / sizeof(InterlacePair));
 
 /// Function used by Gif_Lib to read from the image file.
-int ReadDataFromGif(GifFileType *gifInfo, GifByteType *data, int length)
+int ReadDataFromGif(GifFileType* gifInfo, GifByteType* data, int length)
 {
-  FILE *fp = reinterpret_cast<FILE*>(gifInfo->UserData);
-  return fread( data, sizeof( GifByteType ), length, fp);
+  FILEfp = reinterpret_cast<FILE*>(gifInfo->UserData);
+  return fread(data, sizeof(GifByteType), length, fp);
 }
 
 /// Loads the GIF Header.
-bool LoadGifHeader(FILE *fp, unsigned int &width, unsigned int &height, GifFileType** gifInfo)
+bool LoadGifHeader(FILE* fp, unsigned int& width, unsigned int& height, GifFileType** gifInfo)
 {
   int errorCode = 0; //D_GIF_SUCCEEDED is 0
 
 #ifdef LIBGIF_VERSION_5_1_OR_ABOVE
-  *gifInfo = DGifOpen( reinterpret_cast<void*>(fp), ReadDataFromGif, &errorCode );
+  *gifInfo = DGifOpen(reinterpret_cast<void*>(fp), ReadDataFromGif, &errorCode);
 #else
-  *gifInfo = DGifOpen( reinterpret_cast<void*>(fp), ReadDataFromGif );
+  *gifInfo = DGifOpen(reinterpret_cast<void*>(fp), ReadDataFromGif);
 #endif
 
-  if ( !(*gifInfo) || errorCode )
+  if(DALI_UNLIKELY(!(*gifInfo) || errorCode))
   {
-    DALI_LOG_ERROR( "GIF Loader: DGifOpen Error. Code: %d\n", errorCode );
+    DALI_LOG_ERROR("GIF Loader: DGifOpen Error. Code: %d\n", errorCode);
     return false;
   }
 
@@ -113,7 +110,7 @@ bool LoadGifHeader(FILE *fp, unsigned int &width, unsigned int &height, GifFileT
   height = (*gifInfo)->SHeight;
 
   // No proper size in GIF.
-  if ( width <= 0 || height <= 0 )
+  if(DALI_UNLIKELY(width <= 0 || height <= 0))
   {
     return false;
   }
@@ -122,21 +119,21 @@ bool LoadGifHeader(FILE *fp, unsigned int &width, unsigned int &height, GifFileT
 }
 
 /// Decode the GIF image.
-bool DecodeImage( GifFileType* gifInfo, unsigned char* 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 )
+  if(gifInfo->Image.Interlace)
   {
     // If the image is interlaced, then use the GIF interlace algorithm to read the file appropriately.
 
-    const InterlacePair* interlacePairPtr( INTERLACE_PAIR_TABLE );
-    for ( unsigned int interlacePair = 0; interlacePair < INTERLACE_PAIR_TABLE_SIZE; ++interlacePair, ++interlacePairPtr )
+    const InterlacePair* interlacePairPtr(INTERLACE_PAIR_TABLE);
+    for(unsigned int interlacePair = 0; interlacePair < INTERLACE_PAIR_TABLE_SIZE; ++interlacePair, ++interlacePairPtr)
     {
-      for( unsigned int currentByte = interlacePairPtr->startingByte; currentByte < height; currentByte += interlacePairPtr->incrementalByte )
+      for(unsigned int currentByte = interlacePairPtr->startingByte; currentByte < height; currentByte += interlacePairPtr->incrementalByte)
       {
         unsigned char* row = decodedData + currentByte * bytesPerRow;
-        if ( DGifGetLine( gifInfo, row, width ) == GIF_ERROR )
+        if(DALI_UNLIKELY(DGifGetLine(gifInfo, row, width) == GIF_ERROR))
         {
-          DALI_LOG_ERROR( "GIF Loader: Error reading Interlaced GIF\n" );
+          DALI_LOG_ERROR("GIF Loader: Error reading Interlaced GIF\n");
           return false;
         }
       }
@@ -145,13 +142,13 @@ bool DecodeImage( GifFileType* gifInfo, unsigned char* decodedData, const unsign
   else
   {
     // Non-interlace does not require any erratic reading / jumping.
-    unsigned char* decodedDataPtr( decodedData );
+    unsigned char* decodedDataPtr(decodedData);
 
-    for ( unsigned int row = 0; row < height; ++row )
+    for(unsigned int row = 0; row < height; ++row)
     {
-      if ( DGifGetLine( gifInfo, decodedDataPtr, width ) == GIF_ERROR)
+      if(DALI_UNLIKELY(DGifGetLine(gifInfo, decodedDataPtr, width) == GIF_ERROR))
       {
-        DALI_LOG_ERROR( "GIF Loader: Error reading non-interlaced GIF\n" );
+        DALI_LOG_ERROR("GIF Loader: Error reading non-interlaced GIF\n");
         return false;
       }
       decodedDataPtr += bytesPerRow;
@@ -161,10 +158,10 @@ bool DecodeImage( GifFileType* gifInfo, unsigned char* decodedData, const unsign
 }
 
 // Retrieves the colors used in the GIF image.
-GifColorType* GetImageColors( SavedImage* image, GifFileType* gifInfo )
+GifColorType* GetImageColors(SavedImage* image, GifFileType* gifInfo)
 {
-  GifColorType* color( NULL );
-  if ( image->ImageDesc.ColorMap )
+  GifColorType* color(NULL);
+  if(image->ImageDesc.ColorMap)
   {
     color = image->ImageDesc.ColorMap->Colors;
   }
@@ -177,53 +174,53 @@ GifColorType* GetImageColors( SavedImage* image, GifFileType* gifInfo )
 }
 
 /// Called when we want to handle IMAGE_DESC_RECORD_TYPE
-bool HandleImageDescriptionRecordType( Dali::Devel::PixelBuffer& 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 )
+  if(DALI_UNLIKELY(DGifGetImageDesc(gifInfo) == GIF_ERROR))
   {
-    DALI_LOG_ERROR( "GIF Loader: Error getting Image Description\n" );
+    DALI_LOG_ERROR("GIF Loader: Error getting Image Description\n");
     return false;
   }
 
   // Ensure there is at least 1 image in the GIF.
-  if ( gifInfo->ImageCount < 1 )
+  if(DALI_UNLIKELY(gifInfo->ImageCount < 1))
   {
-    DALI_LOG_ERROR( "GIF Loader: No Images\n" );
+    DALI_LOG_ERROR("GIF Loader: No Images\n");
     return false;
   }
 
-  Pixel::Format pixelFormat( Pixel::RGB888 );
+  Pixel::Format pixelFormat(Pixel::RGB888);
 
-  SavedImage* image( &gifInfo->SavedImages[ gifInfo->ImageCount - 1 ] );
-  const GifImageDesc& desc( image->ImageDesc );
+  SavedImage*         image(&gifInfo->SavedImages[gifInfo->ImageCount - 1]);
+  const GifImageDesc& desc(image->ImageDesc);
 
-  auto decodedData = new unsigned char[ width * height * sizeof( GifPixelType ) ];
+  auto decodedData = new unsigned char[width * height * sizeof(GifPixelType)];
 
-  std::unique_ptr<unsigned char[]> ptr{ decodedData };
+  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 );
+  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 );
+  bitmap = Dali::Devel::PixelBuffer::New(actualWidth, actualHeight, pixelFormat);
 
   // Decode the GIF Image
-  if ( !DecodeImage( gifInfo, decodedData, actualWidth, actualHeight, bytesPerRow ) )
+  if(DALI_UNLIKELY(!DecodeImage(gifInfo, decodedData, actualWidth, actualHeight, bytesPerRow)))
   {
     return false;
   }
 
   // Get the colormap for the GIF
-  GifColorType* color( GetImageColors( image, gifInfo ) );
+  GifColorType* color(GetImageColors(image, gifInfo));
 
   // If it's an animated GIF, we still only read the first image
 
   // Create and populate pixel buffer.
   auto pixels = bitmap.GetBuffer();
-  for (unsigned int row = 0; row < actualHeight; ++row)
+  for(unsigned int row = 0; row < actualHeight; ++row)
   {
-    for (unsigned int column = 0; column < actualWidth; ++column)
+    for(unsigned int column = 0; column < actualWidth; ++column)
     {
       unsigned char index = decodedData[row * width + column];
 
@@ -238,30 +235,30 @@ bool HandleImageDescriptionRecordType( Dali::Devel::PixelBuffer& bitmap, GifFile
 }
 
 /// Called when we want to handle EXTENSION_RECORD_TYPE
-bool HandleExtensionRecordType( GifFileType* gifInfo )
+bool HandleExtensionRecordType(GifFileType* gifInfo)
 {
-  SavedImage image;
-  GifByteType *extensionByte( NULL );
+  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;
+  intextensionBlockTypePointer = &image.ExtensionBlocks->Function;
 #else
-  image.ExtensionBlocks     = NULL;
+  image.ExtensionBlocks = NULL;
   image.ExtensionBlockCount = 0;
-  int *extensionBlockTypePointer = &image.Function;
+  intextensionBlockTypePointer = &image.Function;
 #endif
 
   // Not really interested in the extensions so just skip them unless there is an error.
-  for ( int extRetCode = DGifGetExtension( gifInfo, extensionBlockTypePointer, &extensionByte );
-        extensionByte != NULL;
-        extRetCode = DGifGetExtensionNext( gifInfo, &extensionByte ) )
+  for(int extRetCode = DGifGetExtension(gifInfo, extensionBlockTypePointer, &extensionByte);
+      extensionByte != NULL;
+      extRetCode = DGifGetExtensionNext(gifInfo, &extensionByte))
   {
-    if ( extRetCode == GIF_ERROR )
+    if(DALI_UNLIKELY(extRetCode == GIF_ERROR))
     {
-      DALI_LOG_ERROR( "GIF Loader: Error reading GIF Extension record.\n" );
+      DALI_LOG_ERROR("GIF Loader: Error reading GIF Extension record.\n");
       return false;
     }
   }
@@ -271,53 +268,53 @@ bool HandleExtensionRecordType( GifFileType* gifInfo )
 
 } // unnamed namespace
 
-bool LoadGifHeader( const Dali::ImageLoader::Input& input, unsigned int& width, unsigned int& height )
+bool LoadGifHeader(const Dali::ImageLoader::Input& input, unsigned int& width, unsigned int& height)
 {
-  GifFileType* gifInfo = NULL;
+  GifFileType*   gifInfo = NULL;
   AutoCleanupGif autoCleanupGif(gifInfo);
-  FILE* const fp = input.file;
+  FILE* const    fp = input.file;
 
   return LoadGifHeader(fp, width, height, &gifInfo);
 }
 
-bool LoadBitmapFromGif( const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap )
+bool LoadBitmapFromGif(const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap)
 {
   FILE* const fp = input.file;
   // Load the GIF Header file.
 
-  GifFileType* gifInfo( NULL );
-  unsigned int width( 0 );
-  unsigned int height( 0 );
-  if ( !LoadGifHeader( fp, width, height, &gifInfo ) )
+  GifFileType* gifInfo(NULL);
+  unsigned int width(0);
+  unsigned int height(0);
+  if(DALI_UNLIKELY(!LoadGifHeader(fp, width, height, &gifInfo)))
   {
     return false;
   }
-  AutoCleanupGif autoGif( gifInfo );
+  AutoCleanupGif autoGif(gifInfo);
 
   // Check each record in the GIF file.
 
-  bool finished( false );
-  GifRecordType recordType( UNDEFINED_RECORD_TYPE );
-  for ( int returnCode = DGifGetRecordType( gifInfo, &recordType );
-        !finished && recordType != TERMINATE_RECORD_TYPE;
-        returnCode = DGifGetRecordType( gifInfo, &recordType ) )
+  bool          finished(false);
+  GifRecordType recordType(UNDEFINED_RECORD_TYPE);
+  for(int returnCode = DGifGetRecordType(gifInfo, &recordType);
+      !finished && recordType != TERMINATE_RECORD_TYPE;
+      returnCode = DGifGetRecordType(gifInfo, &recordType))
   {
-    if ( returnCode == GIF_ERROR )
+    if(DALI_UNLIKELY(returnCode == GIF_ERROR))
     {
-      DALI_LOG_ERROR( "GIF Loader: Error getting Record Type\n" );
+      DALI_LOG_ERROR("GIF Loader: Error getting Record Type\n");
       return false;
     }
 
-    if( IMAGE_DESC_RECORD_TYPE == recordType )
+    if(IMAGE_DESC_RECORD_TYPE == recordType)
     {
-      if ( !HandleImageDescriptionRecordType( bitmap, gifInfo, width, height, finished ) )
+      if(DALI_UNLIKELY(!HandleImageDescriptionRecordType(bitmap, gifInfo, width, height, finished)))
       {
         return false;
       }
     }
-    else if ( EXTENSION_RECORD_TYPE == recordType )
+    else if(EXTENSION_RECORD_TYPE == recordType)
     {
-      if ( !HandleExtensionRecordType( gifInfo ))
+      if(DALI_UNLIKELY(!HandleExtensionRecordType(gifInfo)))
       {
         return false;
       }