Декодирование и преобразование форматов изображений с D2D - PullRequest
0 голосов
/ 19 января 2020

Я хотел бы использовать D2D для декодирования распространенных форматов изображений (.jpeg, .png) и записать их в мои текстуры OpenGL в формате, который я использую по умолчанию, то есть RGBA, 8 бит на канал.

Самый простой способ, казалось бы, просто применить декорированный CreateBitmapFromSource(IWIC_decoder_frame, ..., &IWIC_bitmap) и прочитать IWICBitmap ...

Однако у меня были проблемы с этим:

  • В: Как я могу прочитать GUID форматов пикселей WI C? Я случайно догадался, что числа в отладчике ({6FDDC324-4E03-4BFE-B185-3D77768DC920}) соответствуют GUID_WICPixelFormat24bpp3Channels.
  • Но даже после понимания того, что в растровом формате WI C есть только 3 канала, размер возвращаемого байта после вызова IWIC_bitmap_lock->GetDataPointer(&bitmap_buffer_size, &data_ptr), bitmap_buffer_size был 854559, в то время как я ожидал 3*width*height = 653*436*3 = 854124. Я попытался записать растровое изображение на мою текстуру, но в результате получилось следующее:

(я также пытался использовать IWICFormatConverter, но не знал, как создать цель рендеринга. Документация пропускает часть с //Create render target and D2D bitmap from IWICBitmapSource.)

enter image description here enter image description here

IWICBitmapDecoder *IWIC_decoder = NULL;
IWICBitmapFrameDecode *IWIC_decoder_frame  = NULL;

HR(IWIC_imaging_factory->CreateDecoderFromFilename(
L"cat.jpg",                  // Image to be decoded
NULL,                           // Do not prefer a particular vendor
GENERIC_READ,                   // Desired read access to the file
WICDecodeMetadataCacheOnDemand, // Cache metadata when needed
&IWIC_decoder                      // Pointer to the decoder
));

// get frame
HR(IWIC_decoder->GetFrame(0, &IWIC_decoder_frame));

// get frame dimentions
u32 frame_width = 0;
u32 frame_height = 0;
HR(IWIC_decoder_frame->GetSize (&frame_width, &frame_height));

IWICBitmap *IWIC_bitmap = NULL;
IWICBitmapLock *IWIC_bitmap_lock = NULL;
WICRect IWIC_lock_rect = { 0, 0, (s32)frame_width, (s32)frame_height };

HR(IWIC_imaging_factory->CreateBitmapFromSource(IWIC_decoder_frame, WICBitmapCacheOnDemand, &IWIC_bitmap));
HR(IWIC_bitmap->Lock(&IWIC_lock_rect, WICBitmapLockRead, &IWIC_bitmap_lock));

WICPixelFormatGUID pixel_format;
HR(IWIC_bitmap->GetPixelFormat(&pixel_format));

UINT bitmap_buffer_size = 0;
u8 *reader = NULL;
// Retrieve a pointer to the pixel data.
HR(IWIC_bitmap_lock->GetDataPointer(&bitmap_buffer_size, &reader));


...
for(int row_index = 0; row_index < (y1 - y0); row_index++)
{
    for(int column_index = 0; column_index < (x1 - x0); column_index++)
    {
        u32 *pixel = rect_start + column_index + row_index * TEXTURE_DIM;

        u8 *writer = (u8 *)pixel;
        *writer = *source;
        writer++;source++;

        *writer = *source;
        writer++;source++;

        *writer = *source;
        writer++; source++;

        *writer = 255;
        writer++;

        byte_size--;
        if(byte_size < 0)
        {
            break;
        }
    }
}

Читает IWICBitmap разумный способ справиться с этим? Или я должен использовать конвертер?

...