Problems Displaying Mat Image in Windows Forms C++ Visual Studio 2019 - c++

I am new to C++ gui design and I am not too familiar with using pointers. Recently I have run into a few problems when trying to get an OpenCV Mat Image to display in a PictureBox in a constructed gui. I have searching online and even found a very similar post to my question but when trying to implement the guidance I ran into an exception when trying to operate the gui.
A very similar post
Displaying webcam feed in cv::Mat format in a picturebox
Code I grabbed from this post to save you a click:
void DrawCVImage(System::Windows::Forms::Control^ control, cv::Mat& colorImage)
{
System::Drawing::Graphics^ graphics = control->CreateGraphics();
System::IntPtr ptr(colorImage.ptr());
System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(colorImage.cols,colorImage.rows,colorImage.step,System::Drawing::Imaging::PixelFormat::Format24bppRgb,ptr);
System::Drawing::RectangleF rect(0,0,control->Width,control->Height);
graphics->DrawImage(b,rect);
delete graphics;
}
Now I am trying to display a "video" feed (really an array of cv::Mat Objects) but I am having a
"Source Not Available"/System.ArgumentException: 'Parameter is not valid.'
screen come up when I attempt to call the function that houses that playback. I also know specific line of code that throws the issue is the line
System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(colorImage.cols,colorImage.rows,colorImage.step,System::Drawing::Imaging::PixelFormat::Format24bppRgb,ptr);
Now for specifics, the form has an event (currently the click on the picture box, but I want to move to a "play" button in the future) and on this event, the code:
private: System::Void leftEyeImage_Click(System::Object^ sender, System::EventArgs^ e) {
std::cout << "Click Received" << std::endl;
cv::Mat& frame = cv::imread("Desktop/testcapture.png");
std::cout << "Import successful" << std::endl;
drawLeftEye(this, frame);
}
This code does get execute on click and starts the function drawLeftEye. The function is a modified version of the code from the other post and is below:
This is on the ShowResults.cpp file
namespace DevProject {
void ShowResults::drawLeftEye(System::Windows::Forms::Control^ control, cv::Mat& framebmp) {
System::Drawing::Graphics^ graphics = control->CreateGraphics();
std::cout << "Now Here" << std::endl;
System::IntPtr ptr(framebmp.data);
// Issue line
System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(framebmp.cols, framebmp.rows, framebmp.step, System::Drawing::Imaging::PixelFormat::Format32bppRgb, ptr);
std::cout << "Converted successfully" << std::endl;
System::Drawing::RectangleF rect(0, 0, control->Width, control->Height); //No issue
graphics->DrawImage(b, rect);
std::cout << "Now Here before delete" << std::endl;
delete graphics;
//delete b;
}
}
I know based on my cout statements that I do make it into my function and I know my code compiles and runs through the function if I comment out the line:
System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(framebmp.cols, framebmp.rows, framebmp.step, System::Drawing::Imaging::PixelFormat::Format32bppRgb, ptr);
//As well as (but only because b is defined in the line above^
graphics->DrawImage(b, rect);
I am not quite sure how to fix this, my friend mentioned this could be a memory issue but I don't know how I would go about fixing it. It is also very possible I have made a simple mistake in the design of this or where my pointers are going and I am just not competent enough to know the error.
By the way the pointer for "this" that is called in the function is linked to the Windows Autogenerated code (from gui construction) of:
this->leftEyeImage->Anchor = System::Windows::Forms::AnchorStyles::None;
this->leftEyeImage->BorderStyle = System::Windows::Forms::BorderStyle::FixedSingle;
this->leftEyeImage->Location = System::Drawing::Point(11, 836);
this->leftEyeImage->Name = L"leftEyeImage";
this->leftEyeImage->Size = System::Drawing::Size(991, 646);
this->leftEyeImage->TabIndex = 4;
this->leftEyeImage->TabStop = false;
this->leftEyeImage->Click += gcnew System::EventHandler(this, &ShowResults::leftEyeImage_Click);
Any and all advice or tests would be very appreciated as I am both interested in the answer and the reasoning. Thanks in advance!

Related

SFML/C++ | Drawing text from a vector gives access violation error

