Skip to content

Instantly share code, notes, and snippets.

@vipyne
Last active February 24, 2021 20:02
Show Gist options
  • Save vipyne/c463301a07bd348510707bfbc1e7ad5a to your computer and use it in GitHub Desktop.
Save vipyne/c463301a07bd348510707bfbc1e7ad5a to your computer and use it in GitHub Desktop.
write a TARGA image file in C
// vanessa writes a targa file
// compiling and running this file will produce a targa file
// a lot of this is based on Grant Emery's file https://www.tjhsst.edu/~dhyatt/superap/code/targa.c thanks dude
// author: vanessa pyne --- github.com/vipyne
#include <stdio.h>
#define BYTE_RANGE 256;
////// targa file header
typedef struct {
char id_length; // length of id field (number of bytes - max 255)
char map_type; // colormap field (0 or 1; no map or 256 entry palette)
char image_type; // ( 0 - no image data included
// 1 - uncompressed, color mapped image
// 2 - uncompressed, RGB image
// 3 - uncompressed, black & white image
// 9 - run-length encoded(RLE-lossless compression),color mapped image
// 10 - RLE, RGB image
// 11 - compressed, black & white image )
int map_first; // first entry index for color map
int map_length; // total number of entries in color map
char map_entry_size; // number of bits per entry
int x; // x cooridinate of origin
int y; // y cooridinate of origin
int width; // width in pixels
int height; // height in pixels
char bits_per_pixel; // number of bits per pixel
char misc; // srsly? "scan origin and alpha bits" this example uses scan origin
// honestly, don't know what's going on here. we pass in a hex value
// :shrug_emoji:
} targa_header;
int little_endianify (int number)
{
return number % BYTE_RANGE;
}
int big_endianify (int number)
{
return number / BYTE_RANGE;
}
////// write header function
void write_header (targa_header header, FILE *tga)
{
fputc( header.id_length, tga );
fputc( header.map_type, tga );
fputc( header.image_type, tga );
fputc( little_endianify(header.map_first), tga );
fputc( big_endianify(header.map_first), tga );
fputc( little_endianify(header.map_length), tga );
fputc( big_endianify(header.map_length), tga );
fputc( header.map_entry_size, tga );
fputc( little_endianify(header.x), tga );
fputc( big_endianify(header.x), tga );
fputc( little_endianify(header.y), tga );
fputc( big_endianify(header.y), tga );
fputc( little_endianify(header.width), tga );
fputc( big_endianify(header.width), tga );
fputc( little_endianify(header.height), tga );
fputc( big_endianify(header.height), tga );
fputc( header.bits_per_pixel, tga );
fputc( header.misc, tga );
}
////// MAIN
int main (void)
{
FILE *tga; // pointer to file that we will write
targa_header header; // variable of targa_header type
int x, y; // coordinates for `for` loops to pass in
// correct number of values
// set header values
header.id_length = 0;
header.map_type = 0;
header.image_type = 2; // uncompressed RGB image
header.map_first = 0;
header.map_length = 0;
header.map_entry_size = 0;
header.x = 0;
header.y = 0;
header.width = 500;
header.height = 500;
header.bits_per_pixel = 24;
header.misc = 0x20; // scan from upper left corner, wut dude
// start to write file
tga = fopen("vanessa-writes-a.tga", "wb");
write_header(header, tga);
//// magic happens here -- write the pixels
for (y = 0; y < 500; ++y)
for (x = 0; x < 500; ++x)
{
// B G R order
fputc(170, tga);
fputc(200, tga);
fputc(20, tga);
}
//// magic ends here
fclose(tga);
return 0;
}
@Zi7ar21
Copy link

Zi7ar21 commented Feb 24, 2021

Neat, but doesn't this just write the bytes to the disk byte by byte? Why not write the image to an array and then write it to the disk? I would send code but I don't have any idea how to do so

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment