Save a captured image using QCameraImageCapture::capture() in PNG Format - c++

this is literally my first question in a forum.
So I'm a Qt newbie and I'm stuck at this little detail.
I'm creating this application that takes pictures and saves them, but the issue is that it saves then in a "JPEG" format and i need them in "PNG" or "GIF" or "tiff" and i I've tried a lot of stuff but nothing worked, so here's my code :
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
_camera_view = new QCameraViewfinder();
_take_image_button = new QPushButton("Take Image");
_turn_camera_off = new QPushButton("Turn Off");
_turn_camera_on= new QPushButton("Turn On");
_central_widget = new QWidget();
setCentralWidget(_central_widget);
_setup_ui();
_setup_camera_devices();
set_camera(QCameraInfo::defaultCamera());
connect(_take_image_button, &QPushButton::clicked, [this]{
_image_capture.data()->capture();});
connect(_turn_camera_off, &QPushButton::clicked, [this]{_camera.data()->stop();});
connect(_turn_camera_on, &QPushButton::clicked, [this]{_camera.data()->start();});}

You should get QImage in some point of your work. It has save member. Example from cited documentation:
QImage image;
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "PNG"); // writes image into ba in PNG format
So the usage in context of QCameraImageCapture goes something like that:
QObject::connect(cap, &QCameraImageCapture::imageCaptured, [=] (int id, QImage img) {
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
img.save(&buffer, "PNG");
});

For anyone that might encounter this problem in the future, here's the solution i've found :
_image_capture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);
QObject::connect(_image_capture.data(), &QCameraImageCapture::imageCaptured, [=] (int id, QImage img) {
fileName = "image.png";
path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/" + fileName;
img.save(path, "PNG");
});

Related

I want to show image in new window as soon as image is clicked in mainwindow qt

I want to display my image in a new window . So i am trying to pass the path of the image as value through constructor
void DicomWidget::mouseDoubleClickEvent(QMouseEvent *event){
qDebug() << ui->diWidget->whatsThis();
QString path = ui->diWidget->whatsThis();
EditWindow * editWindow = new EditWindow(this);
editWindow->setWindowTitle(path);
editWindow->setWhatsThis(path);
editWindow->show();
}
I want to pass the path in constructor but if I do the UI of the editwindow is not rendering
my editwindow.cpp
#include "editwindow.h"
#include "ui_editwindow.h"
EditWindow::EditWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::EditWindow)
{
ui->setupUi(this);
}
EditWindow::~EditWindow()
{
delete ui;
}
//Here i need to have refernce to this how shoul i give it
EditWindow::EditWindow(QString& filepath){
QFile file (filepath);
QFileInfo fileInfo(file.fileName());
QString filename(fileInfo.fileName());
QString name = filename;
currentDicomPath = filepath;
}
void EditWindow::on_pushButton_clicked()
{
currentDicomPath = EditWindow::windowTitle();
qDebug() <<"Hello9" << currentDicomPath;
}
By rewriting the constructor with EditWindow::EditWindow(QString& filepath) the Qt constructor with EditWindow::EditWindow(QWidget *parent) won't run, and thus you can't see any rendering.
Consider amending the existing constructor with something like EditWindow::EditWindow(QWidget *parent, QString& filepath) and add your custom code below ui->setup(this);
After that, you are able to initiate your class with EditWindow* editWindow = new EditWindow(this, filepath);
Otherwise, you just created an overload of the existing constructor.

How to put a QProgressBar inside a QTextEdit

