Qt application crash when trying to delete Qimage Format_RGB888 - qt

I get a "HEAP CORRUPTION DETECTED: After normal block ... CRT detected that the application wrote to memory after end of heap buffer." when variable test gets destroyed.
If I change the image size, the crash does not occur, I'm thinking it has something to do with memory alignment, but I cannot figure out what.
I am using the official Qt builds for MSVC 2017 64bit
#include <QCoreApplication>
#include <QImage>
QImage foo(int width, int height)
{
QImage retVal(width, height, QImage::Format_RGB888);
for (int i = 0; i < height; ++i) // read each line of the image
{
QRgb *lineBuf = reinterpret_cast<QRgb *>(retVal.scanLine(i));
for (int j = 0; j < width; ++j)
{
lineBuf[j] = qRgb(0,0,0);
}
}
return retVal;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
{
QImage test = foo(5,5);
}
return a.exec();
}

As GM suggested in the comment above, the problem is that QRgb is a 32bit construct.
I've changed the code replacing QRgb with a custom RGB struct
struct RGB {
uint8_t r;
uint8_t g;
uint8_t b;
};
QImage foo(int width, int height)
{
QImage retVal(width, height, QImage::Format_RGB888);
for (int i = 0; i < height; ++i) // read each line of the image
{
RGB *lineBuf = reinterpret_cast<RGB *>(retVal.scanLine(i));
for (int j = 0; j < width; ++j)
{
RGB tmp;
//.... do stuff with tmp
lineBuf[j] = tmp;
}
}
return retVal;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
{
QImage test = foo(5,5);
}
return a.exec();
}

Related

Freeing an array of pointer but heap block

I wrote a program that has to read a 2D array from a text file and save it into a double pointer which will act as a 2D array.
Here's the code :
#include <stdio.h>
#include <stdlib.h>
char **create_map(char* filename);
int n;
int m;
char **map;
int main(int argc, char* argv[]) {
int i;
map = create_map(argv[1]);
for(i = 0; i < n; i++) {
free(map[i]);
}
free(map);
return 0;
}
char **create_map(char *filename) {
int i = 0;
char *row;
char **map;
FILE *file = fopen(filename, "r");
fscanf(file, "%d %d", &n, &m);
map = malloc(sizeof(char *) * n);
row = malloc(sizeof(char)*m);
while(fscanf(file, "%s\n", row) != EOF) {
map[i] = malloc(sizeof(char)*m);
strcpy(map[i], row);
i++;
}
free(map[9]);
free(row);
fclose(file);
return map;
}
The content of the file is stored successfully in the map variable, but when it comes to freeing some space the debugger prints "warning: Heap block at 0000029967AF5770 modified at 0000029967AF578A past requested size of a".
Why the memory can't be freed?
Where's the error?
Thank you in advance.

Pass array pointer to other program and extract that pointer in c

