Giter Club home page Giter Club logo

Comments (10)

syoyo avatar syoyo commented on August 12, 2024 1

@pgrit Thanks! After debugging TinyEXR and OpenEXR(recent main branch). I found the issue was in TinyEXR.

The issue was introduced in

#78

Accessing in is still valid for in < in_end case. With this, some huffman decoding was not performed well for your EXR data.
Also, there was a over-allocation of tmp buffer memory when storing uncompressed huffman data.

I made an PR. This PR should fix pink-dot issue. #161
(After your confirmation, I'll add gen.exr as a regression test and merge it into master)

from tinyexr.

syoyo avatar syoyo commented on August 12, 2024 1

@pgrit BTW simpleimageio is nice! You may be interested in https://github.com/syoyo/tinydngloader to support loading/saving 32bit FP TIFF images for simpleimageio

from tinyexr.

syoyo avatar syoyo commented on August 12, 2024

Uncomment SIMPLE_API_EXAMPLE and change compression to PIZ in test_tinyexr, read/convert RedDotsTest.exr and open output_test.exr in exrviewer does not show any artifact.

You need to provide minimal reproducible code.

$ file output_test.exr 
output_test.exr: OpenEXR image data, version 2, storage: scanline, compression: piz, dataWindow: (0 0)-(639 479), displayWindow: (0 0)-(639 479), lineOrder: increasing y

Screenshot from 2021-07-18 19-34-38

from tinyexr.

pgrit avatar pgrit commented on August 12, 2024

Not sure what your "exrviewer" is, if that is not using tinyexr than it will not yet show the problem.

Not quite "minimal" but I boiled it down to a single C++ file with my loading / writing code: TinyExrPIZ.zip

You can compile and run via something along the lines of: (depends on OS, of course)

mkdir build && cd build && cmake .. && cmake --build . && ./TinyExrPIZ

The output will be:

(639, 479).R = 0
(639, 479).R = 6.69209e+21

Expected output, e.g., if you change lines 167-169 in main.cpp to use ZIP instead of PIZ:

(639, 479).R = 0
(639, 479).R = 0

And the key procedure, if you'd rather reproduce it with your own loading / writing code is:

int main() {
    // Read the original image
    int width = 640, height = 480, numChannels = 4;
    int idx = CacheExrImage("../original.exr");
    float* data = new float[width * height * numChannels];
    CopyCachedExrLayer(idx, "default", data);

    std::cout << "(639, 479).R = " << data[479 * width * numChannels + 639 * numChannels] << std::endl;

    // Save under a new name with PIZ compression
    int rowStride = numChannels * width;
    WriteImageToExr(&data, &rowStride, width, height, &numChannels, 1, nullptr, "../test.exr");

    // Read the new image file
    idx = CacheExrImage("../test.exr");
    CopyCachedExrLayer(idx, "default", data);

    std::cout << "(639, 479).R = " << data[479 * width * numChannels + 639 * numChannels] << std::endl;

    // Save again, red dots will only appear in this new "test2.exr"
    WriteImageToExr(&data, &rowStride, width, height, &numChannels, 1, nullptr, "../test2.exr");

    return 0;
}

When I view the images with tev (which uses OpenEXR), then only test2.exr will have a row of red dots in the bottom right.

from tinyexr.

syoyo avatar syoyo commented on August 12, 2024

@pgrit Thanks! I can reproduce it(macOS + apple clang).

When I dump the pixel value after the decode,

...
val = 3.57681e-41
val = 6.67772e+21
val = 0
val = 6.69209e+21
val = 0
val = 6.69209e+21
val = 0
val = 6.69209e+21
...

It has too small and too large fp value.

The issue will be within PIZ compression or decompression. But finding the bug is difficult since the code is ported from rather old OpenEXR and add TinyEXR adds some fixes. The solution may be port PIZ compress/decompress routine from recent OpenEXR but it is a time-consuming task.

So, workaround so far is not to use PIZ compression 😃

FYI OpenMP was not related to the issue.

exrviewer : Ah, I meant exrdisplay program in OpenEXR package https://www.openexr.com/using.html

from tinyexr.

syoyo avatar syoyo commented on August 12, 2024

@pgrit FYI the issue seems exit in PIZ decode.

Decode attached PIZ compressed EXR in OpenEXR viewer(e.g. macOS Finder) : No issue
Decode attached PIZ compressed EXR in tinyexr and save it as NO_COMPRESSION: Has white-dot artifacts(in the last line of image)
Screen Shot 2021-07-23 at 2 20 05

piztest.exr.zip

from tinyexr.

pgrit avatar pgrit commented on August 12, 2024

I made a little Python script to generate images that produce the problem.

This seems to only happen if the image contains noisy data, and has a solid-color or black region on the right that is at least 60 pixels wide.

The lines are always in a scanline that is a multiple of 32 when counting from the top, i.e., the last of num_scanline_blocks for the PIZ encoding.

If I put a red pixel right next to where such an artifact dot would appear, the whole line goes away.

import OpenEXR
import Imath
import numpy as np
import simpleimageio as sio

width = 420
height = 32
border_left = 0
border_right = 420 - 80
num_splats = 10000

red = np.zeros((height, width), dtype=np.float32)
green = np.zeros((height, width), dtype=np.float32)
blue = np.zeros((height, width), dtype=np.float32)

# splat random color values
rng = np.random.default_rng()
row = rng.integers(low=0, high=height, size=num_splats)
col = rng.integers(low=border_left, high=border_right, size=num_splats)

# if any of the three channels has a fixed value, the problem goes away!
red[row, col] = rng.random(num_splats)
green[row, col] = rng.random(num_splats)
blue[row, col] = rng.random(num_splats)

# add a bunch of test pixels
red[-8, -10] = 1
green[-8, -10] = 1
blue[-8, -10] = 1

red[-4, -8] = 1
green[-4, -8] = 1
blue[-4, -8] = 1

red[-4, -2] = 1
green[-4, -2] = 1
blue[-4, -2] = 1

red[-2, -3] = 0 # setting this to anything other than 0 fixes the problem
green[-2, -3] = 1
blue[-2, -3] = 1

# fill in all of the black region with 0-red color
# red[:,border_right:] = 0
# green[:,border_right:] = 1
# blue[:,border_right:] = 1

# write PIZ compressed via OpenEXR
header = OpenEXR.Header(width, height)
header['compression'] = Imath.Compression(Imath.Compression.PIZ_COMPRESSION)
exr = OpenEXR.OutputFile("gen.exr", header)
exr.writePixels({'R': red.tobytes(), 'G': green.tobytes(), 'B': blue.tobytes()})
exr.close()

# read back in via tinyexr (used internally by simpleimageio)
tinyresult = sio.read("gen.exr")
sio.write("test2.exr", tinyresult)

image

from tinyexr.

pgrit avatar pgrit commented on August 12, 2024

@pgrit BTW simpleimageio is nice! You may be interested in https://github.com/syoyo/tinydngloader to support loading/saving 32bit FP TIFF images for simpleimageio

Thanks for the link! And nice work! Incorporating it was really quick and easy. Although the saving part is quite well hidden in the repo ;)

from tinyexr.

syoyo avatar syoyo commented on August 12, 2024

@pgrit Writer module is added later so code is not organized well and have less information about it. Added some comments in tinydngloader's README.

from tinyexr.

syoyo avatar syoyo commented on August 12, 2024

PR has been merged! #161

@pgrit Thank you for reporting the issue & creating reproducible scripts!

from tinyexr.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.