Skip to content

Instantly share code, notes, and snippets.

@xanathar
Last active January 7, 2021 09:57
Show Gist options
  • Save xanathar/da1a534e323ed8f543b663a6844998b9 to your computer and use it in GitHub Desktop.
Save xanathar/da1a534e323ed8f543b663a6844998b9 to your computer and use it in GitHub Desktop.
Write TGA file in C with zero dependencies (apart stdio)
/**
* writetga: A zero dependencies writer for the TGA file format.
*
* Copyright 2020 Marco Mastropaolo <marco@mastropaolo.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __WRITE_TGA_H__
#define __WRITE_TGA_H__
#include <stdio.h>
typedef enum _TgaPixelFormat {
TGAPIXELFMT_BGR,
TGAPIXELFMT_BGRA,
TGAPIXELFMT_ABGR,
TGAPIXELFMT_BGRX,
TGAPIXELFMT_XBGR,
TGAPIXELFMT_RGB,
TGAPIXELFMT_RGBA,
TGAPIXELFMT_ARGB,
TGAPIXELFMT_RGBX,
TGAPIXELFMT_XRGB,
} TgaPixelFormat;
static void write_tga_ftpr(const char *data, int width, int height, TgaPixelFormat format, FILE *fptr)
{
char TGA_HEADER_PREFIX[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
fwrite(TGA_HEADER_PREFIX, sizeof(TGA_HEADER_PREFIX), 1, fptr);
putc(width & 0xFF, fptr);
putc(width >> 8, fptr);
putc(height & 0xFF, fptr);
putc(height >> 8, fptr);
switch(format) {
case TGAPIXELFMT_BGR:
case TGAPIXELFMT_RGB:
case TGAPIXELFMT_BGRX:
case TGAPIXELFMT_XBGR:
case TGAPIXELFMT_RGBX:
case TGAPIXELFMT_XRGB:
putc(24, fptr);
break;
case TGAPIXELFMT_BGRA:
case TGAPIXELFMT_ABGR:
case TGAPIXELFMT_RGBA:
case TGAPIXELFMT_ARGB:
putc(32, fptr);
break;
}
putc(0x20, fptr); /* flip vertical */
switch(format) {
case TGAPIXELFMT_BGR:
fwrite(data, width * height, 3, fptr);
break;
case TGAPIXELFMT_BGRA:
fwrite(data, width * height, 4, fptr);
break;
case TGAPIXELFMT_BGRX:
for (int i = 0, len = width * height * 4; i < len; i += 4) {
putc(data[i + 0], fptr);
putc(data[i + 1], fptr);
putc(data[i + 2], fptr);
}
break;
case TGAPIXELFMT_ABGR:
for (int i = 0, len = width * height * 4; i < len; i += 4) {
putc(data[i + 1], fptr);
putc(data[i + 2], fptr);
putc(data[i + 3], fptr);
putc(data[i + 0], fptr);
}
break;
case TGAPIXELFMT_XBGR:
for (int i = 0, len = width * height * 4; i < len; i += 4) {
putc(data[i + 1], fptr);
putc(data[i + 2], fptr);
putc(data[i + 3], fptr);
}
break;
case TGAPIXELFMT_RGB:
for (int i = 0, len = width * height * 3; i < len; i += 3) {
putc(data[i + 2], fptr);
putc(data[i + 1], fptr);
putc(data[i + 0], fptr);
}
break;
case TGAPIXELFMT_ARGB:
for (int i = 0, len = width * height * 4; i < len; i += 4) {
putc(data[i + 3], fptr);
putc(data[i + 2], fptr);
putc(data[i + 1], fptr);
putc(data[i + 0], fptr);
}
break;
case TGAPIXELFMT_XRGB:
for (int i = 0, len = width * height * 4; i < len; i += 4) {
putc(data[i + 3], fptr);
putc(data[i + 2], fptr);
putc(data[i + 1], fptr);
}
break;
case TGAPIXELFMT_RGBA:
for (int i = 0, len = width * height * 4; i < len; i += 4) {
putc(data[i + 2], fptr);
putc(data[i + 1], fptr);
putc(data[i + 0], fptr);
putc(data[i + 3], fptr);
}
break;
case TGAPIXELFMT_RGBX:
for (int i = 0, len = width * height * 4; i < len; i += 4) {
putc(data[i + 2], fptr);
putc(data[i + 1], fptr);
putc(data[i + 0], fptr);
}
break;
}
}
static int write_tga(const void *framebuffer, int width, int height, TgaPixelFormat format, const char* filename)
{
FILE *fptr = fopen(filename, "wb");
if (!fptr) {
return 0;
}
write_tga_ftpr((const char *)framebuffer, width, height, format, fptr);
fclose(fptr);
return 1;
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment