draw graphics over kinect video image in processing 3.0 - computer-vision

I am working through Greg Borenstein's book "Making Things See" and have figured out how to create a cursor that tracks the movement of the closest thing to the Kinect. Right now the cursor is a simple red ball. So I am able to track my finger over
image(kinect.getVideoImage(), 0, 0)
I have also created buttons that apply a filter to the video image when I put the cursor ball in the area of the button.
Its kind of fun but the novelty has run out so now I want to turn the cursor ball into an animated graphic using particles or something fun like that. This animated graphic should still track my finger and be drawn over the video image.
When I try to write this, the graphic comes out wrong because the video image keeps redrawing over the particles so it doesn't look right.
I was thinking I could use the capture() method to draw the video image under the graphics but I can't figure out how to do it with video from the Kinect.
Does anyone have any ideas on how I could do this? Any help would be greatly appreciated.
A sample of my kinect tracker and filter button is below. If you copy and paste it into processing and have a kinect plugged in it should run. my apologies for the code's lack of eloquence. I'm still learning how to make beautiful code.
Instead of filters, I would like to trigger a new graphic for the red ball maybe apply particles or something.
//my kinect tracker
import org.openkinect.freenect.*;
import org.openkinect.processing.*;
Kinect kinect;
boolean ir = true;
boolean colorDepth = true;
boolean mirror = true;
float closestValue;
float closestX;
float closestY;
// create arrays to store recent closest x- and y-coordinates for averaging
int[] recentXValues = new int[3];
int[] recentYValues = new int[3];
// keep track of which is the current value in the array to be changed
int currentIndex = 0;
float circleButtonX, circleButtonY; // position of circle button
float circleButtonSize; // diameter of circle button
color circleButtonColor; // color of circle button
void setup() {
size(640, 480, P3D);
kinect = new Kinect(this);
kinect.initDepth();
kinect.initVideo();
//kinect.enableIR(ir);
kinect.enableMirror(mirror);
kinect.enableColorDepth(colorDepth);
circleButtonColor = color(0, 0, 255);
}
void draw() {
closestValue = 1700;
int[] depthValues = kinect.getRawDepth();
for(int y = 0; y < 480; y++) {
for(int x = 0; x < 640; x++) {
int i = x + y * 640;
int currentDepthValue = depthValues[i];
if(currentDepthValue > 0 && currentDepthValue < closestValue) {
//save its value
closestValue = currentDepthValue;
recentXValues[currentIndex] = x;
recentYValues[currentIndex] = y;
}
}
}
currentIndex++;
if(currentIndex > 2) {
currentIndex = 0;
}
// closetX and ClosestY become a running average
// with currentX and CurrentY
closestX = (recentXValues[0] + recentXValues[1] + recentXValues[2]) / 3;
closestY = (recentYValues[0] + recentYValues[1] + recentYValues[2]) / 3;
//draw the depth image on the screen
image(kinect.getVideoImage(), 0, 0);
fill(0, 0, 250);
ellipse(75, 75, 100, 100);
ellipse(200, 75, 100, 100);
ellipse(75, 200, 100, 100);
rect(540, 25, 75, 100);
//buttons
fill(255,0,0);
textSize(24);
text("Invert", 40, 85);
text("Blur", 50, 210);
textSize(18);
text("Threshold", 155, 85);
text("Stop", 560, 75);
ellipse(closestX, closestY, 25, 25);
if (closestX > 25 && closestX < 125 && closestY > 25 && closestY < 125) {
filter(INVERT);
};
if (closestX > 150 && closestX < 250 && closestY > 25 && closestY < 125) {
filter(THRESHOLD);
};
if (closestX > 25 && closestX < 125 && closestY > 150 && closestY < 250) {
filter(BLUR, 6);
};
if (closestX > 540 && closestX < 615 && closestY > 25 && closestY < 100) {
noLoop();
loop();
background(0);
};

I believe you're asking how to create a particle trail in Processing. This doesn't really have anything to do with kinect- a simple call to background() would also draw over any of your particles. So you currently have something like this:
void setup(){
size(500, 500);
}
void draw(){
background(0);
ellipse(mouseX, mouseY, 10, 10);
}
You're drawing something to the screen (in your code, a red ball, in my code, an ellipse), but it's cleared away (in your code, the kinect video, in my code, a call to background(0)). You're asking how to make it so the ellipse stays on the screen even after you draw the background.
The answer is this: You need to store the positions of your trail in a data structure and then redraw them every frame.
A simple way to do that is to create an ArrayList of PVector instances. To add a particle to the trail, you just add a PVector to the ArrayList. And then you just iterate over the trail and draw every PVector point.
ArrayList<PVector> trail = new ArrayList<PVector>();
void setup(){
size(500, 500);
}
void draw(){
background(0);
//add to the trail
trail.add(new PVector(mouseX, mouseY));
//draw the trail
for(PVector p : trail){
ellipse(p.x, p.y, 10, 10);
}
}
However, this trail will constantly grow, and you'll eventually run out of memory to hold every point. So to keep your trail from doing that, you need to limit its size:
ArrayList<PVector> trail = new ArrayList<PVector>();
void setup(){
size(500, 500);
}
void draw(){
background(0);
//add to the trail
trail.add(new PVector(mouseX, mouseY));
if(trail.size() > 10){
//trail is too long, remove the oldest point
trail.remove(0);
}
//draw the trail
for(PVector p : trail){
ellipse(p.x, p.y, 10, 10);
}
}
From here you can do fancier things: give each point in your trail a momentum or a color, or fade it out, or decrease its width. But the basics are this: you have to store the particles in a data structure, update that data structure to add or remove particles, and then iterate over that data structure to draw the trail.

Related

Rendering in Vertical Layout fails to occur

I am trying to create a timeline app for visualization of certain time-sensitive requirements information and have begun experimentation with Qt since I am new to it. The problem I am having is that the rendered object will show up if I render it just basically on the main background, but when I tried to add the TimeLine objects to the vertical layout I have on my UI they refuse to render.
Here is my main window code for creating the objects:
void MainWindow::drawTimelines()
{
for(int i=0; i <= 3; i++)
{
TimeLine *tl = new TimeLine(this, this);
// ui->verticalLayout->addWidget(tl, 0, Qt::AlignLeft);
tl->lower();
QPoint * dest = new QPoint(this->width() - (this->width() / 12), i * this->height() / 4 + this->height() / 4);
QPoint * src = new QPoint(this->width() / 12, i * this->height() / 4 + this->height() / 4);
// tl->setGeometry(0, 0, this->width(), 100);
tl->setGeometry(src->x(), src->y(), this->width(), 100);
tl->updateGeometry();
QPoint *startPt = new QPoint(src->x(), 50);
QPoint *endPt = new QPoint(dest->x(), 50);
// QPoint *src = new QPoint(this->width() /8, 50);
// QPoint *dest = new QPoint(this->width() - (this->width() / 8), 50);
tl->setSrcPt(startPt);
tl->setDestPt(endPt);
tl->setNumSegments(3);
timeLineList.push_back(tl);
timeLineList.at(i)->show();
}
update();
}
Here is the maint function present in the TimeLine object itself:
void TimeLine::paintEvent(QPaintEvent * event)
{
QRectF frame(QPointF(sourcePoint->x(), sourcePoint->y()), geometry().size());
QPainter painter(this);
painter.setPen(QPen(Qt::FlatCap));
painter.drawRoundedRect(frame, 10.0, 10.0);
int translateAmount = sourcePoint->y() - window->getPainterY();
painter.translate(0, translateAmount);
// window->setPainterY(translateAmount);
painter.drawLine(sourcePoint->x(), 25, destPoint->x(), 25);
for(int i = 0; i <= numSegments; i++){
int xPoint = ((destPoint->x() - sourcePoint->x()) * i / numSegments) + sourcePoint->x();
int yPoint = 25;
painter.drawLine(xPoint, yPoint + 20, xPoint, yPoint - 20);
}
QWidget::paintEvent(event);
}
For reference, the verticalLayout is meant to have one
The TimeLines (and bounded rect boxes) do not render when I have the
// ui->verticalLayout->addWidget(tl, 0, Qt::AlignLeft);
uncommented. As you can see from a bunch of the other commented lines, I have tried numerous other things to try and render these TimeLines. I have tried:
changing reference points of the geometry to be (0,0) for the new segment of the vertical layout
changing the size of the geometry
both translating and not translating the painter
changing line thickness, type of line, etc.
even tried rendering something else simple in the vertical layout
The part that confuses me is that even the bounded rect made based on the geometry of the TimeLine frame gets cut off on the side and top of the timeline (it only shows top left corner and the top and left side-lines) even when rendered on the normal screen.

Draw using textured QBrush without translating texture

I have made a simple texture of an outlined box and have the following snippet of code which draws a checkerboard pattern:
scene.setSceneRect(0, 0, 1000, 1000);
ui->g_view->setScene(&scene);
QPixmap texture("block.png");
QBrush brush(texture);
int count = 0;
for(int x=0; x<1000; x += 50) {
for(int y=0; y<1000; y += 50) {
if (count % 2 == 0) {
scene.addRect(x, y, 50, 50, Qt::NoPen, brush);
}
count++;
}
// Offset rows by 1
count++;
}
This works fine:
However, when I modify the code so that the boxes are drawn "off grid":
scene.addRect(x + 5, y + 5, 50, 50, Qt::NoPen, brush);
The following output is produced:
What I expected to happen was that each call to addRect would draw the texture starting from the top corner each time.
However, for some reason qt translates the texture using the location that it is being drawn too, almost like the texture is infinitely tiled in the background and addRect is just cutting away a window.
How can I make drawRect behave as I expected, i.e. no matter what the values of x and y are the texture is always drawn from the top left corner.
Edit: block.png
I solved this issue by instead using the addPixmap method.
//scene.addRect(x + 5, y + 5, 50, 50, Qt::NoPen, brush);
QGraphicsPixmapItem *pix_map = scene.addPixmap(texture);
pix_map->setPos(x + 5, y + 5);

How to solve performance issues with QPixmap (large drawingjobs)?

I am coding a small map editor (with rectangle tiles) and I need a way to draw a large amount of images OR one big image. The application is simple: You draw images on an empty screen with your mouse and when you are finished you can save it. A tile consists of a small image.
I tried out several solutions to display the tiles:
Each tile has its own QGraphicsItem (This works until you have a
1000x1000 map)
Each tile gets drawn on one big QPixmap (This means a very large image. Example: Map with 1000x100 and each tile has a size of 32x32 means that the QPixmap has a size of 32000x32000. This is a problem for QPainter.)
The current solution: Iterate through width & height of the TileLayer and draw each single tile with painter->drawPixmap(). The paint() method of my TileLayer looks like this:
void TileLayerGraphicsItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option,QWidget* /*widget*/)
{
painter->setClipRect(option->exposedRect);
int m_width=m_layer->getSize().width();
int m_height=m_layer->getSize().height();
for(int i=0;i<m_width;i++)
{
for(int j=0;j<(m_height);j++)
{
Tile* thetile=m_layer->getTile(i,j);
if(thetile==NULL)continue;
const QRectF target(thetile->getLayerPos().x()*thetile->getSize().width(),thetile->getLayerPos().y()*thetile->getSize().height(),thetile->getSize().width(),thetile->getSize().height());
const QRectF source(0, 0, thetile->getSize().width(), thetile->getSize().height());
painter->drawImage(target,*thetile->getImage(),source);
}
}}
This works for small maps with 100x100 or even 1000x100 tiles. But not for 1000x1000. The whole application begins to lag, this is of course because I have a for loop that is extremely expensive. To make my tool useful I need to be able to make at least 1000x1000 tilemaps without lags. Does anyone have an idea what I can do? How should I represent the tiles?
Update:
I changed the following: Only maps that exceed the window size of the minimap will be drawn with drawing single pixels for each tile. This is my render function now:
void RectangleRenderer::renderMinimapImage(QPainter* painter, TileMap* map,QSize windowSize)
{
for(int i=0;i<map->getLayers().size();i++)
{
TileLayer* currLayer=map->getLayers().at(i);
//if the layer is small draw it completly
if(windowSize.width()>currLayer->getSize().width()&&windowSize.height()>currLayer->getSize().height())
{
...
}
else // This is the part where the map is so big that only some pixels are drawn!
{
painter->fillRect(0,0,windowSize.width(),windowSize.height(),QBrush(QColor(map->MapColor)));
for(float i=0;i<windowSize.width();i++)
for(float j=0;j<windowSize.height();j++)
{
float tX=i/windowSize.width();
float tY=j/windowSize.height();
float pX=lerp(i,currLayer->getSize().width(),tX);
float pY=lerp(j,currLayer->getSize().height(),tY);
Tile* thetile=currLayer->getTile((int)pX,(int)pY);
if(thetile==NULL)continue;
QRgb pixelcolor=thetile->getImage()->toImage().pixel(thetile->getSize().width()/2,thetile->getSize().height()/2);
QPen pen;
pen.setColor(QColor::fromRgb(pixelcolor));
painter->setPen(pen);
painter->drawPoint(i,j);
}
}
}
}
This works not correct, however it is pretty fast. The problem is my lerp(linear interpolation) function to get the correct tiles to draw a pixel from.
Does anyone have a better solution to get the correct tiles while I iterate through the minimap pixels? At the moment I use linear interpolation between 0 and the maximum size of the tilemap and it does not work correctly.
UPDATE 2
//currLayer->getSize() returns how many tiles are in the map
// currLayer->getTileSize() returns how big each tile is (32 pixels width for example)
int raw_width = currLayer->getSize().width()*currLayer->getTileSize().width();
int raw_height = currLayer->getSize().height()*currLayer->getTileSize().height();
int desired_width = windowSize.width();
int desired_height = windowSize.height();
int calculated_width = 0;
int calculated_height = 0;
// if dealing with a one dimensional image buffer, this ensures
// the rows come out clean, and you don't lose a pixel occasionally
desired_width -= desired_width%2;
// http://qt-project.org/doc/qt-5/qt.html#AspectRatioMode-enum
// Qt::KeepAspectRatio, and the offset can be used for centering
qreal ratio_x = (qreal)desired_width / raw_width;
qreal ratio_y = (qreal)desired_height / raw_height;
qreal floating_factor = 1;
QPointF offset;
if(ratio_x < ratio_y)
{
floating_factor = ratio_x;
calculated_height = raw_height*ratio_x;
calculated_width = desired_width;
offset = QPointF(0, (qreal)(desired_height - calculated_height)/2);
}
else
{
floating_factor = ratio_y;
calculated_width = raw_width*ratio_y;
calculated_height = desired_height;
offset = QPointF((qreal)(desired_width - calculated_width)/2,0);
}
for (int r = 0; r < calculated_height; r++)
{
for (int c = 0; c < calculated_width; c++)
{
//trying to do the following: use your code to get the desired pixel. Then divide that number by the size of the tile to get the correct pixel
Tile* thetile=currLayer->getTile((int)((r * floating_factor)*raw_width)/currLayer->getTileSize().width(),(int)(((c * floating_factor)*raw_height)/currLayer->getTileSize().height()));
if(thetile==NULL)continue;
QRgb pixelcolor=thetile->getImage()->toImage().pixel(thetile->getSize().width()/2,thetile->getSize().height()/2);
QPen pen;
pen.setColor(QColor::fromRgb(pixelcolor));
painter->setPen(pen);
painter->drawPoint(r,c);
}
}
Trying to reverse engineer the example code, but it still does not work correctly.
Update 3
I tried (update 1) with linear interpolation again. And while I looked at the code I saw the error:
float pX=lerp(i,currLayer->getSize().width(),tX);
float pY=lerp(j,currLayer->getSize().height(),tY);
should be:
float pX=lerp(0,currLayer->getSize().width(),tX);
float pY=lerp(0,currLayer->getSize().height(),tY);
That's it. Now it works.
This shows how to do it properly. You use a level of detail (lod) variable to determine how to draw the elements that are currently visible on the screen, based on their zoom.
http://qt-project.org/doc/qt-5/qtwidgets-graphicsview-chip-example.html
Also don't iterate through all the elements that could be visible, but only go through the ones that have changed, and of those, only the ones that are currently visible.
Your next option to use is some other manual caching, so you don't have to repeatedly iterate through O(n^2) constantly.
If you can't optimize it for QGraphicsView/QGraphicsScene... then OpenGL is probably what you may want to look into. It can do a lot of the drawing and caching directly on the graphics card so you don't have to worry about it as much.
UPDATE:
Pushing changes to QImage on a worker thread can let you cache, and update a cache, while leaving the rest of your program responsive, and then you use a Queued connection to get back on the GUI thread to draw the QImage as a Pixmap.
QGraphicsView will let you know which tiles are visible if you ask nicely:
http://qt-project.org/doc/qt-5/qgraphicsview.html#items-5
UPDATE 2:
http://qt-project.org/doc/qt-5/qtwidgets-graphicsview-chip-chip-cpp.html
You may need to adjust the range of zooming out that is allowed on the project to test this feature...
Under where it has
const qreal lod = option->levelOfDetailFromTransform(painter->worldTransform());
if (lod < 0.2) {
if (lod < 0.125) {
painter->fillRect(QRectF(0, 0, 110, 70), fillColor);
return;
}
QBrush b = painter->brush();
painter->setBrush(fillColor);
painter->drawRect(13, 13, 97, 57);
painter->setBrush(b);
return;
}
Add in something like:
if(lod < 0.05)
{
// using some sort of row/col value to know which ones to not draw...
// This below would only draw 1/3 of the rows and 1/3 of the column
// speeding up the redraw by about 9x.
if(row%3 != 0 || col%3 != 0)
return;// don't do any painting, return
}
UPDATE 3:
Decimation Example:
// How to decimate an image to any size, properly
// aka fast scaling
int raw_width = 1000;
int raw_height = 1000;
int desired_width = 300;
int desired_height = 200;
int calculated_width = 0;
int calculated_height = 0;
// if dealing with a one dimensional image buffer, this ensures
// the rows come out clean, and you don't lose a pixel occasionally
desired_width -= desired_width%2;
// http://qt-project.org/doc/qt-5/qt.html#AspectRatioMode-enum
// Qt::KeepAspectRatio, and the offset can be used for centering
qreal ratio_x = (qreal)desired_width / raw_width();
qreal ratio_y = (qreal)desired_height / raw_height();
qreal floating_factor = 1;
QPointF offset;
if(ratio_x < ratio_y)
{
floating_factor = ratio_x;
calculated_height = raw_height*ratio_x;
calculated_width = desired_width;
offset = QPointF(0, (qreal)(desired_height - calculated_height)/2);
}
else
{
floating_factor = ratio_y;
calculated_width = raw_width*ratio_y;
calculated_height = desired_height;
offset = QPointF((qreal)(desired_width - calculated_width)/2);
}
for (int r = 0; r < calculated_height; r++)
{
for (int c = 0; c < calculated_width; c++)
{
pixel[r][c] = raw_pixel[(int)(r * floating_factor)*raw_width][(int)(c * floating_factor)];
}
}
Hope that helps.

