Comments (10)
@pgrit Thanks! After debugging TinyEXR and OpenEXR(recent main
branch). I found the issue was in TinyEXR.
The issue was introduced in
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.
@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.
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
from tinyexr.
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.
@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.
@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)
from tinyexr.
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)
from tinyexr.
@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.
@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.
PR has been merged! #161
@pgrit Thank you for reporting the issue & creating reproducible scripts!
from tinyexr.
Related Issues (20)
- heap overflow in tinyexr::DecodePixelData HOT 8
- Heap-buffer-overflow still exists in the rleUncompress HOT 3
- Warnings when compiling with VS2019 and W3 (32 bit) HOT 5
- Windows install HOT 1
- Heap-buffer-overflow exists in the DecompressPiz HOT 2
- Heap-buffer-overflow exists in the DecodePixelData HOT 2
- [TODO] Support nested layer name
- Got "-Wreserved-identifier" compiler warning when compiling with Clang-13.0.1 HOT 4
- Use wuffs for fast & secure ZIP/LZW decoding/encoding HOT 3
- UBSan issue when loading an .exr HOT 2
- compilation error on 1.0.1 with ZFP HOT 2
- "Failed to read attribute" error message on Big Endian platform? HOT 2
- [TODO] Setup Github Actions CI build
- memory error in tinyexr::InitSingleResolutionOffsets HOT 3
- [TODO] [Improve Security] Remove assert HOT 1
- PIZ decompression error with tinyexr 1.0.2 HOT 5
- Three Bugs in tinyexr.h HOT 2
- [TODO] Memory limit feature HOT 4
- SEGV on unknown address in tinyexr.h:5779 HOT 2
- allocator is out of memory HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from tinyexr.