Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] new img container support BMP 24-16 bit #371

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/BuddyLeNet/buddy-lenet-main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include <vector>

constexpr size_t ParamsSize = 44426;
const std::string ImgName = "8.bmp";
const std::string ImgName = "8-16bit-565.bmp";

/// Declare LeNet forward function.
extern "C" void _mlir_ciface_forward(MemRef<float, 2> *output,
Expand Down
Binary file added examples/BuddyLeNet/images/8-16bit-565.bmp
Binary file not shown.
Binary file added examples/BuddyLeNet/images/8-24bit.bmp
Binary file not shown.
144 changes: 142 additions & 2 deletions frontend/Interfaces/buddy/DIP/ImgContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,9 @@ bool Image<T, N>::decodeBMP(const std::vector<uint8_t> &fileData) {
uint32_t compression = *reinterpret_cast<const uint32_t *>(&fileData[30]);
size_t pixelDataOffset = *reinterpret_cast<const uint32_t *>(&fileData[10]);

// Currently, only the BI_RGB (value 0) compression method is supported.
if (compression != 0) {
// Currently, only the BI_RGB (value 0) or BI_BITFIELDS (value 3) compression
// method is supported.
if (compression != 0 && compression != 3) {
std::cerr << "Unsupported BMP file compression method." << std::endl;
return false;
}
Expand Down Expand Up @@ -192,6 +193,73 @@ bool Image<T, N>::decodeBMP(const std::vector<uint8_t> &fileData) {
memrefIndex++;
}
}
} else if (this->bitDepth == 24) {
// BMP file is upside-down storage.
for (size_t i = this->height; i > 0; i--) {
for (size_t j = 0; j < this->width; j++) {
// Locate the current pixel.
size_t pixelIndex =
pixelDataOffset + (((i - 1) * this->width) + j) * 3;
// Extract the blue, green, and red value from the current pixel.
int bluePixel =
*reinterpret_cast<const uint8_t *>(&fileData[pixelIndex]);
int greenPixel =
*reinterpret_cast<const uint8_t *>(&fileData[pixelIndex + 1]);
int redPixel =
*reinterpret_cast<const uint8_t *>(&fileData[pixelIndex + 2]);
// Calculate the gray scale value.
int grayScaleValue = static_cast<int>(
0.299 * redPixel + 0.587 * greenPixel + 0.114 * bluePixel);
// Store the gray scale value into memref container.
this->aligned[memrefIndex] =
this->isNorm ? static_cast<T>(grayScaleValue) / 255
: static_cast<T>(grayScaleValue);
memrefIndex++;
}
}
} else if (this->bitDepth == 16) {
// BMP file is upside-down storage.
for (size_t i = this->height; i > 0; i--) {
for (size_t j = 0; j < this->width; j++) {
// Locate the current pixel.
size_t pixelIndex =
pixelDataOffset + (((i - 1) * this->width) + j) * 2;
// Extract the 16-bit pixel value
uint16_t pixelValue =
*reinterpret_cast<const uint16_t *>(&fileData[pixelIndex]);

int redPixel, greenPixel, bluePixel;
if (compression == 3) {
// Extract individual color components (assuming RGB565 format)
redPixel = (pixelValue >> 11) & 0x1F;
greenPixel = (pixelValue >> 5) & 0x3F;
bluePixel = pixelValue & 0x1F;

// Expand to 8-bit per channel
redPixel = (redPixel << 3) | (redPixel >> 2);
greenPixel = (greenPixel << 2) | (greenPixel >> 4);
bluePixel = (bluePixel << 3) | (bluePixel >> 2);
} else {
// Extract individual color components for 5-5-5 format
redPixel = (pixelValue >> 10) & 0x1F;
greenPixel = (pixelValue >> 5) & 0x1F;
bluePixel = pixelValue & 0x1F;

// Expand to 8-bit per channel
redPixel = (redPixel << 3) | (redPixel >> 2);
greenPixel = (greenPixel << 3) | (greenPixel >> 2);
bluePixel = (bluePixel << 3) | (bluePixel >> 2);
}
// Calculate the gray scale value.
int grayScaleValue = static_cast<int>(
0.299 * redPixel + 0.587 * greenPixel + 0.114 * bluePixel);
// Store the gray scale value into memref container.
this->aligned[memrefIndex] =
this->isNorm ? static_cast<T>(grayScaleValue) / 255
: static_cast<T>(grayScaleValue);
memrefIndex++;
}
}
} else {
std::cerr << "Unsupported: " << this->bitDepth << "bit depth."
<< std::endl;
Expand Down Expand Up @@ -236,6 +304,78 @@ bool Image<T, N>::decodeBMP(const std::vector<uint8_t> &fileData) {
memrefIndex++;
}
}
} else if (this->bitDepth == 24) {
// BMP file is upside-down storage.
for (size_t i = height; i > 0; i--) {
for (size_t j = 0; j < width; j++) {
// Locate the current pixel.
size_t pixelIndex = pixelDataOffset + (((i - 1) * width) + j) * 3;
// Extract the blue, green, and red value from the current pixel.
int bluePixel =
*reinterpret_cast<const uint8_t *>(&fileData[pixelIndex]);
int greenPixel =
*reinterpret_cast<const uint8_t *>(&fileData[pixelIndex + 1]);
int redPixel =
*reinterpret_cast<const uint8_t *>(&fileData[pixelIndex + 2]);
// Store the values into memref container as RGB order. (BGR -> RGB)
this->aligned[memrefIndex] = this->isNorm
? static_cast<T>(redPixel) / 255
: static_cast<T>(redPixel);
this->aligned[memrefIndex + colorStride] =
this->isNorm ? static_cast<T>(greenPixel) / 255
: static_cast<T>(greenPixel);
this->aligned[memrefIndex + 2 * colorStride] =
this->isNorm ? static_cast<T>(bluePixel) / 255
: static_cast<T>(bluePixel);
memrefIndex++;
}
}
} else if (this->bitDepth == 16) {
// BMP file is upside-down storage.
for (size_t i = height; i > 0; i--) {
for (size_t j = 0; j < width; j++) {
// Locate the current pixel.
size_t pixelIndex = pixelDataOffset + (((i - 1) * width) + j) * 2;
// Extract the 16-bit pixel value
uint16_t pixelValue =
*reinterpret_cast<const uint16_t *>(&fileData[pixelIndex]);

int redPixel, greenPixel, bluePixel;
if (compression == 3) {
// Extract individual color components (assuming RGB565 format)
redPixel = (pixelValue >> 11) & 0x1F;
greenPixel = (pixelValue >> 5) & 0x3F;
bluePixel = pixelValue & 0x1F;

// Expand to 8-bit per channel
redPixel = (redPixel << 3) | (redPixel >> 2);
greenPixel = (greenPixel << 2) | (greenPixel >> 4);
bluePixel = (bluePixel << 3) | (bluePixel >> 2);
} else {
// Extract individual color components for 5-5-5 format
redPixel = (pixelValue >> 10) & 0x1F;
greenPixel = (pixelValue >> 5) & 0x1F;
bluePixel = pixelValue & 0x1F;

// Expand to 8-bit per channel
redPixel = (redPixel << 3) | (redPixel >> 2);
greenPixel = (greenPixel << 3) | (greenPixel >> 2);
bluePixel = (bluePixel << 3) | (bluePixel >> 2);
}

// Store the values into memref container as RGB order. (BGR -> RGB)
this->aligned[memrefIndex] = this->isNorm
? static_cast<T>(redPixel) / 255
: static_cast<T>(redPixel);
this->aligned[memrefIndex + colorStride] =
this->isNorm ? static_cast<T>(greenPixel) / 255
: static_cast<T>(greenPixel);
this->aligned[memrefIndex + 2 * colorStride] =
this->isNorm ? static_cast<T>(bluePixel) / 255
: static_cast<T>(bluePixel);
memrefIndex++;
}
}
} else {
std::cerr << "Unsupported: " << this->bitDepth << "bit depth."
<< std::endl;
Expand Down
82 changes: 70 additions & 12 deletions tests/Interface/core/NewImageContainerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,90 @@ int main() {
// Test new image container - bmp format image.
//===--------------------------------------------------------------------===//
// Default Gray Scale
dip::Image<float, 4> bmpGrayDefault(
dip::Image<float, 4> bmp32bitGrayDefault(
"../../../../tests/Interface/core/TestImage.bmp", dip::DIP_GRAYSCALE);
// CHECK: BMP
fprintf(stderr, "%s\n", bmpGrayDefault.getFormatName().c_str());
fprintf(stderr, "%s\n", bmp32bitGrayDefault.getFormatName().c_str());
// CHECK: 28
fprintf(stderr, "%ld\n", bmpGrayDefault.getWidth());
fprintf(stderr, "%ld\n", bmp32bitGrayDefault.getWidth());
// CHECK: 28
fprintf(stderr, "%ld\n", bmpGrayDefault.getHeight());
fprintf(stderr, "%ld\n", bmp32bitGrayDefault.getHeight());
// CHECK: 32
fprintf(stderr, "%d\n", bmpGrayDefault.getBitDepth());
fprintf(stderr, "%d\n", bmp32bitGrayDefault.getBitDepth());
// CHECK: 7
fprintf(stderr, "%f\n", bmpGrayDefault.getData()[0]);
fprintf(stderr, "%f\n", bmp32bitGrayDefault.getData()[0]);
// Gray Scale + Normalization
dip::Image<float, 4> bmpGrayNorm(
dip::Image<float, 4> bmp32bitGrayNorm(
"../../../../tests/Interface/core/TestImage.bmp", dip::DIP_GRAYSCALE,
true /* norm */);
// CHECK: BMP
fprintf(stderr, "%s\n", bmpGrayNorm.getFormatName().c_str());
fprintf(stderr, "%s\n", bmp32bitGrayNorm.getFormatName().c_str());
// CHECK: 28
fprintf(stderr, "%ld\n", bmpGrayNorm.getWidth());
fprintf(stderr, "%ld\n", bmp32bitGrayNorm.getWidth());
// CHECK: 28
fprintf(stderr, "%ld\n", bmpGrayNorm.getHeight());
fprintf(stderr, "%ld\n", bmp32bitGrayNorm.getHeight());
// CHECK: 32
fprintf(stderr, "%d\n", bmpGrayNorm.getBitDepth());
fprintf(stderr, "%d\n", bmp32bitGrayNorm.getBitDepth());
// CHECK: 0.027451
fprintf(stderr, "%f\n", bmpGrayNorm.getData()[0]);
fprintf(stderr, "%f\n", bmp32bitGrayNorm.getData()[0]);

// BMP 24bit Default Gray Scale
dip::Image<float, 4> bmp24bitGrayDefault(
"../../../../tests/Interface/core/TestImage-24bit.bmp",
dip::DIP_GRAYSCALE);
// CHECK: BMP
fprintf(stderr, "%s\n", bmp24bitGrayDefault.getFormatName().c_str());
// CHECK: 28
fprintf(stderr, "%ld\n", bmp24bitGrayDefault.getWidth());
// CHECK: 28
fprintf(stderr, "%ld\n", bmp24bitGrayDefault.getHeight());
// CHECK: 24
fprintf(stderr, "%d\n", bmp24bitGrayDefault.getBitDepth());
// CHECK: 7
fprintf(stderr, "%f\n", bmp24bitGrayDefault.getData()[0]);
// BMP 24bit Gray Scale + Normalization
dip::Image<float, 4> bmp24bitGrayNorm(
"../../../../tests/Interface/core/TestImage-24bit.bmp",
dip::DIP_GRAYSCALE, true /* norm */);
// CHECK: BMP
fprintf(stderr, "%s\n", bmp24bitGrayNorm.getFormatName().c_str());
// CHECK: 28
fprintf(stderr, "%ld\n", bmp24bitGrayNorm.getWidth());
// CHECK: 28
fprintf(stderr, "%ld\n", bmp24bitGrayNorm.getHeight());
// CHECK: 24
fprintf(stderr, "%d\n", bmp24bitGrayNorm.getBitDepth());
// CHECK: 0.027451
fprintf(stderr, "%f\n", bmp24bitGrayNorm.getData()[0]);

// BMP 16bit Default Gray Scale
dip::Image<float, 4> bmp16bitGrayDefault(
"../../../../tests/Interface/core/TestImage-16bit-rgb565.bmp",
dip::DIP_GRAYSCALE);
// CHECK: BMP
fprintf(stderr, "%s\n", bmp16bitGrayDefault.getFormatName().c_str());
// CHECK: 28
fprintf(stderr, "%ld\n", bmp16bitGrayDefault.getWidth());
// CHECK: 28
fprintf(stderr, "%ld\n", bmp16bitGrayDefault.getHeight());
// CHECK: 16
fprintf(stderr, "%d\n", bmp16bitGrayDefault.getBitDepth());
// CHECK: 2
fprintf(stderr, "%f\n", bmp16bitGrayDefault.getData()[0]);
// BMP 16bit Gray Scale + Normalization
dip::Image<float, 4> bmp16bitGrayNorm(
"../../../../tests/Interface/core/TestImage-16bit-rgb565.bmp",
dip::DIP_GRAYSCALE, true /* norm */);
// CHECK: BMP
fprintf(stderr, "%s\n", bmp16bitGrayNorm.getFormatName().c_str());
// CHECK: 28
fprintf(stderr, "%ld\n", bmp16bitGrayNorm.getWidth());
// CHECK: 28
fprintf(stderr, "%ld\n", bmp16bitGrayNorm.getHeight());
// CHECK: 16
fprintf(stderr, "%d\n", bmp16bitGrayNorm.getBitDepth());
// CHECK: 0.007843
fprintf(stderr, "%f\n", bmp16bitGrayNorm.getData()[0]);

return 0;
}
Binary file added tests/Interface/core/TestImage-16bit-rgb565.bmp
Binary file not shown.
Binary file added tests/Interface/core/TestImage-24bit.bmp
Binary file not shown.