From 8ee0fe0ef036a9477079190d8725920db2f2aa1c Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Wed, 2 Jun 2021 09:54:41 +0900 Subject: [PATCH] Add api for load image from encoded buffer + fix file-reader.h bug Add api ImageLoading::LoadImageFromBuffer(const Dali::Vector&) We can load image from encoded image buffer. + Fix some portential error when we use Internal::Platform::FileReader This patch will increase the convenience of using a Internal::Platform::FileReader Change-Id: I0e9b77fc4665261959ed6e027e398e78db2c1d31 Signed-off-by: Eunki, Hong --- .../src/dali-adaptor/utc-Dali-ImageLoading.cpp | 165 +++++++++++++++++++++ dali/devel-api/adaptor-framework/image-loading.cpp | 24 +++ dali/devel-api/adaptor-framework/image-loading.h | 20 +++ dali/internal/system/common/file-reader.h | 12 +- 4 files changed, 217 insertions(+), 4 deletions(-) diff --git a/automated-tests/src/dali-adaptor/utc-Dali-ImageLoading.cpp b/automated-tests/src/dali-adaptor/utc-Dali-ImageLoading.cpp index 23e2450..1019707 100644 --- a/automated-tests/src/dali-adaptor/utc-Dali-ImageLoading.cpp +++ b/automated-tests/src/dali-adaptor/utc-Dali-ImageLoading.cpp @@ -70,6 +70,23 @@ const char* IMAGE_WIDTH_EVEN_EXIF8_RGB = TEST_RESOURCE_DIR "/f-even-exif-8.jpg"; // this is image is not exist, for negative test const char* IMAGENONEXIST = "non-exist.jpg"; + +Dali::Vector FileToMemory(const char* filename) +{ + Dali::Vector buffer; + FILE *fp; + fp = fopen(filename, "rb"); + if(fp != NULL) + { + fseek(fp, 0, SEEK_END); + size_t size = ftell(fp); + buffer.Resize(size); + fseek(fp, 0, SEEK_SET); + fread(buffer.Begin(), size, sizeof(uint8_t), fp); + fclose(fp); + } + return buffer; +} } // namespace void utc_dali_load_image_startup(void) @@ -223,6 +240,154 @@ int UtcDaliLoadImageN(void) END_TEST; } +int UtcDaliLoadImageFromBufferP(void) +{ + Devel::PixelBuffer pixelBuffer = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_34_RGBA)); + DALI_TEST_CHECK(pixelBuffer); + DALI_TEST_EQUALS(pixelBuffer.GetWidth(), 34u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBuffer.GetHeight(), 34u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBuffer.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION); + + Devel::PixelBuffer pixelBuffer2 = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_128_RGB)); + DALI_TEST_CHECK(pixelBuffer2); + DALI_TEST_EQUALS(pixelBuffer2.GetWidth(), 128u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBuffer2.GetHeight(), 128u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBuffer2.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + + Devel::PixelBuffer pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_LARGE_EXIF3_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 2000u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 2560u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + + Devel::PixelBuffer BufferJpeg1 = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_ODD_EXIF1_RGB)); + DALI_TEST_CHECK(BufferJpeg1); + DALI_TEST_EQUALS(BufferJpeg1.GetWidth(), 55u, TEST_LOCATION); + DALI_TEST_EQUALS(BufferJpeg1.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(BufferJpeg1.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_ODD_EXIF2_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 55u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_ODD_EXIF3_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 55u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_ODD_EXIF4_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 55u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_ODD_EXIF5_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 55u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_ODD_EXIF6_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 55u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_ODD_EXIF7_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 55u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_ODD_EXIF8_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 55u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + BufferJpeg1 = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_EVEN_EXIF1_RGB)); + DALI_TEST_CHECK(BufferJpeg1); + DALI_TEST_EQUALS(BufferJpeg1.GetWidth(), 50u, TEST_LOCATION); + DALI_TEST_EQUALS(BufferJpeg1.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(BufferJpeg1.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_EVEN_EXIF2_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 50u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_EVEN_EXIF3_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 50u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_EVEN_EXIF4_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 50u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_EVEN_EXIF5_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 50u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_EVEN_EXIF6_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 50u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_EVEN_EXIF7_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 50u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + pixelBufferJpeg = Dali::LoadImageFromBuffer(FileToMemory(IMAGE_WIDTH_EVEN_EXIF8_RGB)); + DALI_TEST_CHECK(pixelBufferJpeg); + DALI_TEST_EQUALS(pixelBufferJpeg.GetWidth(), 50u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetHeight(), 64u, TEST_LOCATION); + DALI_TEST_EQUALS(pixelBufferJpeg.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + DALI_IMAGE_TEST_EQUALS(BufferJpeg1, pixelBufferJpeg, 8, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliLoadImageFromBufferN(void) +{ + Devel::PixelBuffer pixelBufferEmpty = Dali::LoadImageFromBuffer(Dali::Vector()); + DALI_TEST_CHECK(!pixelBufferEmpty); + + Dali::Vector strange; + strange.PushBack(0x11); + strange.PushBack(0x22); + strange.PushBack(0x33); + Devel::PixelBuffer pixelBufferStrange = Dali::LoadImageFromBuffer(strange); + DALI_TEST_CHECK(!pixelBufferStrange); + + END_TEST; +} + int UtcDaliDownloadImageP(void) { std::string url("file://"); diff --git a/dali/devel-api/adaptor-framework/image-loading.cpp b/dali/devel-api/adaptor-framework/image-loading.cpp index 44bcac7..cfaaa12 100644 --- a/dali/devel-api/adaptor-framework/image-loading.cpp +++ b/dali/devel-api/adaptor-framework/image-loading.cpp @@ -51,6 +51,30 @@ Devel::PixelBuffer LoadImageFromFile(const std::string& url, ImageDimensions siz return Dali::Devel::PixelBuffer(); } +Devel::PixelBuffer LoadImageFromBuffer(const Dali::Vector& buffer, ImageDimensions size, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection) +{ + if(buffer.Empty()) + { + DALI_LOG_ERROR("buffer is empty!\n"); + return Dali::Devel::PixelBuffer(); + } + Integration::BitmapResourceType resourceType(size, fittingMode, samplingMode, orientationCorrection); + + Internal::Platform::FileReader fileReader(buffer); + FILE* const fp = fileReader.GetFile(); + if(fp != NULL) + { + Dali::Devel::PixelBuffer bitmap; + // Make path as empty string. Path information just for file format hint. + bool success = TizenPlatform::ImageLoader::ConvertStreamToBitmap(resourceType, std::string(""), fp, bitmap); + if(success && bitmap) + { + return bitmap; + } + } + return Dali::Devel::PixelBuffer(); +} + ImageDimensions GetClosestImageSize(const std::string& filename, ImageDimensions size, FittingMode::Type fittingMode, diff --git a/dali/devel-api/adaptor-framework/image-loading.h b/dali/devel-api/adaptor-framework/image-loading.h index a66028d..c1f7ad8 100644 --- a/dali/devel-api/adaptor-framework/image-loading.h +++ b/dali/devel-api/adaptor-framework/image-loading.h @@ -47,6 +47,26 @@ DALI_ADAPTOR_API Devel::PixelBuffer LoadImageFromFile( bool orientationCorrection = true); /** + * @brief Load an image synchronously from encoded buffer. + * + * @note This method is thread safe, i.e. can be called from any thread. + * + * @param [in] buffer The encoded buffer of the image to load. + * The buffer is not owned by FileStream and must be valid for entire lifetime of FileStream + * @param [in] size The width and height to fit the loaded image to, 0.0 means whole image + * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter. + * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size. + * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header. + * @return handle to the loaded PixelBuffer object or an empty handle in case loading failed. + */ +DALI_ADAPTOR_API Devel::PixelBuffer LoadImageFromBuffer( + const Dali::Vector& buffer, + ImageDimensions size = ImageDimensions(0, 0), + FittingMode::Type fittingMode = FittingMode::DEFAULT, + SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR, + bool orientationCorrection = true); + +/** * @brief Determine the size of an image that LoadImageFromFile will provide when * given the same image loading parameters. * diff --git a/dali/internal/system/common/file-reader.h b/dali/internal/system/common/file-reader.h index 031ad2d..b6c3b5d 100644 --- a/dali/internal/system/common/file-reader.h +++ b/dali/internal/system/common/file-reader.h @@ -36,14 +36,18 @@ public: { } - FileReader(Dali::Vector& vector) - : FileStream(&vector[0], vector.Size(), FileStream::READ | FileStream::BINARY) + FileReader(const Dali::Vector& vector) + : FileStream(vector.Begin(), vector.Size(), FileStream::READ | FileStream::BINARY) { } - FileReader(Dali::Vector& vector, size_t dataSize) - : FileStream(&vector[0], dataSize, FileStream::READ | FileStream::BINARY) + FileReader(const Dali::Vector& vector, size_t dataSize) + : FileStream(vector.Begin(), dataSize, FileStream::READ | FileStream::BINARY) { + if(dataSize > vector.Size()) + { + DALI_LOG_ERROR("dataSize(%u) is bigger than vector.Size(%u)!\n", static_cast(dataSize), static_cast(vector.Size())); + } } FileReader(uint8_t* data, size_t dataSize) -- 2.7.4