So im trying to render an image. This code worked fine before I refactored into seperate classes but i cannot see the problem. The file path for the image also worked before the refactoring however i have not moved the image so it should still be in the same place.
The error i am getting is "Unable to create texture from surface. Error: Couldn't open Images/text.bmp" so im fairly certain its the line of code below that is messing up.
if (!(gTexture->LoadFromFile("Images/text.bmp")))
{
return false;
}
Here is the LoadFromFile function code
bool Texture2D::LoadFromFile(string path)
{
Free();
SDL_Texture* pTexture = NULL;
SDL_Surface* pSurface = IMG_Load(path.c_str());
if (pSurface != NULL)
{
//SDL_SetColorKey(pSurface, SDL_TRUE, SDL_MapRGB(pSurface->format, 0, 0xFF, 0xFF));
pTexture = SDL_CreateTextureFromSurface(mRenderer, pSurface);
if (pTexture == NULL)
{
cout << "Unable to create texture from surface. Error: " << SDL_GetError() << endl;
}
mWidth = pSurface->w;
mHeight = pSurface->h;
SDL_FreeSurface(pSurface);
}
else
{
cout << "Unable to create texture from surface. Error: " << IMG_GetError() << endl;
}
mTexture = pTexture;
return pTexture != NULL;
}
Below is the Source.cpp file:
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include "Constants.h"
#include "Texture2D.h"
#include "Commons.h"
#include <iostream>
#include <string>
using namespace std;
//Globals
SDL_Window* gWindow = NULL;
SDL_Renderer* gRenderer = NULL;
Texture2D* gTexture = NULL;
//prototypes
bool InitSDL();
void CloseSDL();
bool Update();
void Render();
int main(int argc, char* args[])
{
if(InitSDL())
{
bool quit = false;
while(!quit)
{
//gTexture->Render(Vector2D(), SDL_FLIP_NONE, 0);
Render();
quit = Update();
}
}
CloseSDL();
return 0;
}
bool InitSDL()
{
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
cout << "SDL did not initialise. Error: " << SDL_GetError();
return false;
}
else
{
//ITS ALL GOOD BRO
gWindow = SDL_CreateWindow("Games Engine Creation",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
//DID IT GO?
if (gWindow == NULL)
{
//NUH UH
cout << "Window was not created. Error: " << SDL_GetError();
return false;
}
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
if (gRenderer != NULL)
{
//INITIALISE THAT PNG BBY
int imageFlags = IMG_INIT_PNG;
if (!(IMG_Init(imageFlags) & imageFlags))
{
cout << "SDL_Image could not initialise. Error: " << IMG_GetError();
return false;
}
}
else
{
cout << "Renderer could not be initialised. Error: " << SDL_GetError();
return false;
}
gTexture = new Texture2D(gRenderer);
if (!(gTexture->LoadFromFile("Images/text.bmp")))
{
return false;
}
return true;
}
}
void CloseSDL()
{
SDL_DestroyWindow(gWindow);
gWindow = NULL;
delete gTexture;
gTexture = NULL;
SDL_DestroyRenderer(gRenderer);
gRenderer = NULL;
IMG_Quit();
SDL_Quit();
}
bool Update()
{
SDL_Event e;
SDL_PollEvent(&e);
switch(e.type)
{
case SDL_QUIT:
return true;
break;
case SDL_KEYUP:
switch(e.key.keysym.sym)
{
case SDLK_q:
return true;
break;
}
break;
case SDL_MOUSEBUTTONDOWN:
return true;
break;
}
return false;
}
void Render()
{
SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(gRenderer);
gTexture->Render(Vector2D(), SDL_FLIP_NONE, 0);
//SDL_Rect renderLocation = { 0, 0, mWidth, mHeight };
//SDL_RenderCopyEx(mRenderer, mTexture, NULL, &renderLocation, 0, NULL, SDL_FLIP_NONE);
SDL_RenderPresent(gRenderer);
}
A simple way to start debugging is to place the image in the same folder with the executable and show the path as ./image.bmp to see if something is wrong with the path.
Related
Currently trying to display a BMP file on a window through SDL 2
This is my main.cpp file:
`#include "pch.h"
#include <iostream>
#include<SDL.h>
using namespace std;
int main(int argc, char* args[])
{
bool run=true;
sdl a;
if (a.init() == false)
{
cout << "SDL not working" << endl;
return 0;
}
else
if (a.screendisplay() == false)
{
cout << "Enable to open the window" << endl;
return 0;
}
else
if (a.loadmedia() == false)
{
cout << "Unable to load the image" << endl << SDL_GetError()<<endl;
return 0;
}
else
a.imageprocessing();
SDL_Delay(2000);
a.quit();
return 0;
}`.
This is my pch.H file,which was mentioned above in the code:
class sdl
{
public:
bool init();
bool screendisplay();
bool quit();
bool loadmedia();
bool imageprocessing();
private:
SDL_Surface *gsurface = NULL;
SDL_Window * Window = NULL;
SDL_Surface * screenSurface = NULL;
};
Pch.cpp file:
#include "pch.h"
using namespace std;
bool sdl::init()
{
bool sucess = true;
if (SDL_Init(SDL_INIT_VIDEO) <0)
{
cout << "SDL not Working properply" << endl;
return false;
}
else return true;
};
bool sdl::screendisplay()
{
bool sucess;
Window = SDL_CreateWindow("SDL Tutorial", 0, 0,640, 280, SDL_WINDOW_SHOWN);
if (Window = NULL)
{
return sucess = false;
}
else
screenSurface= SDL_GetWindowSurface(Window);
return sucess = true;
};
bool sdl::loadmedia()
{
bool success = true;
gsurface = SDL_LoadBMP("asd.bmp");
if (gsurface == NULL)
{
success = false;
}
return success;
};
bool sdl::imageprocessing()
{
bool success = true;
if (SDL_BlitSurface(gsurface, NULL, screenSurface, NULL) < 0)
{
return success = false;
}
else
SDL_UpdateWindowSurface(Window);
SDL_Delay(2000);
return success;
};
bool sdl::quit()
{
bool sucess;
SDL_DestroyWindow(Window);
SDL_Quit();
return sucess = true;
};
When i run this program,the window appears but with no image. What am i doing wrong here?
I think the problem is in your screendisplay() function:
bool sdl::screendisplay()
{
bool sucess;
Window = SDL_CreateWindow("SDL Tutorial", 0, 0,640, 280, SDL_WINDOW_SHOWN);
if (Window = NULL) // <- Right here
{
return sucess = false;
}
else
screenSurface= SDL_GetWindowSurface(Window);
return sucess = true;
};
You're doing an assignment rather than a comparison. You should turn up your compiler warnings so it catches this.
i'm trying to create a manual color key with pixel manipulation in SDL2, but when i execute the program, the color key doesn't work, these pixels become white, but not transparent.
I tried to Lock the surface and set the surface blendmode, but doesn't work too.
Code:
// IO includes
#include <iostream>
// String includes
#include <string>
// SDL includes
#include <SDL.h>
#include <SDL_image.h>
// Screen constants
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
using namespace std;
// Window variables
SDL_Window *window = NULL;
SDL_Surface *windowSurface = NULL;
// Image surfaces
SDL_Surface *background = NULL;
SDL_Surface *image = NULL;
// Functions
bool initializeSDL();
SDL_Surface *loadSurfaceFromFile(string path);
void SetColorKey(SDL_Surface *surface, Uint32 color);
bool LoadFiles();
void FreeMemory();
// SDL_main
int main(int argc, char* argv[]){
// Try to initialize and load files
if(initializeSDL() == false){
FreeMemory();
return -1;
}
if(LoadFiles() == false){
FreeMemory();
return -1;
}
// Blit images
SDL_BlitSurface(background, NULL, windowSurface, NULL);
SDL_BlitSurface(image, NULL, windowSurface, new SDL_Rect(70, 277, image->w, image->h));
// Update screen
SDL_UpdateWindowSurface(window);
// Loop
SDL_Event ev;
while(true){
if(SDL_PollEvent(&ev) && ev.type == SDL_QUIT) break;
}
return 0;
}
bool initializeSDL(){
// Try to initialize the video
if( SDL_Init(SDL_INIT_VIDEO) < 0 ){
// Print error
cout << "Error to initialize the video: " << SDL_GetError() << endl;
return false;
}
// Try to create the window
window = SDL_CreateWindow("Surface", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if(window == NULL){
// Print error
cout << "Error to create the window: " << SDL_GetError() << endl;
return false;
}
// Try to initialize PNG format
int imgFlags = IMG_INIT_PNG;
if(! (IMG_Init(imgFlags) &imgFlags) ) return false;
// Get the window surface
windowSurface = SDL_GetWindowSurface(window);
// If everything is fine, return true
return true;
}
SDL_Surface* loadSurfaceFromFile(string path){
// Create a temporary surface
SDL_Surface *tmpSurface = NULL;
// Create an optimized surface
SDL_Surface *optimizedSurface = NULL;
// Try to load the tmpSurface
tmpSurface = IMG_Load(path.c_str());
if(tmpSurface == NULL){
// Print error
cout << "Error to load the image: " << SDL_GetError() << endl;
return NULL;
}
// Try to optimize the surface
optimizedSurface = SDL_ConvertSurface(tmpSurface, windowSurface->format, NULL);
SDL_FreeSurface(tmpSurface); // Free tmpSurface memory
delete tmpSurface; // Delete the tmpSurface
if(optimizedSurface == NULL){
// Print error
cout << "Error to optimize the image: " << SDL_GetError() << endl;
}
return optimizedSurface;
}
void SetColorKey(SDL_Surface *surface, Uint32 color){
Uint32 *pixels = (Uint32*)surface->pixels;
int pixelCount = (surface->pitch/4) * surface->h;
Uint32 transparent = SDL_MapRGBA(image->format, 255, 255, 255, 0);
for(int i=0;i<pixelCount;i++){
if(pixels[i] == color){
pixels[i] = transparent;
}
}
}
bool LoadFiles(){
// Try to load the background
background = loadSurfaceFromFile("background.bmp");
if(background == NULL) return false;
// Try to load the image
image = loadSurfaceFromFile("image.png");
if(image == NULL) return false;
// Set manual color key to image
SetColorKey(image, SDL_MapRGB(image->format, 0, 255, 255));
return true;
}
void FreeMemory(){
SDL_FreeSurface(background);
SDL_FreeSurface(image);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
}
I'm trying to organize my code a bit more, so I tried putting the SDL2 code used for displaying windows/images into a class. The window opens, the code runs successfully, and the image seems to be loading fine, -but the image will not appear when the code is arranged in a class like this. Why is this happening?
main.cpp:
#include <SDL.h>
#include "display.h"
SDL_Event event;
SDL_Surface* image = nullptr;
int main(int argc, char* args[])
{
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
return false;
Display display;
display.loadImage("image.bmp");
bool quit = false;
while (!quit)
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
quit = true;
}
display.applySurface(0, 0, image, display.windowSurface);
display.update();
}
SDL_FreeSurface(image);
SDL_Quit();
return 0;
}
display.h:
#pragma once
#include <SDL.h>
#include <string>
#include <iostream>
class Display
{
public:
SDL_Window* window;
SDL_Surface* windowSurface;
Display();
SDL_Surface* loadImage(std::string fileName);
void applySurface(int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip = nullptr);
void update();
~Display();
private:
const int WINDOW_WIDTH = 612;
const int WINDOW_HEIGHT = 632;
const int SCREEN_BPP = 2;
};
display.cpp:
#pragma once
#include "display.h"
Display::Display()
{
window = SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
if (window == NULL)
std::cout << "Error: SDL_CreateWindow failed." << std::endl;
windowSurface = SDL_GetWindowSurface(window);
if (windowSurface == NULL)
std::cout << "Error: Window surface is null." << std::endl;
}
SDL_Surface* Display::loadImage(std::string fileName)
{
SDL_Surface* loadedImage = NULL;
SDL_Surface* optimizedImage = NULL;
loadedImage = SDL_LoadBMP(fileName.c_str());
if (loadedImage == NULL)
std::cout << "Loaded image = NULL" << std::endl;
if (loadedImage != NULL)
{
optimizedImage = SDL_ConvertSurface(loadedImage, windowSurface->format, 0);
SDL_FreeSurface(loadedImage);
if (optimizedImage == NULL)
std::cout << "Optimized image = NULL" << std::endl;
if (optimizedImage != NULL)
SDL_SetColorKey(optimizedImage, SDL_TRUE, SDL_MapRGB(optimizedImage->format, 255, 255, 255));
}
return optimizedImage;
}
void Display::applySurface(int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip)
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
SDL_BlitSurface(source, clip, destination, &offset);
}
void Display::update()
{
if (SDL_UpdateWindowSurface(window) == -1)
std::cout << "Error: SDL_UpdateWindowSurface() failed." << std::endl;
}
Display::~Display()
{
SDL_FreeSurface(windowSurface);
windowSurface = NULL;
SDL_DestroyWindow(window);
window = NULL;
}
In your main.cpp your image is empty because you didn't use the return image :
image = display.loadImage("image.bmp");
The code below is meant to show a picture of a rider in the top left corner of the SDL window. With this code the image occasionally does appear as intended, but most of the time when I run the program I just get a black window. Any idea why?
#include "Game.h"
#include <iostream>
bool Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullScreen)
{
int flags = 0;
if (fullScreen)
{
flags = SDL_WINDOW_FULLSCREEN;
}
//attempt to initialize SDL
if (SDL_Init(SDL_INIT_EVERYTHING)==0) {
std::cout << "SDL init success \n";
//init the window
m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
if (m_pWindow !=0) // window init successful
{
std::cout << "Window creation successful\n";
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
if(m_pRenderer !=0) // renderer init success
{
std::cout << "renderer creation successful\n";
SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, 255);
}
else
{
std::cout << "renderer init failed!\n";
return false; // render init failed
}
}
else
{
std::cout << "Window init failed!\n";
return false; //window init failed
}
}
else
{
std::cout << "SDL init failed!\n";
return false; // SDL init failed
}
std::cout << "Init success\n";
m_bRunning = true; // everything init-d successfully, main game loop running
SDL_Surface* pTempSurface = SDL_LoadBMP("rider.bmp");
if(!pTempSurface)
{
std::cout << "Error, tempsurface is null";
}
m_pTexture = SDL_CreateTextureFromSurface(m_pRenderer, pTempSurface);
SDL_FreeSurface(pTempSurface);
SDL_QueryTexture(m_pTexture, NULL, NULL, &m_sourceRectangle.w, &m_sourceRectangle.h);
m_destinationRectangle.x = m_sourceRectangle.x = 0;
m_destinationRectangle.x = m_sourceRectangle.x = 0;
m_destinationRectangle.h = m_sourceRectangle.h;
m_destinationRectangle.w = m_sourceRectangle.w;
return true;
}
void Game::render()
{
SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
SDL_RenderCopy(m_pRenderer, m_pTexture, &m_sourceRectangle, &m_destinationRectangle);
SDL_RenderPresent(m_pRenderer);
}
void Game::handleEvents()
{
SDL_Event event;
if (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
m_bRunning = false;
break;
default:
break;
}
}
}
void Game::clean()
{
std::cout << "cleaning app\n";
SDL_DestroyWindow(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
SDL_Quit();
}
I was following the SDL Game development book and I cant even get the first file to work right. Upon the application starting it renders the window and then after a few seconds Linux says the game is not responding and ask me to force quit. This repeats every few seconds if I click wait. One thing I have noticed is that SDL_PollEvent never returns true.I am not sure why things are not working. Here is my code.
Main.cpp
#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#include "Game.h"
// our Game object
Game* g_game = 0;
int main(int argc, char* argv[]) {
g_game = new Game();
g_game->init("Chapter 1", 100, 100, 640, 480, 0);
while(g_game->running()) {
g_game->handleEvents();
//g_game->update();
g_game->render();
}
g_game->clean();
return 0;
}
Game.h
#ifndef __Game__
#define __Game__
#if !WINDOWS
#include <SDL2/SDL.h>
#else
#include <SDL.h>
#endif
class Game {
public:
Game() {}
~Game() {}
// simply set the running variable to true
bool init(const char* title, int xpos, int ypos, int width, int
height, bool fullscreen);
void render();
void update();
void handleEvents();
void clean();
// a function to access the private running variable
bool running() {
return m_bRunning;
}
private:
SDL_Window* m_pWindow;
SDL_Renderer* m_pRenderer;
bool m_bRunning;
};
#endif /* defined(__Game__) */
Game.cpp
#include "Game.h"
#include <iostream>
bool Game::init(const char* title, int xpos, int ypos, int width,
int height, bool fullscreen) {
// attempt to initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) == 0) {
std::cout << "SDL init success\n";
// init the window
int flags = 0;
if(fullscreen) {
flags = SDL_WINDOW_FULLSCREEN;
}
m_pWindow = SDL_CreateWindow(title, xpos, ypos,
width, height, flags);
if(m_pWindow != 0) { // window init success
std::cout << "window creation success\n";
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
if(m_pRenderer != 0) { // renderer init success
std::cout << "renderer creation success\n";
SDL_SetRenderDrawColor(m_pRenderer,
255,0,255,255);
} else {
std::cout << "renderer init fail\n";
return false; // renderer init fail
}
} else {
std::cout << "window init fail\n";
return false; // window init fail
}
} else {
std::cout << "SDL init fail\n";
return false; // SDL init fail
}
std::cout << "init success\n";
m_bRunning = true; // everything inited successfully, start the main loop
return true;
}
void Game::render() {
SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
SDL_RenderPresent(m_pRenderer); // draw to the screen
}
void Game::clean() {
std::cout << "cleaning game\n";
SDL_DestroyWindow(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
SDL_Quit();
}
void Game::handleEvents() {
SDL_Event event;
while(SDL_PollEvent(&event)) {
std::cout << "Checking Events";
switch(event.type) {
case SDL_QUIT:
std::cout << "Quiting";
m_bRunning = false;
break;
default:
break;
}
}
}
Edit:
so I made a minamal version of the code and now i get a new error. The error says "Segmentation Fault (core dumped)". Based on running it to a specific line in debug the error seems to appear at the line that says "SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);" I am not sure what the error is though
Here is the minial code:
#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#include <iostream>
#include <SDL2/SDL.h>
int main(int argc, char** argv) {
if(SDL_Init(SDL_INIT_EVERYTHING) != 0) {
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if(win == NULL) {
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(ren == NULL) {
SDL_DestroyWindow(win);
std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
std::string imagePath = "cb.bmp";
SDL_Surface *bmp = SDL_LoadBMP(imagePath.c_str());
if(bmp == NULL) {
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);
if(tex == NULL) {
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_FreeSurface(bmp);
SDL_Event e;
bool quit = false;
while(!quit) {
while(SDL_PollEvent(&e)) {
//If user closes the window
if(e.type == SDL_QUIT) {
quit = true;
}
//If user presses any key
if(e.type == SDL_KEYDOWN) {
quit = true;
}
//If user clicks the mouse
if(e.type == SDL_MOUSEBUTTONDOWN) {
quit = true;
}
}
SDL_RenderClear(ren);
SDL_RenderPresent(ren);
}
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
I have compiled and run your minimal code successfully under Linux with SDL 2.0.4. I used a simple image as "cb.bmp".
Try the following :
compile like this : g++ -Wall -ggdb $(sdl2-config --cflags) -o program main.cpp -lSDL2
gdb ./program, then type 'run'
when it crashes, type 'bt' (for backtrace)
copy the output here
My guess is : either the "bmp" file format is not supported or the rendering driver is not supported. try to use :
SDL_CreateRenderer(win, -1, 0);