How to duplicate sprite of sprites in cocos2d-x 2.1.4

Well, my question is simple, I'm starting with cocos2d-x programming and I'm trying to make a tiled infinite background, lets say I have a png of an image I want to repeat infinitely as a background, What I did was that I created a Sprite as a container, then I added sprites with the same image, one aside the next, covering about 110% the screen, then, following the Space game tutorial I created the same sprite of sprites once again as a second background and I use it as two large identical images to scroll infinite... it works perfect... but I'm wondering if it is possible to create the second sprite by just copying the frist. Some code maybe will clear my situation:
this goes in the init():
acum = 0.0;
city1 = CCSprite::create();
for(int i = 0; i < 12; ++i) {
CCSprite *city = CCSprite::createWithSpriteFrameName("env_buildings_background2.png");
city->setPosition(ccp(acum, 0));
city1->addChild(city);
acum+= city->getContentSize().width*0.99;
}
city1->setContentSize(ccp(acum, 0));
city2 = CCSprite::create();
acum = 0.0;
for(int i = 0; i < 12; ++i) {
CCSprite *city = CCSprite::createWithSpriteFrameName("env_buildings_background2.png");
city->setPosition(ccp(acum, 0));
city2->addChild(city);
acum+= city->getContentSize().width*0.99;
}
city2->setContentSize(ccp(acum, 0));
_backgroundNode->addChild(city1, -1 , buildingspeed, ccp(0, winSize.height * 0.6));
_backgroundNode->addChild(city2, -1 , buildingspeed, ccp(city1->getContentSize().width, winSize.height * 0.6));
printf("%f - %f\n", city1->getContentSize().width, city2->getContentSize().width);
The main problem is here, where I need to create city2 from city1 and not just repeat code... is there a way to do this? I don't see a constructor in CCSprite that allows me to do so...
this goes in the update():
CCArray *cities = CCArray::createWithCapacity(2);
cities->addObject(city1);
cities->addObject(city2);
for ( int ii = 0; ii <cities->count(); ii++ ) {
CCSprite * city = (CCSprite *)(cities->objectAtIndex(ii));
float xPosition = _backgroundNode->convertToWorldSpace(city->getPosition()).x;
float size = city->getContentSize().width;
if ( xPosition < -size ) {
_backgroundNode->incrementOffset(ccp(city->getContentSize().width*2,0),city);
}
}
I will appreciate any help, thanks in advance.
This code will create the exact snapshot of your citySprite. And as this is a snapshot, you'll be having no access to the sprites that it contains. Cause they are now embedded in the image or sprite itself.
float citySpriteWidth = 480;
float citySpriteHeight = 320;
//Set position in order to make it fit inside CCRenderTexture (You can change this later)
citySprite->setPosition(ccp(citySpriteWidth/2, citySpriteHeight/2));
CCRenderTexture *render = CCRenderTexture::renderTextureWithWidthAndHeight(citySpriteWidth, citySpriteWidth);
render->beginWithClear(0, 0, 0, 0);
citySprite->visit();
render->end();
CCTexture2D *tex = render->getSprite()->getTexture();
CCSprite *newCitySprite = CCSprite::spriteWithTexture(tex);
newCitySprite->setFlipY(true); //Texture might be upside down
Hope this helps your requirements.
Else if your problem is just code repetition. Then you can write a function which would give you your city sprite containing other sprites like this one. And call it number of times you want it.
CCSprite* creteCitySprite()
{
float acum = 0.0;
CCSprite *city1 = CCSprite::create();
for(int i = 0; i < 12; ++i)
{
CCSprite *city = CCSprite::createWithSpriteFrameName("env_buildings_background2.png");
city->setPosition(ccp(acum, 0));
city1->addChild(city);
acum+= city->getContentSize().width*0.99;
}
city1->setContentSize(CCSizeMake(acum, 0));
return city1;
}
EDITED:
This gives you what you want. But what I wanted to say is, the sub sprites which you added to your city1 will remain static.
CCSptire *getSpriteFromSprite(CCSprite *citySprite, float citySpriteWidth, float citySpriteHeight)
{
CCPoint prevPosition = citySprite->getPosition();
//Set position in order to make it fit inside CCRenderTexture (You can change this later)
citySprite->setPosition(ccp(citySpriteWidth/2, citySpriteHeight/2));
CCRenderTexture *render = CCRenderTexture::renderTextureWithWidthAndHeight(citySpriteWidth, citySpriteWidth);
render->beginWithClear(0, 0, 0, 0);
citySprite->visit();
render->end();
citySprite->setPosition(prevPosition);
CCTexture2D *tex = render->getSprite()->getTexture();
CCSprite *newCitySprite = CCSprite::spriteWithTexture(tex);
newCitySprite->setFlipY(true); //Texture might be upside down
}

