PDA

View Full Version : Need some help with QImage::setPixel and QImage::width()



Fallen_
15th May 2011, 20:41
Hello, my program crashes at QImage::setPixel which calls QImage::width(), it crashes at QImage::width(), my backtrace:

(gdb) bt
#0 0x00ab9b9b in QImage::width (this=0x22cc94) at image\qimage.cpp:1555
#1 0x00ac01ac in QImage::setPixel (this=0x22cc94, x=18, y=29,
index_or_rgb=2280604) at image\qimage.cpp:4118
#2 0x00404500 in MainWindow::putPixel (this=0x22cd60, image=@0x22cc94, x=18,
y=29, red=34 '"', green=0 '\0', blue=248 '°', alpha=255 '*')
at ..\OtlandMapEditor\mainwindow.cpp:441
#3 0x00403e8a in MainWindow::loadItems (this=0x22cd60)
at ..\OtlandMapEditor\mainwindow.cpp:368
#4 0x00402b98 in MainWindow::onNew (this=0xa5f9418)
at ..\OtlandMapEditor\mainwindow.cpp:154
#5 0x00411fe6 in MainWindow::qt_metacall (this=0xa5f9418,
_c=QMetaObject::InvokeMetaMethod, _id=0, _a=0x22ce78)
at debug\moc_mainwindow.cpp:99
#6 0x6a205fb8 in QMetaObject::metacall (object=0xa5f9418,
cl=QMetaObject::InvokeMetaMethod, idx=31, argv=0x22ce78)
at kernel\qmetaobject.cpp:237
#7 0x6a216770 in QMetaObject::activate (sender=0xa5fa0c8, m=0x1256640,
local_signal_index=1, argv=0x22ce78) at kernel\qobject.cpp:3278
#8 0x00a1f630 in QAction::triggered (this=0x22ce90, _t1=false)
at tmp/moc/debug_shared/moc_qaction.cpp:263
#9 0x0022ce8c in ?? ()
#10 0x0022ce90 in ?? ()
#11 0x0022ce94 in ?? ()
#12 0x0022ce98 in ?? ()
#13 0x0022ce9c in ?? ()
#14 0x0022cea0 in ?? ()
#15 0x0022cea4 in ?? ()
#16 0x0022cea8 in ?? ()
#17 0x0022ceac in ?? ()
#18 0x0022ceb0 in ?? ()
#19 0x0022ceb4 in ?? ()
#20 0x0022ceb8 in ?? ()
#21 0x0022cebc in ?? ()
#22 0x0022cec0 in ?? ()
#23 0x0022cec4 in ?? ()
#24 0x0022cec8 in ?? ()
#25 0x0022cecc in ?? ()
#26 0x0022ced0 in ?? ()
#27 0x0022ced4 in ?? ()
#28 0x0022ced8 in ?? ()
#29 0x0022cedc in ?? ()
#30 0x0022cee0 in ?? ()
#31 0x0022cee4 in ?? ()
#32 0x0022cee8 in ?? ()
#33 0x0022ceec in ?? ()
#34 0x0022cef0 in ?? ()
#35 0x0022cef4 in ?? ()
#36 0x0b833648 in ?? ()
#37 0x0022d6ec in ?? ()
#38 0x0022d6ec in ?? ()
#39 0x00000001 in ?? ()
#40 0x00e36a77 in QMenuPrivate::activateAction (this=0xb834748,
action=0xa5fa0c8, action_e=QAction::Trigger, self=true)
at widgets\qmenu.cpp:1085
#41 0x00e3ab53 in QMenu::mouseReleaseEvent (this=0xb834718, e=0x22d6d4)
at widgets\qmenu.cpp:2306
#42 0x00a76a52 in QWidget::event (this=0xb834718, event=0x22d6d4)
at kernel\qwidget.cpp:8259
#43 0x00e3b1ab in QMenu::event (this=0xb834718, e=0x22d6d4)
at widgets\qmenu.cpp:2415
#44 0x00a2bd96 in QApplicationPrivate::notify_helper (this=0xa5f4098,
receiver=0xb834718, e=0x22d6d4) at kernel\qapplication.cpp:4462
#45 0x00a29fdf in QApplication::notify (this=0x22fe2c, receiver=0xb834718,
e=0x22d6d4) at kernel\qapplication.cpp:4023
#46 0x6a2014fe in QCoreApplication::notifyInternal (this=0x22fe2c,
receiver=0xb834718, event=0x22d6d4) at kernel\qcoreapplication.cpp:731
#47 0x010a5ce2 in QCoreApplication::sendSpontaneousEvent (receiver=0xb834718,
event=0x22d6d4)
at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:218
#48 0x00a287ee in QApplicationPrivate::sendMouseEvent (receiver=0xb834718,
event=0x22d6d4, alienWidget=0x0, nativeWidget=0xb834718,
buttonDown=0x14eb41c, lastMouseReceiver=@0x14eb420, spontaneous=true)
at kernel\qapplication.cpp:3120
#49 0x00a9304b in QETWidget::translateMouseEvent (this=0xb834718,
msg=@0x22dba8) at kernel\qapplication_win.cpp:3234
#50 0x00a8e3e2 in QtWndProc@16 (hwnd=0x161638, message=514, wParam=0,
lParam=589864) at kernel\qapplication_win.cpp:1659
#51 0x775186ef in USER32!IsWindowVisible ()
from C:\Windows\system32\user32.dll
#52 0x00161638 in ?? ()
#53 0x00000202 in ?? ()
#54 0x77518876 in USER32!IsWindowVisible ()
from C:\Windows\system32\user32.dll
#55 0x00a8d8e1 in qt_is_translatable_mouse_event (message=0)
at kernel\qapplication_win.cpp:1426
#56 0x775189b5 in USER32!IsWindowVisible ()
from C:\Windows\system32\user32.dll
#57 0x00000000 in ?? ()
(gdb)

