Handle 16x16 MCU blocks in JPEG decoding (#120)
## Summary * Handle 16x16 MCU blocks in JPEG decoding * We were only correctly handling 8x8 blocks, which means that we did not correctly support a lot of JPGs leading to an interlacing style on the images ## Additional Context * Fixes https://github.com/daveallie/crosspoint-reader/issues/118
This commit is contained in:
parent
8d53f3f723
commit
09f6bdc515
@ -182,6 +182,9 @@ bool JpegToBmpConverter::jpegFileToBmpStream(File& jpegFile, Print& bmpOut) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process MCU block into MCU row buffer
|
// Process MCU block into MCU row buffer
|
||||||
|
// MCUs are composed of 8x8 blocks. For 16x16 MCUs, there are four 8x8 blocks:
|
||||||
|
// Block layout for 16x16 MCU: [0, 64] (top row of blocks)
|
||||||
|
// [128, 192] (bottom row of blocks)
|
||||||
for (int blockY = 0; blockY < mcuPixelHeight; blockY++) {
|
for (int blockY = 0; blockY < mcuPixelHeight; blockY++) {
|
||||||
for (int blockX = 0; blockX < mcuPixelWidth; blockX++) {
|
for (int blockX = 0; blockX < mcuPixelWidth; blockX++) {
|
||||||
const int pixelX = mcuX * mcuPixelWidth + blockX;
|
const int pixelX = mcuX * mcuPixelWidth + blockX;
|
||||||
@ -191,16 +194,27 @@ bool JpegToBmpConverter::jpegFileToBmpStream(File& jpegFile, Print& bmpOut) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate which 8x8 block and position within that block
|
||||||
|
const int block8x8Col = blockX / 8; // 0 or 1 for 16-wide MCU
|
||||||
|
const int block8x8Row = blockY / 8; // 0 or 1 for 16-tall MCU
|
||||||
|
const int pixelInBlockX = blockX % 8;
|
||||||
|
const int pixelInBlockY = blockY % 8;
|
||||||
|
|
||||||
|
// Calculate byte offset: each 8x8 block is 64 bytes
|
||||||
|
// Blocks are arranged: [0, 64], [128, 192]
|
||||||
|
const int blockOffset = (block8x8Row * (mcuPixelWidth / 8) + block8x8Col) * 64;
|
||||||
|
const int mcuIndex = blockOffset + pixelInBlockY * 8 + pixelInBlockX;
|
||||||
|
|
||||||
// Get grayscale value
|
// Get grayscale value
|
||||||
uint8_t gray;
|
uint8_t gray;
|
||||||
if (imageInfo.m_comps == 1) {
|
if (imageInfo.m_comps == 1) {
|
||||||
// Grayscale image
|
// Grayscale image
|
||||||
gray = imageInfo.m_pMCUBufR[blockY * mcuPixelWidth + blockX];
|
gray = imageInfo.m_pMCUBufR[mcuIndex];
|
||||||
} else {
|
} else {
|
||||||
// RGB image - convert to grayscale
|
// RGB image - convert to grayscale
|
||||||
const uint8_t r = imageInfo.m_pMCUBufR[blockY * mcuPixelWidth + blockX];
|
const uint8_t r = imageInfo.m_pMCUBufR[mcuIndex];
|
||||||
const uint8_t g = imageInfo.m_pMCUBufG[blockY * mcuPixelWidth + blockX];
|
const uint8_t g = imageInfo.m_pMCUBufG[mcuIndex];
|
||||||
const uint8_t b = imageInfo.m_pMCUBufB[blockY * mcuPixelWidth + blockX];
|
const uint8_t b = imageInfo.m_pMCUBufB[mcuIndex];
|
||||||
// Luminance formula: Y = 0.299*R + 0.587*G + 0.114*B
|
// Luminance formula: Y = 0.299*R + 0.587*G + 0.114*B
|
||||||
// Using integer approximation: (30*R + 59*G + 11*B) / 100
|
// Using integer approximation: (30*R + 59*G + 11*B) / 100
|
||||||
gray = (r * 30 + g * 59 + b * 11) / 100;
|
gray = (r * 30 + g * 59 + b * 11) / 100;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user