SDL2 draw a rectangle in an image without window [closed] - c

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 14 days ago.
Improve this question
Is it possible to draw a rectangle on top of an image without creating a pop up window? I was able to draw a rectangle on top of an image with following code, but I don't want the window to be popped up, is it possible?
What I want is load jpg image -> draw rectangles -> save image as jpg.
int main(int argc, char** argv)
{
bool quit = false;
SDL_Event event;
SDL_Init(SDL_INIT_VIDEO);
IMG_Init(IMG_INIT_JPG);
SDL_Window* window = SDL_CreateWindow("Test",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Surface* image = IMG_Load("test.jpg");
if (!image) {
printf("Image NULL\n");
return -1;
}
SDL_Texture* texture = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC,
image->w, image->h);
image = SDL_ConvertSurfaceFormat(image, SDL_PIXELFORMAT_ARGB8888, 0);
while (!quit)
{
SDL_UpdateTexture(texture, NULL, image->pixels,
image->w * sizeof(Uint32));
SDL_WaitEvent(&event);
switch (event.type)
{
case SDL_QUIT:
quit = true;
break;
}
SDL_SetRenderDrawColor(renderer, 136, 8, 8, 255);
SDL_Rect dstrect = { 20, 10, 320, 145};
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderDrawRect(renderer, &dstrect);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(texture);
SDL_FreeSurface(image);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
return 0;
}

You can use SDL2's software renderer to draw to surface, then save this surface to a file.
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
#include <stdbool.h>
int main(int argc, char** argv)
{
SDL_Init(SDL_INIT_VIDEO);
IMG_Init(IMG_INIT_JPG);
// load input image
SDL_Surface* image = IMG_Load("test.jpg");
if (!image) {
printf("Image NULL\n");
return -1;
}
// create target surface
SDL_Surface *output_surface = SDL_CreateRGBSurface(0,
image->w, image->h, 32,
0, 0, 0, 0);
// create software renderer that renders to target surface
SDL_Renderer *renderer = SDL_CreateSoftwareRenderer(output_surface);
// create texture from input surface
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, image);
SDL_SetRenderDrawColor(renderer, 136, 8, 8, 255);
SDL_Rect dstrect = { 20, 10, 320, 145};
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderDrawRect(renderer, &dstrect);
SDL_RenderPresent(renderer);
// save target surface to JPEG file
IMG_SaveJPG(output_surface, "test_output.jpg", 90);
SDL_DestroyTexture(texture);
SDL_FreeSurface(image);
SDL_DestroyRenderer(renderer);
SDL_FreeSurface(output_surface);
IMG_Quit();
SDL_Quit();
return 0;
}
Other way would be to create SDL_Surface and use functions like SDL_BlitSurface to copy your image on top of it, and SDL_FillRect to draw filled rectangle (e.g. draw 4 sides of not-filled rectangle).

Related

How do I use a software SDL_Renderer correctly while resizing the window?

I'm not sure how to use a software SDL_Renderer to render to a window while resizing that window. For example, I expect the following code to constantly display a fully black window even as the uses resizes the window. Instead, when the user resizes the window, it's not filled with black, you get kind of "streaks" of black against a transparent background.
I'm sure I could cobble something together with catching resize events, maybe using SDL_RenderFilleRect() instead of SDL_RenderClear(), but fundamentally I just don't know what I should be doing at all. Should I be freeing the SDL_Surface and getting an entirely new surface and renderer every time the window resizes? Should I be calling SDL_RenderSetViewport()?
#include <SDL.h>
int main()
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = SDL_CreateWindow(
"Main Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
600,
600,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
);
SDL_Surface *window_surface = SDL_GetWindowSurface(window);
SDL_Renderer *renderer = SDL_CreateSoftwareRenderer(window_surface);
SDL_Event event;
bool quit = false;
while (!quit)
{
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
quit = true;
break;
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_UpdateWindowSurface(window);
SDL_Delay(1000 / 60);
}
SDL_Quit();
return 0;
}

Why is SDL2 window fading out?

I want a quick fix to this issue:
I wrote a simple program to play around with the SDL2 libraries. A cyan box moves along a blue background from left to right. Then the window closes.
The problem is that the window's color "fades out" while the program is running. The contrast decreases significantly and it's annoying. Sometimes it happens when the box is in the middle of the window. Sometimes it happens when the box reaches the right side of the window. Sometimes it doesn't happen at all. This fading of colors seems to be sporadic and random. It is a run time issue. Theoretically, I do not see any issue with the code. What is wrong?
#include "SDL.h"
#include <stdio.h>
#ifdef __cplusplus
extern "C"
#endif
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
window = SDL_CreateWindow("Boxes", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, 0);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Rect myBox = { 200, 150, 50, 50 };
int go = 0;
while (go <= 590) {
myBox.x = go;
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255);
SDL_RenderFillRect(renderer, &myBox);
SDL_RenderPresent(renderer);
if (go == 0)
SDL_Delay(2000);
SDL_Delay(100);
go += 10;
}
SDL_Delay(2000);
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return EXIT_SUCCESS;
}
That's a classical SDL mistake.
You're not handling events that your window receives, and because of that your OS assumes that your program has hung up.
Inside of your while loop, add following:
SDL_Event e;
while (SDL_PollEvent(&e))
if (e.type == SDL_QUIT)
return 0;