I am designing a command log using QTextEdit and I was wondering how to put a QProgressBar, if it is possible, everytime the user interacts with the user interface and only for specific commands. For example if the user upload images than the QProgressBar should be there, if the user is only setting some controls, then it is not necessary. So far I didn't find anything that describes that.
For example I am putting below a snipped of code that should carry the QProgressBar, (e.g. the user uploads images on a QGraphicsView and show the load percentage progress):
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
mDockWidget_A = new QDockWidget(QLatin1String("Command Log"));
mDockWidget_A->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
mDockWidget_A->setMinimumHeight(30);
// Adding object to the DockWidget
mNewText = new QTextEdit;
mNewText->setReadOnly(true);
mNewText->setStyleSheet("background-color: light grey;");
mNewText->setMinimumHeight(50);
mNewText->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
mDockWidget_A->setWidget(mNewText);
addDockWidget(Qt::BottomDockWidgetArea, mDockWidget_A);
resizeDocks({mDockWidget_A}, {200}, Qt::Horizontal);
}
void MainWindow::on_originalmgA_clicked()
{
imageOriginlUploadA();
QSize s{32, 32};
QTextDocumentFragment fragment;
fragment = QTextDocumentFragment::fromHtml(
QString(R"(<img src='/home/path/toDesktop/working.png' height="%1" width="%2">)")
.arg(s.width())
.arg(s.height()));
mNewText->textCursor().insertFragment(fragment);
mNewText->append("\n");
mNewText->setVisible(true);
}
void MainWindow::imageOriginlUploadB()
{
dir_Original_B = QFileDialog::getExistingDirectory(this, tr("Choose an image directory to load"),
filesListRight, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if(dir_Original_B.length() > 0){
QImage image;
QDir dirBObj(dir_Original_B);
QStringList filesListRight = dirBObj.entryList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst);
ui->labelOrigImageB->setPixmap(QPixmap::fromImage(image.scaled(125,125,Qt::KeepAspectRatio,Qt::SmoothTransformation)));
for ( int i = 0 ; i < filesListRight.size() ; i++ )
{
ui->listWidgetOriginalImgB->addItem(filesListRight.at(i));
}
ui->listWidgetOriginalImgB->update();
ui->labelOrigImageB->show();
}
}
Is it possible to insert a QProgressBar inside a QTextEdit? And if yes, can anyone please point in any useful direction or provide some example about this issue?

QTextDocument::DrawContents skips resources?

I have this setup:
// ...
// variable document is a QTextDocument* which has some 'RichText' + 'Images'
QTextEdit textEdit;
textEdit.setDocument(document);
textEdit.setLineWrapMode(QTextEdit::LineWrapMode::NoWrap);
auto image = QImage(document->size().width(), document->size().height(),
QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent);
QPainter painter(&image);
document->drawContents(&painter);
// ...
I'm doing this to have my text rendered in a long horizontal QImage (hence the "NoWrap" LineWrapMode), so I can select a small part of it at a time with QImage::copy(QRect) and create a scrolling text effect.
The reason I'm doing it this way is that I need to have a QImage at the end which then I would feed its buffer (QImage::bits()) to the hardware that I'm using as my final output.
So it works great, it displays formatted text with fonts and colors and everything except for the images, it seems to skip them, notice the file icon in "result of text with image" picture.
This is text only in editor
This is result of text only
This is text with image in editor
This is result of text with image
This is how I'm inserting images to my QTextDocument:
QImage image(url.toLocalFile());
if (image.isNull())
return;
image = image.scaledToHeight(getDocumentHeight(), Qt::SmoothTransformation);
auto filename = QUrl(url.fileName());
textEdit->document()->addResource(QTextDocument::ImageResource, filename, image);
textEdit->textCursor().insertImage(filename);
So I don't think it's because "DrawContents" fails to find the image resource file or something like this.
What should I do? Is there something that I'm missing? Any kind of help in the matter is highly appreciated! ;)
In the following code I show how an image should be loaded, then save it to a file, probably the error is that you have not finished painting, for this you must call painter.end() or delete painter from memory.
main.cpp
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget widget;
QVBoxLayout vlayout(&widget);
QTextEdit textEdit;
QPushButton button("save image");
QPushButton loadButton("Load and Insert");
vlayout.addWidget(&loadButton);
vlayout.addWidget(&textEdit);
vlayout.addWidget(&button);
widget.show();
textEdit.append("some text");
QObject::connect(&loadButton, &QPushButton::clicked,[&textEdit](){
QString filename = QFileDialog::getOpenFileName(&textEdit, "Select", "", "*.png");
if(!filename.isEmpty()){
QImage image(filename);
QUrl url = QUrl::fromLocalFile(filename);
image = image.scaledToHeight(100, Qt::SmoothTransformation);
textEdit.document()->addResource(QTextDocument::ImageResource, url, image);
textEdit.textCursor().insertImage(image);
}
});
QObject::connect(&button, &QPushButton::clicked, [&textEdit](){
QImage image(textEdit.document()->size().toSize() , QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent);
QPainter painter(&image);
textEdit.document()->drawContents(&painter);
painter.end();
image.save("image.png");
});
return a.exec();
}

