Working with Bitmaps in WxWidgets - c++

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.

Related

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

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!

Create Pango Layout Before Cairo Surface

In my application, I am using Pango and Cairo to create text textures. These textures have their width fixed, but should scale their height to fit text contents. The parent objects involved in this situation will then scale their heights to match the text.
The problem is, the way I have been initializing Pango and Cairo does not allow for this. Currently, the system is set up by:
cairo_surface_t* cairoSurface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, sizeX, sizeY );
cairo_t* cairoContext = cairo_create( cairoSurface );
PangoLayout* pangoLayout = pango_cairo_create_layout( cairoContext );
Which fixes the height, at least of the surface - something I do not want to do, at least not all the time.
My understanding is that if the layout height is not specified, it will automatically scale the height, which can then be found via pango_layout_get_size(). I would like to create the layout first and then use the output of this function to create the surface.
However, pango_cairo_create_layout() requires the surface to already be created, and I have been unable to find a way to render a layout from pango_layout_new() via Cairo. The API docs one of the render functions, pango_cairo_update_layout(), specify that pango_cairo_create_layout() had to be used to create the layout; however, the more important function, pango_cairo_show_layout(), notes no such requirement, and I am not sure if that means that any Pango layout is allowed or not. While I could test if it works, I'm afraid that trial and error could lead me to undefined behavior.
I feel like I'm stuck in a chicken and egg situation, and the documentation for Pango is mostly an API reference with little explanation of how the library is intended to be used. Is there a way to do this properly?
I've figured this process out. Hopefully the information is helpful - although I make no claims to this being the "correct" way to do any of this, just that this works.
First, set up FontConfig. This might not be necessary on some systems - it is probably OK to leave it automatic on Linux. On Windows, though, FontConfig is problematic. The easiest way to handle it is to create a config in memory and point it to where you want it to look for fonts. I pointed it to the resource directory of my program. You could use "C:\Windows\Fonts", but note this takes forever to load. Loading a proper font.conf file is probably the best approach, but I had little luck myself.
gchar* workingDir = g_get_current_dir();
gchar* resourceDir = g_strjoin( NULL, workingDir, "/Resources", (char*)0 );
FcConfigAppFontAddDir( fontConfig, (const FcChar8*)resourceDir );
g_free(workingDir);
g_free(resourceDir);
FcConfigBuildFonts( fontConfig );
FcConfigSetCurrent( fontConfig );
Then, you have to create a font map, Pango Context, and Pango Layout:
PangoFontMap* fontMap = pango_cairo_font_map_new();
PangoContext* pangoContext = pango_font_map_create_context( fontMap );
PangoLayout* pangoLayout = pango_layout_new( pangoContext );
Now, using a manually created (not from pango_cairo_create_layout()) layout doesn't seem to automatically load fonts. Trying to use a font that is in the font map but not loaded causes Pango-Cairo to crash (using one that is flat out not listed just goes to the default). As such, load all fonts listed in the font map:
FcPattern *p = FcPatternCreate();
FcObjectSet *os = FcObjectSetBuild(FC_FAMILY,NULL);
FcFontSet *fs = FcFontList(fontConfig, p, os);
FcPatternDestroy( p );
FcObjectSetDestroy( os );
for( int i = 0; i < fs->nfont; ++i )
{
guchar* fontName = FcNameUnparse( fs->fonts[i] );
PangoFontDescription* fontDesc = pango_font_description_from_string( (gchar*)fontName );
pango_font_map_load_font( fontMap, pangoContext, fontDesc );
pango_font_description_free( fontDesc );
g_free(fontName);
}
To specify the width:
pango_layout_set_width( pangoLayout, sizeX * PANGO_SCALE );
This is also around the point you should set justification/alignment/etc..
Then you can insert your text:
pango_layout_set_markup( pangoLayout, text.c_str( ), -1 );
After this, you can get the layout height via pango_layout_get_pixel_size() and use that to create Cairo's objects. Then you can render it via:
cairo_move_to(cairoContext, 0, 0);
pango_cairo_update_layout( cairoContext, pangoLayout );
pango_cairo_show_layout( cairoContext, pangoLayout );

Windows Forms - picture box. How to delete an Image

