C SDL2 - выделение части изображения с последующим увеличением - PullRequest
0 голосов
/ 25 мая 2018

Итак, у меня есть изображение, которое я открываю в окне с SDL2.Я хочу реализовать функцию масштабирования для изображения, которая работает следующим образом: я нажимаю на две точки изображения и делаю прямоугольник с этими точками в качестве противоположных углов.Затем я делаю копию прямоугольника и обновляю окно, чтобы показать часть изображения, которое я выбрал, и это новое изображение имеет большую ширину и высоту, чем прямоугольник, который я выбрал, потому что это будет высота и ширина всего окна,Я могу обнаружить щелчки мыши и по щелчкам мыши вычислить верхний левый угол прямоугольника в координатах x и y.Однако я не знаю, как сделать копию пикселей в этих прямоугольниках, и как заставить окно теперь отображать увеличенное изображение частично.Я много гуглил, но я не знаю, какие функции использовать или как написать свой код.Как бы я написал такую ​​функцию?

Вот что у меня так далеко.Изображение, которое я хочу увеличить, это "map.jpg"

SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = NULL;
window = SDL_CreateWindow("WarmingUp", TOP_LEFT_CORNER_X,
                          TOP_LEFT_CORNER_Y, IMAGE_WIDTH, IMAGE_HEIGHT, 0);
if(window == NULL){
    printf("Erro a abrir janela gráfica\n");
    exit(EXIT_FAILURE);
}

SDL_Renderer *renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL){
    printf("Erro a criar renderer\n");
    exit(EXIT_FAILURE);
}

SDL_Surface *jpgSurface = NULL;
jpgSurface = IMG_Load("map.jpg");
if(jpgSurface == NULL){
    printf("Erro a abrir imagem\n");
    exit(EXIT_FAILURE);
}
SDL_Texture *jpgTexture = NULL;
jpgTexture = SDL_CreateTextureFromSurface(renderer, jpgSurface);
if(jpgTexture == NULL){
    printf("Erro a criar superfície através de imagem\n");
    exit(EXIT_FAILURE);
}
SDL_FreeSurface(jpgSurface);
SDL_Event e;
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, jpgTexture, NULL, NULL);    
while(!quit){
    while(SDL_PollEvent(&e)){
        if(e.type == SDL_QUIT)
            quit = 1;

        SDL_RenderPresent(renderer);
        SDL_Delay(15);
SDL_DestroyTexture(jpgTexture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();

Я знаю, что для взаимодействия мыши в моем while &eventloop мне нужно проверить на if ( event.type == SDL_MOUSEBUTTONUP ), и я могутакже покажу вам код для вычисления верхнего левого угла x и y позиции желаемого прямоугольника, который нужно обрезать, но я действительно не могу идти дальше.

1 Ответ

0 голосов
/ 25 мая 2018

Вот модифицированный код из вопроса:

#include <stdio.h>
#include <SDL.h>
#include <SDL_image.h>

#define IMAGE_WIDTH 1024
#define IMAGE_HEIGHT 768

int main(int argc, char **argv) {
    (void)argc, (void)argv;

    int quit = 0;

    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Window *window = NULL;
    window = SDL_CreateWindow("WarmingUp",
            SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
            IMAGE_WIDTH, IMAGE_HEIGHT, 0);
    if(window == NULL){
        printf("Erro a abrir janela gráfica\n");
        exit(EXIT_FAILURE);
    }

    SDL_Renderer *renderer = NULL;
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if (renderer == NULL){
        printf("Erro a criar renderer\n");
        exit(EXIT_FAILURE);
    }

    SDL_Surface *jpgSurface = NULL;
    jpgSurface = IMG_Load("map.jpg");
    if(jpgSurface == NULL){
        printf("Erro a abrir imagem\n");
        exit(EXIT_FAILURE);
    }
    SDL_Texture *jpgTexture = NULL;
    jpgTexture = SDL_CreateTextureFromSurface(renderer, jpgSurface);
    if(jpgTexture == NULL){
        printf("Erro a criar superfície através de imagem\n");
        exit(EXIT_FAILURE);
    }
    SDL_FreeSurface(jpgSurface);
    SDL_Event e;

    // rectangle to upscale in second window
    const SDL_Rect srcrect = {600, 500, 250, 250};
    SDL_Window *second_window = NULL;
    SDL_Renderer *second_renderer = NULL;
    SDL_Texture *magnified_fragment_texture = NULL;

    while(!quit){
        while(SDL_PollEvent(&e)){
            if(e.type == SDL_QUIT ||
                    (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)) {
                quit = 1;
            } else if(e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_t &&
                    !second_window) {
                // create empty surface of adequate size
                SDL_Surface *const surf = SDL_CreateRGBSurface(0, srcrect.w, srcrect.h, 32,
                        0xff000000, 0xff0000, 0xff00, 0xff);
                SDL_FillRect(surf, NULL, 0);

                // copy pixels
                SDL_RenderReadPixels(renderer, &srcrect, SDL_PIXELFORMAT_RGBA8888,
                        surf->pixels, surf->pitch);

                // error checking should be done...
                second_window = SDL_CreateWindow("mag",
                        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
                        srcrect.w*2, srcrect.h*2, 0);
                second_renderer = SDL_CreateRenderer(second_window, -1, SDL_RENDERER_ACCELERATED);
                magnified_fragment_texture = SDL_CreateTextureFromSurface(second_renderer, surf);
                SDL_FreeSurface(surf);
            }
        }

        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, jpgTexture, NULL, NULL);    
        SDL_RenderPresent(renderer);

        if(second_renderer) {
            const SDL_Rect dstrect = {0, 0, srcrect.w*2, srcrect.h*2};
            SDL_RenderClear(second_renderer);

            // RenderCopy scales texture to destination rect
            SDL_RenderCopy(second_renderer, magnified_fragment_texture, NULL, &dstrect);
            SDL_RenderPresent(second_renderer);
        }

        SDL_Delay(15);
    }

    SDL_DestroyTexture(jpgTexture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

В обработчике событий нажатия клавиш он создает второе окно / средство визуализации / текстуру (не лучшее место для него), а затем он отображает второе окно, если оно существует.

...