I'm making my own text editor with C++ and the SFML multi-media library. I'm now trying to implement a user interface so users can interact and select documents to edit. I have this function:
std::vector<sf::Text> Menu::GetAllTextOptions(TextHandler& handler, sf::Font font) {
std::vector<TextDocument>* all_available_documents = handler.GetTextDocuments();
std::vector<sf::Text> menu_text_options;
for (int i = 0; i < all_available_documents->size(); i++) {
sf::Text text;
text.setFont(font);
text.setString(std::to_string(i) + ") " + all_available_documents->at(i).GetDocumentName() + '\n');
menu_text_options.push_back(text);
}
return menu_text_options;
}
What this is supposed to do is collect all of the names of already existing text documents in a path that I have specified (the code behind gathering the TextDocument objects works perfectly). It then makes a text object, sets a font to it and sets the string to the name of the document. When I std::cout the count of the vector, it displays correctly the amount of documents that exist.
I then have a function that is supposed to go through the vector of texts and draw all of them, so they can be later displayed:
// ACCESS VIOLATION ERROR
void Menu::DrawAllOptions(sf::RenderWindow& window, std::vector<sf::Text>&
menu_text_options) {
std::cout << menu_text_options.size() << " is the current size " << std::endl;
try {
for (int i = 0; i < menu_text_options.size(); i++) {
// EXCEPTION THROWN HERE
window.draw(menu_text_options.at(i));
}
}
catch (const std::exception& ex) {
std::cout << "Exception: " << ex.what() << '\n';
}
}
Finally, I have the main loop where everything comes into place:
std::string Menu::MenuControl(TextHandler& handler) {
Utility utility;
sf::RenderWindow menu_window(sf::VideoMode(800, 600), "Menu");
sf::Color backgroundColor(0, 32, 63);
sf::Event event;
sf::Font font;
sf::Text menu_text;
utility.CheckFontLoaded(font, "../8bitfont.ttf");
std::vector<sf::Text> menu_text_options = GetAllTextOptions(handler, font);
int menu_counter = 0; // Start at the first document, count goes up and down
with arrows
menu_text.setOrigin(sf::Vector2f(-20.f, 0.f));
menu_text.setFont(font);
while (menu_window.isOpen()) {
// DRAWING
menu_window.clear(backgroundColor); // Setting menu background color
//window.draw(background_overlay);
DrawAllOptions(menu_window, menu_text_options);
// DISPLAYING
menu_window.display();
// TO DO - ABSTRACT USER INPUT LOGIC
while (menu_window.pollEvent(event)) {
switch (event.type)
{
case sf::Event::Closed:
menu_window.close();
return "Test";
break;
case sf::Event::TextEntered:
if (event.text.unicode < 128) {
}
break;
case sf::Event::KeyReleased:
break;
}
}
}
return "Not correctly working";
}
The exact error I get is:
Exception thrown at 0x00007FFA3E2869E9 (sfml-graphics-d-2.dll) in texteditor.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
At this point, I've attempted putting a try catch block, initializing the vector with new and making everything within the main loop function. I am sensing its something to do with the Text objects that I push into the vector, but I tried initializing them differently as well with no success. Any suggestions would be greatly appreciated!
The answer to the problem, as mentioned by #Botje, is that the function Menu::GetAllTextOptions was getting a copy of font, which ultimately ended up not being loaded and resulting in an access violation.

Magick++ gif annotation artefacts

