Displaying an .bmp image in C++/SDL2 - c++

I have been having trouble displaying an image in an SDL window and I am not quite sure what I am doing wrong. The code compiles just fine and the image has been placed in the debug folder with my .exe so I am not sure why it is not displaying. Is there something minor I may have missed?
#include <iostream>
#include <stdio.h>
#include <SDL.h>
#undef main
using namespace std;
const int screenWidth = 640;
const int screenHeight = 480;
int main(int argc, char* args[]) {
SDL_Window* window = SDL_CreateWindow("Game", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, screenWidth, screenHeight, SDL_WINDOW_SHOWN);
SDL_Surface* image = SDL_LoadBMP("image.bmp");
SDL_Renderer* render = SDL_CreateRenderer(window, -1, 0);
SDL_Texture* texture1 = SDL_CreateTextureFromSurface(render, image);
SDL_RenderCopy(render, texture1, NULL, NULL);
SDL_RenderPresent(render);
SDL_UpdateWindowSurface(window);
SDL_Delay(5000);
SDL_DestroyTexture(texture1);
SDL_DestroyRenderer(render);
SDL_FreeSurface(image);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

If you step through the code in a debugger, and inspect the
return-values in each step, do you get something unexpected?
Such as a nullpointer. That is probably going to help you
narrow it down.
image has been placed in the debug folder with my .exe
If you run from the IDE, the current working folder is going
to be the project folder.

Related

png not being rendered properly in SDL

I'm new to SDL & I'm trying to render a simple image & this is my code:
#include <SDL.h>
#include<SDL_image.h>
#include <stdio.h>
#include <string>
using namespace std;
int main(int argc, char* args[])
{
SDL_Window* window = NULL;
SDL_Surface* gScreenSurface = NULL;
SDL_Surface* gHelloWorld = NULL;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("SDL Tutorial", 100, 50, 500, 500, SDL_WINDOW_SHOWN);
gScreenSurface = SDL_GetWindowSurface(window);
IMG_Init(IMG_INIT_PNG);
SDL_Surface* optimizedSurface = SDL_ConvertSurface(IMG_Load("glow.png"), gScreenSurface->format, 0);
SDL_BlitSurface(optimizedSurface, NULL, gScreenSurface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(5000);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
but when I run it, I'm getting this type of output
and here's how the image really looks like
I can't understand what I'm doing wrong

SDL: How to set size of pixel (stretch) of a window

I'm making a retro pixel game so I want to make my window a very low resolution (256x256). However when I try to make it fullscreen, the whole window was just rendered top left, while leaving all other areas black.
I want to know a way of globally setting the size of each pixel in a window, in order to let it fit the fullscreen, or, a way of stretching the whole window (or a renderer?) to a specified size(and full screen) while having the (w, h) unchanged in parameter 2 and 3 in SDL_CreateWindow, and also whilst having the sizes proportional (so, if it was a square window, it should be a square window after stretched, not a rect after stretched into a rect displayer).
First, render your game to a 256x256 texture. This gist has an example, I will inline it below.
Next, figure out the correct size and position of your game texture on your actual window, and render the texture there. That will require modifications to the SDL_RenderCopyEx call, as the gist simply renders it stretched to the screen.
#include <iostream>
#ifdef __linux__
#include <SDL2/SDL.h>
#elif defined(_WIN32)
#include <SDL.h>
#endif
const int WIN_WIDTH = 640;
const int WIN_HEIGHT = 480;
int main(int argc, char **argv){
if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
std::cerr << "SDL_Init failed: " << SDL_GetError() << "\n";
return 1;
}
SDL_Window *win = SDL_CreateWindow("Rendering to a texture!", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, WIN_WIDTH, WIN_HEIGHT, 0);
SDL_Renderer *renderer = SDL_CreateRenderer(win, -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
//Put your own bmp image here
SDL_Surface *bmpSurf = SDL_LoadBMP("../res/image.bmp");
SDL_Texture *bmpTex = SDL_CreateTextureFromSurface(renderer, bmpSurf);
SDL_FreeSurface(bmpSurf);
//Make a target texture to render too
SDL_Texture *texTarget = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_TARGET, WIN_WIDTH, WIN_HEIGHT);
//Now render to the texture
SDL_SetRenderTarget(renderer, texTarget);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, bmpTex, NULL, NULL);
//Detach the texture
SDL_SetRenderTarget(renderer, NULL);
//Now render the texture target to our screen, but upside down
SDL_RenderClear(renderer);
SDL_RenderCopyEx(renderer, texTarget, NULL, NULL, 0, NULL, SDL_FLIP_VERTICAL);
SDL_RenderPresent(renderer);
SDL_Delay(1000);
SDL_DestroyTexture(texTarget);
SDL_DestroyTexture(bmpTex);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}

Showing a video using two textures SDL2

I need to build an interface where on the left side of the screen shows part of one streaming video and the right side the other part. Something like this https://www.youtube.com/watch?v=fSPXpdVzamo
The video streaming is saved on a memory buffer that is being loaded on a texture. My question is how to render just the half of the texture, I've bee trying using SDL_Rect but nothing happens.
This is the relevant part of my code:
SDL_UpdateTexture(texture, NULL, buffer_start, fmt.fmt.pix.width * 2);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
If I try something like this, it doesn't work:
SDL_UpdateTexture(texture, NULL, buffer_start, fmt.fmt.pix.width * 2);
SDL_Rect someRect;
someRect.x = 0;
someRect.y = 0;
someRect.w = 1500;
someRect.h = 3000;
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, &someRect);
SDL_RenderPresent(renderer);
Any advice would be great!
Without you posting a MCVE is hard to know where you went wrong. My guess is your x position is wrong. Here is an example where I show how to draw 2 images in the fashion of your video.
Green image: https://i.imgur.com/yaOG8Ng.png
Red image: https://i.imgur.com/faKKShU.png
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#define HEIGHT 600
#define WIDTH 800
using namespace std;
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("Red Green", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
SDL_Renderer *renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
bool quit = false;
SDL_Event event;
SDL_Texture *green_part = IMG_LoadTexture(renderer, "Green400x600.png");
SDL_Texture *red_part = IMG_LoadTexture(renderer, "Red400x600.png");
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
}
SDL_RenderClear(renderer);
SDL_Rect copy_rect{0, 0, 400, 600};
SDL_RenderCopy(renderer, green_part, nullptr, &copy_rect);
// We now draw from half the screen onward x position = WIDTH / 2.
copy_rect.x = 400;
SDL_RenderCopy(renderer, red_part, nullptr, &copy_rect);
SDL_RenderPresent(renderer);
}
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}