I am working in an application where there is a conbobox and a picturebox. The user selects a path and the conbobox loads paths to 2000 images, and displays the first one. When the user changes the index of the conbobox the image displayed changes, but I don't know how to delete the image in the picturebox.
If I just overwrite the image it doesnt do the job, as when I do it repeatedly the program crashes because of memory. How do I delete a image Inside the picturebox?
EDIT:
I made few changes and can't seem to reproduce the error again.. so maybe it was something else. but just for checking, is this code leaking memory?
tips: config is a singleton containing where some info, in this case, where the images are.
private: System::Void comboBox_image1_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e) {
System::String^ aux;
DIC_config* config=DIC_config::Instance();
if(config->images_path!=NULL){
aux=gcnew System::String(config->images_path);
aux=aux+"\\CAM_0\\Snap_0_0"+(this->comboBox_image1->SelectedIndex+1)+".bmp";
System::IO::FileStream^ image_file=gcnew System::IO::FileStream(aux,System::IO::FileMode::Open,System::IO::FileAccess::Read);
System::Drawing::Bitmap^ img = gcnew System::Drawing::Bitmap(image_file);
this->pictureBox_image1->Image=img;
//img->~Bitmap(); this doesnt work, deletes the image of picturebox and makes the program chrash
}
}
You have to dispose the old image. Forgetting to do so makes it likely your program runs out of unmanaged memory when the garbage collector doesn't run frequently enough. Bitmap objects are quite small, you can allocate thousands of them without ever triggering a GC, but can consume a lot of unmanaged memory for the pixel data. You dispose objects in C++/CLI with the delete operator, it calls IDisposable::Dispose().
Do note that the FileStream you use is also a disposable object. Doing it this way requires you to keep the stream opened while the bitmap is in use and close it afterwards. You correctly did not dispose the stream but forgot closing it. Too hard to get right, it is much easier to use the Bitmap constructor that accepts a string for the file path so the Bitmap class manages the underlying stream itself. Fix:
aux = config->images_path;
aux += ....;
System::Drawing::Bitmap^ img = gcnew System::Drawing::Bitmap(aux);
delete this->pictureBox_image1->Image;
this->pictureBox_image1->Image = img;
This doesn't work because you are trying to call destructor of the class, not the instance. Furthermore you do not need to call it as System::Drawing::Bitmap is under control of garbage collector, so the finalizer ( !Bitmap() ) will be called automatically if it's not referenced any longer.
What you can do if you want to close it in picturebox is
delete this->pictureBox_image1->Image;
image_file->Close(); //after closing/deleting the open bitmap
btw. your code is not pure c++, but c++/cli, so I've added the tag
First set a null pointer to the Image property and refresh the pictureBox, as given below,
pictureBox_image1->Image = nullptr;
pictureBox_image1->Refresh();

set qt c++ mainwindow always on bottom mac osx

So I am trying to set this window/ mainwindow / application in qt to always be on the bottom (like always bottom window) (so rainmeter somehow does this with their widgets), but I can't even get mac osx to do such things.
I've tried the whole
this->setWindowFlags(Qt::WindowStaysOnBottomHint);
but without any luck. Any hints? Example code is amazing.
Got bad news and good news. The bad news is it's simply not implemented.
The good news is: as Qt is open source, you can crack it open and take a look to know that. And if there's a bug you can submit a fix. Here's the deal, in the generic code for QWidget::setWindowFlags in
qwidget.cpp:9144 you have this:
void QWidget::setWindowFlags(Qt::WindowFlags flags)
{
if (data->window_flags == flags)
return;
Q_D(QWidget);
if ((data->window_flags | flags) & Qt::Window) {
// the old type was a window and/or the new type is a window
QPoint oldPos = pos();
bool visible = isVisible();
setParent(parentWidget(), flags);
// if both types are windows or neither of them are, we restore
// the old position
if (!((data->window_flags ^ flags) & Qt::Window)
&& (visible || testAttribute(Qt::WA_Moved))) {
move(oldPos);
}
// for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
d->adjustQuitOnCloseAttribute();
} else {
data->window_flags = flags;
}
}
So essentially it just sets window_flags. The mac behavior of QWidget is in qwidget_mac.mm.
And you will find no reference to Qt::WindowStaysOnBottomHint in that file. (You'll find Qt::WindowStaysOnTopHint though...)
I'll stop at saying "not possible unless you either patch Qt, or otherwise go beneath Qt".
Patching qwidget_mac.mm is left as an exercise to the reader. :-)

QT - Pointer to global memory

First: sorry for my English from Google
The question:
I'm changing the IDE, I'm migrating from Borland to QT with QT Creator.
In Borland I used a class contained in a type library (APuma.dll). The prototype was:
BOOL XOpen (long hDIB, LPCTSTR FileName) / / OpenOCR - Cuneiform
hDIB is a pointer to global memory of an image.This version Not Work with files.
To pass a pointer to global memory of an image, I used GDI+, but in QT can not find anything similar, and the inclusion of Gdiplus.h and GdiPlusInit.h generates too many errors.
How do I give access to global memory where I host the image to XOpen?
Thank you very much.
OK, I think i understand what you need. You need a pointer to the pixels of the image so you can pass it. Your simplest option in Qt is using a QImage object and using its bits() member.
Something like this:
QImage image(filename);
uchar* p = image.bits();
XOpen(reinterpret_cast<long>(p), whatever);
just be sure that XOpen somehow knows the dimmensions of the image. And that you have it in the right format (See QImage::convertToFormat). For more overall information check the Qt documentation at http://doc.qt.io/qt-4.8/qimage.html