diff --git a/examples/DIPDialect/resize4D_nchw.cpp b/examples/DIPDialect/resize4D_nchw.cpp index 95d77cc27d..ffa4234bff 100644 --- a/examples/DIPDialect/resize4D_nchw.cpp +++ b/examples/DIPDialect/resize4D_nchw.cpp @@ -23,9 +23,9 @@ //===----------------------------------------------------------------------===// #include "buddy/DIP/imgcodecs/loadsave.h" #include -#include #include #include +#include #include #include @@ -33,7 +33,7 @@ using namespace std; void testImplementation(int argc, char *argv[]) { // Read as colar image. - dip::Image inputBatch(argv[1], dip::DIP_RGB, true); + dip::Image inputBatch(argv[1], dip::DIP_RGB); // Note : Both values in output image dimensions and scaling ratios must be // positive numbers. @@ -42,12 +42,12 @@ void testImplementation(int argc, char *argv[]) { {1, 3, 224, 224} /*{image_cols, image_rows}*/); // Define Img with the output of Resize4D. - intptr_t outSizes[3] = {output.getSizes()[2], output.getSizes()[3], - output.getSizes()[1]}; + intptr_t outSizes[4] = {output.getSizes()[0], output.getSizes()[1], + output.getSizes()[2], output.getSizes()[3]}; - Img outputImageResize4D(output.getData(), outSizes); + dip::Image outputImageResize4D(output.getData(), outSizes); - // dip::imwrite(argv[2], outputImageResize4D); + dip::imageWrite(argv[2], outputImageResize4D); return; } diff --git a/frontend/Interfaces/buddy/DIP/ImgContainer.h b/frontend/Interfaces/buddy/DIP/ImgContainer.h index 2525641bff..82a6ca5ad0 100644 --- a/frontend/Interfaces/buddy/DIP/ImgContainer.h +++ b/frontend/Interfaces/buddy/DIP/ImgContainer.h @@ -42,6 +42,28 @@ inline bool ifBigEndian() { return (*ptr == 0); } +inline int validToInt(size_t sz) { + int valueInt = (int)sz; + assert((size_t)valueInt == sz); + return valueInt; +} + +struct PaletteBlock { + unsigned char b, g, r, a; +}; + +// file bmp image palette +void FillPalette(PaletteBlock *palette, int bpp, bool negative = false) { + int i, length = 1 << bpp; + int xor_mask = negative ? 255 : 0; + + for (i = 0; i < length; i++) { + int val = (i * 255 / (length - 1)) ^ xor_mask; + palette[i].b = palette[i].g = palette[i].r = (unsigned char)val; + palette[i].a = 0; + } +} + template class Image : public MemRef { public: // Constructor initializes the image by loading from a file. @@ -51,6 +73,9 @@ template class Image : public MemRef { // norm: Indicates whether to normalize pixel values (default is false). Image(std::string filename, ImageModes mode, bool norm = false); + // from data to initialize image + Image(T *data, intptr_t sizes[N]); + // Retrieves the name of the current image format as a string. std::string getFormatName() const { switch (this->imageFormat) { @@ -68,6 +93,8 @@ template class Image : public MemRef { size_t getHeight() const { return this->height; } // Returns the bit depth of the image. int getBitDepth() const { return this->bitDepth; } + // Write a image + static void imageWrite(const std::string &filename, Image &image); private: // Enum to represent supported image formats. @@ -90,12 +117,19 @@ template class Image : public MemRef { void determineFormat(const std::vector &fileData); // Decodes a BMP image from raw file data. bool decodeBMP(const std::vector &fileData); - // Decodes a PNG image from raw file data. + // encode image format + int findFormat(const std::string &_ext); + // BMP image encode + void BMPEncode(const std::string &filename, Image &image); #ifdef BUDDY_ENABLE_PNG + // Decodes a PNG image from raw file data. bool decodePNG(const std::vector &fileData); #endif }; +template +Image::Image(T *data, intptr_t sizes[N]): MemRef(data, sizes) {} + // Image Container Constructor // Constructs an image container object from the image file path. template @@ -616,6 +650,102 @@ bool Image::decodePNG(const std::vector &fileData) { } #endif +template +int findFormat(const std::string &_ext){ + if (_ext.size() <= 1) + return 0; + + const char *ext = strrchr(_ext.c_str(), '.'); + if (!ext) + return 0; + + if (strcmp(ext, ".bmp") == 0) { + return 1; + } else { + std::cerr << "Unsupported to generate" << ext << "format image" << std::endl; + return 0; + } +} + +template +static void imageWrite(const std::string &filename, Image &image){ + int imformat = findFormat(filename); + switch (imformat) { + case 1: + BMPEncode(filename, image); + break; + default: + return; + } + return; +} + +template +void BMPEncode(const std::string &filename, Image &image){ + std::ofstream bmp(filename, std::ios::binary); + if (!bmp) { + std::cerr << "Failed to create file" << std::endl; + return; + } + int width = image.getSizes()[3]; + int height = image.getSizes()[2]; + int channels = image.getSizes()[1]; + // Align each row of data with 4 bytes + int fileStep = (width * channels + 3) & -4; + int bitmapHeaderSize = 40; + int paletteSize = channels > 1 ? 0 : 1024; + int headerSize = 14 /* fileheader */ + bitmapHeaderSize + paletteSize; + size_t fileSize = (size_t)fileStep * height + headerSize; + PaletteBlock palette[256]; + // Fixed value in BMP + int zero = 0; + int one = 1; + char zeropad[] = "\0\0\0\0"; + + // Write file header + bmp.write("BM", 2); + int fileSizeInt = validToInt(fileSize); + bmp.write(reinterpret_cast(&fileSizeInt), 4); + bmp.write(reinterpret_cast(&zero), 4); + bmp.write(reinterpret_cast(&headerSize), 4); + + // Write bitmap header + bmp.write(reinterpret_cast(&bitmapHeaderSize), 4); + bmp.write(reinterpret_cast(&width), 4); + bmp.write(reinterpret_cast(&height), 4); + bmp.write(reinterpret_cast(&one), 2); + int bitDepth = channels << 3; + bmp.write(reinterpret_cast(&(bitDepth)), 2); + bmp.write(reinterpret_cast(&zero), 4); + bmp.write(reinterpret_cast(&zero), 4); + bmp.write(reinterpret_cast(&zero), 4); + bmp.write(reinterpret_cast(&zero), 4); + bmp.write(reinterpret_cast(&zero), 4); + bmp.write(reinterpret_cast(&zero), 4); + + // Write palette + if (channels == 1) { + FillPalette(palette, 8); + bmp.write(reinterpret_cast(&palette), sizeof(palette)); + } + + // Write image data + int step = width * height; + T *data = image.getData(); + for (int y = height - 1; y >= 0; y--) { + for (int i = 0; i < width; i++) { + for (int t = channels - 1; t >= 0; t--) { + unsigned char pixel= static_cast(data[y * width + i + t * step]); + bmp.write(reinterpret_cast(&pixel), 1); + } + } + if (fileStep > width * channels) + bmp.write(zeropad, fileStep - width * channels); + } + + bmp.close(); +} + } // namespace dip #endif // FRONTEND_INTERFACES_BUDDY_DIP_IMGCONTAINER