Michael Chourdakis
Michael Chourdakis

Reputation: 11148

Reading EXR file

I'm trying to create a IWICBitmap from an EXR file (error checks removed).

    #pragma pack(push,1)
    struct fl
    {
        float r, g, b, a;
    };
    #pragma pack(pop)
    HRESULT Open(const char* f,IWICBitmap** d)
    {
        exr_context_initializer_t ctxtinit = EXR_DEFAULT_CONTEXT_INITIALIZER;
        exr_context_t myfile = {};
        exr_result_t rv = exr_start_read(&myfile, f, &ctxtinit);

        int part_index = 0;
        const exr_attr_chlist_t* chl = 0;
        exr_get_channels(myfile, part_index, &chl);

        int32_t ck = 0;
        rv = exr_get_chunk_count(myfile, part_index, &ck);
        int32_t sl = 0;
        rv = exr_get_scanlines_per_chunk(myfile, part_index, &sl);

        int y = 0;
        int wi = 0;
        int he = 0;
        std::vector<fl> data; // put here the floats

        exr_decode_pipeline_t dec = {};
        for (int32_t cuk = 0; cuk < ck; cuk++)
        {
            exr_chunk_info_t ch = {};
            exr_read_scanline_chunk_info(myfile, part_index, y, &ch);
            wi = ch.width;
            he += ch.height;
            y += sl;

            bool first = 0;
            if (dec.decompress_fn == 0)
            {
                rv = exr_decoding_initialize(myfile, part_index, &ch, &dec);
                rv = exr_decoding_choose_default_routines(myfile, part_index, &dec);
                first = 1;
            }
            if (!first)
                rv = exr_decoding_update(myfile, part_index,&ch,&dec);
            rv = exr_decoding_run(myfile, part_index, &dec);

            int NumPixels = (wi * ch.height);
            auto BytesPerPixel = ch.unpacked_size / NumPixels;

            if (true)
            {
                // RGB(A)
                if (chl->entries[0].pixel_type == EXR_PIXEL_HALF)
                {
                    if (BytesPerPixel == chl->num_channels * 2)
                    {
                        auto ds = data.size();
                        data.resize(ds + NumPixels);
                        auto p = data.data() + ds;
                        char* x = (char*)dec.unpacked_buffer;
                        for (int j = 0; j < NumPixels; j++)
                        {
                            uint16_t* u = (uint16_t*)x;

                            p->a = 1.0f;
                            for (int jH = 0; jH < chl->num_channels; jH++)
                            {
                                half ha(Imath_3_2::half::FromBits,*u);
                                ha.setBits(*u);
                                if (strcmp(chl->entries[jH].name.str, "R") == 0)                                    p->r = ha.operator float();
                                if (strcmp(chl->entries[jH].name.str, "G") == 0)                                    p->g = ha.operator float();
                                if (strcmp(chl->entries[jH].name.str, "B") == 0)                                    p->b = ha.operator float();
                                if (strcmp(chl->entries[jH].name.str, "A") == 0)                                    p->a = ha.operator float();
                                u++;
                            }
                            x += BytesPerPixel;
                            p++;
                        }
                    }
                    else
                        break;
                }
                if (chl->entries[0].pixel_type == EXR_PIXEL_FLOAT)
                {   
                 // code removed for simplicity, I guess the same issue happens here unless it's a problem of the half-float
                }
            }
        }
        rv = exr_decoding_destroy(myfile, &dec);
        exr_finish(&myfile);

        CComPtr<IWICImagingFactory2> wbfact = 0;
        CoCreateInstance(CLSID_WICImagingFactory2, 0, CLSCTX_INPROC_SERVER,
            __uuidof(IWICImagingFactory2), (void**)&wbfact);
        return wbfact->CreateBitmapFromMemory(wi, he, GUID_WICPixelFormat128bppPRGBAFloat, wi * 16,(UINT)data.size()*16, (BYTE*)data.data(), d);
    }

What am I doing wrong? The pixel number I'm reading is correct (in this image 800x800). My result:

enter image description here

Photoshop:

enter image description here

Is there a problem with the half-float? I'm just using the OpenEXR's IMath implementation.

Upvotes: 0

Views: 123

Answers (0)

Related Questions