I am trying to pass an array of integer to other program and accept that from *argv. Then sort the array and print that from initial program. But I can not accept the pointer of the array and work with it. (can't even compile sort.c)
#include<stdio.h>
int main(int argc, char *argv[])
{
int arr = argv[1];
int temp = 0;
int length = sizeof(arr);
//Sort the array in descending order
for (int i = 0; i < length; i++) {
for (int j = i+1; j < length; j++) {
if(arr[i] < arr[j]) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
int length = args-1;
int arr[length];
for(int i=0;i<length,i++)
{
arr[i]=argv[i+1];
}
int *p=arr
pid_t pid=fork();
if (pid==0) {
execv("sort",p);
}
else {
}
return 0;
}

To draw some points by using QImage, QWidget.update() is too slow, Is there more faster way?

I'm trying to draw a point on the window by using QImage, and update the position of this point as fast as possible(less than 1ms every update). I've wrote the code below and run it, but the result is it's too slow(about 50ms every update). I searched the bottleneck and found the cause of this slowness is calling QWidget.update() takes too long. So I figured out as long as using Widget.update() it won't be faster. So I think I need another way. Is there any faster way to do this? All of the codes and the result are the following.
result:
qimageBehaviorForStackOverflowQuestion.pro
######################################################################
# Automatically generated by qmake (3.1) Wed Mar 29 15:18:09 2017
######################################################################
TEMPLATE = app
TARGET = qimageBehaviorForStackOverflowQuestion
INCLUDEPATH += .
QT += widgets
# Input
HEADERS += qimageBehaviorForStackOverflowQuestion.h
SOURCES += qimageBehaviorForStackOverflowQuestion.cpp
qimageBehaviorForStackOverflowQuestion.h
#include <iostream>
#include <QApplication>
#include <QWidget>
#include <QTimer>
#include <QPainter>
#include <QPushButton>
#include <QImage>
#include <QTime>
class MyWidget : public QWidget {
Q_OBJECT
private:
QImage *image;
int px, py;
uchar d[100*100*4];
QTimer *timer;
QTime time;
public:
MyWidget();
void paintEvent(QPaintEvent * event);
public slots:
void doPaint();
};
qimageBehaviorForStackOverflowQuestion.cpp
#include "qimageBehaviorForStackOverflowQuestion.h"
int my_counter = 0;
MyWidget::MyWidget() : QWidget(0), px(0), py(0){
image = new QImage(d, 100, 100, QImage::Format_ARGB32);
for(int cnt = 0, a, r, g, b; cnt < 100*100*4;){
a = 255; //alpha
r = 0; //red
g = 0; //green
b = 0; //blue
d[cnt] = b; cnt++;
d[cnt] = g; cnt++;
d[cnt] = r; cnt++;
d[cnt] = a; cnt++;
}
// connect QTimer.timeout to my doPaint method
timer = new QTimer();
connect(timer, SIGNAL(timeout()), this, SLOT(doPaint()));
timer->start(1);
};
void MyWidget::doPaint(){
// manipulate the positions of the points
if(px < 100){
int cnt = 0, b = 255, g = 255, r = 255, a = 255;
d[4 * px + cnt] = b; cnt++;
d[4 * px + cnt] = g; cnt++;
d[4 * px + cnt] = r; cnt++;
d[4 * px + cnt] = a; cnt++;
px++;
}
// update the window
update();
};
void MyWidget::paintEvent(QPaintEvent * event){
QPainter painter(this);
painter.drawImage(0, 0, *image);
}
int main(int argc, char *argv[]){
QApplication app(argc, argv);
MyWidget *widget = new MyWidget();
widget->show();
return app.exec();
}
After googling couple of hours, I found more faster way. It becomes incredibly very fast(once 20FPS is now about 500FPS).What I'm using now is QGraphicsView Framework and QPixmap and QGraphicsPixmapItem. However I don't know this is the right or efficient way, if it isn't please correct me. And if you know there is more faster way please let me know. Any way I show you the code. I hope it could help someone who fight same problem.
qgraphicsSceneExample.h
#include <iostream>
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QTimer>
#include <QPainter>
#include <QPushButton>
#include <QImage>
#include <QTime>
#include <QStyleOptionGraphicsItem>
#include <QWidget>
#include <QPixmap>
#include <QGraphicsPixmapItem>
class MyView : public QGraphicsView {
Q_OBJECT
private:
QGraphicsScene *scene;
QImage *image;
QPixmap *pixmap;
QGraphicsPixmapItem *gpixmapItem;
int px, py;
uchar d[100*100*4];
QTimer *timer;
QTime time;
public:
MyView();
//void paintEvent(QPaintEvent * event);
public slots:
void doPaint();
};
qgraphicsSceneExample.cpp
#include "qgraphicsSceneExample.h"
int my_counter = 0;
MyView::MyView() : px(0), py(0){
image = new QImage(d, 100, 100, QImage::Format_ARGB32);
for(int cnt = 0, a, r, g, b; cnt < 100*100*4;){
a = 255; //alpha
r = 0; //red
g = 0; //green
b = 0; //blue
d[cnt] = b; cnt++;
d[cnt] = g; cnt++;
d[cnt] = r; cnt++;
d[cnt] = a; cnt++;
}
// connect QTimer.timeout to my doPaint method
timer = new QTimer();
connect(timer, SIGNAL(timeout()), this, SLOT(doPaint()));
scene = new QGraphicsScene(0);
pixmap = new QPixmap(QPixmap::fromImage(*image));
gpixmapItem = scene->addPixmap(*pixmap);
this->setScene(scene);
timer->start(1);
};
void MyView::doPaint(){
// manipulate the positions of the points
if(px < 100){
int cnt = 0, b = 255, g = 255, r = 255, a = 255;
d[4 * px + cnt] = b; cnt++;
d[4 * px + cnt] = g; cnt++;
d[4 * px + cnt] = r; cnt++;
d[4 * px + cnt] = a; cnt++;
px++;
}
pixmap = new QPixmap(QPixmap::fromImage(*image));
gpixmapItem->setPixmap(*pixmap);
std::cout << my_counter++ << "\n";
};
int main(int argc, char *argv[]){
QApplication app(argc, argv);
MyView *myView = new MyView();
myView->show();
return app.exec();
}
Consider changing the incrementation of Px to more than +1, +5 for example. that will reduce the calls of doPaint() function by 5 times. and will speed up the drawing. Because your problem is that you are updating the drawing a lot, 100 times.
P.S : you should also stop the timer to stop calling doPaint() function when the drawing is finished. because it is called every 1ms. since timer.start(1) will emit timeout() signal every 1ms.
Edit:
Consider also changing the timeout that is very light (an update every 1ms <=> 1000 FPS).

Any ideas, how to encode QR data into png image?

All I need is simple (Q)string to put it as embedded image like:
<img src="data:image/png;base64,iVBORw...">
I use: #include <qrencode.h> (linux -> apt-get install libqrencode-dev)
This is my code:
QRcode *qr=QRcode_encodeString(QString("my test string").toStdString().c_str(), 1, QR_ECLEVEL_L, QR_MODE_8,1);
QByteArray *ba = new QByteArray();
for (unsigned int y=0; y<qr->width;y++)
{
int yy=y*qr->width;
for (unsigned int x=0; x<qr->width;x++)
{
int xx=yy+x;
const unsigned char b=qr->data[xx];
///WHAT TO DO NOW??? IS IT CORRECT?
ba->push_back(b);
qDebug()<<"Char "<<b;
if(b &0x01)
{
qDebug()<<"Point +++";
}
}
}
qDebug()<<ba->toBase64();
Any ideas, how to encode qr->data into a png image?
I did it! :)
First version, without scaling
#include<QString>
#include<QDebug>
#include<QByteArray>
#include<QBuffer>
#include<QImage>
#include<QImageWriter>
#include<QPixmap>
#include<QPainter>
#include<QColor>
#include<QPointF>
#include<QRectF>
//ustawiam kolory
QColor bialy = Qt::white;
QColor czarny = Qt::black;
//PNG
QByteArray ImageAsByteArray;
QBuffer ImageBuffer(&ImageAsByteArray);
ImageBuffer.open(QIODevice::WriteOnly);
QRcode *qr=QRcode_encodeString(QString("afya.pl").toStdString().c_str(), 1, QR_ECLEVEL_L, QR_MODE_8,1);
QPixmap p(qr->width,qr->width);
QPainter pa;
pa.begin(&p);
pa.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing |QPainter::TextAntialiasing| QPainter::Antialiasing);
pa.setPen(bialy);
pa.setBrush(bialy);
//czyścimy tło
QPointF a=QPointF(0.0,0.0);
QPointF b=QPointF(p.width(),p.height());
pa.drawRect(QRectF(a,b));
pa.setPen(czarny);
for (unsigned int y=0; y<qr->width;y++)
{
int yy=y*qr->width;
for (unsigned int x=0; x<qr->width;x++)
{
int xx=yy+x;
const unsigned char b=qr->data[xx];
if(b &0x01){
a=QPointF(y,x);
pa.drawPoint(a);
}
}
}
p.save(&ImageBuffer,"PNG");
qDebug()<<ImageAsByteArray.toBase64();
}

