Reputation: 129
I tried converting SVG to HBITMAP using NanoSVG. Everything works fine but the color of the Bitamp or saved png is different then the original svg. Please help me to fix this
I tried below code
// Load the SVG file
NSVGimage* image = nsvgParseFromFile(filename, "px", 96);
// Create a bitmap with the same dimensions as the SVG image
BITMAPINFO bmpinfo = { 0 };
bmpinfo.bmiHeader.biSize = sizeof(bmpinfo.bmiHeader);
bmpinfo.bmiHeader.biWidth = static_cast<LONG>(image->width);
bmpinfo.bmiHeader.biHeight = -static_cast<LONG>(image->height);
bmpinfo.bmiHeader.biPlanes = 1;
bmpinfo.bmiHeader.biBitCount = 32;
bmpinfo.bmiHeader.biCompression = BI_RGB;
void* bits = nullptr;
HBITMAP hbitmap = CreateDIBSection(NULL, &bmpinfo, DIB_RGB_COLORS, &bits, nullptr, 0);
// Render the SVG image to the bitmap
NSVGrasterizer* rast = nsvgCreateRasterizer();
nsvgRasterize(rast, image, 0, 0, 1, (unsigned char*)bits, static_cast<int>(image->width), static_cast<int>(image->height), static_cast<int>(image->width * 4));
nsvgDeleteRasterizer(rast);
// Clean up
nsvgDelete(image);
Upvotes: 1
Views: 372
Reputation: 9545
The problem is the red and blue channels are swapped because CreateDIBSection
expects BGR ordered color and NanoSVG is outputting RGB. The documentation of CreateDIBSection
is less than clear on this point but if you look at the definition of RGBQUAD
you can see it is layed out as blue-green-red.
Anyway I don't see a way to control the byte order coming out of NanoSVG, so I don't think you can do better than just manually swapping the bytes. As below ... ( I also fixed a bug in your code having to do with the casts from floating point to integer dimensions. The bug was that stride should be four times the integer width, not four times the width as a floating point value.)
void rgb_to_bgr(unsigned char* bits, int n) {
for (int i = 0; i < n; i += 4) {
std::swap(bits[i], bits[i + 2]);
}
}
HBITMAP paint_svg(const char* filename) {
// Load the SVG file
NSVGimage* image = nsvgParseFromFile(filename, "px", 96);
int wd = static_cast<int>(std::ceil(image->width));
int hgt = static_cast<int>(std::ceil(image->height));
int stride = wd * 4;
// Create a bitmap with the same dimensions as the SVG image
BITMAPINFO bmpinfo = { 0 };
bmpinfo.bmiHeader.biSize = sizeof(bmpinfo.bmiHeader);
bmpinfo.bmiHeader.biWidth = wd;
bmpinfo.bmiHeader.biHeight = -hgt;
bmpinfo.bmiHeader.biPlanes = 1;
bmpinfo.bmiHeader.biBitCount = 32;
bmpinfo.bmiHeader.biCompression = BI_RGB;
unsigned char* bits = nullptr;
HBITMAP hbitmap = CreateDIBSection(NULL, &bmpinfo, DIB_RGB_COLORS,
reinterpret_cast<void**>(&bits), nullptr, 0);
// Render the SVG image to the bitmap
NSVGrasterizer* rast = nsvgCreateRasterizer();
nsvgRasterize(rast, image, 0, 0, 1, bits, wd, hgt, stride);
rgb_to_bgr(bits, hgt * stride);
nsvgDeleteRasterizer(rast);
// Clean up
nsvgDelete(image);
return hbitmap
}
Upvotes: 1