dereferencing SDL_Surfaces? - c++

is there any way to copy a SDL surface to another, like creating a backup copy, without modifying the original when the copy is modified? *surface = *original_surface dosnt work. SDL_Surface does not have any constructors, so i cant do anything like surface = new SDL_Surface (original_surface). currently, i am opening the original image constantly, but it takes longer to open the image than for one loop to finish. this causes a lot of lagging, and eventually errors, causing my program to end

You can create a new compatible surface:
copy = SDL_CreateRGBSurface(flags, width, height, original->format.BitsPerPixel,
original->format.Rmask, original->format.Gmask,
original->format.Bmask, original->format.Amask);
And then blit the original into the copy:
SDL_BlitSurface(original, NULL, copy, NULL);

Related

Reloading TTF_Font* for just changing pointsize using TTF_OpenFontRW?

I want to be ablte to dynamically resize the text that I rendered to the screen with my TTF_Font* object. The way I am doing it right now is, I close the font
TTF_CloseFont(font);
and then just open it right after using the new point size
font = TTF_OpenFont(filepath, new_pointsize);
Now my question is, is this the efficient way to do things? Does that mean that every time I reload my font, changing the pointsize, I delete the in-memory structure of my font and then a new one is created meaning I read the whole file from disk again?
Now in order to make it more efficient, I would like to keep my .ttf-file in memory somehow and just change the size of it. Is that possible?
I was trying to do something with SDL_RWops but I didn't succeed. Here is what I did in my load function:
font_rw = SDL_RWFromFile(filepath, "r");
font = TTF_OpenFontRW(font_rw, 0, pointsize);
and in my reload function:
TTF_CloseFont(font);
font = TTF_OpenFontRW(font_rw, 0, pointsize);
Now the problem is, that the font is not being loaded correctly, so I get NULL back as the return value for the TTF_OpenFontRW in reload.

Convert GDI Plus Bitmap to QPixmap

I have a GdiPlus::Bitmap object, and I need to build a function that converts it to a QPixmap. I'm using Qt 5.8.0, and performance is a concern of mine. I cannot find anything about this online, even searching for GDI+ images to QImages. I don't NEED to access pixel data, so all I have to do is get a GDI+ bitmap converted into something that can be displayed in a QWidget.
The most promising solution I've found so far is to use the fromHBitMap() in QtWin: http://doc.qt.io/qt-5/qtwin.html#fromHBITMAP, but I don't have the required knowledge/experience to be able to understand handles to bitmaps.
I assume you have "Bitmap" object in your hand.
Also I assume your development environment supports both "Windows programming" and "Qt".
Based on above assumptions, you can get the HICON from the "Bitmap" and pass it to "QPixmap QtWin::fromHICON(HICON icon)".
Steps:
First you have to include "Gdiplus.h".
Also include "QtWin".
HICON hIcon;
Status st = <<Your Bitmap Object>>.GetHICON(&hIcon);
QPixmap pixM = QtWin::fromHICON(hIcon);
Try this.
The above code is untested.
It gives an idea.
I don't NEED to access pixel data
You don't, but Qt most certainly does. Qt does not use GDI for rendering widgets - instead, it uses the raster backend that operates on a QImage. Under the hood a QPixmap is just a wrapper around a QImage and it's cheap to convert between the two as it doesn't copy any image data.
So, whatever route you choose will involve QImage at some point, even if it's in the form of a QPixmap.
I had a method of doing this where I flipped the red and blue bytes, then used the following code to convert it from a Gdiplus::Bitmap to a QPixmap:
QPixmap getAsQPixmap(Gdiplus::Bitmap bitmap)
{
// One of my functions to flip blue and red bytes of the image
_flipBlueWithRed();
// m_pBytes is a pointer to an unsigned char that marks the start of the image
// It was retrieved from locking the Gdiplus::Bitmap
auto result = QPixmap::fromImage(QImage(m_pBytes, getWidth(), getHeight(), QImage::Format_RGB888));
// Restore data back to original state
_flipBlueWithRed();
return result;
}
This method, however, was slow and took a good 60 milliseconds to execute. So my new method was to save the Gdiplus::Bitmap to file, and use the path to that file to read in from QPixmap's constructor. This method is MUCH faster, around 5 milliseconds.
QPixmap getAsQPixmap(GdiPlus::Bitmap bitmap)
{
std::string path = "C:/path_to_img.....png";
// One of my functions to unlock the Gdi+ bitmap
_unlockGdiPlusBitmap();
// Get Clsid
CLSID pngClsid;
getEncoderClsid(format_mime, &pngClsid);
// Save bitmap
// stringToWString() was a function that I wrote to convert a standard string to be a wide string
bitmap->Save(stringToWString(path).c_str(), static_cast<const CLSID*>(&pngClsid));
// Lock bitmap
_lockGdiPlusBitmap();
// Create the QPixmap
QPixmap new_img(path);
return new_img;
}

Does loading an image in the same surface free the old image?

I'm new to SDL and, in this part of my program, I would like to be able to change the image of an existing surface. My question is, will this automatically unload the previous image or will I have to use SDL_FreeSurface() and then reload the surface altogether? I don't want to end up with a large amount of images loaded that don't need to be loaded. Visual explanation:
string path = "Image.png";
SDL_Surface* loadedSurface = IMG_Load((path.c_str());
If I use loadedSurface again with a different image, will the original one be unloaded?
path = "NewImage.png";
loadedSurface = IMG_Load(path.c_str());
Or will I have to do something like this every time I load a new image:
SDL_FreeSurface(loadedSurface);
path = "NewImage.png";
SDL_Surface* loadedSurface = IMG_Load(path.c_str());
This may be alright, I'm just not sure if creating a new surface every loop will be more intensive than another, easier way. Thank you!
You need to call SDL_FreeSurface before loading a new surface and overwriting the old pointer.
Think about it: at the point you call IMG_Load the second time, SDL is just loading the image, and doesn't know what you're going to do with the returned pointer. So it can't free any of the already loaded surfaces. You have to do that yourself.

C++ SDL How to undo a BlitSurface

I have used SDL to display an image:
SDL_BlitSurface(sprite, NULL, screen, NULL);
My question is: Is it possible to remove the image from the window?
Generally speaking, no. SDL_BlitSurface() overwrites (a subset of) the contents of the destination surface, essentially the same as an assignment to an array of pixel data. One solution is to redraw the entire screen every frame, first clearing with:
SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, r, g, b));
For better performance, you could keep track of which regions on the screen are “dirty” and need to be repainted each frame, and only repaint those regions. SDL offers some functions for doing that (SDL_UpdateRect() and SDL_UpdateRects()) but I wouldn’t bother unless rendering speed becomes a serious issue. Most SDL applications seem to be able to do 30–50 frames per second; beyond that, you’ll want to look at OpenGL.

How to copy a CImage object?

I am trying to copy a CImage so that I can do some manipulation with it's pixels. I've tried this where source is a pointer to a loaded CImage object.
CImage* dest = new CImage(*source);
However this doesn't seem to work and I believe source and dest are pointing to the same memory.
How would I create a new copy totally detached from the previous CImage?
If this is a question about MFC/ATL CImage then you can create new instance and use Create to initialize it to the size of the original CImage. Then use BitBlt to copy contents.