-
Notifications
You must be signed in to change notification settings - Fork 293
Fix case where cropping could be wrong #1941
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
base: release/0.7.1
Are you sure you want to change the base?
Fix case where cropping could be wrong #1941
Conversation
This assumes that every scanline is contiguous in memory and tightly packed with width pixels — i.e., that bytesPerLine() == width * sizeof(QRgb). However, QImage does not ensure that this is the case. Each scanline may have padding, so bytesPerLine() can potentially be greater than width * sizeof(QRgb). Leading to incorrect cropping.
0a58329 to
7e8121b
Compare
|
I think this is a more correct way to iterate over the pixels given that I can't find anything in the QImage documentation explicitly saying what the layout of the QImage data buffer is. So I am in favor of this change. However, I don't think there's any chance this will fix the problem of #1940. This code will only behave differently than the original code if
In all cases, nothing would result in a translation of the frame. If autocropping was the cause of that issue, I think the cause would have to be in |
| // relBottom+1 to mBounds.height() have already been | ||
| // confirmed to contain only transparent pixels | ||
| for (int row = relTop; row <= relBottom; row++) | ||
| // Loop through each row between relTop and relBottom |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're going to call constScanLine for what is effectively every pixel tested in the left and right side cropping, I'm wondering if it might be faster to do something like this (pseudocode):
minLeft = image.width;
for (y = 0; y < image.height; y++) {
cursor = image.constScanLine(y);
for (column = 0; column < minLeft; column++) {
if (qAlpha(*cursor) != 0) {
minLeft = column;
break;
}
cursor++;
}
}
In words, it's finding the minimum span of transparent pixels at the start/end of each row. With this we would only need to call constScanLine once per row (per side probably) instead of once per pixel. There might also be benefits from the sequential memory access. However for certain shapes this will end up iterating over more pixels overall (in a bad case imagine an upside down "T" that fills the image).
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking that we should probably test out if it would be worth the added complexity before making such a change but it's an interesting thought that might be worth looking into.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Autocrop gets called quite frequently (though most of those calls will probably exit early with the mMinBound check) so I think it's worth looking into potential performance improvements. Benchmarking is the way to go, but I'm not sure what a representative sample of test cases would look like.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may not have to be called so often anymore though since we now have the tiled buffer to draw the stroke. The image should ideally only have to be modified on ScribbleArea::endStroke (when the scenario is drawing on the canvas).
I'd really like to be able to get rid of the many autocrop calls from within BitmapImage, in order to get a clearer picture of when we actually need to modify the image.
A potential fix for #1940
Though i haven't been able to reproduce the behavior myself. I looked into the cropping method, took a deep dive into QImage and noticed the way we move the cursor, which could lead to this kind of issue.
I suspect that the bug is related to the auto cropping logic, as the user points out it happens after the project has been saved and re-opened.
By going through scanline for each column, we ensure that image is traversed correctly, no matter the padding.