Download image from QNetworkAccessManager

I saw an other thread talking about this, but I'm not succeeding in the display of my image.
Currently, I'm downloading my image like this :
void MyClass::imgHandle() {
QNetworkAccessManager *nam = new QNetworkAccessManager(this);
QUrl url(_code.c_str());
QNetworkReply* reply = nam->get(QNetworkRequest(url));
QEventLoop eventLoop;
connect(reply,SIGNAL(finished()),&eventLoop,SLOT(quit()));
eventLoop.exec();
if (reply->error() == QNetworkReply::NoError)
{
QImageReader imageReader(reply);
imageReader.setAutoDetectImageFormat (false);
_img = imageReader.read();
}
}
_code is built from a code got from a Json parsing, and the url looks like this : http://l.yimg.com/a/i/us/we/52/33.gif
_img is a QImage in my class.
And in my other class I do this :
int OtherClass::displayWeather()
{
MyClass mC = new MyClass;
mC->exec() // Where I get the code from the Json
QLabel *imgWeather = new QLabel(this);
imgWeather->setPixmap(QPixmap::fromImage(mC->getImg()));
// getImg() return a QImage.
//The QImage created in MyClass.
imgWeather->setGeometry(1700, 0, 120, 120);
}
And at the end .. Nothing is displayed !
You should check the QImageReader::read result:
QImageReader imageReader(reply);
imageReader.setAutoDetectImageFormat(false);
QImage _img = imageReader.read();
if (_img.isNull())
{
qDebug() << imageReader.errorString();
}
In your case the error is "Unsupported image format".
By default QImageReader tries to autodetect the image format and you've just disabled it by calling setAutoDetectImageFormat(false). Remove it and QImageReader will do the job.

How to load an image from a file in Qt?

Generally, I've been searching for a while and could not find a serious answer. The problem is that I've a QString variable containing certain url, e.g. "C:/Users/Me/Desktop/image.png". How to open it and display the image in my application window?
I know the problem might seem trivial, however I can't find a working solution.
Load the image by using QPixmap and then show it with QLabel:
QString url = R"(C:/Users/Me/Desktop/image.png)";
QPixmap img(url);
QLabel *label = new QLabel(this);
label->setPixmap(img);
ImageViewer example
void LoadAvatar(const std::string &strAvatarUrl, QLabel &lable)
{
QUrl url(QString().fromStdString(strAvatarUrl));
QNetworkAccessManager manager;
QEventLoop loop;
QNetworkReply *reply = manager.get(QNetworkRequest(url));
QObject::connect(reply, &QNetworkReply::finished, &loop, [&reply, &lable,&loop](){
if (reply->error() == QNetworkReply::NoError)
{
QByteArray jpegData = reply->readAll();
QPixmap pixmap;
pixmap.loadFromData(jpegData);
if (!pixmap.isNull())
{
lable.clear();
lable.setPixmap(pixmap);
}
}
loop.quit();
});
loop.exec();
}