From ed0b39cfd1fca46328e8ae70d603d6304cc5cf76 Mon Sep 17 00:00:00 2001 From: Markus Kalkbrenner Date: Mon, 1 Apr 2024 12:20:12 +0200 Subject: [PATCH 1/2] added indexed scaling for Pixelcade and PUP --- platforms/android/arm64-v8a/external.sh | 2 +- platforms/ios/arm64/external.sh | 2 +- platforms/linux/aarch64/external.sh | 2 +- platforms/linux/x64/external.sh | 2 +- platforms/macos/arm64/external.sh | 2 +- platforms/macos/x64/external.sh | 2 +- platforms/tvos/arm64/external.sh | 2 +- platforms/win/x64/external.sh | 2 +- platforms/win/x86/external.sh | 2 +- src/DMD.cpp | 68 +++++++++---- src/FrameUtil.cpp | 124 ++++++++++++++++++++++++ src/FrameUtil.h | 6 ++ 12 files changed, 190 insertions(+), 26 deletions(-) diff --git a/platforms/android/arm64-v8a/external.sh b/platforms/android/arm64-v8a/external.sh index 42848f1..bc6d03c 100755 --- a/platforms/android/arm64-v8a/external.sh +++ b/platforms/android/arm64-v8a/external.sh @@ -6,7 +6,7 @@ CARGS_SHA=5949a20a926e902931de4a32adaad9f19c76f251 LIBZEDMD_SHA=42d95ed6f1fe2065ecbd247502d177d7e5eb7e4c LIBSERUM_SHA=b69d2b436bc93570a2e7e78d0946cd3c43f7aed5 SOCKPP_SHA=e6c4688a576d95f42dd7628cefe68092f6c5cd0f -LIBPUPDMD_SHA=5ed99b7c02a3873ba2ef0bd582b6e9fcf8061222 +LIBPUPDMD_SHA=8dedc8c81ded2f6b8ca4614752d395aae0332c6c if [[ $(uname) == "Linux" ]]; then NUM_PROCS=$(nproc) diff --git a/platforms/ios/arm64/external.sh b/platforms/ios/arm64/external.sh index a8da97c..412fc65 100755 --- a/platforms/ios/arm64/external.sh +++ b/platforms/ios/arm64/external.sh @@ -6,7 +6,7 @@ CARGS_SHA=5949a20a926e902931de4a32adaad9f19c76f251 LIBZEDMD_SHA=42d95ed6f1fe2065ecbd247502d177d7e5eb7e4c LIBSERUM_SHA=b69d2b436bc93570a2e7e78d0946cd3c43f7aed5 SOCKPP_SHA=e6c4688a576d95f42dd7628cefe68092f6c5cd0f -LIBPUPDMD_SHA=5ed99b7c02a3873ba2ef0bd582b6e9fcf8061222 +LIBPUPDMD_SHA=8dedc8c81ded2f6b8ca4614752d395aae0332c6c NUM_PROCS=$(sysctl -n hw.ncpu) diff --git a/platforms/linux/aarch64/external.sh b/platforms/linux/aarch64/external.sh index 2d4c2d2..5dbe20e 100755 --- a/platforms/linux/aarch64/external.sh +++ b/platforms/linux/aarch64/external.sh @@ -6,7 +6,7 @@ CARGS_SHA=5949a20a926e902931de4a32adaad9f19c76f251 LIBZEDMD_SHA=42d95ed6f1fe2065ecbd247502d177d7e5eb7e4c LIBSERUM_SHA=b69d2b436bc93570a2e7e78d0946cd3c43f7aed5 SOCKPP_SHA=e6c4688a576d95f42dd7628cefe68092f6c5cd0f -LIBPUPDMD_SHA=5ed99b7c02a3873ba2ef0bd582b6e9fcf8061222 +LIBPUPDMD_SHA=8dedc8c81ded2f6b8ca4614752d395aae0332c6c NUM_PROCS=$(nproc) diff --git a/platforms/linux/x64/external.sh b/platforms/linux/x64/external.sh index 39d25d8..71dcdbd 100755 --- a/platforms/linux/x64/external.sh +++ b/platforms/linux/x64/external.sh @@ -6,7 +6,7 @@ CARGS_SHA=5949a20a926e902931de4a32adaad9f19c76f251 LIBZEDMD_SHA=42d95ed6f1fe2065ecbd247502d177d7e5eb7e4c LIBSERUM_SHA=b69d2b436bc93570a2e7e78d0946cd3c43f7aed5 SOCKPP_SHA=e6c4688a576d95f42dd7628cefe68092f6c5cd0f -LIBPUPDMD_SHA=5ed99b7c02a3873ba2ef0bd582b6e9fcf8061222 +LIBPUPDMD_SHA=8dedc8c81ded2f6b8ca4614752d395aae0332c6c NUM_PROCS=$(nproc) diff --git a/platforms/macos/arm64/external.sh b/platforms/macos/arm64/external.sh index 823c685..4fb3bf7 100755 --- a/platforms/macos/arm64/external.sh +++ b/platforms/macos/arm64/external.sh @@ -6,7 +6,7 @@ CARGS_SHA=5949a20a926e902931de4a32adaad9f19c76f251 LIBZEDMD_SHA=42d95ed6f1fe2065ecbd247502d177d7e5eb7e4c LIBSERUM_SHA=b69d2b436bc93570a2e7e78d0946cd3c43f7aed5 SOCKPP_SHA=e6c4688a576d95f42dd7628cefe68092f6c5cd0f -LIBPUPDMD_SHA=5ed99b7c02a3873ba2ef0bd582b6e9fcf8061222 +LIBPUPDMD_SHA=8dedc8c81ded2f6b8ca4614752d395aae0332c6c NUM_PROCS=$(sysctl -n hw.ncpu) diff --git a/platforms/macos/x64/external.sh b/platforms/macos/x64/external.sh index a5eea69..ec29cd3 100755 --- a/platforms/macos/x64/external.sh +++ b/platforms/macos/x64/external.sh @@ -6,7 +6,7 @@ CARGS_SHA=5949a20a926e902931de4a32adaad9f19c76f251 LIBZEDMD_SHA=42d95ed6f1fe2065ecbd247502d177d7e5eb7e4c LIBSERUM_SHA=b69d2b436bc93570a2e7e78d0946cd3c43f7aed5 SOCKPP_SHA=e6c4688a576d95f42dd7628cefe68092f6c5cd0f -LIBPUPDMD_SHA=5ed99b7c02a3873ba2ef0bd582b6e9fcf8061222 +LIBPUPDMD_SHA=8dedc8c81ded2f6b8ca4614752d395aae0332c6c NUM_PROCS=$(sysctl -n hw.ncpu) diff --git a/platforms/tvos/arm64/external.sh b/platforms/tvos/arm64/external.sh index ea20b64..0ec573e 100755 --- a/platforms/tvos/arm64/external.sh +++ b/platforms/tvos/arm64/external.sh @@ -6,7 +6,7 @@ CARGS_SHA=5949a20a926e902931de4a32adaad9f19c76f251 LIBZEDMD_SHA=42d95ed6f1fe2065ecbd247502d177d7e5eb7e4c LIBSERUM_SHA=b69d2b436bc93570a2e7e78d0946cd3c43f7aed5 SOCKPP_SHA=e6c4688a576d95f42dd7628cefe68092f6c5cd0f -LIBPUPDMD_SHA=5ed99b7c02a3873ba2ef0bd582b6e9fcf8061222 +LIBPUPDMD_SHA=8dedc8c81ded2f6b8ca4614752d395aae0332c6c NUM_PROCS=$(sysctl -n hw.ncpu) diff --git a/platforms/win/x64/external.sh b/platforms/win/x64/external.sh index cadbd7e..5999d61 100755 --- a/platforms/win/x64/external.sh +++ b/platforms/win/x64/external.sh @@ -6,7 +6,7 @@ CARGS_SHA=5949a20a926e902931de4a32adaad9f19c76f251 LIBZEDMD_SHA=42d95ed6f1fe2065ecbd247502d177d7e5eb7e4c LIBSERUM_SHA=b69d2b436bc93570a2e7e78d0946cd3c43f7aed5 SOCKPP_SHA=e6c4688a576d95f42dd7628cefe68092f6c5cd0f -LIBPUPDMD_SHA=5ed99b7c02a3873ba2ef0bd582b6e9fcf8061222 +LIBPUPDMD_SHA=8dedc8c81ded2f6b8ca4614752d395aae0332c6c echo "Building libraries..." echo " CARGS_SHA: ${CARGS_SHA}" diff --git a/platforms/win/x86/external.sh b/platforms/win/x86/external.sh index ba0d172..03e2797 100755 --- a/platforms/win/x86/external.sh +++ b/platforms/win/x86/external.sh @@ -6,7 +6,7 @@ CARGS_SHA=5949a20a926e902931de4a32adaad9f19c76f251 LIBZEDMD_SHA=42d95ed6f1fe2065ecbd247502d177d7e5eb7e4c LIBSERUM_SHA=b69d2b436bc93570a2e7e78d0946cd3c43f7aed5 SOCKPP_SHA=e6c4688a576d95f42dd7628cefe68092f6c5cd0f -LIBPUPDMD_SHA=5ed99b7c02a3873ba2ef0bd582b6e9fcf8061222 +LIBPUPDMD_SHA=8dedc8c81ded2f6b8ca4614752d395aae0332c6c echo "Building libraries..." echo " CARGS_SHA: ${CARGS_SHA}" diff --git a/src/DMD.cpp b/src/DMD.cpp index 132f452..b18b14e 100644 --- a/src/DMD.cpp +++ b/src/DMD.cpp @@ -745,11 +745,13 @@ void DMD::PixelcadeDMDThread() { if (++bufferPosition >= DMDUTIL_FRAME_BUFFER_SIZE) bufferPosition = 0; - // @todo scaling - if (m_pUpdateBufferQueue[bufferPosition]->width == 128 && m_pUpdateBufferQueue[bufferPosition]->height == 32 && - (m_pUpdateBufferQueue[bufferPosition]->hasData || m_pUpdateBufferQueue[bufferPosition]->hasSegData)) + if (m_pUpdateBufferQueue[bufferPosition]->hasData || m_pUpdateBufferQueue[bufferPosition]->hasSegData) { - int length = m_pUpdateBufferQueue[bufferPosition]->width * m_pUpdateBufferQueue[bufferPosition]->height; + uint16_t width = m_pUpdateBufferQueue[bufferPosition]->width; + uint8_t height = m_pUpdateBufferQueue[bufferPosition]->height; + int length = width * height; + uint8_t depth = m_pUpdateBufferQueue[bufferPosition]->depth; + bool update = false; if (m_pUpdateBufferQueue[bufferPosition]->depth != 24) { @@ -758,7 +760,8 @@ void DMD::PixelcadeDMDThread() m_pUpdateBufferQueue[bufferPosition]->b); } - if (m_pUpdateBufferQueue[bufferPosition]->mode == Mode::RGB24) + // @todo scaling / centering + if (m_pUpdateBufferQueue[bufferPosition]->mode == Mode::RGB24 && width == 128 && height == 32) { uint8_t rgb24Data[128 * 32 * 3]; AdjustRGB24Depth(m_pUpdateBufferQueue[bufferPosition]->data, rgb24Data, length, palette, @@ -774,14 +777,16 @@ void DMD::PixelcadeDMDThread() } update = true; } - else if (m_pUpdateBufferQueue[bufferPosition]->mode == Mode::RGB16) + // @todo scaling / centering + else if (m_pUpdateBufferQueue[bufferPosition]->mode == Mode::RGB16 && width == 128 && height == 32) { memcpy(rgb565Data, m_pUpdateBufferQueue[bufferPosition]->segData, 128 * 32 * sizeof(uint16_t)); update = true; } - else + else if (m_pUpdateBufferQueue[bufferPosition]->mode == Mode::Data || + m_pUpdateBufferQueue[bufferPosition]->mode == Mode::AlphaNumeric) { - uint8_t renderBuffer[128 * 32]; + uint8_t renderBuffer[256 * 64]; if (m_pUpdateBufferQueue[bufferPosition]->mode == Mode::Data) { @@ -805,6 +810,23 @@ void DMD::PixelcadeDMDThread() m_pUpdateBufferQueue[bufferPosition]->width * m_pUpdateBufferQueue[bufferPosition]->height); update = true; } + + if (update) + { + uint8_t scaledBuffer[128 * 32]; + if (width == 128 && height == 32) + memcpy(scaledBuffer, renderBuffer, 128 * 32); + else if (width == 128 && height == 16) + FrameUtil::CenterIndexed(scaledBuffer, 128, 32, renderBuffer, 128, 16); + else if (width == 192 && height == 64) + FrameUtil::ScaleDownIndexed(scaledBuffer, 128, 32, renderBuffer, 192, 64); + else if (width == 256 && height == 64) + FrameUtil::ScaleDownIndexed(scaledBuffer, 128, 32, renderBuffer, 256, 64); + else + continue; + + memcpy(renderBuffer, scaledBuffer, 128 * 32); + } } else if (m_pUpdateBufferQueue[bufferPosition]->mode == Mode::AlphaNumeric) { @@ -1332,33 +1354,45 @@ void DMD::PupDMDThread() } } - // @todo scaling/centering 128x16 and 192x64 or check how PUP deals with it. - if (m_pPUPDMD && m_pUpdateBufferQueue[bufferPosition]->width == 128 && - m_pUpdateBufferQueue[bufferPosition]->height == 32 && m_pUpdateBufferQueue[bufferPosition]->hasData && + if (m_pPUPDMD && m_pUpdateBufferQueue[bufferPosition]->hasData && m_pUpdateBufferQueue[bufferPosition]->mode == Mode::Data && m_pUpdateBufferQueue[bufferPosition]->depth != 24) { - int length = m_pUpdateBufferQueue[bufferPosition]->width * m_pUpdateBufferQueue[bufferPosition]->height; + uint16_t width = m_pUpdateBufferQueue[bufferPosition]->width; + uint8_t height = m_pUpdateBufferQueue[bufferPosition]->height; + int length = width * height; + if (memcmp(renderBuffer, m_pUpdateBufferQueue[bufferPosition]->data, length) != 0) { memcpy(renderBuffer, m_pUpdateBufferQueue[bufferPosition]->data, length); + uint8_t depth = m_pUpdateBufferQueue[bufferPosition]->depth; + + uint8_t scaledBuffer[128 * 32]; + if (width == 128 && height == 32) + memcpy(scaledBuffer, renderBuffer, 128 * 32); + else if (width == 128 && height == 16) + FrameUtil::CenterIndexed(scaledBuffer, 128, 32, renderBuffer, 128, 16); + else if (width == 192 && height == 64) + FrameUtil::ScaleDownPUP(scaledBuffer, 128, 32, renderBuffer, 192, 64); + else + return; uint16_t triggerID = 0; if (Config::GetInstance()->IsPUPExactColorMatch()) { - triggerID = m_pPUPDMD->MatchIndexed(renderBuffer); + triggerID = m_pPUPDMD->MatchIndexed(scaledBuffer, width, height); } else { - UpdatePalette(palette, m_pUpdateBufferQueue[bufferPosition]->depth, m_pUpdateBufferQueue[bufferPosition]->r, - m_pUpdateBufferQueue[bufferPosition]->g, m_pUpdateBufferQueue[bufferPosition]->b); + // apply a standard orange palette + UpdatePalette(palette, depth, 255, 69, 0); uint8_t* pFrame = (uint8_t*)malloc(length * 3); for (uint16_t i = 0; i < length; i++) { - uint16_t pos = renderBuffer[i] * 3; + uint16_t pos = scaledBuffer[i] * 3; memcpy(&pFrame[i * 3], &palette[pos], 3); } - triggerID = m_pPUPDMD->Match(pFrame, false); + triggerID = m_pPUPDMD->Match(pFrame, width, height, false); free(pFrame); } diff --git a/src/FrameUtil.cpp b/src/FrameUtil.cpp index 0b60920..4a94a67 100644 --- a/src/FrameUtil.cpp +++ b/src/FrameUtil.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace DMDUtil { @@ -230,4 +231,127 @@ std::string FrameUtil::HexDump(const uint8_t* data, size_t size) return ss.str(); } +void FrameUtil::ScaleDownIndexed(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, + const uint8_t* pSrcFrame, const uint16_t srcWidth, const uint8_t srcHeight) +{ + memset(pDestFrame, 0, destWidth * destHeight); + uint8_t xOffset = (destWidth - (srcWidth / 2)) / 2; + uint8_t yOffset = (destHeight - (srcHeight / 2)) / 2; + + // for half scaling we take the 4 points and look if there is one color repeated + for (uint8_t y = 0; y < srcHeight; y += 2) + { + std::vector row; + row.reserve(srcWidth / 2); + + for (uint16_t x = 0; x < srcWidth; x += 2) + { + uint8_t upper_left = pSrcFrame[y * srcWidth + x]; + uint8_t upper_right = pSrcFrame[y * srcWidth + x + 1]; + uint8_t lower_left = pSrcFrame[(y + 1) * srcWidth + x]; + uint8_t lower_right = pSrcFrame[(y + 1) * srcWidth + x + 1]; + + if (x < srcWidth / 2) + { + if (y < srcHeight / 2) + { + if (upper_left == upper_right || upper_left == lower_left || upper_left == lower_right) + row.push_back(upper_left); + else if (upper_right == lower_left || upper_right == lower_right) + row.push_back(upper_right); + else if (lower_left == lower_right) + row.push_back(lower_left); + else + row.push_back(upper_left); + } + else + { + if (lower_left == lower_right || lower_left == upper_left || lower_left == upper_right) + row.push_back(lower_right); + else if (lower_right == upper_left || lower_right == upper_right) + row.push_back(lower_right); + else if (upper_left == upper_right) + row.push_back(upper_left); + else + row.push_back(lower_left); + } + } + else + { + if (y < srcHeight / 2) + { + if (upper_right == upper_left || upper_right == lower_right || upper_right == lower_left) + row.push_back(upper_right); + else if (upper_left == lower_right || upper_left == lower_left) + row.push_back(upper_left); + else if (lower_right == lower_left) + row.push_back(lower_right); + else + row.push_back(upper_right); + } + else + { + if (lower_right == lower_left || lower_right == upper_right || lower_right == upper_left) + row.push_back(lower_right); + else if (lower_left == upper_right || lower_left == upper_left) + row.push_back(lower_left); + else if (upper_right == upper_left) + row.push_back(upper_right); + else + row.push_back(lower_right); + } + } + } + + memcpy(&pDestFrame[(yOffset + (y / 2)) * destWidth + xOffset], row.data(), srcWidth / 2); + } +} + +void FrameUtil::ScaleDownPUP(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, + const uint8_t* pSrcFrame, const uint8_t srcWidth, const uint8_t srcHeight) +{ + memset(pDestFrame, 0, destWidth * destHeight); + uint8_t xOffset = (destWidth - (srcWidth / 2)) / 2; + uint8_t yOffset = (destHeight - (srcHeight / 2)) / 2; + + // for half scaling we take the 4 points and look if there is one color repeated + for (uint8_t y = 0; y < srcHeight; y += 2) + { + std::vector row; + row.reserve(srcWidth / 2); + + for (uint8_t x = 0; x < srcWidth; x += 2) + { + uint8_t pixel1 = pSrcFrame[y * srcWidth + x]; + uint8_t pixel2 = pSrcFrame[y * srcWidth + x + 1]; + uint8_t pixel3 = pSrcFrame[(y + 1) * srcWidth + x]; + uint8_t pixel4 = pSrcFrame[(y + 1) * srcWidth + x + 1]; + + if (pixel1 == pixel2 || pixel1 == pixel3 || pixel1 == pixel4) + row.push_back(pixel1); + else if (pixel2 == pixel3 || pixel2 == pixel4) + row.push_back(pixel2); + else if (pixel3 == pixel4) + row.push_back(pixel3); + else + row.push_back(pixel1); + } + + memcpy(&pDestFrame[(yOffset + (y / 2)) * destWidth + xOffset], row.data(), srcWidth / 2); + } +} + +void FrameUtil::CenterIndexed(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, + const uint8_t* pSrcFrame, const uint8_t srcWidth, const uint8_t srcHeight) +{ + memset(pDestFrame, 0, destWidth * destHeight); + uint8_t xOffset = (destWidth - srcWidth) / 2; + uint8_t yOffset = (destHeight - srcHeight) / 2; + + for (uint8_t y = 0; y < srcHeight; y++) + { + memcpy(&pDestFrame[(yOffset + y) * destWidth + xOffset], &pSrcFrame[y * srcWidth], srcWidth); + } +} + } // namespace DMDUtil diff --git a/src/FrameUtil.h b/src/FrameUtil.h index 4103319..ed35782 100644 --- a/src/FrameUtil.h +++ b/src/FrameUtil.h @@ -31,6 +31,12 @@ class FrameUtil int destHeight); static float CalcBrightness(float x); static std::string HexDump(const uint8_t* data, size_t size); + static void ScaleDownIndexed(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, + const uint8_t* pSrcFrame, const uint16_t srcWidth, const uint8_t srcHeight); + static void ScaleDownPUP(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, + const uint8_t* pSrcFrame, const uint8_t srcWidth, const uint8_t srcHeight); + static void CenterIndexed(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, + const uint8_t* pSrcFrame, const uint8_t srcWidth, const uint8_t srcHeight); }; } // namespace DMDUtil From c0c841510c70eefb740ac59379eb89382db61292 Mon Sep 17 00:00:00 2001 From: Markus Kalkbrenner Date: Mon, 1 Apr 2024 13:11:33 +0200 Subject: [PATCH 2/2] added scaling for RGB24 and RGB16 --- src/DMD.cpp | 44 ++++++++++++++++----- src/FrameUtil.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++++-- src/FrameUtil.h | 4 ++ 3 files changed, 134 insertions(+), 13 deletions(-) diff --git a/src/DMD.cpp b/src/DMD.cpp index b18b14e..53d0bc3 100644 --- a/src/DMD.cpp +++ b/src/DMD.cpp @@ -760,31 +760,55 @@ void DMD::PixelcadeDMDThread() m_pUpdateBufferQueue[bufferPosition]->b); } - // @todo scaling / centering - if (m_pUpdateBufferQueue[bufferPosition]->mode == Mode::RGB24 && width == 128 && height == 32) + if (m_pUpdateBufferQueue[bufferPosition]->mode == Mode::RGB24) { - uint8_t rgb24Data[128 * 32 * 3]; + uint8_t rgb24Data[256 * 64 * 3]; AdjustRGB24Depth(m_pUpdateBufferQueue[bufferPosition]->data, rgb24Data, length, palette, m_pUpdateBufferQueue[bufferPosition]->depth); + + uint8_t scaledBuffer[128 * 32 * 3]; + if (width == 128 && height == 32) + memcpy(scaledBuffer, m_pUpdateBufferQueue[bufferPosition]->segData, 128 * 32 * 3); + else if (width == 128 && height == 16) + FrameUtil::Center(scaledBuffer, 128, 32, rgb24Data, 128, 16, 24); + else if (width == 192 && height == 64) + FrameUtil::ScaleDown(scaledBuffer, 128, 32, rgb24Data, 192, 64, 24); + else if (width == 256 && height == 64) + FrameUtil::ScaleDown(scaledBuffer, 128, 32, rgb24Data, 256, 64, 24); + else + continue; + for (int i = 0; i < length; i++) { int pos = i * 3; - uint32_t r = rgb24Data[pos]; - uint32_t g = rgb24Data[pos + 1]; - uint32_t b = rgb24Data[pos + 2]; + uint32_t r = scaledBuffer[pos]; + uint32_t g = scaledBuffer[pos + 1]; + uint32_t b = scaledBuffer[pos + 2]; rgb565Data[i] = (uint16_t)(((r & 0xF8u) << 8) | ((g & 0xFCu) << 3) | (b >> 3)); } update = true; } // @todo scaling / centering - else if (m_pUpdateBufferQueue[bufferPosition]->mode == Mode::RGB16 && width == 128 && height == 32) + else if (m_pUpdateBufferQueue[bufferPosition]->mode == Mode::RGB16) { - memcpy(rgb565Data, m_pUpdateBufferQueue[bufferPosition]->segData, 128 * 32 * sizeof(uint16_t)); + if (width == 128 && height == 32) + memcpy(rgb565Data, m_pUpdateBufferQueue[bufferPosition]->segData, 128 * 32 * 2); + else if (width == 128 && height == 16) + FrameUtil::Center((uint8_t*)rgb565Data, 128, 32, (uint8_t*)m_pUpdateBufferQueue[bufferPosition]->segData, + 128, 16, 16); + else if (width == 192 && height == 64) + FrameUtil::ScaleDown((uint8_t*)rgb565Data, 128, 32, (uint8_t*)m_pUpdateBufferQueue[bufferPosition]->segData, + 192, 64, 16); + else if (width == 256 && height == 64) + FrameUtil::ScaleDown((uint8_t*)rgb565Data, 128, 32, (uint8_t*)m_pUpdateBufferQueue[bufferPosition]->segData, + 256, 64, 16); + else + continue; + update = true; } - else if (m_pUpdateBufferQueue[bufferPosition]->mode == Mode::Data || - m_pUpdateBufferQueue[bufferPosition]->mode == Mode::AlphaNumeric) + else { uint8_t renderBuffer[256 * 64]; diff --git a/src/FrameUtil.cpp b/src/FrameUtil.cpp index 4a94a67..93e5f60 100644 --- a/src/FrameUtil.cpp +++ b/src/FrameUtil.cpp @@ -341,17 +341,110 @@ void FrameUtil::ScaleDownPUP(uint8_t* pDestFrame, const uint8_t destWidth, const } } -void FrameUtil::CenterIndexed(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, - const uint8_t* pSrcFrame, const uint8_t srcWidth, const uint8_t srcHeight) +void FrameUtil::ScaleDown(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, + const uint8_t* pSrcFrame, const uint16_t srcWidth, const uint8_t srcHeight, uint8_t bits) { memset(pDestFrame, 0, destWidth * destHeight); + uint8_t xOffset = (destWidth - (srcWidth / 2)) / 2; + uint8_t yOffset = (destHeight - (srcHeight / 2)) / 2; + uint8_t bytes = bits / 8; // RGB24 (3 byte) or RGB16 (2 byte) + + for (uint8_t y = 0; y < srcHeight; y += 2) + { + for (uint16_t x = 0; x < srcWidth; x += 2) + { + uint16_t upper_left = y * srcWidth * bytes + x * bytes; + uint16_t upper_right = upper_left + bytes; + uint16_t lower_left = upper_left + srcWidth * bytes; + uint16_t lower_right = lower_left + bytes; + uint16_t target = (xOffset + (x / 2) + (y / 2) * destHeight) * bytes; + + if (x < srcWidth / 2) + { + if (y < srcHeight / 2) + { + if (memcmp(&pSrcFrame[upper_left], &pSrcFrame[upper_right], bytes) == 0 || + memcmp(&pSrcFrame[upper_left], &pSrcFrame[lower_left], bytes) == 0 || + memcmp(&pSrcFrame[upper_left], &pSrcFrame[lower_right], bytes) == 0) + memcpy(&pDestFrame[target], &pSrcFrame[upper_left], bytes); + else if (memcmp(&pSrcFrame[upper_right], &pSrcFrame[lower_left], bytes) == 0 || + memcmp(&pSrcFrame[upper_right], &pSrcFrame[lower_right], bytes) == 0) + memcpy(&pDestFrame[target], &pSrcFrame[upper_right], bytes); + else if (memcmp(&pSrcFrame[lower_left], &pSrcFrame[lower_right], bytes) == 0) + memcpy(&pDestFrame[target], &pSrcFrame[lower_left], bytes); + else + memcpy(&pDestFrame[target], &pSrcFrame[upper_left], bytes); + } + else + { + if (memcmp(&pSrcFrame[lower_left], &pSrcFrame[lower_right], bytes) == 0 || + memcmp(&pSrcFrame[lower_left], &pSrcFrame[upper_left], bytes) == 0 || + memcmp(&pSrcFrame[lower_left], &pSrcFrame[upper_right], bytes) == 0) + memcpy(&pDestFrame[target], &pSrcFrame[lower_left], bytes); + else if (memcmp(&pSrcFrame[lower_right], &pSrcFrame[upper_left], bytes) == 0 || + memcmp(&pSrcFrame[lower_right], &pSrcFrame[upper_right], bytes) == 0) + memcpy(&pDestFrame[target], &pSrcFrame[lower_right], bytes); + else if (memcmp(&pSrcFrame[upper_left], &pSrcFrame[upper_right], bytes) == 0) + memcpy(&pDestFrame[target], &pSrcFrame[upper_left], bytes); + else + memcpy(&pDestFrame[target], &pSrcFrame[lower_left], bytes); + } + } + else + { + if (y < srcHeight / 2) + { + if (memcmp(&pSrcFrame[upper_right], &pSrcFrame[upper_left], bytes) == 0 || + memcmp(&pSrcFrame[upper_right], &pSrcFrame[lower_right], bytes) == 0 || + memcmp(&pSrcFrame[upper_right], &pSrcFrame[lower_left], bytes) == 0) + memcpy(&pDestFrame[target], &pSrcFrame[upper_right], bytes); + else if (memcmp(&pSrcFrame[upper_left], &pSrcFrame[lower_right], bytes) == 0 || + memcmp(&pSrcFrame[upper_left], &pSrcFrame[lower_left], bytes) == 0) + memcpy(&pDestFrame[target], &pSrcFrame[upper_left], bytes); + else if (memcmp(&pSrcFrame[lower_right], &pSrcFrame[lower_left], bytes) == 0) + memcpy(&pDestFrame[target], &pSrcFrame[lower_right], bytes); + else + memcpy(&pDestFrame[target], &pSrcFrame[upper_right], bytes); + } + else + { + if (memcmp(&pSrcFrame[lower_right], &pSrcFrame[lower_left], bytes) == 0 || + memcmp(&pSrcFrame[lower_right], &pSrcFrame[upper_right], bytes) == 0 || + memcmp(&pSrcFrame[lower_right], &pSrcFrame[upper_left], bytes) == 0) + memcpy(&pDestFrame[target], &pSrcFrame[lower_right], bytes); + else if (memcmp(&pSrcFrame[lower_left], &pSrcFrame[upper_right], bytes) == 0 || + memcmp(&pSrcFrame[lower_left], &pSrcFrame[upper_left], bytes) == 0) + memcpy(&pDestFrame[target], &pSrcFrame[lower_left], bytes); + else if (memcmp(&pSrcFrame[upper_right], &pSrcFrame[upper_left], bytes) == 0) + memcpy(&pDestFrame[target], &pSrcFrame[upper_right], bytes); + else + memcpy(&pDestFrame[target], &pSrcFrame[lower_right], bytes); + } + } + } + } +} + +void FrameUtil::Center(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, const uint8_t* pSrcFrame, + const uint8_t srcWidth, const uint8_t srcHeight, uint8_t bits) +{ + uint8_t bytes = bits / 8; // RGB24 (3 byte) or RGB16 (2 byte) + + memset(pDestFrame, 0, destWidth * destHeight * bytes); uint8_t xOffset = (destWidth - srcWidth) / 2; uint8_t yOffset = (destHeight - srcHeight) / 2; for (uint8_t y = 0; y < srcHeight; y++) { - memcpy(&pDestFrame[(yOffset + y) * destWidth + xOffset], &pSrcFrame[y * srcWidth], srcWidth); + memcpy(&pDestFrame[((yOffset + y) * destWidth + xOffset) * bytes], &pSrcFrame[y * srcWidth * bytes], + srcWidth * bytes); } } +void FrameUtil::CenterIndexed(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, + const uint8_t* pSrcFrame, const uint8_t srcWidth, const uint8_t srcHeight) +{ + Center(pDestFrame, destWidth, destHeight, pSrcFrame, srcWidth, srcHeight, 8); +} + } // namespace DMDUtil diff --git a/src/FrameUtil.h b/src/FrameUtil.h index ed35782..3787a88 100644 --- a/src/FrameUtil.h +++ b/src/FrameUtil.h @@ -35,8 +35,12 @@ class FrameUtil const uint8_t* pSrcFrame, const uint16_t srcWidth, const uint8_t srcHeight); static void ScaleDownPUP(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, const uint8_t* pSrcFrame, const uint8_t srcWidth, const uint8_t srcHeight); + static void ScaleDown(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, + const uint8_t* pSrcFrame, const uint16_t srcWidth, const uint8_t srcHeight, uint8_t bits); static void CenterIndexed(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, const uint8_t* pSrcFrame, const uint8_t srcWidth, const uint8_t srcHeight); + static void Center(uint8_t* pDestFrame, const uint8_t destWidth, const uint8_t destHeight, const uint8_t* pSrcFrame, + const uint8_t srcWidth, const uint8_t srcHeight, uint8_t bits); }; } // namespace DMDUtil