如何访问win32缩略图的图像数据

时间:2014-01-06 12:13:47

标签: c++ image winapi buffer thumbnails

我正在尝试访问win32缩略图的图像数据,以便使用以下步骤将其与其他库一起使用:

  1. 从Windows缩略图缓存中获取缩略图(ISharedBitmap)
  2. 获取缩略图的HBITMAP
  3. 使用GetDIBits获取像素数据
  4. 缩略图检索基于https://stackoverflow.com/a/19529633/3165122

    像素数据检索基于https://stackoverflow.com/a/3688682/3165122

    这是我到目前为止所得到的:

    // error checks omitted
    LPCTSTR path = TEXT("<path-to-jpg-image>");
    
    HRESULT hr = CoInitialize(nullptr);
    
    // Get the thumbnail
    IShellItem* item = nullptr;
    hr = SHCreateItemFromParsingName(path, nullptr, IID_PPV_ARGS(&item));
    
    IThumbnailCache* cache = nullptr;
    hr = CoCreateInstance(
        CLSID_LocalThumbnailCache,
        nullptr,
        CLSCTX_INPROC,
        IID_PPV_ARGS(&cache)); 
    
    ISharedBitmap* shared_bitmap;
    hr = cache->GetThumbnail(
        item,
        1024,
        WTS_EXTRACT,
        &shared_bitmap,
        nullptr,
        nullptr);
    
    // Retrieve thumbnail HBITMAP
    HBITMAP hbitmap = NULL;
    hr = shared_bitmap->GetSharedBitmap(&hbitmap);
    
    HDC dc = GetDC(NULL);
    HDC dc_mem = CreateCompatibleDC(dc);
    
    // Get required buffer size
    BITMAPINFO bmi;
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    GetDIBits(dc_mem, hbitmap, 0, 0, nullptr, &bmi, DIB_RGB_COLORS); // <- this fails
    
    WTS_ALPHATYPE alpha_type;
    hr = shared_bitmap->GetFormat(&alpha_type);
    
    bmi.bmiHeader.biBitCount = alpha_type == WTSAT_RGB ? 24 : 32;
    bmi.bmiHeader.biHeight = std::abs(bmi.bmiHeader.biHeight);
    bmi.bmiHeader.biCompression = BI_RGB;
    
    // Get image data
    std::vector<char> buffer(bmi.bmiHeader.biSizeImage);
    GetDIBits(dc_mem, hbitmap, 0, bmi.bmiHeader.biHeight,
            &buffer[0], &bmi, DIB_RGB_COLORS);
    
    // use buffer...
    

    第一次调用GetDIBits来检索所需的缓冲区大小失败,返回值为0.我猜我正在使用不兼容的DC?如何获得兼容的DC?

    https://stackoverflow.com/a/14207674/3165122声明“[...]如果您不知道您的HBITMAP指向的是什么,您不能期望对它做任何有用的事情。”

    真的没办法吗?难道我做错了什么?有不同的方法吗?

1 个答案:

答案 0 :(得分:0)

根据GetDIBits文档: “如果lpvBits为NULL并且BITMAPINFO的位计数成员初始化为零,则GetDIBits将填充BITMAPINFOHEADER结构[...]”

在我的情况下,位计数成员未初始化为零。在声明修正后立即调用ZeroMemory(&bmi, sizeof(BITMAPINFO))。 为了我的辩护:BITMAPINFO是一个输出参数;)

非常感谢Stuart!