Есть ли в GDI + стандартные CLSID кодировщика изображений? - PullRequest
11 голосов
/ 18 марта 2011

Для метода GDI + Image::Save требуется параметр CLSID, чтобы указать используемый кодер. Документация указывает на некоторый пример кода для получения кодера, связанного с конкретным типом MIME, таким как image / jpeg или image / png. Однако я не согласен с мыслью о том, что нужно скопировать полстраничную функцию просто для поддержки средства отладки в 1 строку, где я сохраняю промежуточный результат на диск.

Разве не должно быть списка стандартных CLSID для стандартных кодировщиков? Где бы я найти такой список? Я не смог найти его, выполнив поиск по включаемым файлам Microsoft.

Ответы [ 3 ]

5 голосов
/ 18 марта 2011

Нет ни одного.Я думаю, что они хотели, чтобы список кодеков был расширяемым и поддерживал плагины, но так и не нашел его.Учитывая, что они не вносили никаких изменений в GDI + в течение достаточно долгого времени, они, вероятно, не будут в ближайшее время.Возможно, вам не удастся сгенерировать свой собственный жестко закодированный список на основе перечисления Gdiplus :: GetImageEncoders.

То есть:

image/bmp  : {557cf400-1a04-11d3-9a73-0000f81ef32e}
image/jpeg : {557cf401-1a04-11d3-9a73-0000f81ef32e} 
image/gif  : {557cf402-1a04-11d3-9a73-0000f81ef32e} 
image/tiff : {557cf405-1a04-11d3-9a73-0000f81ef32e}
image/png  : {557cf406-1a04-11d3-9a73-0000f81ef32e}

Вот функция, которую я обычно вырезал и вставлял между проектами для полученияна CLSID кодера.Вы можете изменить его для поиска в таблице.

HRESULT GetGdiplusEncoderClsid(__in LPCWSTR pwszFormat, __out GUID *pGUID)
{
    HRESULT hr = E_FAIL;
    UINT  nEncoders = 0;          // number of image encoders
    UINT  nSize = 0;              // size of the image encoder array in bytes
    CAutoVectorPtr<BYTE> spData;
    Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL;
    Gdiplus::Status status;
    bool fFound = false;

    // param check

    if ((pwszFormat == NULL) || (pwszFormat[0] == 0) || (pGUID == NULL))
    {
        return E_POINTER;
    }

    *pGUID = GUID_NULL;

    status = Gdiplus::GetImageEncodersSize(&nEncoders, &nSize);

    if ((status != Gdiplus::Ok) || (nSize == 0))
    {
        return E_FAIL;
    }


    spData.Allocate(nSize);

    if (spData == NULL)
    {
        return E_FAIL;
    }

    pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(BYTE*)spData;

    status = Gdiplus::GetImageEncoders(nEncoders, nSize, pImageCodecInfo);

    if (status != Gdiplus::Ok)
    {
       return E_FAIL;
    }

    for(UINT j = 0; j < nEncoders; ++j)
    {
        if( wcscmp(pImageCodecInfo[j].MimeType, pwszFormat) == 0 )
        {
            *pGUID = pImageCodecInfo[j].Clsid;
            fFound = true;
            break;
        }    
    }

    hr = fFound ? S_OK : E_FAIL;

    return hr;
}
2 голосов
/ 17 октября 2015

Если вы просто хотите написать PNG, это работает:

// image/png  : {557cf406-1a04-11d3-9a73-0000f81ef32e}
const CLSID pngEncoderClsId = { 0x557cf406, 0x1a04, 0x11d3,{ 0x9a,0x73,0x00,0x00,0xf8,0x1e,0xf3,0x2e } }; 
stat = image->Save(L"test.png", &pngEncoderClsId, NULL);

Обратите внимание на переформатирование шестнадцатеричных значений.

Из: Как инициализировать постоянный CLSID

2 голосов
/ 18 марта 2011

Возможно, вы захотите использовать ImageCodecInfo с GetImageEncodersSize() и GetImageEncoders() Я не знаю ни одного более простого способа.

РЕДАКТИРОВАТЬ: Если вы точно знаете, что вы хотите и, черт возьми, все остальное, вы можете сойти с рук, делая что-то вроде этого ...

CLSID pngClsid;
GetEncoderClsid("image/png", &pngClsid);
image.Save("imagename.png", &pngClsid, NULL);
...