SDL clears the window screen when clicking on the window of another software in Linux

My program is about drawing the Mandelbrot set. I discovered that when I click another window in the operating system (eg. Chrome, or text editor ...) my program clears the screen to black but continues drawing where it finished. It is during drawing. If the drawing is finished and I click another window then nothing clearing happens.
Is there a solution to fix this (eg. switching something on or off in SDL) without tracking all the pixels onto the screen and print the entire pixel matrix all the times?
Minimal code:
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
enum {WIDTH = 1700, HEIGHT = 950};
int main(){
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("Minimal", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_Event event;
bool exit_ = false;
while (! exit_){
for (int i = 1; i < WIDTH; i++){
for (int j = 1; j < HEIGHT; j++){
SDL_RenderDrawPoint(renderer, i, j);
}
SDL_RenderPresent(renderer);
}
while (SDL_PollEvent(&event)){
if (event.type == SDL_QUIT) exit_ = true;
}
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
(Note: I haven't got any window event handling in the program.)
I think you need to put SDL_RenderClear(Renderer) at the top of the while loop.
If you do like that, window will be never cleared after rendering.
For example if you don't clear the window, a moving dot will leave his traces..
I work woth SDL too, and i always do this

How to draw on a texture using SDL2_gfx in SDL2 and then render?

I want to implement a MS-Paint-like program (although my actual program will do more than this) where one can draw using mouse.
I am using SDL2 and also SDL2_gfx.
I want to maintain an SDL_Texture where the user will do the drawing in a continuously way without clearing (unless requested by the user) at any time.
And then continuously update the SDL_Texture on to the screen.
My question specifically is how to draw SDL2_gfx primitives on the SDL_Texture and copy that to the renderer. Any completely different way than to use texture will also do for me but must be using SDL2.
Below is a minimal runnable extraction from my code:
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <SDL2/SDL.h>
#include <SDL2_gfxPrimitives.h>
#define WIDTH (320)
#define HEIGHT (240)
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_RendererInfo rendererInfo;
SDL_Texture* texture = NULL;
SDL_Event event;
Sint16 cx = WIDTH/2, cy = HEIGHT/2;
uint8_t quit = 0;
void init()
{
SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(WIDTH, HEIGHT, SDL_WINDOW_OPENGL, &window, &renderer);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, WIDTH, HEIGHT); // create texture to draw on to
// SDL_SetRenderTarget(renderer, texture); // this one I have removed
}
void draw()
{
pixelRGBA(renderer, cx, cy, 0xff, 0xff, 0x00, 0xff); // draw a pixel here, or whatever cx and cy are mouse position
// what I want is to draw on to the texture, and not directly on the screen buffer
}
void render()
{
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // set clear color
SDL_RenderClear(renderer); // clear the buffer
SDL_RenderCopy(renderer, texture, NULL, NULL); // now copy the drawn texture to the buffer
SDL_RenderPresent(renderer); // now update window
}
int main(int argc, char* argv[])
{
int p;
init();
while(!quit)
{
SDL_PumpEvents();
p = SDL_PollEvent(&event);
if(p>0)
{
if(event.type==SDL_QUIT) quit = 1;
else
{
// here other things are there to handle the mouse positions etc for drawing exactly what the user wants
// ...
draw();
render();
}
}
}
SDL_Quit();
return 0;
}
Thanks in advance.

C SDL Object movement flow

I just started with SDL and made a small square moving around on a window.
I used DL_GetKeyboardState, and got it moving kind of smoothly. However, just when I start moving it one direction by holding down one key, it moves a bit, stops, then move like I want. This messes up the smoothness. My best guess is that it waits for a doubleclick from the mouse, but im not sure. Any suggestions?
The code:
#include <stdio.h>
#include <SDL.h>
int main(int argc, char * argv[])
{
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Event event;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("Yelda!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1600, 1200, 0);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
const Uint8 *state;
int run = 1;
int xpos=300;
int ypos=300;
int projectileYPos;
int projectileXPos;
int loop;
int lanceLength = 10;
while(run)
{
while(SDL_PollEvent(&event))
{
state=SDL_GetKeyboardState(NULL);
if(state[SDL_SCANCODE_ESCAPE])
run=0;
if(state[SDL_SCANCODE_W])
ypos-=10;
if(state[SDL_SCANCODE_S])
ypos+=10;
if(state[SDL_SCANCODE_A])
xpos-=10;
if(state[SDL_SCANCODE_D])
xpos+=10;
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255 ,255);
SDL_Rect rect = {xpos, ypos, 20, 20 };
SDL_RenderFillRect(renderer, &rect);
SDL_RenderPresent(renderer);
SDL_Delay(20);
}
}
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}
The SDL wiki says that you should use SDL_PumpEvents() to update the keyboard state array.
And indeed, if we
remove the while(SDL_PollEvent(&event)) loop (not its contents) as it's unneeded,
move state=SDL_GetKeyboardState(NULL); before the while(run) loop (the address of the array "will be valid for the whole lifetime of the application", so it always returns the same pointer), and
only call SDL_PumpEvents() inside the loop,
then the movement is smooth.

Resources