tev icon indicating copy to clipboard operation
tev copied to clipboard

Wrong channel order when reading file saved by TINYEXR

Open Thomaswang0822 opened this issue 3 months ago • 1 comments

Steps to reproduce: run the function below, open exr with TEV, inspect the channel values.

In the multi-line comment where we set channel names, I suppose TEV behave like that. Is my guess correct? If yes, could it be fixed (or is it fixed already? I am using version 1.26), since both TEV and TinyEXR are very popular tools.

    bool TestTinyExrWrite()
    {
        EXRHeader header;
        EXRImage image;
        InitEXRHeader(&header);
        InitEXRImage(&image);

        int width = 1920;
        int height = 1080;
        int num_channels = 4;

        // Set up header
        header.num_channels = num_channels;
        header.channels = new EXRChannelInfo[num_channels];
        header.pixel_types = new int[num_channels];
        header.requested_pixel_types = new int[num_channels];

        const char names[4] = { 'R', 'G', 'B', 'A' };
        /// TEV Viewer works like this:
        /// It "blindly" reorders the channels in alphabetical order,
        /// which means even if you pack data in RGBA order and set header.channels also,
        /// it displays data wrongly as ABGR.
        /// In the channel names below, where NONE is a valid common channel name and H comes first,
        /// no matter how we order them, 
        /// TEV will show a single H-channel image with 0.9f as value, because it comes first.
        //const char names[4] = { 'O', 'H', 'P', 'Q' };
        for (int i = 0; i < num_channels; i++) {
            header.channels[i].name[0] = names[i];
            header.channels[i].name[1] = '\0';
            header.pixel_types[i] = TINYEXR_PIXELTYPE_HALF;
            header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_HALF;
        }
        header.compression_type = TINYEXR_COMPRESSIONTYPE_NONE; // No compression for simplicity

        // Allocate data for each channel
        image.num_channels = num_channels;
        image.width = width;
        image.height = height;
        image.images = new unsigned char* [num_channels];

        // Create distinct test values for each channel:
        // Channel A: all 1.0f
        // Channel R: all 0.9f
        // Channel G: all 0.6f
        // Channel B: all 0.1f
        auto fToU16 = [](float value) {
            tinyexr::FP32 f32; 
            f32.f = value;
            return  tinyexr::float_to_half_full(f32).u;
            };
        std::vector<uint16_t> dataR(width * height, fToU16(0.9f));
        std::vector<uint16_t> dataG(width * height, fToU16(0.6f));
        std::vector<uint16_t> dataB(width * height, fToU16(0.1f));
        std::vector<uint16_t> dataA(width * height, fToU16(1.0f));

        image.images[0] = reinterpret_cast<unsigned char*>(dataR.data());
        image.images[1] = reinterpret_cast<unsigned char*>(dataG.data());
        image.images[2] = reinterpret_cast<unsigned char*>(dataB.data());
        image.images[3] = reinterpret_cast<unsigned char*>(dataA.data());

        // Save the EXR file
        const char* err = nullptr;
        int ret = SaveEXRImageToFile(&image, &header, <ANY LOCATION>, &err);
        if (ret != TINYEXR_SUCCESS) {
            printf("Error: %s\n", err);
            return 1;
        }

        // Cleanup
        delete[] header.channels;
        delete[] header.requested_pixel_types;
        delete[] image.images;

        printf("EXR file 'test.exr' created successfully.\n");
        return true;
    }

Thomaswang0822 avatar Sep 17 '25 15:09 Thomaswang0822

No, tev does not perform any reordering or reinterpretation to link channel names to data, alphabetic or not. It uses the official OpenEXR library to load and store exr images (see ExrImageLoader.cpp for details) and loads all the official OpenEXR test images correctly (including RGBA ones).

Did you make sure the exr file you're trying to load actually has the correct values by other means than tev? You can do this e.g. via PyEXR, ImageMagick or macOS's Preview app.

Please also use the latest version of tev for bug reports (that's where fixes are going to happen) and share the broken exr image. Thanks!

Tom94 avatar Sep 18 '25 01:09 Tom94