Qt / C++ QImage sometimes file is not loaded. But file is accessible - c++

In our C++/Qt4.8 application we are using QImage to add images to our documents we print. Sometimes we expierence issues with printing the image, and the image will be printed out blank (just a empty page).
We added logging into our application and added an audit log on our resources folder where the images are.
We initialize our image in this way. And pass it as argument to mPainter (instance of QPainter)
QImage image( strImage );
mPainter.drawImage( QRect( 0, 0, pageRect().width(), pageRect().height() ), image );
The drawImage fuction of mPainter will call the following QPainter function :
inline void QPainter::drawImage(const QRect &r, const QImage &image)
{
drawImage(r, image, QRectF(0, 0, image.width(), image.height()));
}
The windows audit shows us that the application successfully tried to acces the files.
But sometimes the following code will returns false and goes into the else:
QImage* imageToPrint = new QImage;
if (imageToPrint->load("C:/ApplicationName/Resources/page-001.jpg"))
{
//fuction body
}
else
{
if (QFile::exists("C:/ApplicationName/Resources/page-001-copy.jpg"))
{
//Copy the image and try to print with this one.
QFile::copy("C:/ApplicationName/Resources/page-001-copy.jpg", "C:/ApplicationName/Resources/page-001-unixtimestamp.jpg");
printImage("C:/ApplicationName/Resources/page-001-unixtimestamp.jpg");
QFile::remove("C:/ApplicationName/Resources/page-001-unixtimestamp.jpg");
}
}
The strangest thing is that the application can access, copy and delete files in the directory. But sometimes can't read the data from the file. Even the newly created copy with the unixtimestamp can't be loaded (But does exist following the code) and will print a blank page.
Has anybody has this problem? Our does anyone has a solution for this?
Thanks in advance!

Related

How to save a QPixmap as a picture in a folder with C++ and Qt?

I'm trying to code a C++ function to save a selected picture to my program directory, using a Qt GUI.
So far, the "save" function I'm using on my QPixmap object won't save anything, and I can't figure out why.
Here is the code :
qImage = new QPixmap(path);
QPixmap qImage2 = qImage->scaled(this->width(),this->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
qImage2.toImage();
qImage2.save(QDir::currentPath());
qDebug()<<QDir::currentPath();
Can anyone help me ? :)
QDir::currentPath() returns the current working directory. Obviously, the filename itself is not specified. Simply append the needed filename, for example: QDir::currentPath() + "/123.png"
QPixmap::toImage() is a const method returning a QImage converted from a QPixmap. It literally does nothing useful in your code, remove it or use QImage instead.
QDir::currentPath() returns the current working directory which is not necessarily an application executable directory. Use QCoreApplication::applicationDirPath() instead if you need an executable directory.
Also, as pointed out by Violet Giraffe, there could be write permission issues.

How to make windows form release/close/dispose image file

MY QUESTION: Is there a way to get a windows form to release an open image without closing the form.
MY PROBLEM: I am working on a windows form in c++. I have a program that allows users to edit .bmp images. The user selects the image they would like to edit from a dataGridView. The images are displayed in an image column in the dataGridView. When I load the image into the dataGridView control, the form opens the image file and prevents any further editing of the image file. The image file cannot be edited even if the dataGridView control is deleted. The form must completely close before it releases the image file.
MY CODE:
namespace EditImageTest {
public ref class Form1 : public System::Windows::Forms::Form {
public: Form1(void) {
// create an image column & dataGridView.
System::Windows::Forms::DataGridViewImageColumn^ c = gcnew System::Windows::Forms::DataGridViewImageColumn();
c->ImageLayout = System::Windows::Forms::DataGridViewImageCellLayout::Zoom;
System::Windows::Forms::DataGridView^ dgv = gcnew System::Windows::Forms::DataGridView();
// add column to dataGridView.
dgv->Columns->Add(c);
// add dataGridView to form.
this->Controls->Add(dgv);
// add .bmp image on desktop to dataGridView.
dgv->Rows>Add(System::Drawing::Image::FromFile("C:\\Users\\User\\Desktop\\1.bmp"));
// the form has now opened the .bmp image file preventing any edits on this file.
// you can not even manualy delete this file now.
// attempt to open the .bmp image for editing.
FILE* f;
fopen_s(&f,"C:\\Users\\User\\Desktop\\1.bmp","w");
if(f) {
// write garbage in the .bmp image.
fwrite("SOME TEXT",sizeof(unsigned char),9,f);
// close the .bmp image.
fclose(f);
}
}
protected: ~Form1() { if (components) { delete components; } }
private: System::ComponentModel::Container ^components;
};
}
The Image class creates a memory-mapped file to map the bitmap's pixel data into memory. That's efficient, it won't take space in the swapfile and if the RAM pages are unmapped then they can always be reloaded from the file. Tends to matter for bitmaps, they can be quite large.
But the MMF does create a lock on the file, it won't be released until you dispose the object with the delete operator. Which of course can't happen until after the window is closed.
You avoid this by making a deep copy of the image, allowing the lock to be released quickly. Do so with the Bitmap(Image^) constructor:
auto img = System::Drawing::Image::FromFile("C:\\Users\\User\\Desktop\\1.bmp"));
dgv->Rows>Add(gcnew Bitmap(img));
delete img;

