From 1254ea9a027478674a94fa9579855f4dd38a6847 Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Wed, 16 Mar 2022 21:24:30 +0900 Subject: [PATCH] Wbmp load faster 1. Remove useless memcpy. 2. bit operation more faster Change-Id: I7db9a239159670e7a3a22a3c2c951b7da0cd4e59 Signed-off-by: Eunki, Hong --- automated-tests/images/test-image.wbmp.buffer | Bin 0 -> 2048 bytes .../src/dali-adaptor-internal/CMakeLists.txt | 1 + .../src/dali-adaptor-internal/image-loaders.cpp | 4 +- .../dali-adaptor-internal/utc-Dali-WbmpLoader.cpp | 40 +++++++ dali/internal/imaging/common/loader-wbmp.cpp | 117 ++++++++++++++++----- 5 files changed, 133 insertions(+), 29 deletions(-) create mode 100644 automated-tests/images/test-image.wbmp.buffer create mode 100644 automated-tests/src/dali-adaptor-internal/utc-Dali-WbmpLoader.cpp diff --git a/automated-tests/images/test-image.wbmp.buffer b/automated-tests/images/test-image.wbmp.buffer new file mode 100644 index 0000000000000000000000000000000000000000..b40d0bc71b57db09514664c2081c70071ba103d6 GIT binary patch literal 2048 zcmaJ=3AV!^2+aL2oiZDW=GFX)FbkOWKkxHCScu~p3GfLk6X|)s&=^4aDTW0|0%iEQ zOFy6_Y4Sh9pszq_^o|3qTEjeOvw_gX&<#)}fd^iTBej*)q={3zQRXcV#d-#D(*TTJ zx+}z7sGCF~3+$v+*``&{mjN>x$|EUpsEiSf8~vomPk|03AW;GKWH?PdsrQVskb+aoYBFq3-GlD!UkC{0l}wqs3_&U@)57=6D0D zE(gsKi!#@pYHt&RD!6GT2pwcuNr`%W0`tHm#RyP5KJiJp7|Up}t0uF>!-?h1T}K+2 zNL3i}V2PaMCPimLg(lbmA=NsX7}l64vr9?xee4TdkeaiB`-n34bmsrZgk+GuC#GC? yF?LfnnBZj4x-WnqQ$0IHm?pSUFqgWO%YdlVL=Shq8W@CvxT`OOpcvFZ8-pJk0;Glj literal 0 HcmV?d00001 diff --git a/automated-tests/src/dali-adaptor-internal/CMakeLists.txt b/automated-tests/src/dali-adaptor-internal/CMakeLists.txt index b6c2ec9..4fe46cf 100644 --- a/automated-tests/src/dali-adaptor-internal/CMakeLists.txt +++ b/automated-tests/src/dali-adaptor-internal/CMakeLists.txt @@ -17,6 +17,7 @@ SET(TC_SOURCES utc-Dali-Internal-PixelBuffer.cpp utc-Dali-Lifecycle-Controller.cpp utc-Dali-TiltSensor.cpp + utc-Dali-WbmpLoader.cpp ) diff --git a/automated-tests/src/dali-adaptor-internal/image-loaders.cpp b/automated-tests/src/dali-adaptor-internal/image-loaders.cpp index 843cb92..28449f0 100644 --- a/automated-tests/src/dali-adaptor-internal/image-loaders.cpp +++ b/automated-tests/src/dali-adaptor-internal/image-loaders.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 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. @@ -120,7 +120,7 @@ void TestImageLoading(const ImageDetails& image, const LoadFunctions& functions, if(*bufferPtr != *refBufferPtr) { tet_result(TET_FAIL); - tet_printf("%s Failed in %s at line %d\n", __PRETTY_FUNCTION__, __FILE__, __LINE__); + tet_printf("%s Failed in %s at line %d, %u'th buffer (input : %u != expect : %u)\n", __PRETTY_FUNCTION__, __FILE__, __LINE__, i, static_cast(*bufferPtr), static_cast(*refBufferPtr)); break; } } diff --git a/automated-tests/src/dali-adaptor-internal/utc-Dali-WbmpLoader.cpp b/automated-tests/src/dali-adaptor-internal/utc-Dali-WbmpLoader.cpp new file mode 100644 index 0000000..8b2b6d7 --- /dev/null +++ b/automated-tests/src/dali-adaptor-internal/utc-Dali-WbmpLoader.cpp @@ -0,0 +1,40 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include +#include "image-loaders.h" + +using namespace Dali; + +namespace +{ +static const LoadFunctions WbmpLoaders(TizenPlatform::LoadWbmpHeader, TizenPlatform::LoadBitmapFromWbmp); + +} // Unnamed namespace. + +int UtcDaliWbmpLoader(void) +{ + ImageDetails image(TEST_IMAGE_DIR "/test-image.wbmp", 32u, 64u); + + TestImageLoading(image, WbmpLoaders); + + END_TEST; +} \ No newline at end of file diff --git a/dali/internal/imaging/common/loader-wbmp.cpp b/dali/internal/imaging/common/loader-wbmp.cpp index f20b5ce..aee8621 100644 --- a/dali/internal/imaging/common/loader-wbmp.cpp +++ b/dali/internal/imaging/common/loader-wbmp.cpp @@ -37,6 +37,9 @@ namespace Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_LOADER_WBMP"); #endif +// TODO : We need to determine it in dali-common.h or something else. Currently, we set this value in code level. +#define DALI_BYTE_ORDER_BIG_ENDIAN 0 + #define IMG_MAX_SIZE 65536 #define IMG_TOO_BIG(w, h) \ @@ -84,6 +87,35 @@ int extractMultiByteInteger(unsigned int* data, void* map, size_t length, size_t return 0; } +// Calculate 4bit integer into 4byte integer +constexpr std::uint32_t Calculate4BitTo4Byte(const std::uint8_t& input) +{ + std::uint32_t output = 0; +#if DALI_BYTE_ORDER_BIG_ENDIAN + output |= static_cast(input & 0x08) << 21; + output |= static_cast(input & 0x04) << 14; + output |= static_cast(input & 0x02) << 7; + output |= static_cast(input & 0x01); +#else + output |= static_cast(input & 0x08) >> 3; + output |= static_cast(input & 0x04) << 6; + output |= static_cast(input & 0x02) << 15; + output |= static_cast(input & 0x01) << 24; +#endif + return output * 0xff; +} + +/** + * @brief Calculation result bit-->byte table in compile. + * Required memory = 16 * 4byte = 64byte + */ +// clang-format off +constexpr std::uint32_t cachedCalculation4BitTo4ByteTable[16] = { + Calculate4BitTo4Byte(0x00), Calculate4BitTo4Byte(0x01), Calculate4BitTo4Byte(0x02), Calculate4BitTo4Byte(0x03), + Calculate4BitTo4Byte(0x04), Calculate4BitTo4Byte(0x05), Calculate4BitTo4Byte(0x06), Calculate4BitTo4Byte(0x07), + Calculate4BitTo4Byte(0x08), Calculate4BitTo4Byte(0x09), Calculate4BitTo4Byte(0x0a), Calculate4BitTo4Byte(0x0b), + Calculate4BitTo4Byte(0x0c), Calculate4BitTo4Byte(0x0d), Calculate4BitTo4Byte(0x0e), Calculate4BitTo4Byte(0x0f)}; +// clang-format on } // end unnamed namespace bool LoadBitmapFromWbmp(const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap) @@ -95,14 +127,11 @@ bool LoadBitmapFromWbmp(const Dali::ImageLoader::Input& input, Dali::Devel::Pixe return false; } Dali::Vector map; - Dali::Vector surface; //unsigned int size_t position = 0; - unsigned int w, h; - unsigned int type; - unsigned int line_length; - unsigned char* line = NULL; - unsigned int cur = 0, x, y; + std::uint32_t w, h; + std::uint32_t type; + std::uint32_t lineByteLength; if(fseek(fp, 0, SEEK_END)) { @@ -172,36 +201,70 @@ bool LoadBitmapFromWbmp(const Dali::ImageLoader::Input& input, Dali::Devel::Pixe return false; } - surface.ResizeUninitialized(w * h); //(w * h * 4); - memset(&surface[0], 0, w * h); // w * h * 4 + lineByteLength = (w + 7) >> 3; + // fsize was wrong! Load failed. + if(DALI_UNLIKELY(position + h * lineByteLength > fsize)) + { + DALI_LOG_ERROR("Pixel infomation is bigger than file size! (%u + %u * %u > %u)\n", static_cast(position), h, lineByteLength, fsize); + return false; + } - line_length = (w + 7) >> 3; - for(y = 0; y < h; y++) + // w >= 1 and h >= 1. So we can assume that outputPixels is not null. + auto outputPixels = (bitmap = Dali::Devel::PixelBuffer::New(w, h, Pixel::L8)).GetBuffer(); + /** + * @code + * std::uint8_t* line = NULL; + * std::uint32_t cur = 0, x, y; + * for(y = 0; y < h; y++) + * { + * line = &map[0] + position; + * position += lineByteLength; + * for(x = 0; x < w; x++) + * { + * int idx = x >> 3; + * int offset = 1 << (0x07 - (x & 0x07)); + * if(line[idx] & offset) + * { + * outputPixels[cur] = 0xff; //0xffffffff; + * } + * else + * { + * outputPixels[cur] = 0x00; //0xff000000; + * } + * cur++; + * } + * } + * @endcode + */ + + const std::uint8_t* inputPixels = &map[0] + position; + const std::uint32_t lineByteLengthWithoutPadding = w >> 3; + const std::uint8_t linePadding = w & 0x07; + + for(std::uint32_t y = 0; y < h; y++) { - if(position + line_length > fsize) + for(std::uint32_t x = 0; x < lineByteLengthWithoutPadding; x++) { - return false; + // memset whole 8 bits + // outputPixels filled 4 bytes in one operation. + // cachedCalculation4BitTo4ByteTable calculated in compile-time. + *(reinterpret_cast(outputPixels + 0)) = cachedCalculation4BitTo4ByteTable[((*inputPixels) >> 4) & 0x0f]; + *(reinterpret_cast(outputPixels + 4)) = cachedCalculation4BitTo4ByteTable[(*inputPixels) & 0x0f]; + outputPixels += 8; + ++inputPixels; } - line = &map[0] + position; - position += line_length; - for(x = 0; x < w; x++) + if(linePadding > 0) { - int idx = x >> 3; - int offset = 1 << (0x07 - (x & 0x07)); - if(line[idx] & offset) + // memset linePadding bits naive. + for(std::uint8_t x = 0; x < linePadding; ++x) { - surface[cur] = 0xff; //0xffffffff; + const std::uint8_t offset = (0x07 - (x & 0x07)); + *outputPixels = ((*inputPixels) >> offset) & 1 ? 0xff : 0x00; + ++outputPixels; } - else - { - surface[cur] = 0x00; //0xff000000; - } - cur++; + ++inputPixels; } } - auto pixels = (bitmap = Dali::Devel::PixelBuffer::New(w, h, Pixel::L8)).GetBuffer(); - - memcpy(pixels, &surface[0], w * h); //w * h * 4 return true; } -- 2.7.4