Use a PNG as a background image in MFC window - c++

I developed a small program in MFC that can display shapes and move them around.
I would like to be able to select PNG images that can be used as the background of the the main MFC window.
Currently, the background is set to black in the following code:
...
CBrush brush;
brush.CreateSolidBrush(RGB(0,0,0));
myCDC->FillRect(r,&brush);
...
I've found classes that might allow me to upload Bitmaps - for example [CStatic][1] - but have had no luck finding something for PNGs.
Does anyone know how to do this, or have you ever done something similar?

You can try to use the class Image of Gdiplus
http://msdn.microsoft.com/en-us/library/windows/desktop/ms534462(v=vs.85).aspx
because the png file can have the alpha property, but the bitmap does not have,
so I always use the Image to load the png file.
wchar_t szFile[256] = {0}; // png image file path
Image* m_pImage;
m_pImage = new Image(szFile, FALSE); // Load png file
// drawing png image
CPaintDC dc(this); // 用于绘制的设备上下文
Graphics graphics(dc.m_hDC);
if(m_pImage != NULL && (m_pImage->GetLastStatus() == Gdiplus::Status::Ok))
{
graphics.DrawImage(m_pImage, 0, 0, m_pImage->GetWidth(), m_pImage->GetHeight());
}
// need delete it, if you donot need it
if (m_pImage != NULL)
{
delete m_pImage;
m_pImage = NULL;
}

I think that GDI+ is the best and simple way for display images. It supports jpg, gif, tiff as well as png.
You can just display a image as below code,
void OnPaint(HDC hdc)
{
Graphics G(hdc);
Image I(L"snowman.jpg");
if (I.GetLastStatus() != Ok) {
MessageBox(hWndMain,TEXT("cannot read the image file"), TEXT("error"),MB_OK);
return;
}
G.DrawImage(&I,0,0);
}
Also, you can change image during execution time using FromFile static method.
Image *pI;
pI=Image::FromFile(L"snowman.jpg");
G.DrawImage(pI,0,0);
delete pI;

Related

GDI+ round corner image c++

I'm using GDI+ to draw image on a CStatic *element using this class :
https://www.codeproject.com/Articles/24969/An-MFC-picture-control-to-dynamically-show-picture
Here is my code onDraw
void CPictureCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (mBIsPicLoaded) {
RECT rc;
this->GetClientRect(&rc);
Graphics graphics(lpDrawItemStruct->hDC);
Image image(mPstream);
graphics.DrawImage(&image, (INT)rc.left, (INT)rc.top, (INT)(rc.right - rc.left), (INT)(rc.bottom - rc.top));
}
}
The image is displayed as a rectangle. But I would like to make it round.
How to do it ?
Thanks

How to display a image on a user defined rectangle with SDL_surface?

Im working on a project with my friend and we have run into an issue with surfaces and windows in SDL.
Currently we are able to create a window and display a rectangle on that window and move it around. The next thing we want to do is take a image and display it on a rectangle and then move it around the screen.
We started with taking the SDL_window* and turning it into SDL_surface* though this would take the image and display it on the background of the window.
Is there a way to turn a rectangle we create into a surface and display the image on that rectangle?
I have also tried using textures and it distorts the image when I tried to move it and the whole image doesn’t move with the rectangle.
// this happens in the constructor
temp_image_sur = IMG_Load( image_location.c_str() );
if( temp_image_sur == NULL )
{
std::cout << "Image could not be loaded" <<std::endl;
exit(1);
}
// This is in the actual draw function.
display_surface = SDL_GetWindowSurface( display_window );
if(display_surface == NULL )
{
printf(" null im exiting here %s\n", SDL_GetError());
exit(1);
}
image_surface = SDL_ConvertSurface( temp_image_sur, display_surface->format, 0 );
image_size = { this->location.x, this->location.y, this->size.width, this->size.height };
SDL_BlitSurface( image_surface, &image_size, display_surface, &image_size );
This is what we did for our first attempt, and the image was displaying on the base window. I believe I understand why it is displaying on the base window, it is because we are using that window as the surface, though I'm confused how do I make a user defined rectangle the surface?
We did try using SDL_CreateRGBSurface, though nothing is being displayed on the screen when we do this either.
display_surface = SDL_CreateRGBSurface(0, this->size.width, this->size.height, 1, this->color.red, this->color.green, this->color.blue, this->color.alpha);
Thanks guys!
Please let me know if there is anymore information you need, this is my first time posting and I tried to put all the info that I could think of.
Create a texture from your image surface by using SDL_CreateTextureFromSurface:
SDL_Texture* image_surface = SDL_CreateTextureFromSurface(renderer, temp_image_sur);
(remember to free it with SDL_DestroyTexture)
then use SDL_RenderCopy to draw it:
SDL_RenderCopy(renderer, image_texture, nullptr, &image_rect);
where image_rect is a SDL_Rect and the destination rectangle you want to draw your image to, for example:
SDL_rect image_rect = {10, 10, 200, 200};
To move your image simply change image_rect.x and/or image_rect.y

Draw lines using Device Context over a CImage object

