Decompressed bitmap image doesn't properly render when using WinGDI

Joined
Jun 14, 2024
Messages
2
Reaction score
0
I have been trying to make my own custom PDF editor & I have made a PDF parser that works absolutely fine for any PDF feature until images came up. First of all, the images in my PDFs are compressed with the standard DEFLATE/INFLATE algorithm & they all have the FlateDecode filter. the images, compressed & decompressed will have a lot of raw bytes that may be corrupted as a string or a char so I used a vector of uint8_t to be safe. here's my decompression/inflation function :
std::vector<uint8_t> parser::inflate_stream_to_raw(const std::vector<uint8_t>& deflated_stream) {
z_stream stream{};
int ret = inflateInit(&stream);
if (ret != Z_OK) std::cout << "\ncould not init zlib\n";

std::vector<uint8_t> inflated_stream;
const int chunk_size = 16384; // 16 KB chunk size
std::vector<uint8_t> buffer(chunk_size);

stream.next_in = const_cast<Bytef*>(deflated_stream.data());
stream.avail_in = static_cast<uInt>(deflated_stream.size());

while (ret != Z_STREAM_END) {
stream.next_out = reinterpret_cast<Bytef*>(buffer.data());
stream.avail_out = chunk_size;

ret = inflate(&stream, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) {
std::cerr << "Error: zlib stream error. Error code: " << ret << std::endl;
inflateEnd(&stream);
return {}; // Return an empty vector on error
}

inflated_stream.insert(inflated_stream.end(), buffer.data(), buffer.data() + chunk_size - stream.avail_out);
}

inflateEnd(&stream);

return inflated_stream;
}

this supposedly works fine, a version of this that returns the data as a string has worked fine for the PDF contents without any issues. So, when it comes time to render it, I have a .bmp that is the same as the image in the PDF i am testing & its size is about 12 MB, & testing the size of my decompressed image stream it is also around 12 MB, so I don't see how it could be the decompression failing. But when I get it to render, it doesnt look right. its an image of a fox sitting in snow and what i get rendered is a repeating image with the snow rendered fine but the fox is blue for some reason. i have verified the image is RGB

I've tried many ways to even get the bitmap image to render & this is the only way that seems to work so I don't know how to fix it if it is a problem with winGDI or how I render it. here;s the code I use to render it:
#include <C:/code-libs/pdfCoder/pdfCoder.hpp>
#include <Windows.h>
#include <wingdi.h>
#include <string>
#include <sstream>
#include <vector>

#pragma comment(lib, "C:/code-libs/pdfCoder/pdfCoder.lib")
#pragma comment(lib, "gdi32.lib")

LRESULT CALLBACK main_wnd_proc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param);
HWND main_wnd;

std::vector<image_object> img_objs;
parser pdf;

int pt_to_dip(double pt, double dpi) {
if (dpi == 96) return static_cast<int>(std::round((pt / 72) * dpi)); // if DPI is 96, then PX & DIP are equal
else return static_cast<int>(std::round(((pt / 72) * dpi) / (dpi / 96))); // else find PX first then convert to DIP
}

int WINAPI wWinMain(HINSTANCE cur_instance, HINSTANCE prev_instance, LPWSTR cmd_line, int cmd_count) {
const wchar_t* MAIN_WND = L"main_window";
WNDCLASS wc{};
wc.hInstance = cur_instance;
wc.lpszClassName = MAIN_WND;
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpfnWndProc = main_wnd_proc;
RegisterClass(&wc);

pdf.open("C:\\Coding Projects\\test field\\test4.pdf");
objects_root pdf_root = pdf.get_root();
page_object page = pdf.parse_page(pdf_root.pages[0]);

img_objs = pdf.parse_page_images(page);

main_wnd = CreateWindow(MAIN_WND, L"File Organiser",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
1500, 1500,
nullptr, nullptr, nullptr, nullptr);

if (main_wnd == NULL) return 1;
ShowWindow(main_wnd, SW_SHOW);
UpdateWindow(main_wnd);

MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;
}

LRESULT CALLBACK main_wnd_proc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
HDC hdc;
switch (msg) {
case WM_PAINT:
OutputDebugStringA("\nPAINTING...");
PAINTSTRUCT ps;
hdc = BeginPaint(hwnd, &ps);

for (const image_object& img_obj : img_objs) {
OutputDebugStringA("looping images");

std::stringstream ss;
ss << img_obj.image_stream.size();
OutputDebugStringA(ss.str().c_str());

BITMAPINFOHEADER bmp_header = {};
bmp_header.biSize = sizeof(BITMAPINFOHEADER);
bmp_header.biWidth = pt_to_dip(img_obj.width, 96);
bmp_header.biHeight = -pt_to_dip(img_obj.height, 96);
bmp_header.biPlanes = 1;
bmp_header.biBitCount = img_obj.bits_per_component * 3;
bmp_header.biCompression = BI_RGB;
bmp_header.biSizeImage = 0;
BITMAPINFO bmi = {};
bmi.bmiHeader = bmp_header;

void* raw_bits = malloc(img_obj.image_stream.size());
if (raw_bits != nullptr) {
memcpy(raw_bits, img_obj.image_stream.data(), img_obj.image_stream.size());
}

StretchDIBits(hdc, 0, 0, 1500, 1500,
0, 0, pt_to_dip(img_obj.width, 96), pt_to_dip(img_obj.height, 96),
raw_bits, &bmi,
BI_RGB,
SRCCOPY);

free(raw_bits);
HDC hdc = GetDC(hwnd);
ReleaseDC(hwnd, hdc);
}

EndPaint(hwnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, msg, w_param, l_param);
}
 
Joined
Jul 4, 2023
Messages
406
Reaction score
47
I'm a total newbie on this topic, but do other image file formats supported by PDF also cause this problem?
Maybe the solution would be to convert BMP files to e.g. PNG in your application when the BMP file is being entered?
 
Joined
Jun 14, 2024
Messages
2
Reaction score
0
I'm a total newbie on this topic, but do other image file formats supported by PDF also cause this problem?
Maybe the solution would be to convert BMP files to e.g. PNG in your application when the BMP file is being entered?
A PDF will usually have any JPEG or PNG file converted to raw bitmap data then conoressed with the DEFLATE algorithm. the image i am testing used to be A JPEG wheb I first uploaded it. A PDF will only sometimes keep the orifinal format for special purposes and if that's the case it'll tell you. Anything I try will always end up as raw data. The PDF reflects this when the image object defines the compression method as '/Filter FlateDecode'
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,818
Messages
2,569,727
Members
45,664
Latest member
Phil79581

Latest Threads

Top