Qt Error segmentation fault when trying to show window

I have a class ClientWindow. I have created several instances of it and appended the their pointers to a a list. If i try to show any of the windows however, I get "Segmentation fault (core dumped)" I keep the list of windows in a class called controller.
Here is my controller header file:
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include "clientwindow.h"
class Controller
{
public:
Controller();
void createClients(int num);
void showWindows();
private:
QList<ClientWindow*> clWList;
int size;
};
#endif // CONTROLLER_H
this is the cpp file:
#include "controller.h"
Controller::Controller()
{
}
void Controller::createClients(int num)
{
size = num;
for(int i = 0; i < size; i++)
{
ClientWindow cw;
clWList.append(&cw);
}
}
void Controller::showWindows()
{
for(int i = 0; i < size; i++)
{
ClientWindow* cw = clWList.at(0);
cw->show();
}
}
this is my main:
#include <QtGui/QApplication>
#include "clientwindow.h"
#include "controller.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// ClientWindow w;
// w.show();
QString temp = argv[1];
bool ok;
int tempI = temp.toInt(&ok, 10);
Controller c;
c.createClients(tempI);
c.showWindows();
return a.exec();
}
This is where it goes wrong:
for(int i = 0; i < size; i++)
{
ClientWindow cw;
clWList.append(&cw);
}
A local variable cw is created on the stack in each iteration. It is deallocated at the end of each iteration. Meaning the data is gone. So you end up storing pointers pointing to junk.
Calling a member function of a junk typically results in crash. :) Do this instead:
for(int i = 0; i < size; i++)
{
ClientWindow * cw = new ClientWindow();
clWList.append(cw);
}
You'll have to go through the list and delete the objects after you are done with them.

Resources