Im building a MFC c++ application in which i let the user read an image, draw lines on it and then save it.
so i have a "CImage" object which is called "Image" in which the user loads the image to.
and i have a device context object and i was able to draw lines on it
the device context object that is in run-time using "OnLButtonDown" and "OnLButtonUp" event handlers.
i then let the user save the image using "CImage.save" .. the image is saved but the device context drawn lines aren't there which is to be expected ..
but I DO want them to appear in the saved image..
the question is how can i get the device context Object to affect my CImage Object?
this is the event handler for mouse button down
void CProFilterDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
curser =point;
if (draw && Boundry.PtInRect(point) )
{
CDialogEx::OnLButtonDown(nFlags, point);
}
}
and this one when the mouse button is up
void CProFilterDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
if (draw && Boundry.PtInRect(curser) && Boundry.PtInRect(point))
{
CClientDC dc(this);
dc.MoveTo(curser);
dc.LineTo(point);
CDialogEx::OnLButtonUp(nFlags, point);
}
}
this is where i load my Cimage object
void CProFilterDlg::OnBnClickedBtnBrowse()
{
CFileDialog Browse(true);
if(Browse.DoModal() == IDOK)
{
ImagePath = Browse.GetPathName();
}
image.Load(ImagePath);
}
and this is where i save my CImage
void CProFilterDlg::OnBnClickedSave()
{
CFileDialog Save(true);
if(Save.DoModal() == IDOK)
{
ImagePath = Save.GetPathName();
}
image.Save(ImagePath,Gdiplus::ImageFormatBMP);
}
From what you've shown, it appears you are using the wrong DC. You seem to be using the DC for the dialog (ie. CCLientDC) and not the actual CImage. You should be constructing the DC from
CImage::GetDC ().
That DC will have the currently selected bitmap.
Are you looking for CImage:BitBlt? It is used to copy a bitmap from the source device context to current device context.

SDL loading my image messed up

I'm attemting to load an image that I exported from flash CS3 it's a very cute face but it loads very weird it loads on a blueish way this is the code for the two files:
//main.cpp
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "test.hpp"
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_VIDEO);
// Activamos modo de video
screen = SDL_SetVideoMode(640,480,32,SDL_SWSURFACE | SDL_DOUBLEBUF);
image = IMG_Load("face.bmp");
dest.x = 200;
dest.y = 200;
//Main Loop
while(Abierto)
{
//We Draw
Draw();
//Events
while( SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
Abierto = false;
}
}
// We free the image
SDL_FreeSurface(image);
SDL_Quit();
return 0;
}
Now the other one the;
//test.hpp
DL_Surface *image = NULL, *screen = NULL;
SDL_Rect dest;
SDL_Event event;
bool Abierto = true;
float PlaneX = 300, PlaneY = 200;
float velX = 0.1, velY = 0.1;
void Draw()
{
Uint32 color;
// Black Background is created
color = SDL_MapRGB (screen -> format, 0, 0, 0);
SDL_FillRect (screen, NULL, color);
SDL_DisplayFormatAlpha(image);
SDL_BlitSurface(image, NULL, screen, &dest);
// Flip the working image buffer with the screen buffer
SDL_Flip (screen);
}
I need help with this please Im not that experienced on SDL stuff oh and if you want to take a closer look I uplaoded the project here.
Oh my bad I must add the image is 32 pixels with alpha according to flash exporting options
According to docs, SDL_DisplayFormatAlpha returns a new image and keeps the original intact.
So, try in the first part, when you load the image:
SDL_Surface *origImage = IMG_Load("face.bmp");
image = SDL_DisplayFormatAlpha(origImage);
SDL_FreeSurface(origImage)
As there is no need to call SDL_DisplayFormatAlpha each frame.
Then in the second part, just blit image, without calling SDL_DisplayFormatAlpha.
UPDATE
I've just checked your picture, and it looks like it is a weird bmp. I've seen that before: BMP format is such a mess that if you don't keep to the basics chances are that different programs will interpret the data differently.
In your case:
display face.bmp shows correctly.
gthumb face.bmp shows nothing.
eog face.bmp says "bogus header data".
I strongly recommend using PNG files for all your game cartoon-like pictures and JPG for all the photo-like ones.
So run
$ convert face.bmp face.png
And use the PNG file. I'll will work better and you will have a file 20% the size of the original.

Change SDL background

Is there any way to change the color of an empty SDL window to be white instead of black? I don't want to change any default settings. I'm just trying to change it for this particular program that I'm writing. I don't want to use an image file, but if I have to, I will.
I don't know if this matters, but I'm using SDL_SetVideoMode()
My code is very basic:
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
return 1;
SDL_Surface * screen = NULL;
screen = SDL_SetVideoMode(width, height, bpp, SDL_SWSURFACE);
SDL_FillRect(screen, NULL, 0xFFFFFF);
SDL_Delay(3000);
You need to call SDL_Flip for your changes to show up.
Acquire the surface from your Window using surf = SDL_SetVideoMode(...) and then do
SDL_FillRect(surf, NULL, 0xFFFFFF); // 0xFFFFFF = white in RGB, NULL = full window
SDL_Flip(surf);
You could use SDL_FillRect to fill the screen/a surface with your desired color.
You need to call SDL_UpdateRect after SDL_FillRect.