Can't save Images using QImage - c++

I wish to use QImage in Qt to load and save images. While I can load an image, for whatever reason it wont let me save the image.
So I started writing a simple code, made a simple png test file using paint, put it into the same folder as the project itself.
#include <QImage>
#include <iostream>
int main(){
QImage image;
image.load("test.png");
if (image.isNull()){
std::cout << "ERROR!\n";
}
else{
std::cout << "IMAGE LOADED!\n";
}
image.save("test1.png");
return 0;
}
During running the program I get the message of "IMAGE LOADED!" from the application output, however when I check the folder I expect the same image saved as test1.png, which doesn't appear at all.
So, how do I actually save an image? What did I miss?

In the other comments mentioned the image got saved into the working directory, which is not the same as the folder where the project is located.
In my specific case I got the image by adding a full path to the project like
int i = image.save("C:\\Users\\UserName\\Documents\\QT\\testing_ground_cpp\\" + string);
to find the image.
Ideally I should directly access with the working directory.

Related

SDL_Image loading a png returns nullptr

Alright so I'm trying to make a game engine for myself, and I've decided that it would be best to start loading images as files other than bitmaps using the SDL Image library. I've set up the library correctly according to conversations online, include set up and linker set up, and yet when I try to load a file that does indeed exist it just returns an empty surface.
Heres the code loading the file...
SDL_Surface* background = IMG_Load("Assets/bg.png");
background = SDL_ConvertSurface(background, mtrx->format, 0);
if (!background) {
ofstream file("text.txt");
file << IMG_GetError() << endl;
file.close();
}
...And the error I get in "text.txt"...
Parameter 'surface' is invalid
At the beginning of the script I have included SDL.h, then SDL_image.h, and the window initiation has IMG_Init(IMG_INIT_PNG) after SDL_Init. Visual studio shows no errors whatsoever, and everything BUT IMG_Load works fine.
All help would be appreciated, and I can provide any other code that might be helpful!

Show image on windows using imagemagick

I am using ImageMagick for a few modifications in images. My requirement is to capture desktop, update the captured image and show in the window (Canvas, Form or simple Win32 API image).
Everything working perfectly except showing a converted image on the window.
As per this discussion, display functionality of image magick is only supported by Linux and Mac (Please correct me if anything wrong).
The same forum suggested to use im_display to show the image on window. However, I am not able to locate any function related im_display() in the image magick library (Please correct me here if any additional include required).
When I am trying to call following code from visual studio then getting "delegate library support not built-in '' (X11) # error/display.c/DisplayImages/16224" error:
int main(int argc, char **argv)
{
try
{
Magick::InitializeMagick(NULL);
Image screen("screenshot:");
screen.display();
}
catch (exception &error_)
{
cout << "Caught exception: " << error_.what() << endl;
return 1;
}
return 0;
}
So the following are two primary questions:
Is it possible to show an image using image magick on windows (Form or canvas or win32)
If it's not possible then HBITMAP will help to render an image on windows. However, I am not able to find a way to convert Image Magick data to BITMAP. Can you please provide suggestions?

OpenCV imwrite() not saving image

I am trying to save an image from OpenCV on my mac and I am using the following code and so far it has not been working.
cv::imwrite("/Users/nickporter/Desktop/Gray_Image.jpg", cvImage);
Can anyone see why this might not be saving?
OpenCV does have problems in saving to JPG images sometimes, try to save to BMP instead:
cv::imwrite("/Users/nickporter/Desktop/Gray_Image.bmp", cvImage);
Also, before this, make sure you image cvImage is valid. You can check it by showing the image first:
namedWindow("image", WINDOW_AUTOSIZE);
imshow("image", cvImage);
waitKey(30);
I met the same problem and one possible reason is that the target folder to place your image. Suppose you want copy A.jpg to folder "C:\\folder1\\folder2\\", but in fact when folder2 doesn't exist, the copy cannot be successful(It is from my actual test, not from official announcement). And I solved this issue by checking whether the folder exists and create one folder if it doesn't exist. Here is some code may it help using c++ & boost::filesystem. May it help.
#include <boost/filesystem.hpp>
#include <iostream>
std::string str_target="C:\\folder1\\folder2\\img.jpg";
boost::filesystem::path path_target(str_target);
boost::filesystem::path path_folder=path_target.parent_path();//extract folder
if(!boost::filesystem::exists(path_folder)) //create folder if it doesn't exist
{
boost::filesystem::create_directory(path_folder);
}
cv::imwrite(str_target,input_img);
I also suggest to check folder permissions. Opencv quietly returns from imwrite without any exception even if output folder doesn't have write permissions.
I've just had a similar problem, loading in a jpg and trying to save it back as a jpg. Added this code and it seem to be fine now.
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
compression_params.push_back(100);
And you need to include the param in your writefile.
cv::imwrite("/Users/nickporter/Desktop/Gray_Image.jpg", cvImage, compression_params);
OpenCV 3.2 imwrite() seems to have a problem to write jpg file with Windows Debug mode. I use this way instead of imwrite().
cv::Mat cvImage;
#ifdef DEBUG
IplImage image = IplImage(cvImage);
cvSaveImage("filename.jpg", &image);
#else
cv::imwrite("filename.jpg", cvImage);
#endif
The following function can be dropped into your code to support writing out jpg images for debugging purposes.
You just need to pass in an image and a filename for it. In the function, specify a path you wish to write to & have permission to do so with.
void imageWrite(const cv::Mat &image, const std::string filename)
{
// Support for writing JPG
vector<int> compression_params;
compression_params.push_back( CV_IMWRITE_JPEG_QUALITY );
compression_params.push_back( 100 );
// This writes to the specified path
std::string path = "/path/you/provide/" + filename + ".jpg";
cv::imwrite(path, image, compression_params);
}
Although it is not true for your case. This problem may arise if the image path given as argument to the cv::imwrite function exceeds the allowed maximum path length (or possibly allowed file name length) for your system.
for linux see: https://unix.stackexchange.com/questions/32795/what-is-the-maximum-allowed-filename-and-folder-size-with-ecryptfs
for windows see: https://www.quora.com/What-is-the-maximum-character-limit-for-file-names-in-windows-10

