Created
June 30, 2018 13:10
-
-
Save pastagatsan/04ad9bcb8a8bf19303dd7f79e70d5cba to your computer and use it in GitHub Desktop.
OrzoEngine - loading TGA images and displaying them in xterm256-color
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "orzosimplesurface.h" | |
#include "targa.h" | |
#include <stdlib.h> | |
#include <math.h> | |
void SetupColorPairs() | |
{ | |
int i; | |
for (i = 1; i <= 256; i++) { | |
init_pair(i, 0, i-1); | |
} | |
} | |
uint8_t RGB256ToCol(uint8_t r, uint8_t g, uint8_t b, uint8_t gr) | |
{ | |
if (abs(r - g) <= gr && abs(g - b) <= gr && abs(b - r) <= gr) { | |
int mean = (r + g + b) / 3; | |
int ncol = round((mean / 10.625)); | |
if (!ncol) { return 0; } | |
return 231 + ncol; | |
} | |
return RGB6ToCol(round((r / 42.5) - 1), round((g / 42.5) - 1), | |
round((b / 42.5) - 1)); | |
} | |
uint8_t RGB6ToCol(int r, int g, int b) | |
{ | |
if (r > 5) r = 5; | |
if (r < 0) r = 0; | |
if (g > 5) g = 5; | |
if (g < 0) g = 0; | |
if (b > 5) b = 5; | |
if (b < 0) b = 0; | |
return 16 + 36 * r + 6 * g + b; | |
} | |
OrzoSimpleSurface* OSS_New(size_t width, size_t height) | |
{ | |
OrzoSimpleSurface* oss = malloc(sizeof(OrzoSimpleSurface)); | |
oss->width = width; | |
oss->height = height; | |
oss->pixels = malloc(width * sizeof(uint8_t*)); | |
int x; | |
for (x = 0; x < width; x++) { | |
oss->pixels[x] = malloc(height * sizeof(uint8_t)); | |
} | |
OSS_Clear(oss, 0); | |
return oss; | |
} | |
OrzoSimpleSurface* OSS_NewFromTGA(char* filename) | |
{ | |
Targa* tga = Targa_New(); | |
Targa_Read(tga, filename); | |
OrzoSimpleSurface* oss = OSS_New(tga->width, tga->height); | |
int x, y; | |
for (x = 0; x < tga->width; x++) { | |
for (y = 0; y < tga->height; y++) { | |
uint32_t tgapix = tga->pixels[x][y]; | |
uint8_t r = (tgapix & 0xFF00) >> 8, g = tgapix & 0xFF, | |
b = (tgapix & 0xFF000000) >> 24; | |
oss->pixels[x][y] = RGB256ToCol(r, g, b, 5); | |
} | |
} | |
Targa_Delete(tga); | |
return oss; | |
} | |
void OSS_Clear(OrzoSimpleSurface* oss, uint8_t color) | |
{ | |
int x, y; | |
for (x = 0; x < oss->width; x++) { | |
for (y = 0; y < oss->height; y++) { | |
oss->pixels[x][y] = color; | |
} | |
} | |
} | |
void OSS_DrawTo(OrzoSimpleSurface* s, WINDOW* w, int xpos, int ypos) | |
{ | |
int x, y, xmax, ymax; | |
getmaxyx(w, ymax, xmax); | |
for (x = 0; x < s->width; x++) { | |
if (x > xmax) { break; } | |
if (x < 0) { continue; } | |
for (y = 0; y < s->height; y++) { | |
if (y > ymax) { break; } | |
if (y < 0) { continue; } | |
attron(COLOR_PAIR(s->pixels[x][y] + 1)); | |
mvwaddch(w, y + ypos, x + xpos, ' '); | |
attroff(COLOR_PAIR(s->pixels[x][y] + 1)); | |
} | |
} | |
} | |
void OSS_SetPixel(OrzoSimpleSurface* s, int x, int y, uint8_t col) | |
{ | |
if (x < 0 || x > s->width - 1 || y < 0 || y > s->height - 1) return; | |
s->pixels[x][y] = col; | |
} | |
void OSS_DrawRect(OrzoSimpleSurface* s, int x, int y, int w, int h, uint8_t col) | |
{ | |
int i, j; | |
for (i = 0; i < w; i++) { | |
for (j = 0; j < h; j++) { | |
OSS_SetPixel(s, x + i, y + j, col); | |
} | |
} | |
} | |
void OSS_Delete(OrzoSimpleSurface* s) | |
{ | |
int x; | |
for (x = 0; x < s->width; x++) { | |
free(s->pixels[x]); | |
} | |
free(s->pixels); | |
free(s); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <ncurses.h> | |
#include <stdint.h> | |
typedef struct { | |
size_t width, height; | |
uint8_t** pixels; | |
} OrzoSimpleSurface; | |
/* Initialises color pairs 1 - 256 for OrzoSimpleSurface | |
* | |
* Any one of these color pairs 'x' corresponds to a background of color x-1 | |
* and a foreground color of 0 (COLOR_BLACK) | |
*/ | |
void SetupColorPairs(); | |
/* | |
* Converts a 24-bit RGB colour to an xterm-256 colour. | |
* | |
* If the components r, g and b differ between eachother by greyscalerange | |
* or less, the colour is considered greyscale and colours 0, 232-255 are used. | |
* Otherwise, colours 16-231 are used. | |
*/ | |
uint8_t RGB256ToCol(uint8_t r, uint8_t g, uint8_t b, uint8_t greyscalerange); | |
uint8_t RGB6ToCol(int r, int g, int b); | |
/* Creates a new OrzoSimpleSurface */ | |
OrzoSimpleSurface* OSS_New(size_t width, size_t height); | |
/* Creates a new OrzoSimpleSurface from an uncompressed TGA. Pixels colours are | |
* approximated using RGB256ToCol. | |
* | |
* Only unmapped RGB (data type 2) targa files are accepted. | |
*/ | |
OrzoSimpleSurface* OSS_NewFromTGA(char* filename); | |
/* Sets each pixel in the surface to color */ | |
void OSS_Clear(OrzoSimpleSurface* oss, uint8_t color); | |
/* Draws an OrzoSimpleSurface's pixel information to a window at an xpos and | |
* ypos. | |
*/ | |
void OSS_DrawTo(OrzoSimpleSurface* s, WINDOW* w, int xpos, int ypos); | |
void OSS_SetPixel(OrzoSimpleSurface* s, int x, int y, uint8_t col); | |
void OSS_DrawRect(OrzoSimpleSurface* s, int x, int y, int w, int h, uint8_t c); | |
/* Delete an OrzoSimpleSurface instance */ | |
void OSS_Delete(OrzoSimpleSurface* s); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "targa.h" | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <math.h> | |
Targa* Targa_New() | |
{ | |
Targa* t = malloc(sizeof(Targa)); | |
memset(t, 0, sizeof(Targa)); | |
return t; | |
} | |
void Targa_AllocatePixelMemory(Targa* t) | |
{ | |
t->pixels = malloc(t->width * sizeof(uint32_t*)); | |
int x; | |
for (x = 0; x < t->width; x++) { | |
t->pixels[x] = malloc(t->height * sizeof(uint32_t)); | |
} | |
} | |
void Targa_Read(Targa* t, char* filename) | |
{ | |
FILE* file = fopen(filename, "r"); | |
fread(&t->idlength, 1, 1, file); | |
fread(&t->colourmaptype, 1, 1, file); | |
fread(&t->datatypecode, 1, 1, file); | |
fread(&t->colourmaporigin, 2, 1, file); | |
fread(&t->colourmaplength, 2, 1, file); | |
fread(&t->colourmapdepth, 1, 1, file); | |
fread(&t->x_origin, 2, 1, file); | |
fread(&t->y_origin, 2, 1, file); | |
fread(&t->width, 2, 1, file); | |
fread(&t->height, 2, 1, file); | |
fread(&t->bitsperpixel, 1, 1, file); | |
fread(&t->imagedescriptor, 2, 1, file); | |
Targa_PrintHeader(t); | |
if (t->bitsperpixel != 32 && t->bitsperpixel != 24) { | |
printf("Targa file %s has %d bits per pixel. Only 24/32 are " | |
"accepted.\n", filename, t->bitsperpixel); | |
fclose(file); | |
return; | |
} | |
if (t->datatypecode != 2) { // i.e. if it is not uncompressed RGB | |
printf("Targa file %s is not uncompressed RGB.\n", filename); | |
fclose(file); | |
return; | |
} | |
uint32_t pixel; | |
char pixel_length = t->bitsperpixel / 8; | |
size_t area = t->width * t->height; | |
size_t amount_to_read = pixel_length * area; | |
Targa_AllocatePixelMemory(t); | |
int k; | |
for (k = 0; k < area; k++) { | |
pixel = 0; | |
fread(&pixel, pixel_length, 1, file); | |
if (t->bitsperpixel == 32) { | |
pixel = (pixel & 0x00FFFFFF); | |
} | |
int x = k % t->width; | |
int y = floor((t->height) - (k / t->width)); | |
t->pixels[x][y] = pixel; | |
} | |
if (!feof(file)) { | |
printf("Some error reading Targa file %s occurred.\n", filename); | |
fclose(file); | |
return; | |
} | |
fclose(file); | |
} | |
void Targa_PrintHeader(Targa* t) | |
{ | |
printf("sizeof header = %lu\n", sizeof(Targa) - sizeof(uint32_t**)); | |
printf("ID Length: %d\n", t->idlength); | |
printf("Colour map type: %d\n", t->colourmaptype); | |
printf("Data Type Code: %d\n", t->datatypecode); | |
printf("Colour Map Origin: %d\n", t->colourmaporigin); | |
printf("Colour Map Length: %d\n", t->colourmaplength); | |
printf("Colour Map Depth: %d\n", t->colourmapdepth); | |
printf("X Origin: %d\n", t->x_origin); | |
printf("Y Origin: %d\n", t->y_origin); | |
printf("Width: %d\n", t->width); | |
printf("Height: %d\n", t->height); | |
printf("Bits per pixel: %d\n", t->bitsperpixel); | |
printf("Image descriptor: %d\n", t->imagedescriptor); | |
} | |
void Targa_Delete(Targa* t) | |
{ | |
int x; | |
for (x = 0; x < t->width; x++) { | |
if (t->pixels[x]) free(t->pixels[x]); | |
} | |
if (t->pixels) free(t->pixels); | |
free(t); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <stdint.h> | |
typedef struct { | |
int8_t idlength; | |
int8_t colourmaptype; | |
int8_t datatypecode; | |
int16_t colourmaporigin; | |
int16_t colourmaplength; | |
int8_t colourmapdepth; | |
int16_t x_origin; | |
int16_t y_origin; | |
int16_t width; | |
int16_t height; | |
int8_t bitsperpixel; | |
int8_t imagedescriptor; | |
uint32_t** pixels; | |
} Targa; | |
Targa* Targa_New(); | |
void Targa_AllocatePixelMemory(Targa* t); | |
void Targa_Read(Targa* dest, char* filename); | |
void Targa_PrintHeader(Targa* t); | |
void Targa_Delete(Targa* t); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <ncurses.h> | |
#include "orzosimplesurface.h" | |
#include "targa.h" | |
int main() | |
{ | |
OrzoSimpleSurface* s = OSS_NewFromTGA("dike2.tga"); | |
getch(); | |
initscr(); | |
start_color(); | |
SetupColorPairs(); | |
int c, x, y; | |
do { | |
if (c == 'w') { | |
y--; | |
} else if (c == 's') { | |
y++; | |
} else if (c == 'a') { | |
x--; | |
} else if (c == 'd') { | |
x++; | |
} | |
OSS_DrawTo(s, stdscr, 0, 0); | |
} while ((c = getch()) != 'q'); | |
endwin(); | |
OSS_Delete(s); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment