erkkah / tigr

TIGR - the TIny GRaphics library for Windows, macOS, Linux, iOS and Android.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Adding functions for manipulating bitmaps

GrahamJoonsar opened this issue · comments

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!