I want to make an annotation in a gif image using ImageMagick and specifically Magick++, the code is quite simple, but the output image has artifacts in the text, if the gif does not move, then the artifacts do not appear, here:
here is the code itself, very simple:
int main()
{
InitializeMagick(nullptr);
list<Image> *imageList = new list<Image>();
try {
readImages(imageList, "source.gif" );
}
catch( exception &error_ )
{
cout << "Caught exception: " << error_.what() << endl;
return 1;
}
for(Image &i : *imageList) {
i.fontPointsize(36);
i.font("helvetica-bold");
i.fillColor(Color("white"));
i.fontStyle(MagickCore::ObliqueStyle);
i.annotate("why are you lagging", SouthGravity);
}
writeImages(imageList->begin(), imageList->end(), "/home/deymos/GifnText/n.gif");
return 0;
I tried to save the list of images as png and this is what I saw when the movement on the gif started:
is it possible to fix it, or is it a bug?
If this cannot be fixed, maybe there are similar tools with which I can implement text on gifs? or at least a library that can disassemble gifs into images and fold, I can do the rest with qt, tnx.

Problem when dereferencing std::unique_ptr with QT (Segmentation fault)

(Sorry for my future mistakes, I am fr)
I am creating a program to control the pc with a phone in c++ ( https://github.com/titicplusplus/PCPhone )
The server part works good, so I would like to add graphics interfaces for user, I decided to use QT.
When I stop the program QT, I have segmentation fault, and that stops the server.
My function that run the graphic interface:
void start_g(int argc, char **argv)
{
QApplication app(argc,argv);
QFile File(":/stylesheet.qss");
File.open(QFile::ReadOnly);
QString StyleSheet = QLatin1String(File.readAll());
app.setStyleSheet(StyleSheet);
ui interface; //QWidget window
interface.start();
std::cout << "start gui" << std::endl;
interface.show();
app.exec(); //return 0
return;
}
I encapsulated the code in a function because I would like to run it in a thread, but for now during my tests, I don't do this.
Here is my class ui (user interface)
class ui : public QWidget
{
public:
ui();
void start();
void change_file();
void change_port();
void freset();
void fapply();
~ui(); //Here is the problem
private:
openf f_open; //to open the extension s file
std::unique_ptr<QFormLayout> formLayout;
std::unique_ptr<QGroupBox> settings;
std::unique_ptr<QVBoxLayout> main_layout;
std::unique_ptr<QGridLayout> grid;
std::vector< std::vector< std::unique_ptr<QPushButton> > > tab2d;
std::unique_ptr<QGroupBox> all_button;
std::unique_ptr<QSpinBox> port_l;
std::unique_ptr<QPushButton> button_f;
std::unique_ptr<QPushButton> apply;
std::unique_ptr<QPushButton> reset;
std::unique_ptr<QLabel> text_f;
};
and the important function
ui::ui() {}
void ui::start()
{
grid = std::make_unique<QGridLayout>( this );
/** Code that you don't need, I guess **/
std::cout << "setting part" << std::endl;
all_button = std::make_unique<QGroupBox>("Slide");
all_button->setLayout(grid.get());
port_l =std::make_unique<QSpinBox>(this);
port_l->setMaximum(65535);
port_l->setValue( config_json["port"].get<int>() );
button_f = std::make_unique<QPushButton>("Open Image" ,this);
text_f = std::make_unique<QLabel>(QString::fromStdString(fs::absolute(config_json["image"].get<std::string>())), this);
apply = std::make_unique<QPushButton>(" Apply " ,this);
reset = std::make_unique<QPushButton>("Reset" ,this);
//connect(button_f.get(), &QPushButton::clicked, this, &ui::change_file);
connect(port_l.get(), QOverload<int>::of(&QSpinBox::valueChanged), this, &ui::change_port);
connect(apply.get(), &QPushButton::clicked, this, &ui::fapply);
connect(reset.get(), &QPushButton::clicked, this, &ui::freset);
//auto fileName = QFileDialog::getOpenFileName(&window, "Open Image", "/home/$USER", ("Image Files (*.png *.jpg *.bmp)"));
formLayout = std::make_unique<QFormLayout>();
formLayout->addRow("The port", port_l.get());
formLayout->addRow(text_f.get(), button_f.get()); //////////The problem is here
//formLayout->addRow(apply.get(), reset.get());
settings = std::make_unique<QGroupBox>("Settings");
settings->setLayout(formLayout.get());
main_layout = std::make_unique<QVBoxLayout>(this);
main_layout->addWidget(all_button.get());
main_layout->addWidget(settings.get());
}
So I saw on google, the problem come with the pointers and they destroy, so I try this
ui::~ui()
{
main_layout = nullptr;
settings = nullptr;
all_button = nullptr;
std::cout << "1u" << std::endl;
button_f = nullptr;
std::cout << "2u" << std::endl;
text_f = nullptr;
std::cout << "3u" << std::endl;
apply = nullptr;
std::cout << "4u" << std::endl;
reset = nullptr;
std::cout << "5u" << std::endl;
grid = nullptr;
std::cout << "bye bye" << std::endl;
}
The result is [ the errors are in french so I try to translate it ]:
1u
Segmentation fault (core dumped)
When I delete this line formLayout->addRow(text_f.get(), button_f.get());
There are no problems the deference of text_f and button_f, but with the next (apply and reset).
1u
2u
3u
Segmentation fault (core dumped)
On google, I saw a lot a time the people use the pointer and not the std::unique_ptr with qt, but I saw in general that people say "the smart pointer are better than the normal pointer.
Also, I try to replace button_f.get() to std::move(button_f).get() but that doesn't work.
For information, I am on Ubuntu 20.04, with g++-9.3 and qt5.
Thank you in advance for your answers !
Thanks G.M. and vahancho
I understand why I don't need to do std::unique_ptr .
When I learn C++ and pointer, there are rule : write one delete for every new, or better, use the smart pointer.
But with this two topics:
https://codereview.stackexchange.com/questions/43189/deleting-pointers-in-qt5/43201
Deleting Pointer to widget Qt C++
For the QT object, it's QT that deletes the pointers when the class is delete.
So I just need to need change all of my std::unique_ptr in raw pointer.

Is there a way to effectively update CAN data in QML?

Currently I am receiving CAN data in real time using socketcan API in main.cpp file.
I am constantly updating the data frame of CAN in one variable in main.cpp.
I want to express the gauge in real time by passing the variable containing the CAN data frame in main.cpp to the QML animation gauge.
I need to detect the change of the variable containing CAN data in QML in real time. I wonder if there is an effective way.
I tried to share data with QML using emit.
However, the function written by emit inside device-> connect (device, & QCanBusDevice :: framesReceived, [device] () {...} does not work.
When using it, I get the error
'this' cannot be implicitly captured in this context.
I looked up the error, but did not find the answer.
if (QCanBus::instance()->plugins().contains(QStringLiteral("socketcan"))) {
qWarning() << "plugin available";
}
QString errorString;
QCanBusDevice *device = QCanBus::instance()->createDevice(
QStringLiteral("socketcan"), QStringLiteral("vcan0"), &errorString);
if (!device) {
qWarning() << errorString;
} else {
device->connectDevice();
std::cout << "connected vcan0" << std::endl;
device->connect(device, &QCanBusDevice::framesReceived, [device]() {
QCanBusFrame frame = device->readFrame();
QString testV = frame.toString();
QString qvSpeed = frame.payload();
std::string text = testV.toUtf8().constData();
std::string vSpeed = qvSpeed.toUtf8().constData();
//At that point the vVal values ​​are being updated in real time.
//I want to pass the updated vVal to qml gui in real time.
int vVal = static_cast<int>(frame.payload()[0]);
//emit sendMessage(vVal); // 'this' cannot be implicitly captured in this context error.
std::cout << text << std::endl;
});
}
As of now, main.cpp can't send the data and QML can't solve the error.
Inside device-> connect, emit sendMessage (vVal); will cause "'this' cannot be implicitly captured in this context" error.
I'm wondering if there is a good way to implement animation by expressing QML GUI data in real time.
Your capture clause only captures device. You need to also explicitly capture this:
device->connect(device, &QCanBusDevice::framesReceived, [this,device]{ /*...*/ });
BTW, note that there's no need to specify the () for a no-args lambda expression.

Getting the file clicked on in a window or desktop window

I'm new to shell programming and having trouble getting the filepath (or really, any information) about which item is being clicked on in a window (desktop or otherwise). I'm following the general path laid out by the answer to Can i use Global System Hooks to capture which file was clicked on? but I'm not having any luck.
The clicking is the smaller issue here, so I've just substituted random values (where I know the desktop is and where a file should be located) for the mouse position. (Regardless, it doesn't work even when I'm trying this out on my mouse's current position).
LVHITTESTINFO hitTest = { 0 };
hitTest.pt.x = 55;
hitTest.pt.y = 230;
hitTest.flags = LVHT_ONITEM;
currWindow = WindowFromPoint(pt);
int index = ListView_HitTest(currWindow, &hitTest);
//cout << index + " index";
//cout << hitTest.iItem + " iltem ";
if (index != -1) {
//char* itemText = new char[256];
std::vector<wchar_t> itemText(1024);
ListView_GetItemText(window, index, 0, &itemText[0], 256);
PIDLIST_ABSOLUTE filepidl;
SFGAOF out;
std::wstring strtext = std::wstring(itemText.begin(), itemText.end());
//cout << " ";
//cout << *(strtext.c_str()) + " ";
HRESULT parse = SHParseDisplayName(strtext.c_str(), NULL, &filepidl, SFGAO_CANDELETE, &out);
if (filepidl != NULL) {
LPTSTR filePath = new TCHAR[MAX_PATH];
BOOL getPath = SHGetPathFromIDList(filepidl, filePath);
cout << *filePath ;
}
}
This is part of my code. I think there's something wrong with how I'm getting the index of the file because it keeps returning 0 but I've been hacking at this for days and am stuck. The MSDN documentation is confusing to me at best.
Any help or insight would be appreciated! I can't find any example code of this online. Thanks!
Using the listview directly like this is not a good idea because Explorer is free to implement the shell view in any way it wants and in Windows 7 and later a Explorer window no longer uses a listview, it uses a custom control by default!
If you only care about the display name and invoking the default action you can use UI Automation, it should work on other types of windows/controls as well, not just a shell file list.
If you need to know the full path and other details you can use the IShellWindows interface. Examples can be found on Raymond Chens blog here and here...