my code:

void MainWindow::loadItems()
{
if (m_loader)
delete m_loader;

m_loader = new XLoader(this);

QString error = "Cannot load items.xml: ";
switch (m_loader->loadItems("items.xml")) {
case ERR_FILE_D_EXIST:
error += "File does not exist";
break;
case ERR_CANNOT_OPEN:
error += "Cannot open file";
break;
case ERR_MALFORMED_FILE:
error += "Malformed XML File";
break;
default:
case ERR_SUCCESS:
error = "";
break;
}

if (!error.isEmpty()) {
QMessageBox::information(this, tr("Fatal error"), tr("The following errors occured: %1").arg(error));
return;
}

QListWidget *listWidget = findChild<QListWidget *>("listWidget");
for (ItemsSprites::ItemMap::iterator it = g_itemSprites->begin(); it != g_itemSprites->end(); ++it) {
SpriteType *sType = it->second;
if (sType) {
ItemRet *itemRet = m_loader->item(it->first);
unsigned short spriteId = g_itemSprites->getItemSpriteID(it->first, 0);
ItemType *iType = g_itemTypes->getType(it->first);
if (iType && iType->group == ITEM_GROUP_DEPRECATED) {
qDebug() << "Found item but it's deprected.";
continue;
}

if (spriteId <= 1) {
qDebug() << "Image Not Found";
continue;
}

char dump[4000];
unsigned short size = g_itemSprites->getSpriteDump(spriteId, dump);
if (size < 1) {
qDebug() << "Image Not Found #2";
continue;
}

/// \todo better progress handling...
if ((rand() % 2) == 1)
incrementProgressBar();

qDebug() << "Everyting ok...";
g_itemSprites->getSpriteDump(sType->imageID[1], dump);
QImage image((uchar *)dump, 34, 34, QImage::Format_ARGB32_Premultiplied);
if (!image.isNull()) {
for (int n = 0; n < 33; ++n) {
putPixel(image, n, 0, 0xFF, 0x00, 0x00, 0xFF);
putPixel(image, n, 33, 0xFF, 0x00, 0x00, 0xFF);
}

for (int p = 1; p < 33; ++p) {
putPixel(image, 0, p, 0xFF, 0x00, 0x00, 0xFF);
putPixel(image, 33, p, 0xFF, 0x00, 0x00, 0xFF);
}

unsigned short x, y, npix;
int state;
int i,j;
int posx=1, posy=1;

state=0;
x=0;
y=0;
for (i=0; i < size;) {
memcpy(&npix, dump+i, 2); // number of pixels (transparent or defined)
i += 2;
switch (state) {
default: // state 0, drawing transparent pixels
for (j=0; j < npix; ++j) {
putPixel(image, posx+x, posy+y, 0x00, 0x00, 0x00, 0x00);
if (x < 31) {
x++;
} else {
x=0;
y++;
}
}
state=1;
break;
case 1: // state 1, drawing defined pixels
for (j=0; j < npix; ++j) {
putPixel(image, posx+x, posy+y, dump[i], dump[i+1], dump[i+2], 0xFF);
i += 3;
if (x < 31) {
x++;
} else {
x=0;
y++;
}
}
state=0;
break;
}
}

while (x < 32 && y < 32) {
putPixel(image, posx+x, posy+y, 0x00, 0x00, 0x00, 0x00);
if (x < 31) {
x++;
} else {
x=0;
y++;
}
}

QListWidgetItem *widgetItem = new QListWidgetItem;
widgetItem->setIcon(QIcon(QPixmap::fromImage(image)));
if (itemRet) {
widgetItem->setText(itemRet->name);
delete itemRet;
} else {
widgetItem->setText("Unknown");
}

listWidget->addItem(widgetItem);
qDebug() << "OK";
ItemData *itemData = new ItemData;
itemData->item = widgetItem;
itemData->pixmap = QPixmap::fromImage(image);
m_items.append(itemData);
}
}
}
}

