GDI 图像的最大尺寸?

问题描述 投票:0回答:1

我正在尝试使用 GDI+ 从像素数据创建一个非常大的图像。代码看起来像这样:

Gdiplus::Status CreatePNG(int tileSize, int height = 16 * 1024)
{
    Gdiplus::Status status = Gdiplus::Ok;
    int width = 1024 * 16;
    Gdiplus::Bitmap bitmap(width, height, PixelFormat32bppRGB);
    Gdiplus::BitmapData bitmapData;
    INT *pixels = new INT[width * tileSize];
    ZeroMemory(pixels, width * tileSize * sizeof(INT));
    for (int y = 0; y != tileSize; ++y) {
        for (int x = 0; x != width; ++x) {
            INT color = 0xffff00;
            pixels[y * width + x] = color;
        }
    }
    ZeroMemory(&bitmapData, sizeof(bitmapData));
    bitmapData.Scan0 = pixels;
    bitmapData.Stride = width * sizeof(INT);
    bitmapData.Width = width;
    bitmapData.Height = tileSize;
    bitmapData.PixelFormat = bitmap.GetPixelFormat();
    Gdiplus::Rect tile(0, 0, width, tileSize);
    status = bitmap.LockBits(&tile, Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
        bitmap.GetPixelFormat(), &bitmapData);
    if (status == Gdiplus::Ok)
        status = bitmap.UnlockBits(&bitmapData);

    if (status == Gdiplus::Ok) {
        CLSID encoderClsid;
        if (GetEncoderClsid(L"image/png", &encoderClsid) >= 0) {
            status = bitmap.Save(TEXT("big.png"), &encoderClsid);
        }
    }
    return status;
}

换句话说,我创建了一个宽和高均为 16K 像素的位图,并用来自用户输入缓冲区 (Gdiplus::ImageLockModeUserInputBuf) 的黄色像素填充顶部。仅当高度足够小时,此方法才有效:31K 行可以,32K 不行。图像越宽,它就可以越高,所以我认为 256 兆像素存在一些逻辑障碍。

这个限制从何而来?

如何操作更大的图像?

c++ winapi gdi+
1个回答
1
投票

这看起来很可疑:

INT *pixels = new INT[width * tileSize];

width*tileSize
都超过 32K 时,您开始接近整数溢出限制。

这个怎么样:

uint64_t uWidth = (unsigned)width;
uint64_t uTileSize = (unsigned)tileSize;
uint64_t totalPixels = uWidth * uTileSize;
INT *pixels = new INT[width * tileSize];

所有这些都假设是 64 位操作系统,并且您编译为 64 位进程。 您无法在 32 位进程上可靠地分配 32Kx32K ARGB 位图,因为那时您将耗尽内存.

© www.soinside.com 2019 - 2024. All rights reserved.