Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding functions for manipulating bitmaps #39

Open
GrahamJoonsar opened this issue Jan 7, 2023 · 0 comments
Open

Adding functions for manipulating bitmaps #39

GrahamJoonsar opened this issue Jan 7, 2023 · 0 comments

Comments

@GrahamJoonsar
Copy link

GrahamJoonsar commented Jan 7, 2023

I want to add some more functions to help people with manipulating bitmaps.

tigrClone

Tigr * tigrClone(Tigr * bmp){
    Tigr * new_bmp = tigrBitmap(bmp->w, bmp->h);
    for (int y = 0; y < bmp->h; y++){
        memcpy(new_bmp->pix + y*bmp->w, bmp->pix + y*bmp->w, bmp->w*sizeof(TPixel));
    }
    return new_bmp;
}

This function is pretty simple, it just makes a copy of the bitmap you pass it and returns a reference to it.

tigrGetResized

Tigr * tigrGetResized (Tigr * bmp, int new_width, int new_height){
    Tigr * new_bmp = tigrBitmap(new_width, new_height);
    
    for (int y = 0; y < new_height; y++){
    for (int x = 0; x < new_width; x++){
        new_bmp->pix[(y)*new_width + (x)] = bmp->pix[(y*bmp->h/new_height)*bmp->w + (x*bmp->w/new_width)];
    }}

    return new_bmp;
}

This function takes a bitmap and returns it resized to the dimensions you pass it.

tigrSetResized

void tigrSetResized (Tigr ** bmp, int new_width, int new_height){
    Tigr * new_bmp = tigrBitmap(new_width, new_height);

    for (int y = 0; y < new_height; y++){
    for (int x = 0; x < new_width; x++){
        new_bmp->pix[(y)*new_width + (x)] = (*bmp)->pix[(y*((*bmp)->h)/new_height)*(*bmp)->w + (x*(*bmp)->w/new_width)];
    }}

    tigrFree(*bmp);
    *bmp = new_bmp;
}

Exact same as previous, just modifying the bitmap you pass in. (Not advisable to repeat on the same bitmap more than once)

tigrGetRotated

Tigr * tigrGetRotated (Tigr * bmp, double angle){
    // Caching the sine and cosine values of the angle for performance
    const double sin_a = sin(angle);
    const double cos_a = cos(angle);

    // Width and height of rotated bmp
    const int new_height = abs(bmp->w * sin_a) + abs(bmp->h * cos_a);
    const int new_width = abs(bmp->w * sin_a) + abs(bmp->h * cos_a);
    const int new_center_x = new_width/2;
    const int new_center_y = new_height/2;

    // Getting the center of the bmp
    const int old_center_x = bmp->w/2;
    const int old_center_y = bmp->h/2;

    Tigr * new_bmp = tigrBitmap(new_width, new_height);
    for (int y = 0; y < new_height; y++){
    for (int x = 0; x < new_width; x++){
        int old_x =  (x-new_center_x)*cos_a + (y-new_center_y)*sin_a + old_center_x;
        int old_y = -(x-new_center_x)*sin_a + (y-new_center_y)*cos_a + old_center_y;
        if (old_x >= 0 && old_y >= 0 && old_x < bmp->w && old_y < bmp->h){
            new_bmp->pix[y*new_width + x] = bmp->pix[old_y*bmp->w + old_x];
        } else {
            new_bmp->pix[y*new_width + x] = tigrRGBA(0, 0, 0, 0);
        }
    }}

    return new_bmp;
}

Takes the bitmap you pass it and rotates it the angle you pass it clockwise. It will fill in the whitespace caused by the rotation by a transparent color.

Example program

The following is an example displaying the use of all four of these functions:

#include "tigr.h"

#include <math.h>
#include <stdlib.h>
#include <string.h>

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 640

int main () {
    Tigr * screen = tigrWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Testing", 0);

    Tigr * img = tigrLoadImage("tigr.png");
    tigrSetResized(&img, 300, 300);
    Tigr * scale_img = tigrClone(img);
    Tigr * rotate_img = tigrClone(img);

    double scale_angle = 3.1415926535/4;
    double dir = 0.01;

    double rotate_angle = 0;

    while (!tigrClosed(screen)) {
        if (scale_angle < 0.01 || scale_angle > 3.1415926535/2 - dir){
            dir *= -1;
            scale_angle += dir;
        }
        scale_angle += dir;
        rotate_angle += 0.01;
        if (rotate_angle > 2*3.1415926535){
            rotate_angle -= 2*3.1415926535;
        }

        tigrClear(screen, tigrRGB(255, 255, 255));

        tigrFree(scale_img);
        tigrFree(rotate_img);
        scale_img = tigrGetResized(img, SCREEN_WIDTH * cos(scale_angle), SCREEN_HEIGHT * sin(scale_angle));
        rotate_img = tigrGetRotated(img, rotate_angle);
        
        tigrBlitAlpha(screen, scale_img, 0, 0, 0, 0, scale_img->w, scale_img->h, 1.0);
        tigrBlitAlpha(screen, rotate_img, SCREEN_WIDTH - (rotate_img->w/2 + 135), SCREEN_HEIGHT - (rotate_img->h/2 + 135), 0, 0, rotate_img->w, rotate_img->h, 1.0);

        tigrUpdate(screen);
    }

    tigrFree(img);
    tigrFree(scale_img);
    tigrFree(rotate_img);
    tigrFree(screen);

    return 0;
}

To use it, add in the definitions of the functions below, and compile. When running you will see the tigr logo being resized to various dimensions and another logo spinning in the corner.

I do believe that these functions are useful enough to be added, and if there is any problems with them feedback would be awesome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant