-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
ofPixels - artifacts / crashes with .resize() #6226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hello,
It would be nice to integrate this in the ofPixel class... |
Hey Julien, this was some time ago. I remember that Arturo had fixed some internal indexing vars to size_t (64 bit) at one point, the source of the issue. I cannot recall which OF version though. Probably of 0.10.1 with win10 vs2017. Which version do you work with? Does it appear at all sizes of images or above a 32bit threshold? Cheers M |
Hello Michael, |
Hello @janimatic can you please write the minimal code example that can reproduce the issue and post here? |
Hello @dimitre @johanjohan
|
Hey @dimitre @johanjohan ,
size_t bytesPerPixel = getBytesPerPixel(); by size_t bytesPerPixel = channelsFromPixelFormat(pixelFormat); would fix OF_INTERPOLATE_NEAREST_NEIGHBOR (renaming the variable accordingly of course) sizeof(int) was ok but sizeof(float) 4 would make it fail. I don't really understand why the pointer would use the size of pixel type to walk through color channels... I didn't check for OF_INTERPOLATE_BICUBIC though ! thanks |
PS :
But with this test
i am facing strange logged values from a simple
|
I'm proposing a simplification of channel / bytes handling here: |
Please test the PR to see if it works for you @janimatic pixelsSize = newSize / sizeof(PixelType); and pixelsSize = bytesFromPixelFormat(w,h,_pixelFormat) / sizeof(PixelType);
we should not divide the pixelsSize by the sizeof(PixelType), it works with char because it is / 1 (memory size of char) but it will cause problems with float etc, |
Hello @dimitre ,
Is my testing method incorrect?
I can create a tiny exr app quickly if that helps for a more concrete and visual testing. PS : I once wrote a template class to avoid dealing with pixels pointers arithmetic wich drive me nut when writing openfx cpu image effect plugins, without any allocation unless (requested). It was used with float image (in fusion) and arbitrary data type. Thank you very much for your great work !
|
I didnt' read everything yet, but some suggestions in your code: 2 - ofColor(1, 1, 1, 1) is almost black. maybe you wanted ofFloatColor(1, 1, 1, 1) |
And I've changed the NEAREST_NEIGHBOR code, but didn't test it. if you find it is wrong you can revert to OF core one. |
it seems to be working here : #include "ofMain.h"
//========================================================================
template <typename PixelType>
void resizeTest(int width, int height, int thumbnailProxy, ofInterpolationMethod interp, ofColor col) {
ofPixels_<PixelType> pixels;
pixels.allocate(width, height, OF_IMAGE_COLOR_ALPHA);
pixels.setColor(col);
{
ofColor color = pixels.getColor(pixels.getWidth() * .5, pixels.getHeight() * .5);
ofLogWarning() << color;
}
// ofLogWarning() << pixels.getColor(0);
// ofLogWarning() << int(pixels.getColor(0).r) << "," << int(pixels.getColor(0).g) << "," << int(pixels.getColor(0).b) << "," << int(pixels.getColor(0).a);
auto proxy = pixels;
proxy.resize(pixels.getWidth() / thumbnailProxy, pixels.getHeight() / thumbnailProxy, interp);
{
ofColor color = pixels.getColor(pixels.getWidth() * .5, pixels.getHeight() * .5);
ofLogWarning() << color;
}
// ofLogWarning() << color;
// ofLogWarning() << int(proxy.getColor(0).r) << "," << int(proxy.getColor(0).g) << "," << int(proxy.getColor(0).b) << "," << int(proxy.getColor(0).a);
}
int main() {
int thumbnailProxy = 16;
cout << "--- one" << endl;
resizeTest<unsigned char>(1920, 1080, thumbnailProxy, ofInterpolationMethod::OF_INTERPOLATE_NEAREST_NEIGHBOR, ofColor(255, 255, 0, 255));
cout << "--- two" << endl;
resizeTest<unsigned char>(1920, 1080, thumbnailProxy, ofInterpolationMethod::OF_INTERPOLATE_BICUBIC, ofColor(255, 255, 0, 255));
cout << "--- three" << endl;
resizeTest<float>(1920, 1080, thumbnailProxy, ofInterpolationMethod::OF_INTERPOLATE_NEAREST_NEIGHBOR, ofFloatColor(1, 1, 0, 1));
cout << "--- four" << endl;
resizeTest<float>(1920, 1080, thumbnailProxy, ofInterpolationMethod::OF_INTERPOLATE_BICUBIC, ofFloatColor(1, 1, 0, 1));
} |
@dimitre
|
@dimitre |
Thanks, let me know when you have the tests. you can try a minimal change to the core by finding "pixelsSize = " and removing sizeof() |
hello @dimitre
|
@janimatic can you please test this other PR? |
@dimitre hello!
![]() ![]()
That looks correct to me (see ofpixel_resize_exrPatch.png) ![]() I didn't check the OF_INTERPOLATE_BICUBIC... Thank you ! |
@dimitre
![]() |
To summarize, here is a diff of my changes made in #7936 diff --git a/libs/openFrameworks/graphics/ofPixels.cpp b/libs/openFrameworks/graphics/ofPixels.cpp
index 44a3f926e..d23f4eeaa 100644
--- a/libs/openFrameworks/graphics/ofPixels.cpp
+++ b/libs/openFrameworks/graphics/ofPixels.cpp
@@ -1328,7 +1328,8 @@ float ofPixels_<PixelType>::bicubicInterpolate (const float *patch, float x,floa
a20 * x2 + a21 * x2 * y + a22 * x2 * y2 + a23 * x2 * y3 +
a30 * x3 + a31 * x3 * y + a32 * x3 * y2 + a33 * x3 * y3;
- return std::min(static_cast<size_t>(255), std::max(static_cast<size_t>(out), static_cast<size_t>(0)));
+ //return std::min(static_cast<size_t>(255), std::max(static_cast<size_t>(out), static_cast<size_t>(0)));
+ return out;
}
//----------------------------------------------------------------------
@@ -1361,8 +1362,10 @@ bool ofPixels_<PixelType>::resizeTo(ofPixels_<PixelType>& dst, ofInterpolationMe
float srcx = 0.5;
size_t srcIndex = static_cast<size_t>(srcy) * srcWidth;
for (size_t dstx=0; dstx<dstWidth; dstx++){
- size_t pixelIndex = static_cast<size_t>(srcIndex + srcx) * bytesPerPixel;
- for (size_t k=0; k<bytesPerPixel; k++){
+ //size_t pixelIndex = static_cast<size_t>(srcIndex + srcx) * bytesPerPixel;
+ //for (size_t k=0; k<bytesPerPixel; k++){
+ size_t pixelIndex = static_cast<size_t>(srcIndex + srcx) * channelsFromPixelFormat(pixelFormat);
+ for (size_t k=0; k< channelsFromPixelFormat(pixelFormat); k++){
dstPixels[dstIndex] = pixels[pixelIndex];
dstIndex++;
pixelIndex++;
@@ -1391,19 +1394,19 @@ bool ofPixels_<PixelType>::resizeTo(ofPixels_<PixelType>& dst, ofInterpolationMe
size_t patchIndex;
float patch[16];
- size_t srcRowBytes = srcWidth*bytesPerPixel;
+ size_t srcRowBytes = srcWidth*channelsFromPixelFormat(pixelFormat);
size_t loIndex = (srcRowBytes)+1;
- size_t hiIndex = (srcWidth*srcHeight*bytesPerPixel)-(srcRowBytes)-1;
+ size_t hiIndex = (srcWidth*srcHeight*channelsFromPixelFormat(pixelFormat))-(srcRowBytes)-1;
for (size_t dsty=0; dsty<dstHeight; dsty++){
for (size_t dstx=0; dstx<dstWidth; dstx++){
- size_t dstIndex0 = (dsty*dstWidth + dstx) * bytesPerPixel;
+ size_t dstIndex0 = (dsty*dstWidth + dstx) * channelsFromPixelFormat(pixelFormat);
float srcxf = srcWidth * (float)dstx/(float)dstWidth;
float srcyf = srcHeight * (float)dsty/(float)dstHeight;
size_t srcx = static_cast<size_t>(std::min(srcWidth-1, static_cast<size_t>(srcxf)));
size_t srcy = static_cast<size_t>(std::min(srcHeight-1, static_cast<size_t>(srcyf)));
- size_t srcIndex0 = (srcy*srcWidth + srcx) * bytesPerPixel;
+ size_t srcIndex0 = (srcy*srcWidth + srcx) * channelsFromPixelFormat(pixelFormat);
px1 = srcxf - srcx;
py1 = srcyf - srcy;
@@ -1412,14 +1415,14 @@ bool ofPixels_<PixelType>::resizeTo(ofPixels_<PixelType>& dst, ofInterpolationMe
py2 = py1 * py1;
py3 = py2 * py1;
- for (size_t k=0; k<bytesPerPixel; k++){
+ for (size_t k=0; k<channelsFromPixelFormat(pixelFormat); k++){
size_t dstIndex = dstIndex0+k;
size_t srcIndex = srcIndex0+k;
for (size_t dy=0; dy<4; dy++) {
patchRow = srcIndex + ((dy-1)*srcRowBytes);
for (size_t dx=0; dx<4; dx++) {
- patchIndex = patchRow + (dx-1)*bytesPerPixel;
+ patchIndex = patchRow + (dx-1)*channelsFromPixelFormat(pixelFormat);
if ((patchIndex >= loIndex) && (patchIndex < hiIndex)) {
srcColor = pixels[patchIndex];
}
|
PS : |
in the the zip file , |
@dimitre |
oops, you're right the copy doesn't copy the correct channel for alpha... |
new image link appear as uploading here |
well i am not sure it works at all in float if not using channels instead of bytes...
|
Yes I was suggesting mergin only the pixelsSize issue for now, so I'll be able to test on master later. |
now copy looks OK 🖼️ |
yes that's fine for me if you prefer to merge only the pixelsSize for now, even if we know that it creates a channel offset in resize. |
@dimitre
That ensure that there won't be any regression. |
@janimatic yes, PR updated. |
@janimatic I suggest two separate PRs. |
Hello @janimatic PR was just merged. Feel free to open another PR with resize fixes |
@janimatic can you please make a PR with your patch, so we can test it ? |
hello guys, thank you for fixing this after such a long time. |
Now merged. can you please test with the latest master to see if this issue can be closed? |
@janimatic I've added your code for testing exr, tiff, png images with some changes to this repo it would be great if we could maybe support some different bit depth in ofImage. EDIT: feel free to push changes there |
This is wicked!!! Yeah let's get CI on this ofTests. OpenEXR issues looking patched on FreeImage SVN upstream, I'll port those into the Patched Repo. |
@dimitre
|
Great! it will be amazing if OF could handle more image formats and bit depth. Even simple tests like opening your tiff file is failing, so maybe there is more work needed on OF core |
I think the place to have a look is |
@dimitre, HDR loading should be supported, not sure about saving though. |
yess. I suppose it can be done now allocating the right kind of ofPixels and using ofLoadImage right? EDIT: My bad, there was no GLFW window on tests, so no OpenGL context for textures |
Yeah, check out here for loading into a texture.
I had to do some checks for OPENGL_ES since some versions or platforms didn't like GL_RGB32F and values over a certain limit would cause strange issues.
|
Using ofLoadImage( texture, "img.hdr" ) to load a texture should be supported as well. openFrameworks/libs/openFrameworks/graphics/ofImage.cpp Lines 361 to 382 in 638a6cb
|
@janimatic I've updated your tests and pushed code to ofTests repo. |
@dimitre
|
@dimitre |
I think this issue can be tested again with latest master so we know if it can be closed already |
Since ofPixels.cpp has not been updated for over a year in the master branch, i therefore assume the following issue has not been fixed. i am using of 0.10.1 with win10 vs2017.
I am resizing images/pixels with the following function.
That leads to issues:
calling the same function using image.resize() produces best results
question: i assume that i may use pixelsRes = _pixels; to create a full twin copy, right?
if yes, then there is the described issue in the pixel resizeTo() function.
CODE:
The text was updated successfully, but these errors were encountered: