Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Iterating over pixels in QImage (Qt): which method adapts better for any image size?
I asked this in SE years ago.
I'm aware of two methods in order to access all the pixels in a QImage
called img
.
Method 1
for (int y = 0; y < img.height(); y++) {
QRgb *line = (QRgb *) img.scanline(y);
for (int x = 0; x < img.width(); x++) {
// line[x] has an individual pixel
line[x] = QColor(255, 128, 0).rgb();
}
}
Method 2
QRgb *st = (QRgb *) img.bits();
quint64 pixelCount = img.width() * img.height();
for (quint64 p = 0; p < pixelCount; p++) {
// st[p] has an individual pixel
st[p] = QColor(255, 128, 0).rgb();
}
I'm keen on using the second method as it only involves one loop, but am also concerned about any possible overflows on pixelCount
if processing a "big enough" image.
Given this situation, I would like to ask:
What is the most "scalable" way to iterate over all pixels stored in a QImage? By scalable I mean that it will still work no matter what the image dimensions (width and height) are.
NOTE: I'm already aware there are "physical" limits in terms of memory usage. I just want to know whether both methods are capable of reaching such a limit.
1 answer
If your only concern is overflowing the 64-bit pixelCount
value, you can safely forget about it. By the time you are processing an image with 18 quintillion (2^64
) pixels, you will have bigger problems than a simple loop counter. The largest images produced so far are approaching 1 terapixel (10^12
pixels), and you'd need 18 million of these to get anywhere near the limit of a 64-bit value. All the data centers of Google and Facebook combined probably couldn't store such a large image, and no computer in the world could load it into memory as a QImage that you can process pixel-by-pixel. Even if you could load it, iterating over its pixels one at a time would take over 140 years, assuming your loop runs on a 4 GHz CPU and requires at least one clock cycle per iteration.
The more relevant danger with the pixelCount approach is that there is no guarantee that the lines of the image are stored "packed" in memory: in other words, the final pixel of line 0 might not be immediately followed by the first pixel of line 1. There might be some padding bytes in between, especially if the image has an odd size like 639x451 and the QImage implementation wants to keep line start addresses aligned to 4-byte (or greater) boundaries. If this is the case, then your assumption that you can treat the 2D image as a 1D array will not hold, and your loop will end up reading a certain amount of garbage data.
For this reason, I would recommend processing the image one scanline at a time, unless you know that successive scanlines are packed together without any padding.
0 comment threads