Change background of SDL2 window?

I can create a SDL2 window but I don't know how to change background color of this window.
My code:
#include "SDL.h"
SDL_Window *window;
void main()
{
window = SDL_CreateWindow("TEST", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
SDL_Delay(3000);
}
How can I change background color of this window to black?
You should set drawing colour with SDL_SetRenderDrawColor and then use SDL_RenderClear:
(code comes directly from SDL wiki)
int main(int argc, char* argv[])
{
SDL_Window* window;
SDL_Renderer* renderer;
// Initialize SDL.
if (SDL_Init(SDL_INIT_VIDEO) < 0)
return 1;
// Create the window where we will draw.
window = SDL_CreateWindow("SDL_RenderClear",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
512, 512,
0);
// We must call SDL_CreateRenderer in order for draw calls to affect this window.
renderer = SDL_CreateRenderer(window, -1, 0);
// Select the color for drawing. It is set to red here.
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
// Clear the entire screen to our selected color.
SDL_RenderClear(renderer);
// Up until now everything was drawn behind the scenes.
// This will show the new, red contents of the window.
SDL_RenderPresent(renderer);
// Give us time to see the window.
SDL_Delay(5000);
// Always be sure to clean up
SDL_Quit();
return 0;
}
If you do not use SDL2 renderer you can do this:
Just call:
SDL_GL_SwapWindow(window);
After :
SDL_GL_MakeCurrent(window, context);
That's all! Now you have a black screen.
#include <SDL2/SDL.h>
#include <iostream>
using namespace std;
int main(){
int width=512, height=512;
SDL_Window *window=SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_RESIZABLE);
if(window==NULL)
cout << "There was an error while initializing the window" << endl << SDL_GetError << endl;
SDL_Event event;
bool running=true;
while(running){
while(SDL_PollEvent(&event)){
if(event.type==SDL_QUIT){
running=false;
break;
}
}
SDL_GetWindowSize(window, &width, &height);
SDL_Surface *surface=SDL_GetWindowSurface(window);
Uint32 skyblue=SDL_MapRGB(surface->format, 65,193,193);
SDL_FillRect(surface, NULL, skyblue);
SDL_UpdateWindowSurface(window);
}
SDL_DestroyWindow(window);
SDL_Quit();
}
Note, none of these solutions work properly with OpenGL. The question was how to init the window with predefined color, not how to paint the first frame. There's still a blink of white color before the first frame is painted.
Try this one :
SDL_Window *wind;
SDL_Surface *windSurface = NULL
void main()
{
wind = SDL_CreateWindow("TEST", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
windSurface = SDL_GetWindowSurface(wind);
SDL_FillRect(windSurface, NULL, SDL_MapRGB(windSurface->format, 240, 200, 112));
SDL_UpdateWindowSurface(wind);
SDL_Delay(3000);
}

SDL2 - VSYNC active, but tearing at specific window height

I am using SDL2 in windowed mode on Windows 7 64bit to create a small game.
I get tearing at the same height of the window despite having VSYNC active. The weird thing is that the movement in itself is fluid, but there is this line, about 50px from the bottom, where tearing is noticeable. It always stays there, without moving or anything.
The weird thing is that if I crate a smaller window, I get tearing at exactly the same height from the bottom.
I tried taking screens of it but it doesn't show the tearing.
I have no idea if this is a problem of SDL2, a problem with Windows, a problem with my pc or a problem in my source file. I have tried looking online for a solution but I could not find anything like this problem.
It is a first for me since I have been playing with a lot of SDL games in the past in windowed mode and none had this problem.
Here is a snippet of the source I have been using:
#include <stdio.h>
#include <SDL.h>
#include <SDL_image.h>
const int SCREEN_WIDTH = 400;
const int SCREEN_HEIGHT = 300;
bool init( SDL_Window** window, SDL_Renderer** renderer ) {
SDL_Init(SDL_INIT_VIDEO);
*window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
*renderer = SDL_CreateRenderer(*window, 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
int flags = IMG_INIT_PNG;
IMG_Init(flags);
return true;
}
void close( SDL_Texture** image, SDL_Window** window ) {
SDL_DestroyTexture( *image );
*image = NULL;
SDL_DestroyWindow( *window );
*window = NULL;
SDL_Quit();
}
int main(int argc, char* argv[]) {
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_Texture* image = NULL;
const SDL_Rect rect = { 0, 0, SCREEN_WIDTH, 200 };
SDL_Rect rectImage, rectImageOriginal;
int w, h;
SDL_QueryTexture(image, NULL, NULL, &w, &h);
rectImage = { 0, 0, w, h };
rectImageOriginal = rectImage;
init( window, renderer );
image = IMG_LoadTexture( renderer, path );
while (running) {
[... here I move rectImage ...]
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 200, 0, 0, 255);
SDL_RenderFillRect(renderer, NULL);
SDL_RenderCopy(renderer, image, &rectImageOriginal, &rectImage);
SDL_RenderPresent(renderer);
}
close(&image, &window);
}