I am trying to write a function, that saves a QImage object on a hard drive as image-type file. Here's the code of the function:
void ImageMaster::saveImage()
{
QStringList mimeTypeFilters;
foreach (const QByteArray &mimeTypeName, QImageWriter::supportedMimeTypes()) {
mimeTypeFilters.append(mimeTypeName);
}
mimeTypeFilters.sort();
const QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
QFileDialog dialog(this, tr("Save Image"),
picturesLocations.isEmpty() ? QDir::currentPath() : picturesLocations.last());
dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.setMimeTypeFilters(mimeTypeFilters);
dialog.selectMimeTypeFilter("image/png");
if (dialog.exec() == QDialog::Accepted) {
qDebug() << "accepted!";
const QString& fileName = dialog.selectedFiles().first();
qDebug() << fileName;
QImageWriter writer;
writer.setFormat("png");
writer.setDevice(new QFile(fileName));
writer.setFileName(fileName);
if (!writer.write(getCurrentImage())) {
qDebug() << writer.errorString();
}
}
else {
qDebug() << "not accepted!";
}
}
And here's the output when I try to save image previously loaded into my program from the hard drive:
accepted!
"C:/Users/toshiba/Pictures/im.png"
QFSFileEngine::open: No file name specified
QFile::remove: Empty or null file name
"Device not writable"
What do I do wrong? The getCurrentImage method returns a perfectly looking when displayed QImage object.
Related
I'm following a vulkan tutorial and when i'm trying to check for validation layer support.
the function always returns false when it is supposed to return true.
this is the code:
bool app::checkValidationLayersSupport() {
uint32_t layersCount = 0;
vkEnumerateInstanceLayerProperties(&layersCount, nullptr);
std::vector<VkLayerProperties> availableLayers(layersCount);
vkEnumerateInstanceLayerProperties(&layersCount, availableLayers.data());
std::cout << layersCount << "\n";
for (const char* layerName : validationLayers) {
std::cout << layerName << "\n";
for (const auto& layerProperties : availableLayers) {
if (strcmp(layerName, layerProperties.layerName) == 0) {
std::cout << layerProperties.layerName << std::endl;
return true;
}
}
}
return false;}
validationLayers value is { "VK_LAYER_KHRONOS_validation" } (std::vector<const char*>)
after vkEnumerateInstanceLayerProperties LayersCount value is 5 so i think the problem is that the second vkEnumerateInstanceLayerProperties can't change the value of availableLayers so it remains empty
edit:
I checked it and the second vkEnumerateInstanceLayerProperties is initializing the vector but the needed validation layer is not in it.
fix: i reinstalled the sdk
I'm developing a driver for a device with Qt. I have already done that many times and I have a code that I use every time. But, this time, when I open the QserialPort, it seems to work correctly, but it is not : I can write, the device receives commands, but I cannot receive on the soft : the signal QSerialPort::ReadyRead is never triggered.
When I open the serial port with Putty (just open it without sending anything) and close it just after, my Qt soft work perfectly when I reconnect it : I can now receive correctly...
Do you have an idea of what putty do of different/more than my soft when opening the port ?
(I have the same parameters and I'm on windows and Qt 5.15.2).
My code for opening :
_serial->setPortName(com);
_serial->setBaudRate(QSerialPort::Baud115200);
_serial->setDataBits(QSerialPort::Data8);
_serial->setParity(QSerialPort::NoParity);
_serial->setStopBits(QSerialPort::OneStop);
_serial->setFlowControl(QSerialPort::NoFlowControl);
if(!_serial->open(QIODevice::ReadWrite))
{
emit error(tr("Unable to open port"));
return;
}
_serial->clear();
My code for write (simple string like "hello") :
_serial->write("Hello");
My code for connect the signal :
connect(_serial, &QSerialPort::readyRead, this, &device::processCommand);
My code for read serial (processCommand()):
QString bufferData;
if (_serial->isOpen())
{
_datas.append(_serial->readAll());
bufferData = _datas.constData();
}
EDIT : The Qt exemple 'Terminal' do not works on windows with my device but works on ubuntu...
EDIT 2 : SOLUTION : I have finally find the solution, just add _serial->setDataTerminalReady(true); after opening the QSerialPort.
Thanks.
I ran into the same problem where the read signal was not detected in the virtual USB port. In the end I came to the conclusion that the QSerialPort class shouldn't.
I solved it using QThread and Win32 API.
#pragma once
#include <windows.h>
#include <QMutex>
#include <QThread>
#include <QWaitCondition>
#define SERIAL_RX_BUF_SIZE 2047
class SerialThread : public QThread
{
Q_OBJECT
public:
explicit SerialThread(QObject *parent = nullptr);
~SerialThread();
bool startThread(const QString& portName);
void stopThread();
void request(const QString& command);
signals:
void response(char* text);
void timeout();
private:
void run() override;
bool writeCommand(const QString& command);
QString m_portName;
QString m_command;
QMutex m_mutex;
QWaitCondition m_wait;
volatile bool m_quit = false;
HANDLE m_hComm;
char m_buf[SERIAL_RX_BUF_SIZE + 1];
};
#include "serial_thread.h"
#include <QDebug>
SerialThread::SerialThread(QObject *parent) :
QThread(parent)
{
memset(m_buf, 0, sizeof(m_buf));
}
SerialThread::~SerialThread()
{
}
bool SerialThread::startThread(const QString &portName)
{
const QMutexLocker locker(&m_mutex);
m_hComm = CreateFileA(portName.toStdString().c_str(), // PORT NAME
GENERIC_READ | GENERIC_WRITE, // READ/WRITE
0, // NO SHARING
NULL, // NO SECURITY
OPEN_EXISTING, // OPEN EXISTING PORT ONLY
0, // NON OVERLAPPED I/O
NULL); // NULL FOR COMM DEVICES
if (m_hComm == INVALID_HANDLE_VALUE)
{
return false;
}
m_portName = portName;
if (!SetCommMask(m_hComm, EV_RXCHAR | EV_ERR))
{
qCritical() << "SetCommMask failed";
CloseHandle(m_hComm);
return false;
}
COMMTIMEOUTS comm_timeouts;
if (!GetCommTimeouts(m_hComm, &comm_timeouts))
{
qCritical() << "GetCommTimeouts failed";
CloseHandle(m_hComm);
return false;
}
comm_timeouts.ReadIntervalTimeout = 1;
comm_timeouts.ReadTotalTimeoutMultiplier = 0;
comm_timeouts.ReadTotalTimeoutConstant = 500;
comm_timeouts.WriteTotalTimeoutMultiplier = 0;
comm_timeouts.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(m_hComm, &comm_timeouts))
{
qCritical() << "SetCommTimeouts failed";
CloseHandle(m_hComm);
return false;
}
start();
return true;
}
void SerialThread::stopThread()
{
m_mutex.lock();
m_quit = true;
m_mutex.unlock();
m_wait.wakeAll();
wait();
}
void SerialThread::request(const QString& command)
{
m_mutex.lock();
m_command = command;
m_mutex.unlock();
m_wait.wakeAll();
}
void SerialThread::run()
{
DWORD dwEvtMask, nRead;
while (!m_quit)
{
m_mutex.lock();
m_wait.wait(&m_mutex);
m_mutex.unlock();
{
const QMutexLocker locker(&m_mutex);
if (m_command.isEmpty())
{
continue;
}
if (!writeCommand(m_command))
{
continue;
}
if (WaitCommEvent(m_hComm, &dwEvtMask, NULL))
{
if (dwEvtMask & EV_ERR)
{
qCritical() << "Wait failed with error: " << GetLastError();
break;
}
if (dwEvtMask & EV_RXCHAR)
{
if (!ReadFile(m_hComm, &m_buf, SERIAL_RX_BUF_SIZE, &nRead, NULL))
{
qCritical() << "ReadFile error: " << GetLastError();
}
else
{
m_buf[nRead] = 0;
qDebug() << "Read: " << nRead;
emit response(m_buf);
}
}
}
else
{
DWORD dwRet = GetLastError();
if (ERROR_IO_PENDING == dwRet)
{
qDebug() << "RX timeout";
emit timeout();
}
else
{
qCritical() << "WaitCommEvent failed: " << dwRet;
}
}
m_command.clear();
}
}
CloseHandle(m_hComm);
m_quit = false;
}
bool SerialThread::writeCommand(const QString& command)
{
std::string s = command.toStdString();
DWORD n;
if (!WriteFile(m_hComm, s.data(), s.length(), &n, NULL))
{
qCritical() << "WriteFile error";
return false;
}
return true;
}
I have written code to play video using ffmpeg.
The code works fine when i open AVI files but when i try to open a RTMP feed i get error.
in the utils.c file in the following function of the utils.c file
utils.c
int avcodec_parameters_to_context(AVCodecContext *codec,
const AVCodecParameters *par)
{
codec->codec_type = par->codec_type; // crash happens at this line.
}
**par was nullptr
this is my code
if (load_frame("rtmp://192.168.1.2/live/sumit", &file_width, &file_height, &myData)) {
std::cout << "file Loaded";
}
defination for load_frame function
AVFormatContext *av_format_ctx = avformat_alloc_context();
if (!av_format_ctx) {
std::cout << "could not create a format context\n";
return false;
}
if (avformat_open_input(&av_format_ctx, filename, NULL, NULL) < 0) {
std::cout << "Couldn't open video file\n";
return false;
}
AVCodecParameters* av_codec_params = nullptr;
AVCodec* av_codec = nullptr;
int video_stream_index = -1;
for (unsigned int i = 0; i < av_format_ctx->nb_streams; i++) {
auto stream = av_format_ctx->streams[i];
av_codec_params = av_format_ctx->streams[i]->codecpar;
av_codec = avcodec_find_decoder(av_codec_params->codec_id);
if (!av_codec) {
std::cout << "Couldn't find the codec\n";
continue;
}
if (av_codec_params->codec_type == AVMEDIA_TYPE_VIDEO)
{
video_stream_index = i;
std::cout << "Video stream found" << std::endl;
break;
}
if (video_stream_index < 0)
return false;
}
// set up codec context for the decoder
AVCodecContext* av_codec_ctx = avcodec_alloc_context3(av_codec);
if (!av_codec_ctx) {
std::cout << "Couldn't create AV context";
return false;
}
// this function invokes the error
if (avcodec_parameters_to_context(av_codec_ctx, av_codec_params) < 0) {
std::cout << "Couldn't initialize AVCodecContext";
return false;
}
////////////////// EDIT /////////////////////////////////
I am streaming a mpeg file and av_format_ctx->nb_streams return value of 0 , why is it not able to find any streams.
i can view the same file on vlc through streaming option in vlc.
Think of avformat_open_input like fopen. It will open a stream/file, but you still do not have an information on the stream/file contents, only a handle to do further operation with.
If you want to actually look at the data in the stream/file, you must first read the headers to determine what is inside. avformat_find_stream_info will accomplish that
On Windows, one can get any special folder path using SHGetKnownFolderPath or SHGetSpecialFolder (If I remember correctly this last one). However, I want the reverse, I have a path and want to know which special folder it belongs to, if any. I prefer this approach, because to find out if a given path's is in a particular special folder or not, I'll have to enumerate all special folders for all users which is a bit of ugly, but if there's no other way, the sky is the limit :)
I searched it but couldn't find anything useful. So does WinApi has a function to do just that?
Thanks.
You can use IKnownFolderManager::FindFolderFromPath
Available since Vista.
PS: check out the CComPtr<> class for simpler interfacing with COM.
Here is a sample i just made up, showing how to use it:
#include <atlsafe.h>
#include <Shobjidl.h>
#include <comdef.h>
void PrintKnownFolder( const CComPtr<IKnownFolder>& folder )
{
KNOWNFOLDER_DEFINITION def;
HRESULT hr = folder->GetFolderDefinition( &def );
if( SUCCEEDED(hr) ) {
std::wcout << L"Result: " << def.pszName << std::endl;
FreeKnownFolderDefinitionFields( &def );
} else {
_com_error err(hr);
std::wcout << L"Error while querying GetFolderDefinition: " << err.ErrorMessage() << std::endl;
}
}
class CCoInitialize
{
public:
CCoInitialize() : m_hr(CoInitialize(NULL)) { }
~CCoInitialize() { if (SUCCEEDED(m_hr)) CoUninitialize(); }
operator HRESULT() const { return m_hr; }
private:
HRESULT m_hr;
};
bool test()
{
CCoInitialize co;
CComPtr<IKnownFolderManager> knownFolderManager;
HRESULT hr = knownFolderManager.CoCreateInstance( CLSID_KnownFolderManager );
if( !SUCCEEDED(hr) ) {
_com_error err(hr);
std::wcout << L"Error while creating KnownFolderManager: " << err.ErrorMessage() << std::endl;
return false;
}
CComPtr<IKnownFolder> folder;
hr = knownFolderManager->FindFolderFromPath( L"C:\\Users\\All Users\\Microsoft", FFFP_NEARESTPARENTMATCH, &folder );
if( SUCCEEDED(hr) ) {
PrintKnownFolder(folder);
} else {
_com_error err(hr);
std::wcout << L"Error while querying KnownFolderManager for nearest match: " << err.ErrorMessage() << std::endl;
}
// dispose it.
folder.Attach( NULL );
hr = knownFolderManager->FindFolderFromPath( L"C:\\Users\\All Users\\Microsoft", FFFP_EXACTMATCH, &folder );
if( SUCCEEDED(hr) ) {
PrintKnownFolder(folder);
} else {
_com_error err(hr);
std::wcout << L"Error while querying KnownFolderManager for exact match: " << err.ErrorMessage() << std::endl;
}
return true;
}
CCoInitialize borrowed from The Old New Thing
I'm currently trying to learn how to use the FreeType2 library for drawing fonts with OpenGL. However, when I start the program it immediately crashes with the following error: problem loading file 'file name', this will crash in FT_Init_FreeType in xcode(cocos2dx).
#include <ft2build.h>
#include FT_FREETYPE_H
class ttf_file
{
public:
std::string filename;
FT_Library library;
FT_Error error;
ttf_file( std::string fname )
{
filename = fname;
error = FT_Init_FreeType( &library );
if (error) {
std::cerr << "problem loading file " << filename << "\n";
exit(1);
}
}
};