void MainWindow::putPixel(QImage& image, int x, int y, uchar red, uchar green, uchar blue, uchar alpha)
{
if (image.isNull() || !image.valid(x, y))
return;

int width, height, rowstride, n_channels;
uchar *pixels, *p;

n_channels = image.depth() / 8;

Q_ASSERT(image.hasAlphaChannel());
Q_ASSERT(n_channels == 4);

width = image.width();
height = image.height();

Q_ASSERT(x >= 0 && x < width);
qDebug() << "y = " << y << ", height = " << height << ".";
Q_ASSERT(y >= 0 && y < height);

rowstride = image.bytesPerLine();
pixels = image.bits();

p = pixels + y * rowstride + x * n_channels;
p[0] = red;
p[1] = green;
p[2] = blue;
p[3] = alpha;

image.setPixel(x, y, QRgb(p));
}

it crashes here:

for (j=0; j < npix; ++j) {
putPixel(image, posx+x, posy+y, dump[i], dump[i+1], dump[i+2], 0xFF);
then in here:

image.setPixel(x, y, QRgb(p));

any ideas?

norobro
16th May 2011, 04:44
Don't know if this is your problem or not, but my Linux box won't compile this line:
image.setPixel(x, y, QRgb(p));The compiler spits out the following:
error: cast from ‘uchar*’ to ‘QRgb’ loses precision and it looks like you have some garbage in line #2 of your backtrace.

Try this:
image.setPixel(x,y,*(reinterpret_cast<QRgb *>(p)));
or the Qt way:
image.setPixel(x, y, qRgba(int(red),int(green),int(blue),int(alpha)));

Fallen_
16th May 2011, 13:00
Don't know if this is your problem or not, but my Linux box won't compile this line:
image.setPixel(x, y, QRgb(p));The compiler spits out the following: and it looks like you have some garbage in line #2 of your backtrace.

Try this:
image.setPixel(x,y,*(reinterpret_cast<QRgb *>(p)));
or the Qt way:
image.setPixel(x, y, qRgba(int(red),int(green),int(blue),int(alpha)));
still the same <,<

norobro
16th May 2011, 14:50
Well, your putPixel() function works fine here:
#include <QtGui>

void putPixel(QImage& image, int x, int y, uchar red, uchar green, uchar blue, uchar alpha)
{
if (image.isNull() || !image.valid(x, y)) return;
int width, height, rowstride, n_channels;
uchar *pixels, *p;
n_channels = image.depth() / 8;
Q_ASSERT(image.hasAlphaChannel());
Q_ASSERT(n_channels == 4);
width = image.width();
height = image.height();
Q_ASSERT(x >= 0 && x < width);
// qDebug() << "y = " << y << ", height = " << height << ".";
Q_ASSERT(y >= 0 && y < height);
rowstride = image.bytesPerLine();
pixels = image.bits();
p = pixels + y * rowstride + x * n_channels;
p[0] = alpha;
p[1] = red;
p[2] = green;
p[3] = blue;
image.setPixel(x, y, *reinterpret_cast<QRgb *>(p));
// image.setPixel(x, y, qRgba(int(red),int(green),int(blue),int(alpha)));
}

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QLabel *label = new QLabel;
QPixmap pix(290,290);
QPainter painter(&pix);
painter.setBrush(QBrush(QColor(102,205,170)));
painter.setFont(QFont("Arial",75));
painter.drawRect(0,0,290,290);
painter.setPen(QColor(34,139,34));
painter.drawText(QRect(0,20,290,290), Qt::AlignCenter, "Qt");
QImage image(pix.toImage());
for(int x=25;x<50;++x)
for(int y=25;y<50;++y)
putPixel(image, x, y, 0x22, 0x00, 0xf8, 0xff);
label->setPixmap(QPixmap::fromImage(image));
label->show();

return a.exec();
}

Fallen_
16th May 2011, 15:45
Its still the same using your code:

image.setPixel(x, y, *reinterpret_cast<QRgb *>(p));

wysota
16th May 2011, 22:15
Are you using threads? Please provide a minimal compilable example reproducing the problem.