OpenCV let user choose to open image

I am trying to create a simple image processor in opencv. I so far have experimented to open a set image from file with this code.
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat im = imread("c:/image.jpg");
if (im.empty())
{
cout << "Cannot load image!" << endl;
return -1;
}
imshow("Image", im);
waitKey(0);
}
As this only allows a set image file to be open, how could i modify it so it allows the user to select an image?
Is this possible or can i only load a set image from file?
Thanks.
If you want your program to run in console only, let the user to input the path of the image file ( or may be using command line arguments).
If you want to make it GUI application, (some fancy window will show up when you click a "Open File" button ) then you have to learn some GUI programming. Choose some GUI programming tool depending on your platform ( Windows, Linux etc) or go for cross platform ( Give a try to Qt )
If you want the user to be able to browse for an image on their computer, you can use the open file dialog box. You can find a sample on MSDN.

Problem with iterating over a lots of images in OpenCv with mac os

I'm trying to iterator over some directories containing approximately 3000 images. I load the image. If the image is loaded I release it.
That is the smallest program that I can write to reproduce the error.
After loading and releasing 124 images the program stops loading images. I think this a memory issue but I don't understand what exactly causes the program to stop loading images.
I'm using OpenCV on my Mac. I don't know how exactly I can figure out which version I'm using.
Here is the Code from my project.
bool FaceDetectionStrategy::detectFace(std::string imagePath) {
IplImage *img = cvLoadImage(imagePath.c_str(), CV_LOAD_IMAGE_COLOR);
if (img) {
std::cout << "Image loaded " << imagePath << std::endl;
cvReleaseImage(&img);
} else {
std::cout << "Image not loaded " << imagePath << std::endl;
}
return true;
}
This method is called for every image in the directorys I'm iterating through. After 124 images the if(img) part evaluates to false and the else branch is executed. If I try to load images from other parts of the program later on they also won't load.
Edit it is not a memory issue. Mac Os standard max open files is 256 after changing it to 512 I can open 251 images. so it seems that OpenCV doesn't closes the image files after loading them.
Searching the bugtracker from OpenCv showed this answer to the problem: cvLoadImage with Mac ImageIO leaves file handles open.
It seems that this is a bug in the OpenCV mac implementation and the only way to solve it is to install a newer version of OpenCV.
EDIT installing the last version of OpenCV from the repository trunk solves the problem. Sometimes it helps checking the BugTracker of the frameworks you are using...
Behavior concerning memory rarely has to do with a consistent number, in my experience. The only way it could be that consistent is if there is some sort of internal limit in cvLoadImage that happens to be the not-very-common number 124. But your logic seems fine to me, that your images should be released.
More likely, since I assume your directories aren't changing between tests, that 125th image is bad.
Have you verified that the image you are trying to load actually exists? If it does (which it probably does), check that the image file format is supported by OpenCV. If that is also true, make sure the file is not corrupted by opening it with another editor.
You can have OpenCV help you out with errors. Use cvGetErrStatus() to check if there was an error, then use cvErrorStr() to get a textual description of it. You can do something like this:
// I would recommend putting this in a file, like CVUtility.h
#include <exception>
void check_CV_Error(void)
{
int errorCode = cvGetErrStatus();
if (errorCode) // I'm assuming 0 means no reportable error
{
throw std::runtime_error(cvErrorStr(errorCode));
// std::cerr << cvErrorStr(errorCode);
// ^ if you would rather not use exceptions
}
}
Your code then becomes:
bool FaceDetectionStrategy::detectFace(std::string imagePath) {
IplImage *img = cvLoadImage(imagePath.c_str(), CV_LOAD_IMAGE_COLOR);
if (img) {
std::cout << "Image loaded " << imagePath << std::endl;
cvReleaseImage(&img);
} else {
std::cout << "Image not loaded " << imagePath << std::endl;
check_CV_Error(); // find reason for error
}
return true;
And that will throw an exception for you to catch and log, and possibly react on. (Or print the error to console if you use the std::cerr version)