diff --git a/src/DMD.cpp b/src/DMD.cpp index b18b14e..a4f0266 100644 --- a/src/DMD.cpp +++ b/src/DMD.cpp @@ -760,31 +760,54 @@ 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