C++ 缩放位图输出会扭曲图像

C++ 缩放位图输出会扭曲图像,c++,image,mfc,bitmap,C++,Image,Mfc,Bitmap,我有一个2752x2200位图图像。我只能在MFC对话框中显示它的1/3(对于明显的大小问题),因此如果我不缩放图像,我只能得到左上角的917x733块(左上角的1/3块)。我想将图像缩小3倍,这样整个图像就会显示在图像1/3大小的区域中。我已按如下方式设置灰度位图: ////////////////////////////////////////////////////////////////////////// ////////// Setup Bitmap //////

我有一个2752x2200位图图像。我只能在MFC对话框中显示它的1/3(对于明显的大小问题),因此如果我不缩放图像,我只能得到左上角的917x733块(左上角的1/3块)。我想将图像缩小3倍,这样整个图像就会显示在图像1/3大小的区域中。我已按如下方式设置灰度位图:

    //////////////////////////////////////////////////////////////////////////
    //////////  Setup Bitmap  ////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////

    //// FILEHEADER ////
    BITMAPFILEHEADER* bf = new BITMAPFILEHEADER;
    bf->bfType = 0x4d42;
    bf->bfSize = 6054400 + 54 + sizeof(BITMAPINFO);
    bf->bfOffBits = 54;

    //// INFOHEADER ////
    BITMAPINFOHEADER* bi = new BITMAPINFOHEADER;
    bi->biSize = 40;
    bi->biWidth = 2752;
    bi->biHeight = -2200;
    bi->biPlanes = 1;
    bi->biBitCount = 8;
    bi->biCompression = 0;
    //bi->biSizeImage = 6054400; //not required
    bi->biXPelsPerMeter = 2835;
    bi->biYPelsPerMeter = 2835;
    bi->biClrUsed = 0;
    bi->biClrImportant = 0;

    //// INFO ////
    BITMAPINFO* pbmi = (BITMAPINFO*)alloca( sizeof(BITMAPINFOHEADER) +   
        sizeof(RGBQUAD)*256);
    pbmi->bmiHeader.biSize = sizeof (pbmi->bmiHeader);
    pbmi->bmiHeader.biWidth = 2752;
    pbmi->bmiHeader.biHeight = -2200;
    pbmi->bmiHeader.biPlanes = 1;
    pbmi->bmiHeader.biBitCount = 8;
    pbmi->bmiHeader.biCompression = BI_RGB;
    pbmi->bmiHeader.biSizeImage = 0;
    pbmi->bmiHeader.biXPelsPerMeter = 14173;
    pbmi->bmiHeader.biYPelsPerMeter = 14173;
    pbmi->bmiHeader.biClrUsed = 0;
    pbmi->bmiHeader.biClrImportant = 0;
    //create grayscale color palette
    for(int i=0; i<256; i++)
    {
        pbmi->bmiColors[i].rgbRed = i;
        pbmi->bmiColors[i].rgbGreen = i;
        pbmi->bmiColors[i].rgbBlue = i;
        pbmi->bmiColors[i].rgbReserved = 0;
    }

    //// IMAGE DATA ////
    pFrame->GetImage(m_imageData);

    //////////////////////////////////////////////////////////////////////
    ////// Create image that's printed to dialog box /////////////////////
    //////////////////////////////////////////////////////////////////////
    HDC hdc = ::GetDC(NULL);  
    hbit = CreateDIBitmap(hdc, bi, CBM_INIT, m_imageData,
       pbmi, DIB_RGB_COLORS);
使用此代码,图像看起来不错,但它只是完整图像的左上角块:

在尝试缩小图像时,我更改了行:

        dc.StretchBlt(384,21,bi->bmWidth,bi->bmHeight,&bmDC,0,0,
            bi->bmWidth,bi->bmHeight,SRCCOPY);
致:

现在,我的输出看起来缩小了,它显示了整个图像(好),但所有内容看起来都扭曲了(坏):

(注意图像边界周围的圆环。这些圆环不应该在那里,当你真正看到我的图像流的实时视频时,它们会跳动,基本上破坏了图像)

我的问题是:是什么导致了这种失真?我能做些简单的事情来修复它吗

编辑:尝试StretchDIBits()后:

我的输出如下所示:

    BITMAP* bi = new BITMAP;
    CBitmap bmp;
    bmp.Attach(hbit);
    CClientDC dc(pWnd);
    CDC bmDC;
    bmDC.CreateCompatibleDC(&dc);
    CBitmap *pOldbmp = bmDC.SelectObject(&bmp);
    bmp.GetBitmap(bi);
    dc.StretchBlt(384,21,bi->bmWidth,bi->bmHeight,&bmDC,0,0,
        bi->bmWidth,bi->bmHeight,SRCCOPY);
    bmDC.SelectObject(pOldbmp);

i、 imgur.com/DA49P8x.png

而不是
StretchBLT
尝试:


尝试以下操作,而不是
StretchBLT


如果要缩放位图,windows api可能会在视觉上表现不佳,因为它是为优化性能而设计的。在StretchBlt之前添加以下行以增强位图操作:

SetStretchBltMode(dc.m_hDC, HALFTONE);

如果要缩放位图,windows api可能会在视觉上表现不佳,因为它是为优化性能而设计的。在StretchBlt之前添加以下行以增强位图操作:

SetStretchBltMode(dc.m_hDC, HALFTONE);

有没有办法在某处发布100%大小的屏幕截图?我怀疑你看到的是图像中固有的噪声混叠,但无法确定此处显示的调整大小的图像。没关系,我发现你可以在新选项卡中打开图像,并以100%的速度看到它。问题不在于混叠,而在于后期处理——调色板被减少到非常少的颜色。有没有办法在某个地方发布100%大小的屏幕截图?我怀疑你看到的是图像中固有的噪声混叠,但无法确定此处显示的调整大小的图像。没关系,我发现你可以在新选项卡中打开图像,并以100%的速度看到它。问题不在于混叠,而在于后期处理——调色板被缩减为非常少量的颜色。@xcdemon05,这很奇怪。我唯一能想到的另一件事是将
biClrUsed
biclrementant
设置为256,但我不希望这会改变任何事情。@xcdemon05我最新的想法是,您可能有调色板损坏。尝试在StretchDIBits之后测试调色板,确保它仍然是灰度调色板。@xcdemon05,这很奇怪。我唯一能想到的另一件事是将
biClrUsed
biclrementant
设置为256,但我不希望这会改变任何事情。@xcdemon05我最新的想法是,您可能有调色板损坏。尝试在StretchDIBits之后测试调色板,以确保它仍然是灰度调色板。这里可能有一些内容,但对于灰度调色板,我建议使用
COLORONCOLOR
。@MarkRansom-是的,我认为你是对的,它更适合xcdemon05的使用,我只是从我的旧代码中选择了它。这里可能有一些内容,但对于灰度调色板,我建议改为
COLORONCOLOR
。@markransem-是的,我认为你是对的,它更适合xcdemon05的使用,我只是从我的旧代码中选择它。
StretchDIBits(dc.m_hDC, 384, 21, bi->bmWidth/3, bi->bmHeight/3, 0, 0,
              bi->bmWidth, bi->bmHeight, m_imageData, pbmi, DIB_RGB_COLORS, SRCCOPY);
SetStretchBltMode(dc.m_hDC, HALFTONE);