Qt draw a blue pixel if the original pixel was black in a new image

I've written some code that should make a new image. My background image has black areas, when the for loop comes on a black pixel then it should draw in the new image a blue one instead otherwise it should just draw the original pixel. Thought I could do that like this but the program keeps running.
QApplication a(argc, argv);
int c, m, y, k, al;
QColor color;
QColor drawColor;
QImage background;
QImage world(1500, 768, QImage::Format_RGB32);
QSize sizeImage;
int height, width;
background.load("Background.jpg");
world.fill(1);
QPainter painter(&background);
sizeImage = background.size();
width = sizeImage.width();
height = sizeImage.height();
for(int i = 0; i < height; i++)
{
for(int z = 0; z < width; z++)
{
color = QColor::fromRgb (background.pixel(i,z) );
color.getCmyk(&c,&m,&y,&k,&al);
if(c == 0 && m == 0 && y == 0 && k == 0) //then we have black as color and then we draw the color blue
{
drawColor.setBlue(255);
painter.setPen(drawColor);
painter.drawPoint(i,z);
}
}
}
//adding new image to the graphicsScene
QGraphicsPixmapItem item( QPixmap::fromImage(background));
QGraphicsScene* scene = new QGraphicsScene;
scene->addItem(&item);
QGraphicsView view(scene);
view.show();
Is my for loop wrong or is it my painter? It sais QImage::pixel: coordinate (292,981) out of range but for soo many pixels, it is also not fast enough to use.
As noted in the comments, drawing pixels one by one can be incredibly slow. Even pixel-by-pixel access can be quite slow. E.g. the following is probably faster, but still not very good:
const QRgb black = 0;
const QRgb blue = 255;
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
if (background.pixel(x,y) == black) {
background.SetPixel(blue);
}
}
}
The quicker solution involves direct bitoperations via scanline(). You might want to call convertToFormat() first, so you don't need to deal with the different possible scanline formats.
As a creative hack, call createMaskFromColor to make all black pixels transparent, and then paint over a blue background.