Dividing QImage to smaller pieces
Asked Answered
B

3

7

I have an image, and I want to divide this image to n pieces. So what I'm wondering is that how can I do this with QImage? Or is there a better(performance wise) Qt class for this task?

For example imagine I have an image consist of 1920x1080 pixels, and I want to divide it to 100 pieces which means each piece will consist of 192x108 pixels. Note that I don't want to create same piece scaled to 192x108. Each piece is a distinct piece of the main picture.

enter image description here

I have attached an Image to make my question clearer. This image consist of 1920x1080 pixels and each part dived with grids consists of 192x108 pixels, I want to treat each of them as QImage object without actually dividing it to 100 pieces.

Is there a way to do this with QImage? Performance is important here because I'll analyze each piece and usually there is going to be more than 1000 piece.

Thank you for your help!

EDIT: Both methods work perfectly, however alexisdm's method is bit more complex, lower-level, but faster. jmk's method is easier to use but it's slower.

Thanks for both answers.

Boomerang answered 1/10, 2012 at 21:43 Comment(0)
P
14

You can create a QImage without copying any data by using the same stride (bytes per line) and format as the source image and passing the raw data buffer, with an offset corresponding to the desired starting position, to one of the constructors of QImage:

QImage createSubImage(QImage* image, const QRect & rect) {
    size_t offset = rect.x() * image->depth() / 8
                    + rect.y() * image->bytesPerLine();
    return QImage(image->bits() + offset, rect.width(), rect.height(),
                  image->bytesPerLine(), image->format());
}

The source image must exist as long as the sub QImage exists.

But it might not work if the analyzing code tries to access the image raw data directly without using QImage::bytesPerLine(), QImage::scanLine() or QImage::pixel().

Preliminaries answered 1/10, 2012 at 22:28 Comment(2)
This is perfect, thanks a lot! just what I was looking for, but I'm very new to image processing and I don't quite understand why you're dividing depth to 8, I'm guessing its because each color channel is 8-bit is that why you're dividing depth to 8?Boomerang
The QImage documentation for depth() states that it returns the number of bits per pixel. The first argument, a pointer to the raw data, must be incremented by an offset specified in bytes, which is why you divide by 8.Vic
V
3

You can accomplish this by creating new QImage objects of the desired dimensions, then drawing the appropriate pieces of the source image into them. To do this, create a QPainter from the empty target image, and use the drawImage() method to copy a specific sub-rectangle.

If performance is important, however, you might want to look at ways to avoid unnecessary copies of your source image. For example, if your algorithm only needs to look at a 192x108 piece of the picture at a time, could it just limit its analysis to a particular sub-rectangle of the original image?

If you can restructure your code this way, you can avoid creating additional images entirely.

Vic answered 1/10, 2012 at 21:51 Comment(2)
Thanks! That's a great idea, I haven't used QPainter before so I didn't know I could do that with it. Actually my algorithm will never create additional images because after analyzing each piece, I'll destroy that QImage object and move on to the next one, so I'll never store the pieces however I need to treat them as QImage because I want to use QImage functions to analyze the piece.Boomerang
I have a class to attend to but I'll try your method as soon as I come home and will accept the answer if it works for me. Thanks again!Boomerang
P
3

You can use built-in function QImage QImage::copy(const QRect &part) that creates subimage.

Precast answered 12/9, 2014 at 18:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.