From 7da91338489ff54813539c8abca8d93afc3e94a6 Mon Sep 17 00:00:00 2001 From: "adam.b" Date: Fri, 22 Dec 2017 14:46:26 +0000 Subject: [PATCH] Exposing Exif Image metadata Additionally, the use of Integration::Bitmap has been reduced and replaced with Dali::Devel::PixelBuffer. Change-Id: I866d3b3ac0a7844e974ae8fc92e9295f1c9d40a7 --- adaptors/common/pixel-buffer-impl.cpp | 23 ++- adaptors/common/pixel-buffer-impl.h | 36 ++++- .../adaptor-framework/image-loading.cpp | 31 +--- .../adaptor-framework/pixel-buffer.cpp | 5 + .../adaptor-framework/pixel-buffer.h | 9 ++ .../dali-adaptor-internal/image-loaders.cpp | 38 ++--- .../src/dali-adaptor-internal/image-loaders.h | 3 +- .../utc-Dali-ImageOperations.cpp | 11 +- .../utc-image-fitting-modes.cpp | 25 ++- .../portable/image-operations.cpp | 89 ++++------- .../portable/image-operations.h | 14 +- .../tizen/image-loaders/image-loader.cpp | 47 ++++-- .../tizen/image-loaders/image-loader.h | 9 +- .../tizen/image-loaders/loader-astc.cpp | 22 +-- .../tizen/image-loaders/loader-astc.h | 8 +- .../tizen/image-loaders/loader-bmp.cpp | 97 ++++++------ .../tizen/image-loaders/loader-bmp.h | 8 +- .../tizen/image-loaders/loader-gif.cpp | 50 ++---- .../tizen/image-loaders/loader-gif.h | 8 +- .../tizen/image-loaders/loader-ico.cpp | 10 +- .../tizen/image-loaders/loader-ico.h | 7 +- .../tizen/image-loaders/loader-jpeg-turbo.cpp | 148 +++++++++++++++--- .../tizen/image-loaders/loader-jpeg.h | 8 +- .../tizen/image-loaders/loader-ktx.cpp | 14 +- .../tizen/image-loaders/loader-ktx.h | 7 +- .../tizen/image-loaders/loader-png.cpp | 14 +- .../tizen/image-loaders/loader-png.h | 7 +- .../tizen/image-loaders/loader-wbmp.cpp | 11 +- .../tizen/image-loaders/loader-wbmp.h | 6 +- .../tizen/tizen-platform-abstraction.cpp | 26 ++- 30 files changed, 459 insertions(+), 332 deletions(-) diff --git a/adaptors/common/pixel-buffer-impl.cpp b/adaptors/common/pixel-buffer-impl.cpp index 24ea4bca9..8390a48d6 100644 --- a/adaptors/common/pixel-buffer-impl.cpp +++ b/adaptors/common/pixel-buffer-impl.cpp @@ -42,7 +42,8 @@ PixelBuffer::PixelBuffer( unsigned char* buffer, unsigned int width, unsigned int height, Dali::Pixel::Format pixelFormat ) -: mBuffer( buffer ), +: mMetadata(), + mBuffer( buffer ), mBufferSize( bufferSize ), mWidth( width ), mHeight( height ), @@ -264,6 +265,26 @@ PixelBufferPtr PixelBuffer::NewCrop( const PixelBuffer& inBuffer, uint16_t x, ui } +void PixelBuffer::SetMetadata( const Property::Map& map ) +{ + mMetadata.reset(new Property::Map(map)); +} + +bool PixelBuffer::GetMetadata(Property::Map& outMetadata) const +{ + if( !mMetadata ) + { + return false; + } + outMetadata = *mMetadata; + return true; +} + +void PixelBuffer::SetMetadata(std::unique_ptr metadata) +{ + mMetadata = std::move(metadata); +} + void PixelBuffer::Resize( ImageDimensions outDimensions ) { if( mWidth != outDimensions.GetWidth() || mHeight != outDimensions.GetHeight() ) diff --git a/adaptors/common/pixel-buffer-impl.h b/adaptors/common/pixel-buffer-impl.h index 1882909f9..0cacb5691 100644 --- a/adaptors/common/pixel-buffer-impl.h +++ b/adaptors/common/pixel-buffer-impl.h @@ -23,6 +23,10 @@ #include // For ImageDimensions #include #include +#include + +// EXTERNAL INCLUDES +#include namespace Dali { @@ -175,6 +179,27 @@ public: */ void Resize( ImageDimensions outDimensions ); + /** + * @brief Sets image metadata + * + * @param map Property map containing Exif fields + */ + void SetMetadata( const Property::Map& map ); + + /** + * @brief Returns image metadata as a property map + * @param[out] outMetadata Property map to copy the data into + * @return True on success + */ + bool GetMetadata(Property::Map& outMetadata) const; + + /** + * @brief Sets metadata property map for the pixel buffer + * @note The function takes over the ownership of the property map + * @param[in] metadata Property map to copy the data into + */ + void SetMetadata(std::unique_ptr metadata); + private: /* * Undefined copy constructor. @@ -231,11 +256,12 @@ private: private: - unsigned char* mBuffer; ///< The raw pixel data - unsigned int mBufferSize; ///< Buffer sized in bytes - unsigned int mWidth; ///< Buffer width in pixels - unsigned int mHeight; ///< Buffer height in pixels - Pixel::Format mPixelFormat; ///< Pixel format + std::unique_ptr mMetadata; ///< Metadata fields + unsigned char* mBuffer; ///< The raw pixel data + unsigned int mBufferSize; ///< Buffer sized in bytes + unsigned int mWidth; ///< Buffer width in pixels + unsigned int mHeight; ///< Buffer height in pixels + Pixel::Format mPixelFormat; ///< Pixel format }; } // namespace Adaptor diff --git a/adaptors/devel-api/adaptor-framework/image-loading.cpp b/adaptors/devel-api/adaptor-framework/image-loading.cpp index 2beb24d4f..88203feab 100644 --- a/adaptors/devel-api/adaptor-framework/image-loading.cpp +++ b/adaptors/devel-api/adaptor-framework/image-loading.cpp @@ -18,11 +18,14 @@ #include "image-loading.h" // INTERNAL INCLUDES +#include #include "image-loaders/image-loader.h" #include #include #include "pixel-buffer-impl.h" + + namespace Dali { @@ -44,23 +47,11 @@ Devel::PixelBuffer LoadImageFromFile( const std::string& url, ImageDimensions si FILE * const fp = fileReader.GetFile(); if( fp != NULL ) { - Integration::BitmapPtr bitmap; + Dali::Devel::PixelBuffer bitmap; bool success = TizenPlatform::ImageLoader::ConvertStreamToBitmap( resourceType, url, fp, bitmap ); if( success && bitmap ) { - // Use bitmap->GetBufferOwnership() to transfer the buffer ownership - // to pixelData. The destroy of bitmap will not release the buffer, - // instead, the pixelBuffer is responsible for releasing when its - // reference count falls to zero. - Internal::Adaptor::PixelBufferPtr pixelBufferImpl = - Internal::Adaptor::PixelBuffer::New( bitmap->GetBufferOwnership(), - bitmap->GetBufferSize(), - bitmap->GetImageWidth(), - bitmap->GetImageHeight(), - bitmap->GetPixelFormat() ); - - Dali::Devel::PixelBuffer pixelBuffer( pixelBufferImpl.Get() ); - return pixelBuffer; + return bitmap; } } return Dali::Devel::PixelBuffer(); @@ -104,7 +95,7 @@ Devel::PixelBuffer DownloadImageSynchronously( const std::string& url, ImageDime FILE * const fp = fileReader.GetFile(); if ( NULL != fp ) { - Integration::BitmapPtr bitmap; + Dali::Devel::PixelBuffer bitmap; bool result = TizenPlatform::ImageLoader::ConvertStreamToBitmap( resourceType, url, @@ -113,15 +104,7 @@ Devel::PixelBuffer DownloadImageSynchronously( const std::string& url, ImageDime if ( result && bitmap ) { - Internal::Adaptor::PixelBufferPtr pixelBufferImpl = - Internal::Adaptor::PixelBuffer::New( bitmap->GetBufferOwnership(), - bitmap->GetBufferSize(), - bitmap->GetImageWidth(), - bitmap->GetImageHeight(), - bitmap->GetPixelFormat() ); - - Dali::Devel::PixelBuffer pixelBuffer( pixelBufferImpl.Get() ); - return pixelBuffer; + return bitmap; } else { diff --git a/adaptors/devel-api/adaptor-framework/pixel-buffer.cpp b/adaptors/devel-api/adaptor-framework/pixel-buffer.cpp index d8245b113..245d3a2e9 100644 --- a/adaptors/devel-api/adaptor-framework/pixel-buffer.cpp +++ b/adaptors/devel-api/adaptor-framework/pixel-buffer.cpp @@ -116,6 +116,11 @@ void PixelBuffer::Resize( uint16_t width, uint16_t height ) GetImplementation(*this).Resize( ImageDimensions( width, height ) ); } +bool PixelBuffer::GetMetadata( Property::Map& metadata ) const +{ + return GetImplementation(*this).GetMetadata(metadata); +} + } // namespace Devel } // namespace Dali diff --git a/adaptors/devel-api/adaptor-framework/pixel-buffer.h b/adaptors/devel-api/adaptor-framework/pixel-buffer.h index 8a777bfe6..b06299833 100644 --- a/adaptors/devel-api/adaptor-framework/pixel-buffer.h +++ b/adaptors/devel-api/adaptor-framework/pixel-buffer.h @@ -18,6 +18,7 @@ * */ +// INTERNAL INCLUDES #include #include #include @@ -200,6 +201,14 @@ public: */ void Resize( uint16_t width, uint16_t height ); + /** + * Returns Exif metadata as a property map + * + * @param[out] metadata Property map object to write into + * @return True on success + */ + bool GetMetadata( Property::Map& metadata ) const; + public: /** diff --git a/automated-tests/src/dali-adaptor-internal/image-loaders.cpp b/automated-tests/src/dali-adaptor-internal/image-loaders.cpp index a5fd26eaa..754695a8b 100644 --- a/automated-tests/src/dali-adaptor-internal/image-loaders.cpp +++ b/automated-tests/src/dali-adaptor-internal/image-loaders.cpp @@ -17,7 +17,7 @@ #include "image-loaders.h" #include - +#include AutoCloseFile::AutoCloseFile( FILE *fp ) : filePtr( fp ) @@ -101,17 +101,15 @@ void TestImageLoading( const ImageDetails& image, const LoadFunctions& functions // Loading the header moves the pointer within the file so reset to start of file. fseek( fp, 0, 0 ); - // Create a bitmap object and store a pointer to that object so it is destroyed at the end. - Dali::Integration::Bitmap * bitmap = Dali::Integration::Bitmap::New( bitmapProfile, ResourcePolicy::OWNED_RETAIN ); - Dali::Integration::BitmapPtr bitmapPtr( bitmap ); + Dali::Devel::PixelBuffer bitmap; // Load Bitmap and check its return values. - DALI_TEST_CHECK( functions.loader( input, *bitmap ) ); - DALI_TEST_EQUALS( image.width, bitmap->GetImageWidth(), TEST_LOCATION ); - DALI_TEST_EQUALS( image.height, bitmap->GetImageHeight(), TEST_LOCATION ); + DALI_TEST_CHECK( functions.loader( input, bitmap ) ); + DALI_TEST_EQUALS( image.width, bitmap.GetWidth(), TEST_LOCATION ); + DALI_TEST_EQUALS( image.height, bitmap.GetHeight(), TEST_LOCATION ); // Compare buffer generated with reference buffer. - Dali::PixelBuffer* bufferPtr( bitmapPtr->GetBuffer() ); + Dali::PixelBuffer* bufferPtr( bitmap.GetBuffer() ); Dali::PixelBuffer* refBufferPtr( image.refBuffer ); for ( unsigned int i = 0; i < image.refBufferSize; ++i, ++bufferPtr, ++refBufferPtr ) { @@ -141,21 +139,19 @@ void CompareLoadedImageData( const ImageDetails& image, const LoadFunctions& fun // Loading the header moves the pointer within the file so reset to start of file. fseek( filePointer, 0, SEEK_SET ); - // Create a bitmap object and store a pointer to that object so it is destroyed at the end. - Dali::Integration::Bitmap * bitmap = Dali::Integration::Bitmap::New( Dali::Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); - Dali::Integration::BitmapPtr bitmapPointer( bitmap ); + Dali::Devel::PixelBuffer bitmap; // Load Bitmap and check its return values. - DALI_TEST_CHECK( functions.loader( input, *bitmap ) ); - DALI_TEST_EQUALS( image.width, bitmap->GetImageWidth(), TEST_LOCATION ); - DALI_TEST_EQUALS( image.height, bitmap->GetImageHeight(), TEST_LOCATION ); + DALI_TEST_CHECK( functions.loader( input, bitmap ) ); + DALI_TEST_EQUALS( image.width, bitmap.GetWidth(), TEST_LOCATION ); + DALI_TEST_EQUALS( image.height, bitmap.GetHeight(), TEST_LOCATION ); // Check the bytes per pixel. - const Pixel::Format pixelFormat = bitmap->GetPixelFormat(); + const Pixel::Format pixelFormat = bitmap.GetPixelFormat(); const unsigned int bytesPerPixel = Pixel::GetBytesPerPixel( pixelFormat ); // Compare buffer generated with reference buffer. - Dali::PixelBuffer* pBitmapData( bitmapPointer->GetBuffer() ); + Dali::PixelBuffer* pBitmapData( bitmap.GetBuffer() ); const uint32_t* pMaster( master ); // Loop through each pixel in the bitmap. @@ -178,15 +174,15 @@ void DumpImageBufferToTempFile( std::string filename, std::string targetFilename FILE* fp = fopen( filename.c_str() , "rb" ); AutoCloseFile autoClose( fp ); - Dali::Integration::Bitmap* bitmap = Dali::Integration::Bitmap::New( Dali::Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); - Dali::Integration::BitmapPtr bitmapPtr( bitmap ); + Dali::Devel::PixelBuffer bitmap; const Dali::TizenPlatform::ImageLoader::Input input( fp ); - DALI_TEST_CHECK( functions.loader( input, *bitmap ) ); + DALI_TEST_CHECK( functions.loader( input, bitmap ) ); - Dali::PixelBuffer* bufferPtr( bitmapPtr->GetBuffer() ); + Dali::PixelBuffer* bufferPtr( bitmap.GetBuffer() ); FILE* writeFp = fopen( targetFilename.c_str(), "wb" ); AutoCloseFile autoCloseWrite( writeFp ); - fwrite( bufferPtr, 1, bitmap->GetBufferSize(), writeFp ); + auto& impl = GetImplementation(bitmap); + fwrite( bufferPtr, 1, impl.GetBufferSize(), writeFp ); } diff --git a/automated-tests/src/dali-adaptor-internal/image-loaders.h b/automated-tests/src/dali-adaptor-internal/image-loaders.h index 9a3ce7aa6..a81702064 100644 --- a/automated-tests/src/dali-adaptor-internal/image-loaders.h +++ b/automated-tests/src/dali-adaptor-internal/image-loaders.h @@ -20,6 +20,7 @@ #include #include +#include #include "platform-abstractions/tizen/image-loaders/image-loader-input.h" // Simple structure to close the file when finished with it. @@ -82,7 +83,7 @@ private: */ struct LoadFunctions { - typedef bool (*LoadBitmapFunction)( const Dali::TizenPlatform::ImageLoader::Input& input, Dali::Integration::Bitmap& ); + typedef bool (*LoadBitmapFunction)( const Dali::TizenPlatform::ImageLoader::Input& input, Dali::Devel::PixelBuffer& ); typedef bool (*LoadBitmapHeaderFunction)( const Dali::TizenPlatform::ImageLoader::Input& input, unsigned int& width, unsigned int& height ); LoadFunctions( LoadBitmapHeaderFunction _header, LoadBitmapFunction _loader ); diff --git a/automated-tests/src/dali-adaptor-internal/utc-Dali-ImageOperations.cpp b/automated-tests/src/dali-adaptor-internal/utc-Dali-ImageOperations.cpp index 6301ad8bd..ec480f02c 100644 --- a/automated-tests/src/dali-adaptor-internal/utc-Dali-ImageOperations.cpp +++ b/automated-tests/src/dali-adaptor-internal/utc-Dali-ImageOperations.cpp @@ -358,14 +358,13 @@ void TestDownscaledBitmapHasRightDimensionsAndFormat( FittingMode::Type fittingMode( FittingMode::SHRINK_TO_FIT ); SamplingMode::Type samplingMode( SamplingMode::BOX ); - Integration::BitmapPtr sourceBitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD ); - sourceBitmap->GetPackedPixelsProfile()->ReserveBuffer( format, sourceDimension, sourceDimension, sourceDimension, sourceDimension ); + Dali::Devel::PixelBuffer sourceBitmap = Dali::Devel::PixelBuffer::New( sourceDimension, sourceDimension, format ); - Integration::BitmapPtr downScaled = DownscaleBitmap( *sourceBitmap, desired, fittingMode, samplingMode ); + Dali::Devel::PixelBuffer downScaled = DownscaleBitmap( sourceBitmap, desired, fittingMode, samplingMode ); - DALI_TEST_EQUALS( downScaled->GetImageWidth(), expectedDimension, location ); - DALI_TEST_EQUALS( downScaled->GetImageHeight(), expectedDimension, location ); - DALI_TEST_EQUALS( downScaled->GetPixelFormat(), format, location ); + DALI_TEST_EQUALS( downScaled.GetWidth(), expectedDimension, location ); + DALI_TEST_EQUALS( downScaled.GetHeight(), expectedDimension, location ); + DALI_TEST_EQUALS( downScaled.GetPixelFormat(), format, location ); } /** diff --git a/automated-tests/src/dali-platform-abstraction/utc-image-fitting-modes.cpp b/automated-tests/src/dali-platform-abstraction/utc-image-fitting-modes.cpp index 477c1d44c..ab074dd3b 100644 --- a/automated-tests/src/dali-platform-abstraction/utc-image-fitting-modes.cpp +++ b/automated-tests/src/dali-platform-abstraction/utc-image-fitting-modes.cpp @@ -37,13 +37,13 @@ const char* ASCII_PAD_VALUE = ANSI_BLUE "#"; typedef unsigned char PixelBuffer; -void FillBitmap( BitmapPtr bitmap ) +void FillBitmap( Dali::Devel::PixelBuffer bitmap ) { // Fill the given bitmap fully. - const Pixel::Format pixelFormat = bitmap->GetPixelFormat(); + const Pixel::Format pixelFormat = bitmap.GetPixelFormat(); const unsigned int bytesPerPixel = Pixel::GetBytesPerPixel( pixelFormat ); - PixelBuffer * const targetPixels = bitmap->GetBuffer(); - const int bytesToFill = bitmap.Get()->GetImageWidth() * bitmap.Get()->GetImageHeight() * bytesPerPixel; + PixelBuffer * const targetPixels = bitmap.GetBuffer(); + const int bytesToFill = bitmap.GetWidth() * bitmap.GetHeight() * bytesPerPixel; memset( targetPixels, BORDER_FILL_VALUE, bytesToFill ); } @@ -97,16 +97,15 @@ void PerformFittingTests( TestContainer& tests ) // Create a source bitmap. ImageDimensions desiredDimensions( desiredWidth, desiredHeight ); SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR; - BitmapPtr sourceBitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD ); - Integration::Bitmap::PackedPixelsProfile *packedView = sourceBitmap->GetPackedPixelsProfile(); - const Pixel::Format pixelFormat = sourceBitmap->GetPixelFormat(); - packedView->ReserveBuffer( pixelFormat, sourceWidth, sourceHeight, sourceWidth, sourceHeight ); + + auto sourceBitmap = Dali::Devel::PixelBuffer::New( sourceWidth, sourceHeight, Pixel::Format::RGBA8888 ); + const Pixel::Format pixelFormat = sourceBitmap.GetPixelFormat(); // Completely fill the source bitmap (with white). FillBitmap( sourceBitmap ); // Perform fitting operations (this is the method we are testing). - BitmapPtr newBitmap = ApplyAttributesToBitmap( sourceBitmap, desiredDimensions, fittingMode, samplingMode ); + auto newBitmap = ApplyAttributesToBitmap( sourceBitmap, desiredDimensions, fittingMode, samplingMode ); DALI_TEST_CHECK( newBitmap ); @@ -116,16 +115,16 @@ void PerformFittingTests( TestContainer& tests ) return; } - Bitmap *bitmap = newBitmap.Get(); + auto bitmap( newBitmap ); - unsigned int resultWidth = bitmap->GetImageWidth(); - unsigned int resultHeight = bitmap->GetImageHeight(); + unsigned int resultWidth = bitmap.GetWidth(); + unsigned int resultHeight = bitmap.GetHeight(); // Check the dimensions of the modified image match against the expected values defined in the test. DALI_TEST_EQUALS( resultWidth, test.expectedWidth, TEST_LOCATION ); DALI_TEST_EQUALS( resultHeight, test.expectedHeight, TEST_LOCATION ); - PixelBuffer* resultBuffer = bitmap->GetBuffer(); + PixelBuffer* resultBuffer = bitmap.GetBuffer(); const unsigned int bytesPerPixel = Pixel::GetBytesPerPixel( pixelFormat ); // We generate an ASCII representation of the source, desired and result images to log, purely as a debugging aid. diff --git a/platform-abstractions/portable/image-operations.cpp b/platform-abstractions/portable/image-operations.cpp index e9a94cc4b..a1408cea6 100644 --- a/platform-abstractions/portable/image-operations.cpp +++ b/platform-abstractions/portable/image-operations.cpp @@ -411,30 +411,17 @@ void CalculateBordersFromFittingMode( ImageDimensions sourceSize, FittingMode:: } /** - * @brief Construct a bitmap with format and dimensions requested. + * @brief Construct a pixel buffer object from a copy of the pixel array passed in. */ -BitmapPtr MakeEmptyBitmap( Pixel::Format pixelFormat, unsigned int width, unsigned int height ) -{ - DALI_ASSERT_DEBUG( Pixel::GetBytesPerPixel(pixelFormat) && "Compressed formats not supported." ); - - // Allocate a pixel buffer to hold the image passed in: - Integration::BitmapPtr newBitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD ); - newBitmap->GetPackedPixelsProfile()->ReserveBuffer( pixelFormat, width, height, width, height ); - return newBitmap; -} - -/** - * @brief Construct a bitmap object from a copy of the pixel array passed in. - */ -BitmapPtr MakeBitmap( const uint8_t * const pixels, Pixel::Format pixelFormat, unsigned int width, unsigned int height ) +Dali::Devel::PixelBuffer MakePixelBuffer( const uint8_t * const pixels, Pixel::Format pixelFormat, unsigned int width, unsigned int height ) { DALI_ASSERT_DEBUG( pixels && "Null bitmap buffer to copy." ); // Allocate a pixel buffer to hold the image passed in: - Integration::BitmapPtr newBitmap = MakeEmptyBitmap( pixelFormat, width, height ); + auto newBitmap = Dali::Devel::PixelBuffer::New( width, height, pixelFormat ); // Copy over the pixels from the downscaled image that was generated in-place in the pixel buffer of the input bitmap: - memcpy( newBitmap->GetBuffer(), pixels, width * height * Pixel::GetBytesPerPixel( pixelFormat ) ); + memcpy( newBitmap.GetBuffer(), pixels, width * height * Pixel::GetBytesPerPixel( pixelFormat ) ); return newBitmap; } @@ -525,14 +512,14 @@ ImageDimensions CalculateDesiredDimensions( ImageDimensions rawDimensions, Image * bitmaps dimensions to only be as large as necessary, as a memory saving optimization. This will cause * GPU scaling to be performed at render time giving the same result with less texture traversal. * - * @param[in] bitmap The source bitmap to perform modifications on. + * @param[in] bitmap The source pixel buffer to perform modifications on. * @param[in] desiredDimensions The target dimensions to aim to fill based on the fitting mode. * @param[in] fittingMode The fitting mode to use. * * @return A new bitmap with the padding and cropping required for fitting mode applied. * If no modification is needed or possible, the passed in bitmap is returned. */ -Integration::BitmapPtr CropAndPadForFittingMode( Integration::BitmapPtr bitmap, ImageDimensions desiredDimensions, FittingMode::Type fittingMode ); +Dali::Devel::PixelBuffer CropAndPadForFittingMode( Dali::Devel::PixelBuffer& bitmap, ImageDimensions desiredDimensions, FittingMode::Type fittingMode ); /** * @brief Adds horizontal or vertical borders to the source image. @@ -544,41 +531,34 @@ Integration::BitmapPtr CropAndPadForFittingMode( Integration::BitmapPtr bitmap, */ void AddBorders( PixelBuffer *targetPixels, const unsigned int bytesPerPixel, const ImageDimensions targetDimensions, const ImageDimensions padDimensions ); -BitmapPtr ApplyAttributesToBitmap( BitmapPtr bitmap, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode ) +Dali::Devel::PixelBuffer ApplyAttributesToBitmap( Dali::Devel::PixelBuffer bitmap, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode ) { if( bitmap ) { // Calculate the desired box, accounting for a possible zero component: - const ImageDimensions desiredDimensions = CalculateDesiredDimensions( bitmap->GetImageWidth(), bitmap->GetImageHeight(), dimensions.GetWidth(), dimensions.GetHeight() ); + const ImageDimensions desiredDimensions = CalculateDesiredDimensions( bitmap.GetWidth(), bitmap.GetHeight(), dimensions.GetWidth(), dimensions.GetHeight() ); // If a different size than the raw one has been requested, resize the image // maximally using a repeated box filter without making it smaller than the // requested size in either dimension: - bitmap = DownscaleBitmap( *bitmap, desiredDimensions, fittingMode, samplingMode ); + bitmap = DownscaleBitmap( bitmap, desiredDimensions, fittingMode, samplingMode ); // Cut the bitmap according to the desired width and height so that the // resulting bitmap has the same aspect ratio as the desired dimensions. // Add crop and add borders if necessary depending on fitting mode. - if( bitmap && bitmap->GetPackedPixelsProfile() ) + if( bitmap ) { bitmap = CropAndPadForFittingMode( bitmap, desiredDimensions, fittingMode ); } - - // Examine the image pixels remaining after cropping and scaling to see if all - // are opaque, allowing faster rendering, or some have non-1.0 alpha: - if( bitmap && bitmap->GetPackedPixelsProfile() && Pixel::HasAlpha( bitmap->GetPixelFormat() ) ) - { - bitmap->GetPackedPixelsProfile()->TestForTransparency(); - } } return bitmap; } -BitmapPtr CropAndPadForFittingMode( BitmapPtr bitmap, ImageDimensions desiredDimensions, FittingMode::Type fittingMode ) +Dali::Devel::PixelBuffer CropAndPadForFittingMode( Dali::Devel::PixelBuffer& bitmap, ImageDimensions desiredDimensions, FittingMode::Type fittingMode ) { - const unsigned int inputWidth = bitmap->GetImageWidth(); - const unsigned int inputHeight = bitmap->GetImageHeight(); + const unsigned int inputWidth = bitmap.GetWidth(); + const unsigned int inputHeight = bitmap.GetHeight(); if( desiredDimensions.GetWidth() < 1u || desiredDimensions.GetHeight() < 1u ) { @@ -623,18 +603,16 @@ BitmapPtr CropAndPadForFittingMode( BitmapPtr bitmap, ImageDimensions desiredDim return bitmap; } - // Create a new bitmap with the desired size. - BitmapPtr croppedBitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD ); - Integration::Bitmap::PackedPixelsProfile *packedView = croppedBitmap->GetPackedPixelsProfile(); - DALI_ASSERT_DEBUG( packedView ); - const Pixel::Format pixelFormat = bitmap->GetPixelFormat(); - packedView->ReserveBuffer( pixelFormat, desiredWidth, desiredHeight, desiredWidth, desiredHeight ); + // Create new PixelBuffer with the desired size. + const auto pixelFormat = bitmap.GetPixelFormat(); + + auto croppedBitmap = Devel::PixelBuffer::New( desiredWidth, desiredHeight, pixelFormat ); // Add some pre-calculated offsets to the bitmap pointers so this is not done within a loop. // The cropping is added to the source pointer, and the padding is added to the destination. - const unsigned int bytesPerPixel = Pixel::GetBytesPerPixel( pixelFormat ); - const PixelBuffer * const sourcePixels = bitmap->GetBuffer() + ( ( ( ( scanlinesToCrop / 2 ) * inputWidth ) + ( columnsToCrop / 2 ) ) * bytesPerPixel ); - PixelBuffer * const targetPixels = croppedBitmap->GetBuffer(); + const auto bytesPerPixel = Pixel::GetBytesPerPixel( pixelFormat ); + const PixelBuffer * const sourcePixels = bitmap.GetBuffer() + ( ( ( ( scanlinesToCrop / 2 ) * inputWidth ) + ( columnsToCrop / 2 ) ) * bytesPerPixel ); + PixelBuffer * const targetPixels = croppedBitmap.GetBuffer(); PixelBuffer * const targetPixelsActive = targetPixels + ( ( ( ( scanlinesToPad / 2 ) * desiredWidth ) + ( columnsToPad / 2 ) ) * bytesPerPixel ); DALI_ASSERT_DEBUG( sourcePixels && targetPixels ); @@ -662,7 +640,7 @@ BitmapPtr CropAndPadForFittingMode( BitmapPtr bitmap, ImageDimensions desiredDim // Add vertical or horizontal borders to the final image (if required). desiredDimensions.SetWidth( desiredWidth ); desiredDimensions.SetHeight( desiredHeight ); - AddBorders( croppedBitmap->GetBuffer(), bytesPerPixel, desiredDimensions, ImageDimensions( columnsToPad, scanlinesToPad ) ); + AddBorders( croppedBitmap.GetBuffer(), bytesPerPixel, desiredDimensions, ImageDimensions( columnsToPad, scanlinesToPad ) ); // Overwrite the loaded bitmap with the cropped version bitmap = croppedBitmap; } @@ -719,26 +697,26 @@ void AddBorders( PixelBuffer *targetPixels, const unsigned int bytesPerPixel, co } } -Integration::BitmapPtr DownscaleBitmap( Integration::Bitmap& bitmap, +Dali::Devel::PixelBuffer DownscaleBitmap( Dali::Devel::PixelBuffer bitmap, ImageDimensions desired, FittingMode::Type fittingMode, SamplingMode::Type samplingMode ) { // Source dimensions as loaded from resources (e.g. filesystem): - const unsigned int bitmapWidth = bitmap.GetImageWidth(); - const unsigned int bitmapHeight = bitmap.GetImageHeight(); + auto bitmapWidth = bitmap.GetWidth(); + auto bitmapHeight = bitmap.GetHeight(); // Desired dimensions (the rectangle to fit the source image to): - const unsigned int desiredWidth = desired.GetWidth(); - const unsigned int desiredHeight = desired.GetHeight(); + auto desiredWidth = desired.GetWidth(); + auto desiredHeight = desired.GetHeight(); - BitmapPtr outputBitmap( &bitmap ); + Dali::Devel::PixelBuffer outputBitmap { bitmap }; // If a different size than the raw one has been requested, resize the image: - if( bitmap.GetPackedPixelsProfile() && + if( (desiredWidth > 0.0f) && (desiredHeight > 0.0f) && ((desiredWidth < bitmapWidth) || (desiredHeight < bitmapHeight)) ) { - const Pixel::Format pixelFormat = bitmap.GetPixelFormat(); + auto pixelFormat = bitmap.GetPixelFormat(); // Do the fast power of 2 iterated box filter to get to roughly the right side if the filter mode requests that: unsigned int shrunkWidth = -1, shrunkHeight = -1; @@ -756,16 +734,17 @@ Integration::BitmapPtr DownscaleBitmap( Integration::Bitmap& bitmap, if( samplingMode == SamplingMode::LINEAR || samplingMode == SamplingMode::BOX_THEN_LINEAR || samplingMode == SamplingMode::NEAREST || samplingMode == SamplingMode::BOX_THEN_NEAREST ) { - outputBitmap = MakeEmptyBitmap( pixelFormat, filteredWidth, filteredHeight ); + outputBitmap = Dali::Devel::PixelBuffer::New( filteredWidth, filteredHeight, pixelFormat ); + if( outputBitmap ) { if( samplingMode == SamplingMode::LINEAR || samplingMode == SamplingMode::BOX_THEN_LINEAR ) { - LinearSample( bitmap.GetBuffer(), ImageDimensions(shrunkWidth, shrunkHeight), pixelFormat, outputBitmap->GetBuffer(), filteredDimensions ); + LinearSample( bitmap.GetBuffer(), ImageDimensions(shrunkWidth, shrunkHeight), pixelFormat, outputBitmap.GetBuffer(), filteredDimensions ); } else { - PointSample( bitmap.GetBuffer(), shrunkWidth, shrunkHeight, pixelFormat, outputBitmap->GetBuffer(), filteredWidth, filteredHeight ); + PointSample( bitmap.GetBuffer(), shrunkWidth, shrunkHeight, pixelFormat, outputBitmap.GetBuffer(), filteredWidth, filteredHeight ); } filtered = true; } @@ -774,7 +753,7 @@ Integration::BitmapPtr DownscaleBitmap( Integration::Bitmap& bitmap, // Copy out the 2^x downscaled, box-filtered pixels if no secondary filter (point or linear) was applied: if( filtered == false && ( shrunkWidth < bitmapWidth || shrunkHeight < bitmapHeight ) ) { - outputBitmap = MakeBitmap( bitmap.GetBuffer(), pixelFormat, shrunkWidth, shrunkHeight ); + outputBitmap = MakePixelBuffer( bitmap.GetBuffer(), pixelFormat, shrunkWidth, shrunkHeight ); } } diff --git a/platform-abstractions/portable/image-operations.h b/platform-abstractions/portable/image-operations.h index 0c1e2533b..b790da5b3 100644 --- a/platform-abstractions/portable/image-operations.h +++ b/platform-abstractions/portable/image-operations.h @@ -26,6 +26,13 @@ #include #include +#ifdef DALI_ADAPTOR_COMPILATION +#include +#else +#include +#endif + + namespace Dali { namespace Internal @@ -80,13 +87,16 @@ ImageDimensions CalculateDesiredDimensions( ImageDimensions rawDimensions, Image * bitmap passed-in, or the original bitmap passed in if the attributes * have no effect. */ -Integration::BitmapPtr ApplyAttributesToBitmap( Integration::BitmapPtr bitmap, ImageDimensions dimensions, FittingMode::Type fittingMode = FittingMode::DEFAULT, SamplingMode::Type samplingMode = SamplingMode::DEFAULT ); +Dali::Devel::PixelBuffer ApplyAttributesToBitmap( Dali::Devel::PixelBuffer bitmap, ImageDimensions dimensions, FittingMode::Type fittingMode = FittingMode::DEFAULT, SamplingMode::Type samplingMode = SamplingMode::DEFAULT ); /** * @brief Apply downscaling to a bitmap according to requested attributes. * @note The input bitmap pixel buffer may be modified and used as scratch working space for efficiency, so it must be discarded. **/ -Integration::BitmapPtr DownscaleBitmap( Integration::Bitmap& bitmap, ImageDimensions desired, FittingMode::Type fittingMode, SamplingMode::Type samplingMode ); +Dali::Devel::PixelBuffer DownscaleBitmap( Dali::Devel::PixelBuffer bitmap, + ImageDimensions desired, + FittingMode::Type fittingMode, + SamplingMode::Type samplingMode ); /**@}*/ /** diff --git a/platform-abstractions/tizen/image-loaders/image-loader.cpp b/platform-abstractions/tizen/image-loaders/image-loader.cpp index 16a012e46..d7a6da154 100644 --- a/platform-abstractions/tizen/image-loaders/image-loader.cpp +++ b/platform-abstractions/tizen/image-loaders/image-loader.cpp @@ -17,8 +17,8 @@ #include "image-loader.h" #include -#include -#include +#include + #include "loader-astc.h" #include "loader-bmp.h" @@ -29,7 +29,6 @@ #include "loader-png.h" #include "loader-wbmp.h" #include "image-operations.h" -#include "image-loader-input.h" #include "portable/file-reader.h" using namespace Dali::Integration; @@ -41,7 +40,7 @@ namespace TizenPlatform namespace { -typedef bool (*LoadBitmapFunction)( const ImageLoader::Input& input, Integration::Bitmap& bitmap ); +typedef bool (*LoadBitmapFunction)( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& pixelData ); typedef bool (*LoadBitmapHeaderFunction)( const ImageLoader::Input& input, unsigned int& width, unsigned int& height ); #if defined(DEBUG_ENABLED) @@ -252,17 +251,17 @@ bool GetBitmapLoaderFunctions( FILE *fp, namespace ImageLoader { -bool ConvertStreamToBitmap( const BitmapResourceType& resource, std::string path, FILE * const fp, BitmapPtr& ptr ) +bool ConvertStreamToBitmap( const BitmapResourceType& resource, std::string path, FILE * const fp, Dali::Devel::PixelBuffer& pixelBuffer ) { DALI_LOG_TRACE_METHOD( gLogFilter ); bool result = false; - BitmapPtr bitmap = 0; if (fp != NULL) { LoadBitmapFunction function; LoadBitmapHeaderFunction header; + Bitmap::Profile profile; if ( GetBitmapLoaderFunctions( fp, @@ -271,22 +270,19 @@ bool ConvertStreamToBitmap( const BitmapResourceType& resource, std::string path header, profile ) ) { - bitmap = Bitmap::New( profile, ResourcePolicy::OWNED_DISCARD ); - - DALI_LOG_SET_OBJECT_STRING( bitmap, path ); const ScalingParameters scalingParameters( resource.size, resource.scalingMode, resource.samplingMode ); const ImageLoader::Input input( fp, scalingParameters, resource.orientationCorrection ); // Run the image type decoder: - result = function( input, *bitmap ); + result = function( input, pixelBuffer ); if (!result) { DALI_LOG_WARNING( "Unable to convert %s\n", path.c_str() ); - bitmap = 0; + pixelBuffer.Reset(); } - bitmap = Internal::Platform::ApplyAttributesToBitmap( bitmap, resource.size, resource.scalingMode, resource.samplingMode ); + pixelBuffer = Internal::Platform::ApplyAttributesToBitmap( pixelBuffer, resource.size, resource.scalingMode, resource.samplingMode ); } else { @@ -294,23 +290,40 @@ bool ConvertStreamToBitmap( const BitmapResourceType& resource, std::string path } } - ptr.Reset( bitmap.Get() ); return result; } ResourcePointer LoadImageSynchronously( const Integration::BitmapResourceType& resource, const std::string& path ) { ResourcePointer result; - BitmapPtr bitmap = 0; + Dali::Devel::PixelBuffer bitmap; Internal::Platform::FileReader fileReader( path ); FILE * const fp = fileReader.GetFile(); if( fp != NULL ) { - bool success = ConvertStreamToBitmap( resource, path, fp, bitmap ); - if( success && bitmap ) + bool success = ConvertStreamToBitmap(resource, path, fp, bitmap); + if (success && bitmap) { - result.Reset(bitmap.Get()); + Bitmap::Profile profile{Bitmap::Profile::BITMAP_2D_PACKED_PIXELS}; + + // For backward compatibility the Bitmap must be created + auto retval = Bitmap::New(profile, Dali::ResourcePolicy::OWNED_DISCARD); + + DALI_LOG_SET_OBJECT_STRING( retval, path ); + + retval->GetPackedPixelsProfile()->ReserveBuffer( + bitmap.GetPixelFormat(), + bitmap.GetWidth(), + bitmap.GetHeight(), + bitmap.GetWidth(), + bitmap.GetHeight() + ); + + auto& impl = Dali::GetImplementation(bitmap); + + std::copy( impl.GetBuffer(), impl.GetBuffer()+impl.GetBufferSize(), retval->GetBuffer()); + result.Reset(retval); } } return result; diff --git a/platform-abstractions/tizen/image-loaders/image-loader.h b/platform-abstractions/tizen/image-loaders/image-loader.h index 15469ba9d..d619a305c 100644 --- a/platform-abstractions/tizen/image-loaders/image-loader.h +++ b/platform-abstractions/tizen/image-loaders/image-loader.h @@ -21,6 +21,9 @@ #include #include #include +#include +#include +#include namespace Dali { @@ -41,16 +44,16 @@ namespace ImageLoader * @param[out] bitmap Pointer to write bitmap to * @return true on success, false on failure */ -bool ConvertStreamToBitmap( const Integration::BitmapResourceType& resource, std::string path, FILE * const fp, Integration::BitmapPtr& ptr ); +bool ConvertStreamToBitmap( const Integration::BitmapResourceType& resource, std::string path, FILE * const fp, Dali::Devel::PixelBuffer& pixelBuffer ); /** * Convert a bitmap and write to a file stream. * @param[in] path The path to the resource. * @param[in] fp File Pointer. Closed on exit. - * @param[out] bitmap Pointer from which to read bitmap + * @param[out] pixelData Reference to PixelData object. * @return true on success, false on failure */ -bool ConvertBitmapToStream( std::string path, FILE * const fp, Integration::BitmapPtr& ptr ); +bool ConvertBitmapToStream( std::string path, FILE * const fp, Dali::Devel::PixelBuffer& pixelBuffer ); /** * Loads an image synchronously diff --git a/platform-abstractions/tizen/image-loaders/loader-astc.cpp b/platform-abstractions/tizen/image-loaders/loader-astc.cpp index bddf9546e..a0362aa36 100755 --- a/platform-abstractions/tizen/image-loaders/loader-astc.cpp +++ b/platform-abstractions/tizen/image-loaders/loader-astc.cpp @@ -19,23 +19,16 @@ #include "loader-astc.h" // EXTERNAL INCLUDES -#include -#include #include -#include #include #include -#include #include +#include namespace Dali { -using Integration::Bitmap; -using Dali::Integration::PixelBuffer; - namespace TizenPlatform { - namespace { @@ -174,7 +167,7 @@ bool LoadAstcHeader( const ImageLoader::Input& input, unsigned int& width, unsig } // File loading API entry-point: -bool LoadBitmapFromAstc( const ImageLoader::Input& input, Integration::Bitmap& bitmap ) +bool LoadBitmapFromAstc( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ) { FILE* const filePointer = input.file; if( !filePointer ) @@ -231,16 +224,13 @@ bool LoadBitmapFromAstc( const ImageLoader::Input& input, Integration::Bitmap& b return false; } - // Allocate space to load the image data in to. - PixelBuffer* const pixels = bitmap.GetCompressedProfile()->ReserveBufferOfSize( pixelFormat, width, height, imageByteCount ); - if( !pixels ) - { - DALI_LOG_ERROR( "Unable to reserve a pixel buffer to load the requested bitmap into.\n" ); - return false; - } + // allocate pixel data + bitmap = Dali::Devel::PixelBuffer::New(width, height, pixelFormat); + auto pixels = bitmap.GetBuffer(); // Load the image data. const size_t bytesRead = fread( pixels, 1, imageByteCount, filePointer ); + // Check the size of loaded data is what we expected. if( bytesRead != imageByteCount ) { diff --git a/platform-abstractions/tizen/image-loaders/loader-astc.h b/platform-abstractions/tizen/image-loaders/loader-astc.h index cb50b937c..f5cf6b421 100644 --- a/platform-abstractions/tizen/image-loaders/loader-astc.h +++ b/platform-abstractions/tizen/image-loaders/loader-astc.h @@ -23,12 +23,12 @@ namespace Dali { - -namespace Integration +namespace Devel { - class Bitmap; +class PixelBuffer; } + namespace TizenPlatform { @@ -49,7 +49,7 @@ const unsigned char MAGIC_BYTE_2 = 0xAB; * @param[out] bitmap The bitmap class where the decoded image will be stored * @return True if file loaded successfully, false otherwise */ -bool LoadBitmapFromAstc( const ImageLoader::Input& input, Integration::Bitmap& bitmap ); +bool LoadBitmapFromAstc( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ); /** * Loads the header of a ASTC file and fills in the width and height appropriately. diff --git a/platform-abstractions/tizen/image-loaders/loader-bmp.cpp b/platform-abstractions/tizen/image-loaders/loader-bmp.cpp index 37f3c2698..1ab158ab1 100644 --- a/platform-abstractions/tizen/image-loaders/loader-bmp.cpp +++ b/platform-abstractions/tizen/image-loaders/loader-bmp.cpp @@ -18,15 +18,12 @@ #include "loader-bmp.h" #include +#include #include -#include - -#include namespace Dali { -using Integration::Bitmap; -using Dali::Integration::PixelBuffer; + namespace TizenPlatform { @@ -130,7 +127,7 @@ bool LoadBmpHeader(FILE *fp, unsigned int &width, unsigned int &height, BmpFileH * @return true, if decode successful, false otherwise */ bool DecodeRGB24V5(FILE *fp, - PixelBuffer *pixels, + unsigned char* pixels, unsigned int width, unsigned int height, unsigned int offset, @@ -151,7 +148,7 @@ bool DecodeRGB24V5(FILE *fp, for(unsigned int yPos = 0; yPos < height; yPos ++) { - PixelBuffer *pixelsPtr = NULL; + unsigned char* pixelsPtr = NULL; if(topDown) { pixelsPtr = pixels + ( yPos * rowStride); @@ -197,7 +194,7 @@ bool DecodeRGB24V5(FILE *fp, * @return true, if decode successful, false otherwise */ bool DecodeBF32V4(FILE *fp, - PixelBuffer *pixels, + unsigned char* pixels, unsigned int width, unsigned int height, unsigned int offset, @@ -218,7 +215,7 @@ bool DecodeBF32V4(FILE *fp, for(unsigned int yPos = 0; yPos < height; yPos ++) { - PixelBuffer *pixelsPtr = NULL; + unsigned char* pixelsPtr = NULL; if(topDown) { pixelsPtr = pixels + ( yPos * rowStride); @@ -264,7 +261,7 @@ bool DecodeBF32V4(FILE *fp, * @return true, if decode successful, false otherwise */ bool DecodeBF32(FILE *fp, - PixelBuffer *pixels, + unsigned char* pixels, unsigned int width, unsigned int height, unsigned int offset, @@ -285,7 +282,7 @@ bool DecodeBF32(FILE *fp, for (unsigned int yPos = 0; yPos < height; yPos++) { - PixelBuffer *pixelsPtr; + unsigned char* pixelsPtr; if (topDown) { // the data in the file is top down, and we store the data top down @@ -332,7 +329,7 @@ bool DecodeBF32(FILE *fp, * @return true, if decode successful, false otherwise */ bool DecodeBF565(FILE *fp, - PixelBuffer *pixels, + unsigned char* pixels, unsigned int width, unsigned int height, unsigned int offset, @@ -354,7 +351,7 @@ bool DecodeBF565(FILE *fp, for(unsigned int i = 0; i < height; i++) { - PixelBuffer *pixelsPtr = NULL; + unsigned char* pixelsPtr = NULL; if (topDown) { // the data in the file is top down, and we store the data top down @@ -385,7 +382,7 @@ bool DecodeBF565(FILE *fp, * @return true, if decode successful, false otherwise */ bool DecodeBF555(FILE *fp, - PixelBuffer *pixels, + unsigned char* pixels, unsigned int width, unsigned int height, unsigned int offset, @@ -421,7 +418,7 @@ bool DecodeBF555(FILE *fp, for (unsigned int yPos = 0; yPos < height; yPos++) { - PixelBuffer *pixelsPtr = NULL; + unsigned char* pixelsPtr = NULL; if (topDown) { // the data in the file is top down, and we store the data top down @@ -455,7 +452,7 @@ bool DecodeBF555(FILE *fp, * @return true, if decode successful, false otherwise */ bool DecodeRGB555(FILE *fp, - PixelBuffer *pixels, + unsigned char* pixels, unsigned int width, unsigned int height, unsigned int offset, @@ -488,7 +485,7 @@ bool DecodeRGB555(FILE *fp, } for(unsigned int i = 0; i < height; i++) { - PixelBuffer *pixelsPtr = NULL; + unsigned char* pixelsPtr = NULL; if (topDown) { // the data in the file is top down, and we store the data top down @@ -522,7 +519,7 @@ bool DecodeRGB555(FILE *fp, * @return true, if decode successful, false otherwise */ bool DecodeRGB1(FILE *fp, - PixelBuffer *pixels, + unsigned char* pixels, unsigned int width, unsigned int height, unsigned int offset, @@ -570,7 +567,7 @@ bool DecodeRGB1(FILE *fp, for(unsigned int index = 0; index < height; index = index + 1) { - PixelBuffer *pixelsPtr = NULL; + unsigned char* pixelsPtr = NULL; if (topDown) { // the data in the file is top down, and we store the data top down @@ -615,7 +612,7 @@ bool DecodeRGB1(FILE *fp, * @return true, if decode successful, false otherwise */ bool DecodeRGB4(FILE *fp, - PixelBuffer *pixels, + unsigned char* pixels, unsigned int width, unsigned int height, unsigned int offset, @@ -657,7 +654,7 @@ bool DecodeRGB4(FILE *fp, for(unsigned int index = 0; index < height; index = index + 1) { - PixelBuffer *pixelsPtr = NULL; + unsigned char* pixelsPtr = NULL; if (topDown) { // the data in the file is top down, and we store the data top down @@ -691,7 +688,7 @@ bool DecodeRGB4(FILE *fp, * @return true, if decode successful, false otherwise */ bool DecodeRGB8(FILE *fp, - PixelBuffer *pixels, + unsigned char* pixels, unsigned int width, unsigned int height, unsigned int offset, @@ -730,7 +727,7 @@ bool DecodeRGB8(FILE *fp, unsigned int ctIndex = 0; for(unsigned int index = 0; index < height; index = index + 1) { - PixelBuffer *pixelsPtr = NULL; + unsigned char* pixelsPtr = NULL; if (topDown) { // the data in the file is top down, and we store the data top down @@ -763,7 +760,7 @@ bool DecodeRGB8(FILE *fp, * @return true, if decode successful, false otherwise */ bool DecodeRLE4(FILE *fp, - PixelBuffer *pixels, + unsigned char* pixels, unsigned int width, unsigned int height, unsigned int offset, @@ -774,7 +771,7 @@ bool DecodeRLE4(FILE *fp, DALI_LOG_ERROR("Error decoding BMP_RLE4 format\n"); return false; } - PixelBuffer *pixelsPtr = pixels; + unsigned char* pixelsPtr = pixels; width = ((width & 3) != 0) ? width + 4 - (width & 3) : width; char cmd[2]; unsigned int cmdStride = 2; @@ -931,7 +928,7 @@ bool DecodeRLE4(FILE *fp, * @return true, if decode successful, false otherwise */ bool DecodeRLE8(FILE *fp, - PixelBuffer *pixels, + unsigned char* pixels, unsigned int width, unsigned int height, unsigned int offset, @@ -942,7 +939,7 @@ bool DecodeRLE8(FILE *fp, DALI_LOG_ERROR("Error decoding BMP_RLE8 format\n"); return false; } - PixelBuffer *pixelsPtr = pixels; + unsigned char* pixelsPtr = pixels; unsigned int x = 0; unsigned int y = 0; unsigned int cmdStride = 2; @@ -1056,9 +1053,9 @@ bool LoadBmpHeader( const ImageLoader::Input& input, unsigned int& width, unsign return ret; } -bool LoadBitmapFromBmp( const ImageLoader::Input& input, Integration::Bitmap& bitmap ) +bool LoadBitmapFromBmp( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ) { - DALI_ASSERT_DEBUG( bitmap.GetPackedPixelsProfile() != 0 && "Need a packed pixel bitmap to load into." ); + //DALI_ASSERT_DEBUG( bitmap.GetPackedPixelsProfile() != 0 && "Need a packed pixel bitmap to load into." ); FILE* const fp = input.file; if(fp == NULL) { @@ -1199,9 +1196,11 @@ bool LoadBitmapFromBmp( const ImageLoader::Input& input, Integration::Bitmap& bi padding = 4 - padding; } - PixelBuffer *pixels = NULL; int imageW = infoHeader.width; - int pixelBufferW = 0; + int pixelBufferW = infoHeader.width; + int pixelBufferH = infoHeader.height; + auto newPixelFormat = Pixel::Format::INVALID; + switch(customizedFormat) { case BMP_RLE8: @@ -1212,43 +1211,45 @@ bool LoadBitmapFromBmp( const ImageLoader::Input& input, Integration::Bitmap& bi case BMP_BITFIELDS555: { pixelBufferW = ((imageW & 3) != 0) ? imageW + 4 - (imageW & 3) : imageW; - pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB888, pixelBufferW, abs(infoHeader.height)); + pixelBufferH = abs(infoHeader.height); + newPixelFormat = Pixel::RGB888; break; } case BMP_RGB1: { pixelBufferW = ((imageW & 63) != 0) ? imageW + 64 - (imageW & 63) : imageW; - pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB888, pixelBufferW, abs(infoHeader.height)); + pixelBufferH = abs(infoHeader.height); + newPixelFormat = Pixel::RGB888; break; } case BMP_BITFIELDS32: case BMP_BITFIELDS32V4: { - pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB8888, infoHeader.width, abs(infoHeader.height)); + pixelBufferH = abs(infoHeader.height); + newPixelFormat = Pixel::RGB8888; break; } case BMP_RGB24V5: { - pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB888, infoHeader.width, infoHeader.height); + newPixelFormat = Pixel::RGB888; break; } default: if(pixelFormat == Pixel::RGB565 ) { pixelBufferW = ((imageW & 3) != 0) ? imageW + 4 - (imageW & 3) : imageW; - pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB565, pixelBufferW, abs(infoHeader.height)); - } - else - { - pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(pixelFormat, infoHeader.width, infoHeader.height); + pixelBufferH = abs(infoHeader.height); + newPixelFormat = Pixel::RGB565; } break; } - // TODO: Add scaling support + bitmap = Dali::Devel::PixelBuffer::New(pixelBufferW, pixelBufferH, newPixelFormat); + auto pixels = bitmap.GetBuffer(); // Read the raw bitmap data - PixelBuffer *pixelsPtr; + decltype(pixels) pixelsIterator = nullptr; + bool decodeResult(false); switch(customizedFormat) { @@ -1315,15 +1316,15 @@ bool LoadBitmapFromBmp( const ImageLoader::Input& input, Integration::Bitmap& bi if (topDown) { // the data in the file is top down, and we store the data top down - pixelsPtr = pixels + ( yPos * rowStride); + pixelsIterator = pixels + ( yPos * rowStride); } else { // the data in the file is bottom up, and we store the data top down - pixelsPtr = pixels + (((height-1)-yPos) * rowStride); + pixelsIterator = pixels + (((height-1)-yPos) * rowStride); } - if (fread(pixelsPtr, 1, rowStride, fp) != rowStride) + if (fread(pixelsIterator, 1, rowStride, fp) != rowStride) { DALI_LOG_ERROR("Error reading the BMP image\n"); break; @@ -1335,9 +1336,9 @@ bool LoadBitmapFromBmp( const ImageLoader::Input& input, Integration::Bitmap& bi { for(unsigned int i = 0; i < rowStride; i += 3) { - unsigned char temp = pixelsPtr[i]; - pixelsPtr[i] = pixelsPtr[i+2]; - pixelsPtr[i+2] = temp; + unsigned char temp = pixelsIterator[i]; + pixelsIterator[i] = pixelsIterator[i+2]; + pixelsIterator[i+2] = temp; } } diff --git a/platform-abstractions/tizen/image-loaders/loader-bmp.h b/platform-abstractions/tizen/image-loaders/loader-bmp.h index 53286320c..bb781dbd2 100644 --- a/platform-abstractions/tizen/image-loaders/loader-bmp.h +++ b/platform-abstractions/tizen/image-loaders/loader-bmp.h @@ -23,12 +23,12 @@ namespace Dali { - -namespace Integration +namespace Devel { -class Bitmap; +class PixelBuffer; } + namespace TizenPlatform { @@ -47,7 +47,7 @@ const unsigned char MAGIC_BYTE_2 = 0x4D; * @param[out] bitmap The bitmap class where the decoded image will be stored * @return true if file decoded successfully, false otherwise */ -bool LoadBitmapFromBmp( const ImageLoader::Input& input, Integration::Bitmap& bitmap ); +bool LoadBitmapFromBmp( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ); /** * Loads the header of a BMP file and fills in the width and height appropriately. diff --git a/platform-abstractions/tizen/image-loaders/loader-gif.cpp b/platform-abstractions/tizen/image-loaders/loader-gif.cpp index 1891eb13e..9bcd17b76 100644 --- a/platform-abstractions/tizen/image-loaders/loader-gif.cpp +++ b/platform-abstractions/tizen/image-loaders/loader-gif.cpp @@ -18,10 +18,10 @@ #include "loader-gif.h" #include -#include #include -#include +#include +#include // We need to check if giflib has the new open and close API (including error parameter). #ifdef GIFLIB_MAJOR @@ -30,8 +30,6 @@ namespace Dali { -using Integration::Bitmap; -using Dali::Integration::PixelBuffer; namespace TizenPlatform { @@ -69,22 +67,6 @@ struct AutoCleanupGif 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 @@ -140,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 ) { @@ -151,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" ); @@ -163,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 ) { @@ -195,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 ) { @@ -210,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 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 ) ) { @@ -233,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) @@ -249,9 +233,7 @@ bool HandleImageDescriptionRecordType( Bitmap& bitmap, GifFileType* gifInfo, uns pixels += 3; } } - finished = true; - return true; } @@ -298,7 +280,7 @@ bool LoadGifHeader( const ImageLoader::Input& input, unsigned int& width, unsign return LoadGifHeader(fp, width, height, &gifInfo); } -bool LoadBitmapFromGif( 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. diff --git a/platform-abstractions/tizen/image-loaders/loader-gif.h b/platform-abstractions/tizen/image-loaders/loader-gif.h index 59d259142..e637ac1e8 100644 --- a/platform-abstractions/tizen/image-loaders/loader-gif.h +++ b/platform-abstractions/tizen/image-loaders/loader-gif.h @@ -23,12 +23,12 @@ namespace Dali { - -namespace Integration +namespace Devel { - class Bitmap; +class PixelBuffer; } + namespace TizenPlatform { @@ -48,7 +48,7 @@ const unsigned char MAGIC_BYTE_2 = 0x49; * @param[out] bitmap The bitmap class where the decoded image will be stored * @return true if file decoded successfully, false otherwise */ -bool LoadBitmapFromGif( const ImageLoader::Input& input, Integration::Bitmap& bitmap ); +bool LoadBitmapFromGif( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ); /** * Loads the header of a GIF file and fills in the width and height appropriately. diff --git a/platform-abstractions/tizen/image-loaders/loader-ico.cpp b/platform-abstractions/tizen/image-loaders/loader-ico.cpp index 4a469315f..5078e8c9f 100644 --- a/platform-abstractions/tizen/image-loaders/loader-ico.cpp +++ b/platform-abstractions/tizen/image-loaders/loader-ico.cpp @@ -56,12 +56,10 @@ // INTERNAL INCLUDES #include -#include +#include namespace Dali { -using Integration::Bitmap; -using Dali::Integration::PixelBuffer; namespace TizenPlatform { @@ -357,7 +355,7 @@ bool LoadIcoHeader( const ImageLoader::Input& input, unsigned int& width, unsign return true; } -bool LoadBitmapFromIco( const ImageLoader::Input& input, Integration::Bitmap& bitmap ) +bool LoadBitmapFromIco( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ) { IcoData chosen; Dali::Vector map; @@ -380,7 +378,6 @@ bool LoadBitmapFromIco( const ImageLoader::Input& input, Integration::Bitmap& bi int diff_size = 0; unsigned int* pix; - PixelBuffer* pixels = NULL; size_t position = chosen.bmoffset;//22 == position @@ -664,7 +661,8 @@ bool LoadBitmapFromIco( const ImageLoader::Input& input, Integration::Bitmap& bi } } - pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, w, h ); + bitmap = Dali::Devel::PixelBuffer::New(w, h, Pixel::Format::RGBA8888); + auto pixels = bitmap.GetBuffer(); memcpy( pixels, &surface[0], w * h * 4 ); return true; diff --git a/platform-abstractions/tizen/image-loaders/loader-ico.h b/platform-abstractions/tizen/image-loaders/loader-ico.h index 3d9adb5fa..1c845d567 100644 --- a/platform-abstractions/tizen/image-loaders/loader-ico.h +++ b/platform-abstractions/tizen/image-loaders/loader-ico.h @@ -23,10 +23,9 @@ namespace Dali { - -namespace Integration +namespace Devel { - class Bitmap; +class PixelBuffer; } namespace TizenPlatform @@ -45,7 +44,7 @@ const unsigned char MAGIC_BYTE_2 = 0x00; * @param[out] bitmap The bitmap class where the decoded image will be stored * @return true if file decoded successfully, false otherwise */ -bool LoadBitmapFromIco( const ImageLoader::Input& input, Integration::Bitmap& bitmap ); +bool LoadBitmapFromIco( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ); /** * @param[in] input Information about the input image (including file pointer) diff --git a/platform-abstractions/tizen/image-loaders/loader-jpeg-turbo.cpp b/platform-abstractions/tizen/image-loaders/loader-jpeg-turbo.cpp index 93f95d899..54019c6f2 100755 --- a/platform-abstractions/tizen/image-loaders/loader-jpeg-turbo.cpp +++ b/platform-abstractions/tizen/image-loaders/loader-jpeg-turbo.cpp @@ -31,21 +31,22 @@ #include #include -#include +#include +#include +#include + // INTERNAL HEADERS #include "platform-capabilities.h" #include "image-operations.h" #include +#include namespace { -using Dali::Integration::Bitmap; -using Dali::Integration::PixelBuffer; using Dali::Vector; namespace Pixel = Dali::Pixel; - - +using PixelArray = unsigned char*; const unsigned int DECODED_L8 = 1; const unsigned int DECODED_RGB888 = 3; const unsigned int DECODED_RGBA8888 = 4; @@ -172,7 +173,7 @@ UniquePointerSetter SetPointer(std::unique_ptr& uniquePo return UniquePointerSetter{uniquePointer}; } -using TransformFunction = std::function; +using TransformFunction = std::function; using TransformFunctionArray = std::array; // 1, 3 and 4 bytes per pixel /// @brief Select the transform function depending on the pixel format @@ -209,9 +210,94 @@ TransformFunction GetTransformFunction(const TransformFunctionArray& functions, return function; } +// Storing Exif fields as properties +template +R ConvertExifNumeric( const ExifEntry& entry ) +{ + return static_cast((*reinterpret_cast(entry.data))); +} + +void AddExifFieldPropertyMap( Dali::Property::Map& out, const ExifEntry& entry, ExifIfd ifd ) +{ + auto shortName = std::string(exif_tag_get_name_in_ifd(entry.tag, ifd )); + switch( entry.format ) + { + case EXIF_FORMAT_ASCII: + { + out.Insert( shortName, std::string(reinterpret_cast(entry.data)) ); + break; + } + case EXIF_FORMAT_SHORT: + { + out.Insert( shortName, ConvertExifNumeric(entry) ); + break; + } + case EXIF_FORMAT_LONG: + { + out.Insert( shortName, ConvertExifNumeric(entry) ); + break; + } + case EXIF_FORMAT_SSHORT: + { + out.Insert( shortName, ConvertExifNumeric(entry) ); + break; + } + case EXIF_FORMAT_SLONG: + { + out.Insert( shortName, ConvertExifNumeric(entry) ); + break; + } + case EXIF_FORMAT_FLOAT: + { + out.Insert (shortName, ConvertExifNumeric(entry) ); + break; + } + case EXIF_FORMAT_DOUBLE: + { + out.Insert( shortName, ConvertExifNumeric(entry) ); + break; + } + case EXIF_FORMAT_RATIONAL: + { + auto values = reinterpret_cast( entry.data ); + Dali::Property::Array array; + array.Add( static_cast(values[0]) ); + array.Add( static_cast(values[1]) ); + out.Insert(shortName, array); + break; + } + case EXIF_FORMAT_SBYTE: + { + out.Insert(shortName, "EXIF_FORMAT_SBYTE Unsupported"); + break; + } + case EXIF_FORMAT_BYTE: + { + out.Insert(shortName, "EXIF_FORMAT_BYTE Unsupported"); + break; + } + case EXIF_FORMAT_SRATIONAL: + { + auto values = reinterpret_cast( entry.data ); + Dali::Property::Array array; + array.Add(values[0]); + array.Add(values[1]); + out.Insert(shortName, array); + break; + } + case EXIF_FORMAT_UNDEFINED: + default: + { + std::stringstream ss; + ss << "EXIF_FORMAT_UNDEFINED, size: " << entry.size << ", components: " << entry.components; + out.Insert( shortName, ss.str()); + } + } +} + /// @brief Apply a transform to a buffer bool Transform(const TransformFunctionArray& transformFunctions, - PixelBuffer *buffer, + PixelArray buffer, int width, int height, Pixel::Format pixelFormat ) @@ -232,7 +318,7 @@ struct PixelType }; template -void FlipVertical(PixelBuffer* buffer, int width, int height) +void FlipVertical(PixelArray buffer, int width, int height) { // Destination pixel, set as the first pixel of screen auto to = reinterpret_cast*>( buffer ); @@ -248,7 +334,7 @@ void FlipVertical(PixelBuffer* buffer, int width, int height) } template -void FlipHorizontal(PixelBuffer* buffer, int width, int height) +void FlipHorizontal(PixelArray buffer, int width, int height) { for(auto iy = 0; iy < height; ++iy) { @@ -264,7 +350,7 @@ void FlipHorizontal(PixelBuffer* buffer, int width, int height) } template -void Transpose(PixelBuffer* buffer, int width, int height) +void Transpose(PixelArray buffer, int width, int height) { //Transform vertically only for(auto iy = 0; iy < height / 2; ++iy) @@ -279,7 +365,7 @@ void Transpose(PixelBuffer* buffer, int width, int height) } template -void Transverse(PixelBuffer* buffer, int width, int height) +void Transverse(PixelArray buffer, int width, int height) { using PixelT = PixelType; Vector data; @@ -302,7 +388,7 @@ void Transverse(PixelBuffer* buffer, int width, int height) template -void Rotate90(PixelBuffer* buffer, int width, int height) +void Rotate90(PixelArray buffer, int width, int height) { using PixelT = PixelType; Vector data; @@ -331,7 +417,7 @@ void Rotate90(PixelBuffer* buffer, int width, int height) } template -void Rotate180(PixelBuffer* buffer, int width, int height) +void Rotate180(PixelArray buffer, int width, int height) { using PixelT = PixelType; Vector data; @@ -355,7 +441,7 @@ void Rotate180(PixelBuffer* buffer, int width, int height) template -void Rotate270(PixelBuffer* buffer, int width, int height) +void Rotate270(PixelArray buffer, int width, int height) { using PixelT = PixelType; Vector data; @@ -442,7 +528,7 @@ bool LoadJpegHeader( FILE *fp, unsigned int &width, unsigned int &height ) return true; } -bool LoadBitmapFromJpeg( const ImageLoader::Input& input, Integration::Bitmap& bitmap ) +bool LoadBitmapFromJpeg( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ) { const int flags= 0; FILE* const fp = input.file; @@ -505,12 +591,28 @@ bool LoadBitmapFromJpeg( const ImageLoader::Input& input, Integration::Bitmap& b auto transform = JpegTransform::NONE; - if( input.reorientationRequested ) + // extract exif data + auto exifData = MakeExifDataFromData(jpegBufferPtr, jpegBufferSize); + + if( exifData && input.reorientationRequested ) + { + transform = ConvertExifOrientation(exifData.get()); + } + + std::unique_ptr exifMap; + exifMap.reset( new Property::Map() ); + + for( auto k = 0u; k < EXIF_IFD_COUNT; ++k ) { - auto exifData = MakeExifDataFromData(jpegBufferPtr, jpegBufferSize); - if( exifData ) + auto content = exifData->ifd[k]; + for (auto i = 0u; i < content->count; ++i) { - transform = ConvertExifOrientation(exifData.get()); + auto &&tag = content->entries[i]; + const char *shortName = exif_tag_get_name_in_ifd(tag->tag, static_cast(k)); + if(shortName) + { + AddExifFieldPropertyMap(*exifMap, *tag, static_cast(k)); + } } } @@ -601,7 +703,12 @@ bool LoadBitmapFromJpeg( const ImageLoader::Input& input, Integration::Bitmap& b } #endif // Allocate a bitmap and decompress the jpeg buffer into its pixel buffer: - PixelBuffer* bitmapPixelBuffer = bitmap.GetPackedPixelsProfile()->ReserveBuffer( pixelFormat, scaledPostXformWidth, scaledPostXformHeight ) ; + bitmap = Dali::Devel::PixelBuffer::New(scaledPostXformWidth, scaledPostXformHeight, pixelFormat); + + // set metadata + GetImplementation(bitmap).SetMetadata( std::move(exifMap) ); + + auto bitmapPixelBuffer = bitmap.GetBuffer(); if( tjDecompress2( jpeg.get(), jpegBufferPtr, jpegBufferSize, reinterpret_cast( bitmapPixelBuffer ), scaledPreXformWidth, 0, scaledPreXformHeight, pixelLibJpegType, flags ) == -1 ) { @@ -707,6 +814,7 @@ bool LoadBitmapFromJpeg( const ImageLoader::Input& input, Integration::Bitmap& b break; } } + return result; } diff --git a/platform-abstractions/tizen/image-loaders/loader-jpeg.h b/platform-abstractions/tizen/image-loaders/loader-jpeg.h index baf69b0db..bae32c69c 100644 --- a/platform-abstractions/tizen/image-loaders/loader-jpeg.h +++ b/platform-abstractions/tizen/image-loaders/loader-jpeg.h @@ -26,12 +26,12 @@ namespace Dali { - -namespace Integration +namespace Devel { - class Bitmap; +class PixelBuffer; } + namespace TizenPlatform { @@ -50,7 +50,7 @@ const unsigned char MAGIC_BYTE_2 = 0xD8; * @param[out] bitmap The bitmap class where the decoded image will be stored * @return true if file decoded successfully, false otherwise */ -bool LoadBitmapFromJpeg( const ImageLoader::Input& input, Integration::Bitmap& bitmap ); +bool LoadBitmapFromJpeg( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ); /** * Loads the header of a JPEG file and fills in the width and height appropriately. diff --git a/platform-abstractions/tizen/image-loaders/loader-ktx.cpp b/platform-abstractions/tizen/image-loaders/loader-ktx.cpp index d39c361ec..fc671049d 100755 --- a/platform-abstractions/tizen/image-loaders/loader-ktx.cpp +++ b/platform-abstractions/tizen/image-loaders/loader-ktx.cpp @@ -19,19 +19,13 @@ #include "loader-ktx.h" // EXTERNAL INCLUDES -#include -#include #include -#include #include #include -#include -#include +#include namespace Dali { -using Integration::Bitmap; -using Dali::Integration::PixelBuffer; namespace TizenPlatform { @@ -538,7 +532,7 @@ bool LoadKtxHeader( const ImageLoader::Input& input, unsigned int& width, unsign } // File loading API entry-point: -bool LoadBitmapFromKtx( const ImageLoader::Input& input, Integration::Bitmap& bitmap ) +bool LoadBitmapFromKtx( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ) { DALI_COMPILE_TIME_ASSERT( sizeof(Byte) == 1); DALI_COMPILE_TIME_ASSERT( sizeof(uint32_t) == 4); @@ -592,7 +586,9 @@ bool LoadBitmapFromKtx( const ImageLoader::Input& input, Integration::Bitmap& bi } // Load up the image bytes: - PixelBuffer* const pixels = bitmap.GetCompressedProfile()->ReserveBufferOfSize( pixelFormat, width, height, imageByteCount ); + bitmap = Dali::Devel::PixelBuffer::New(width, height, pixelFormat); + auto pixels = bitmap.GetBuffer(); + if(!pixels) { DALI_LOG_ERROR( "Unable to reserve a pixel buffer to load the requested bitmap into.\n" ); diff --git a/platform-abstractions/tizen/image-loaders/loader-ktx.h b/platform-abstractions/tizen/image-loaders/loader-ktx.h index c019ae865..b7f01a80a 100644 --- a/platform-abstractions/tizen/image-loaders/loader-ktx.h +++ b/platform-abstractions/tizen/image-loaders/loader-ktx.h @@ -23,10 +23,9 @@ namespace Dali { - -namespace Integration +namespace Devel { - class Bitmap; +class PixelBuffer; } namespace TizenPlatform @@ -48,7 +47,7 @@ const unsigned char MAGIC_BYTE_2 = 0x4B; * @param[out] bitmap The bitmap class where the decoded image will be stored * @return true if file loaded successfully, false otherwise */ -bool LoadBitmapFromKtx( const ImageLoader::Input& input, Integration::Bitmap& bitmap ); +bool LoadBitmapFromKtx( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ); /** * Loads the header of a KTX file and fills in the width and height appropriately. diff --git a/platform-abstractions/tizen/image-loaders/loader-png.cpp b/platform-abstractions/tizen/image-loaders/loader-png.cpp index 2b2309e3d..872e8eea6 100755 --- a/platform-abstractions/tizen/image-loaders/loader-png.cpp +++ b/platform-abstractions/tizen/image-loaders/loader-png.cpp @@ -18,24 +18,17 @@ #include "loader-png.h" #include -#include #include #include -#include #include #include -#include "dali/public-api/math/math-utils.h" -#include "dali/public-api/math/vector2.h" #include "platform-capabilities.h" +#include namespace Dali { - -using Integration::Bitmap; -using Dali::Integration::PixelBuffer; - namespace TizenPlatform { @@ -128,7 +121,7 @@ bool LoadPngHeader( const ImageLoader::Input& input, unsigned int& width, unsign return success; } -bool LoadBitmapFromPng( const ImageLoader::Input& input, Integration::Bitmap& bitmap ) +bool LoadBitmapFromPng( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ) { png_structp png = NULL; png_infop info = NULL; @@ -137,7 +130,6 @@ bool LoadBitmapFromPng( const ImageLoader::Input& input, Integration::Bitmap& bi /// @todo: consider parameters unsigned int y; unsigned int width, height; - unsigned char *pixels; png_bytep *rows; unsigned int bpp = 0; // bytes per pixel bool valid = false; @@ -312,7 +304,7 @@ bool LoadBitmapFromPng( const ImageLoader::Input& input, Integration::Bitmap& bi } // decode the whole image into bitmap buffer - pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(pixelFormat, width, height, bufferWidth, bufferHeight); + auto pixels = (bitmap = Dali::Devel::PixelBuffer::New(bufferWidth, bufferHeight, pixelFormat)).GetBuffer(); DALI_ASSERT_DEBUG(pixels); rows = reinterpret_cast< png_bytep* >( malloc(sizeof(png_bytep) * height) ); diff --git a/platform-abstractions/tizen/image-loaders/loader-png.h b/platform-abstractions/tizen/image-loaders/loader-png.h index e67658808..0c9c4933e 100644 --- a/platform-abstractions/tizen/image-loaders/loader-png.h +++ b/platform-abstractions/tizen/image-loaders/loader-png.h @@ -26,10 +26,9 @@ namespace Dali { - -namespace Integration +namespace Devel { - class Bitmap; +class PixelBuffer; } namespace TizenPlatform @@ -50,7 +49,7 @@ const unsigned char MAGIC_BYTE_2 = 0x50; * @param[out] bitmap The bitmap class where the decoded image will be stored * @return true if file decoded successfully, false otherwise */ -bool LoadBitmapFromPng( const ImageLoader::Input& input, Integration::Bitmap& bitmap ); +bool LoadBitmapFromPng( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ); /** * Loads the header of a PNG file and fills in the width and height appropriately. diff --git a/platform-abstractions/tizen/image-loaders/loader-wbmp.cpp b/platform-abstractions/tizen/image-loaders/loader-wbmp.cpp index 4a176ef3b..44560bbbe 100755 --- a/platform-abstractions/tizen/image-loaders/loader-wbmp.cpp +++ b/platform-abstractions/tizen/image-loaders/loader-wbmp.cpp @@ -25,13 +25,11 @@ // INTERNAL INCLUDES #include -#include -#include +#include namespace Dali { -using Integration::Bitmap; -using Dali::Integration::PixelBuffer; + namespace TizenPlatform { @@ -92,7 +90,7 @@ int extractMultiByteInteger(unsigned int *data, void *map, size_t length, size_t }// end unnamed namespace -bool LoadBitmapFromWbmp( const ImageLoader::Input& input, Integration::Bitmap& bitmap ) +bool LoadBitmapFromWbmp( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ) { FILE* const fp = input.file; if(fp == NULL) @@ -102,7 +100,6 @@ bool LoadBitmapFromWbmp( const ImageLoader::Input& input, Integration::Bitmap& b } Dali::Vector map; Dali::Vector surface;//unsigned int - PixelBuffer* pixels = NULL; size_t position = 0; unsigned int w, h; @@ -206,7 +203,7 @@ bool LoadBitmapFromWbmp( const ImageLoader::Input& input, Integration::Bitmap& b cur++; } } - pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::L8, w, h);//Pixel::RGBA8888 + auto pixels = (bitmap = Dali::Devel::PixelBuffer::New(w, h, Pixel::L8)).GetBuffer(); memcpy( pixels, &surface[0], w * h ); //w * h * 4 diff --git a/platform-abstractions/tizen/image-loaders/loader-wbmp.h b/platform-abstractions/tizen/image-loaders/loader-wbmp.h index a2040a0b3..619449f0e 100755 --- a/platform-abstractions/tizen/image-loaders/loader-wbmp.h +++ b/platform-abstractions/tizen/image-loaders/loader-wbmp.h @@ -24,9 +24,9 @@ namespace Dali { -namespace Integration +namespace Devel { - class Bitmap; +class PixelBuffer; } namespace TizenPlatform @@ -39,7 +39,7 @@ class ResourceLoadingClient; * @param[out] bitmap The bitmap class where the decoded image will be stored * @return true if file decoded successfully, false otherwise */ -bool LoadBitmapFromWbmp( const ImageLoader::Input& input, Integration::Bitmap& bitmap ); +bool LoadBitmapFromWbmp( const ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ); /** * @param[in] input Information about the input image (including file pointer) diff --git a/platform-abstractions/tizen/tizen-platform-abstraction.cpp b/platform-abstractions/tizen/tizen-platform-abstraction.cpp index 1a8a876c8..2bf6e6f99 100644 --- a/platform-abstractions/tizen/tizen-platform-abstraction.cpp +++ b/platform-abstractions/tizen/tizen-platform-abstraction.cpp @@ -28,6 +28,7 @@ // INTERNAL INCLUDES #include "image-loaders/image-loader.h" #include "portable/file-reader.h" +#include namespace Dali { @@ -69,7 +70,8 @@ Integration::ResourcePointer TizenPlatformAbstraction::LoadImageSynchronously(co Integration::BitmapPtr TizenPlatformAbstraction::DecodeBuffer( const Integration::BitmapResourceType& resource, uint8_t * buffer, size_t size ) { - Integration::BitmapPtr bitmap = 0; + Integration::BitmapPtr resultBitmap; + Dali::Devel::PixelBuffer bitmap; Dali::Internal::Platform::FileReader fileReader( buffer, size ); FILE * const fp = fileReader.GetFile(); @@ -81,9 +83,29 @@ Integration::BitmapPtr TizenPlatformAbstraction::DecodeBuffer( const Integration bitmap.Reset(); DALI_LOG_WARNING( "Unable to decode bitmap supplied as in-memory blob.\n" ); } + else + { + Integration::Bitmap::Profile profile{Integration::Bitmap::Profile::BITMAP_2D_PACKED_PIXELS}; + + // For backward compatibility the Bitmap must be created + auto retval = Integration::Bitmap::New(profile, Dali::ResourcePolicy::OWNED_DISCARD); + + retval->GetPackedPixelsProfile()->ReserveBuffer( + bitmap.GetPixelFormat(), + bitmap.GetWidth(), + bitmap.GetHeight(), + bitmap.GetWidth(), + bitmap.GetHeight() + ); + + auto& impl = Dali::GetImplementation(bitmap); + + std::copy( impl.GetBuffer(), impl.GetBuffer()+impl.GetBufferSize(), retval->GetBuffer()); + resultBitmap.Reset(retval); + } } - return bitmap; + return resultBitmap; } bool TizenPlatformAbstraction::LoadShaderBinaryFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const -- 2.34.1