图片缩放并设置dpi

这几天遇到个需求,要求缩放图片,但是不能改变图片的dpi,用 opencv 不行,于是在网上找,但是找了很久没有找到相关的信息,只有一篇帖子说使用 Gdiplus 可以满足这个需求,遂研究了一下 Gdiplus 的接口,终于找到了 Gdiplus::Bitmap::SetResolution 这个方法,新技能 Get!

完整的代码如下:

#pragma comment(lib, "Gdiplus.lib")

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
    /*
     * 该方法获取相应图片的 class id
     */

    UINT num = 0;  // number of image encoders 
    UINT size = 0;  // size of the image encoder array in bytes 

    Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL;

    Gdiplus::GetImageEncodersSize(&num, &size);
    if (size == 0)
    {
        return -1;
    }

    pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
    if (pImageCodecInfo == NULL)
    {
        return -1;
    }

    Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);

    for (UINT j = 0; j < num; ++j)
    {
        if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
        {
            *pClsid = pImageCodecInfo[j].Clsid;
            free(pImageCodecInfo);
            return j;
        }
    }

    free(pImageCodecInfo);
    return -1;
}

bool GdiplusUtils::resizeImage(const std::string &sourceImagePath,
    const std::string &targetImagePath,
    int targetImageWidth,
    int targetImageHeight,
    const std::string &targetImageEncoder,
    Gdiplus::PixelFormat targetImagePixelFormat,
    bool remainResolution)
{
    /*
    * Load source image and get information
    */

    Gdiplus::Bitmap sourceImage(StringUtils::MB2WC(sourceImagePath).c_str(), FALSE);

    /*
    * Rescale and set resolution
    */

    // rescale
    Gdiplus::Bitmap targetImage(targetImageWidth, targetImageHeight, targetImagePixelFormat);
    Gdiplus::Graphics graphics(&targetImage);
    graphics.DrawImage(&sourceImage, 0, 0, targetImageWidth, targetImageHeight);

    // set resolution
    if (remainResolution)
    {
        auto hResolution = sourceImage.GetHorizontalResolution();
        auto vResolution = sourceImage.GetVerticalResolution();
        targetImage.SetResolution(hResolution, vResolution);
    }

    /*
    * Save Image
    */
    CLSID clsid;
    GetEncoderClsid(StringUtils::MB2WC(targetImageEncoder).c_str(), &clsid);
    targetImage.Save(StringUtils::MB2WC(targetImagePath).c_str(), &clsid);

    return true;
}

需要注意的是必须引入 Gdiplus.lib ,并且需要通过 Gdiplus::GdiplusStartupGdiplus::GdiplusShutdown 来初始化和反初始化 Gdiplus。这些内容没有体现在上面的代码中,读者需要在合适的位置自行添加。

最后,代码中的 StringUtils::MB2WC 是一个将多字节字符转换为宽字节字符的辅助函数,代码如下:

std::wstring StringUtils::MB2WC(const std::string &mb)
{
    int lenWC = ::MultiByteToWideChar(CP_ACP, 0, mb.c_str(), mb.length(), NULL, 0);
    std::unique_ptr<wchar_t> wc(new wchar_t[lenWC]());
    ::MultiByteToWideChar(CP_ACP, 0, mb.c_str(), mb.length(), wc.get(), lenWC);
    return std::wstring(wc.get(), lenWC);
}

猜你喜欢

转载自blog.csdn.net/u011304970/article/details/81303111
今日推荐