You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将Targa(TGA)加载为HBITMAP后颜色显示异常问题排查

TGA转HBITMAP颜色异常问题解决及替代方案

问题根源

你的TGA文件是24位RGB格式,但TGA的24位像素存储顺序是BGR,而Windows GDI的24位DIB(设备无关位图)同样使用BGR顺序存储像素。你直接将TGA的RGB数据传入SetDIBits,导致红色和蓝色通道反转,这就是显示颜色不一致的核心原因。

解决方案

方案1:修改现有代码,转换像素通道顺序

在调用SetDIBits前,遍历像素数据,交换每个像素的R和B通道:

auto image = ReadImageFile("test.tga");
if (image == nullptr)
    break;

unsigned int displayWidth = 1920;
unsigned int displayHeight = 1080;

BITMAPINFO bmi = {};
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = image->GetWidth();
bmi.bmiHeader.biHeight = -static_cast<int>(image->GetHeight());
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biCompression = BI_RGB;

PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
HDC hdcMem = CreateCompatibleDC(hdc);

HBITMAP hBitmap = CreateDIBSection(hdcMem, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
if (hBitmap) {
    // 获取像素数据并转换RGB到BGR
    unsigned char* pixels = image->GetPixels();
    const unsigned int pixelCount = image->GetWidth() * image->GetHeight();
    for (unsigned int i = 0; i < pixelCount; ++i) {
        const unsigned char temp = pixels[i*3];
        pixels[i*3] = pixels[i*3 + 2];
        pixels[i*3 + 2] = temp;
    }

    SetDIBits(hdcMem, hBitmap, 0, image->GetHeight(), pixels, &bmi, DIB_RGB_COLORS);
    SelectObject(hdcMem, hBitmap);

    SetStretchBltMode(hdc, HALFTONE);
    StretchBlt(hdc, 0, 0, displayWidth, displayHeight, hdcMem, 0, 0, image->GetWidth(), image->GetHeight(), SRCCOPY);

    DeleteObject(hBitmap);
}

DeleteDC(hdcMem);
EndPaint(hWnd, &ps);
break;

注意:如果image->GetPixels()返回的是const指针,需要先将像素数据拷贝到可修改的内存区域再进行通道转换。

方案2:使用GDI+直接加载TGA(更简洁高效)

如果不想手动处理像素格式,GDI+支持直接加载TGA文件,无需自行解析格式或转换通道:

#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")

// 程序启动时初始化GDI+(仅需调用一次)
Gdiplus::GdiplusStartupInput gdiplusInput;
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusInput, nullptr);

// 加载并绘制TGA的代码
auto displayWidth = 1920u;
auto displayHeight = 1080u;

PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);

Gdiplus::Image tgaImage(L"test.tga");
if (tgaImage.GetLastStatus() == Gdiplus::Ok) {
    Gdiplus::Graphics graphics(hdc);
    // 设置高质量插值模式,拉伸时更清晰
    graphics.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic);
    graphics.DrawImage(&tgaImage, 0, 0, displayWidth, displayHeight);
}

EndPaint(hWnd, &ps);

// 程序退出时关闭GDI+
Gdiplus::GdiplusShutdown(gdiplusToken);

优势:无需手动处理TGA格式细节,GDI+会自动完成格式转换和内存管理,代码更简洁,不易出错。

内容的提问来源于stack exchange,提问作者avgcoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 15:18:43