Displaying picture that is not in resources of Qt

I am currently writing an application in Qt, which is basically a warehouse. An application reads CSV, enables user to process it and enables to show picture of each good. I tried displaying picture using QLabel and Pixmap, however nothing happens even though the file is in the same folder and the name provided is exactly as it should be. Is it the resources issue or my code fails somehow? Is there any possibility to display the image without adding it to resources in order to avoid adding many photos manually?
void ImageViewer::viewImage(QString imgName)
{
QString pathWithName = imgName;
pathWithName.append(".jpg");
ui->label->setPixmap( QPixmap(pathWithName) );
ui->label->show();
update();
}
Sorry for any mistakes in post creation or code displaying here- it's my first post.
Edit:
I am adding code from MainWindow (called CsvReader in my project) to how I'm invoking the method viewImage:
void CsvReader::on_imgView_clicked()
{
ImageViewer* img = new ImageViewer(this);
img->setModal(true);
img->exec();
QModelIndex List selInd ui->tableView->selectionModel()->selectedIndexes();
QString id = model->item(selInd.first().row(), 0)->text();
img->viewImage(id);
}
Edit 2:
Solved. Had to change path using QDir:
QDir* directory = new QDir("/home/kokos/Magazyn/photos");
QFileInfo checkFile(*directory, pathWithName);
Thanks in advance,
Kokos
Confirm your file's location and existence first. Add this;
QFileInfo checkFile(pathWithName);
if (checkFile.exists() && checkFile.isFile()) {
// your code
}

QIcon not being displayed on QPushButton

I'm learning how to use Qt for C++ programming. I have this image I want to display after when I click at a button and the position on a matrix related to that button is equal to -1, I also want to clear the text on that same button, my code up to now for that part is:
if(Tabuleiro[x][y] == -1){
this->Botoes[x][y]->setText("");
this->Botoes[x][y]->setIcon(QIcon("bomba.png"));
}
Being that Tabuleiro is a matrix of int, Botoes is a matrix of pointers to QPushButtons and "bomba.png" is the image I want to display. The image is in the same folder as the project, but once I run it is not displayed. I also tryed using Qt Resource system, I created a new resource called imagens.qrc on it I created a prefix /Imagem and placed my image there, this is what the code looked like after this:
if(Tabuleiro[x][y] == -1){
this->Botoes[x][y]->setText("");
this->Botoes[x][y]->setIcon(QIcon(":/Imagem/bomba.png"));
}
But it still won't work. What am I doing wrong? Also, I tryed using
this->Botoes[x][y]->text().clear();
instead of
this->Botoes[x][y]->setText("");
But it didn't work, do you know why?
Please include <QApplication> and <QStyle> and try:
this->Botoes[x][y]->setIcon( qApp->style()->standardIcon( QStyle::SP_MessageBoxWarning ) );
If it works (warning icon being displayed): then, it means you're not loading your resources correctly.
You can also check this:
QPixmap foo( ":/Imagem/bomba.png" );
bool found = !foo.isNull(); // true if png file was found, false if it was not
If false, again, it means you're not loading your resources correctly, if true, icon should be displayed in the button.
Morevover, you can also try this->Botoes[x][y]->setIconSize( QSize(16,16) ) because if someone earlier did this->Botoes[x][y]->setIconSize( QSize(0,0) ); your button icon will not be displayed!

Working with Bitmaps in WxWidgets

I have the following code given in the book "Cross-Platform GUI Programming with wxWidgets" which I'm reading:
BEGIN_EVENT_TABLE(MyWindow, wxWindow)
EVT_ERASE_BACKGROUND(MyWindow::OnErase)
END_EVENT_TABLE()
void MyWindow::OnErase(wxEraseEvent& event)
{
wxClientDC* clientDC = NULL;
if (!event.GetDC())
clientDC = new wxClientDC(this);
wxDC* dc = clientDC ? clientDC : event.GetDC() ;
wxSize sz = GetClientSize();
wxEffects effects;
effects.TileBitmap(wxRect(0, 0, sz.x, sz.y), *dc, m_bitmap);
if (clientDC)
delete clientDC;
}
This code doesn't show how do I load a bitmap so after some searching on google I came up with:
wxBitmap m_bitmap;
bool result = m_bitmap.LoadFile("D:\image.png", wxBITMAP_TYPE_PNG);
But this returns a boolean result of false which means the function LoadFile was failed to load the file. I have also tried to load a BMP file which fails too.
One another problem I'm having is that wxEffects is flagged deprecated by the complier warning.
You need to register the PNG image handler to be able to load PNG bitmaps. The simplest way to do is to call wxInitAllImageHandlers() function at some point during your application initialization, e.g. in your overridden MyApp::OnInit().
As for wxEffects being deprecated, this is just because the book is rather old and quite a few things have changed since then. I strongly recommend you to read the overview of important changes if you are using wxWidgets 3.0. And if you don't, I recommend you even stronger to use it.