Merge branch 'write-support'

This commit is contained in:
Aaron Helton
2017-04-15 21:33:33 -04:00
5 changed files with 115 additions and 14 deletions

View File

@@ -15,6 +15,7 @@ set(SOURCE_FILES
src/test.c
src/TGAImage.c
src/TGADecode.c
src/TGAEncode.c
)
IF (CMAKE_COMPILER_IS_GNUCC)

View File

@@ -12,9 +12,10 @@ typedef enum {
TGA_GEN_IO_ERR = 4,
TGA_READ_ERR = 5,
TGA_WRITE_ERR = 6,
TGA_IMAGE_IMMUTABLE_ERR = 7,
TGA_UNSUPPORTED = 8,
TGA_INTERNAL_ERR = 9
TGA_INV_FILE_NAME = 7,
TGA_IMAGE_IMMUTABLE_ERR = 8,
TGA_UNSUPPORTED = 9,
TGA_INTERNAL_ERR = 10
} TGAError;
typedef enum {
@@ -43,6 +44,7 @@ TGAError TGA_ERR;
TGAError tga_error(void); /* Returns the current error, if any. */
void tga_clear_error(void);
TGAImage *read_tga_image(FILE *file);
int write_tga_image(TGAImage *image, const char *filename);
TGAImage *new_tga_image(TGAColorType type, uint8_t depth,
uint16_t width, uint16_t height);
void free_tga_image(TGAImage* image);

View File

@@ -78,12 +78,11 @@ error:
*/
static int _read_tga_header(TGAImage *image, FILE *file)
{
uint8_t data[TGA_HEADER_SIZE];
uint8_t data[TGA_HEADER_SIZE] = {0};
/* Sanity Checks */
if(!_tga_sanity(image))
goto error;
check(file, TGA_INV_IMAGE_PNT, "Invalid File Pointer Passed.");
check(_tga_sanity(image), TGA_INV_IMAGE_PNT, "Invalid TGAImage Pointer.");
check(file, TGA_INV_FILE_PNT, "Invalid File Pointer Passed.");
/* Ensure that we are at the beginning of the file. */
check(fseek(file, 0, SEEK_SET) == 0, TGA_GEN_IO_ERR,
"Unable to seek to beginning of file.");
@@ -111,7 +110,7 @@ error:
static int _read_tga_id_field(TGAImage *image, FILE *file)
{
check(file, TGA_INV_FILE_PNT, "Invalid File.");
check(image, TGA_INV_IMAGE_PNT, "Invalid Image Pointer.");
check(_tga_sanity(image), TGA_INV_IMAGE_PNT, "Invalid TGAImage Pointer.");
check(image->_meta->id_length != 0, TGA_INTERNAL_ERR,
"TGA Image ID Length is 0. This should not have been called.");
@@ -119,8 +118,8 @@ static int _read_tga_id_field(TGAImage *image, FILE *file)
check(image->id_field, TGA_MEM_ERR,
"Unable to allocate memory for TGA ID Field.");
if(ftell(file) != 18) /*Unlikely, assuming no problems, but never assume.*/
check(fseek(file, 18, SEEK_SET) == 0, TGA_GEN_IO_ERR,
if(ftell(file) != TGA_HEADER_SIZE)
check(fseek(file, TGA_HEADER_SIZE, SEEK_SET) == 0, TGA_GEN_IO_ERR,
"Unable to seek to ID Field.");
check(fread(image->id_field, image->_meta->id_length, 1, file) == 1,
@@ -141,8 +140,7 @@ error:
static int _read_tga_image_data(TGAImage *image, FILE *file)
{
if(!_tga_sanity(image))
goto error;
check(_tga_sanity(image), TGA_INV_IMAGE_PNT, "Invalid TGAImage Pointer.");
if(image->data)
free(image->data);
check(file, TGA_INV_FILE_PNT, "Invalid File Pointer passed.");

99
src/TGAEncode.c Normal file
View File

@@ -0,0 +1,99 @@
#include <stdint.h>
#include <stdlib.h>
#include "Private/TGAPrivate.h"
static int _write_tga_header(TGAImage *image, FILE *file)
{
uint8_t data[TGA_HEADER_SIZE] = {0};
check(_tga_sanity(image), TGA_INV_IMAGE_PNT, "Invalid TGAImage Pointer.");
check(file, TGA_INV_FILE_PNT, "Invalid file pointer passed.");
check(fseek(file, 0, SEEK_SET) == 0, TGA_GEN_IO_ERR,
"Unable to seek to beginning of file.");
data[0] = image->_meta->id_length;
data[1] = image->_meta->c_map_type;
data[2] = image->_meta->image_type;
*((uint16_t*)(data+3)) = image->_meta->c_map_start;
*((uint16_t*)(data+5)) = image->_meta->c_map_length;
data[7] = image->_meta->c_map_depth;
*((uint16_t*)(data+8)) = image->_meta->x_offset;
*((uint16_t*)(data+10)) = image->_meta->y_offset;
*((uint16_t*)(data+12)) = image->_meta->width;
*((uint16_t*)(data+14)) = image->_meta->height;
data[16] = image->_meta->pixel_depth;
data[17] = image->_meta->image_descriptor;
check(fwrite(data, TGA_HEADER_SIZE, 1, file) == 1, TGA_WRITE_ERR,
"Unable to write TGA Header.");
return 1;
error:
return 0;
}
static int _write_tga_id_field(TGAImage *image, FILE *file)
{
check(file, TGA_INV_FILE_PNT, "Invalid FILE Pointer.");
check(_tga_sanity(image), TGA_INV_IMAGE_PNT, "Invalid TGAImage Pointer.");
check(image->_meta->id_length != 0 && image->id_field, TGA_INTERNAL_ERR,
"TGA Image ID Null or 0. This should not have been called.");
if(ftell(file) != TGA_HEADER_SIZE)
check(fseek(file, TGA_HEADER_SIZE, SEEK_SET) == 0, TGA_GEN_IO_ERR,
"Unable to seek to beginning of ID Field.");
check(fwrite(image->id_field, image->_meta->id_length, 1, file) == 1,
TGA_WRITE_ERR, "Unable to write ID Field to file.");
return 1;
error:
return 0;
}
static int _write_tga_image_data(TGAImage *image, FILE *file)
{
uint8_t depth = 0;
uint32_t total = 0;
check(_tga_sanity(image), TGA_INV_IMAGE_PNT, "Invalid TGAImage Pointer.");
check(file, TGA_INV_FILE_PNT, "Invalid File Pointer.");
if(image->_meta->image_type == TGA_NO_DATA ||
image->_meta->image_type == TGA_INVALID_TYPE)
return 1; /* No Data to be written, according to meta-data. */
depth = (uint8_t)((image->_meta->pixel_depth + 7) / 8);
total = image->_meta->width * image->_meta->height * depth;
if(total == 0)
return 1;
check(image->data, TGA_INV_IMAGE_PNT, "Data missing.");
check(fwrite(image->data, total, 1, file) == 1, TGA_WRITE_ERR,
"Unable to write image data to file.");
return 1;
error:
return 0;
}
int write_tga_image(TGAImage *image, const char* filename)
{
FILE *file = NULL;
check(_tga_sanity(image), TGA_INV_IMAGE_PNT, "Invalid TGAImage Pointer.");
check(image->_meta->image_type == TGA_TRUECOLOR, TGA_UNSUPPORTED,
"Currently, only writing for TRUECOLOR TGA Images is supported.");
check(image->version == 1 || image->version == 2, TGA_UNSUPPORTED,
"Unsupported TGA Version.");
check(filename && filename[0] != '\0', TGA_INV_FILE_NAME,
"Invalid or Null filename.");
file = fopen(filename, "wb");
check(file, TGA_WRITE_ERR, "Unable to open file for writing.");
check(_write_tga_header(image, file), tga_error(),
"Unable to write TGA Header.");
if(image->_meta->id_length > 0)
check(_write_tga_id_field(image, file), tga_error(),
"Unable to write TGA ID Field.");
check(_write_tga_image_data(image, file), tga_error(),
"Unable to write TGA Data to file.");
return 1;
error:
if(file)
fclose(file);
return 0;
}

View File

@@ -11,9 +11,9 @@ static void print_tga_data(TGAImage *img)
int main(int argc, char **argv)
{
if(argc != 2)
if(argc != 3)
{
fprintf(stderr, "USAGE: TGAReader <image>\n");
fprintf(stderr, "USAGE: TGAReader <image> <newname>\n");
return 1;
}
@@ -30,6 +30,7 @@ int main(int argc, char **argv)
return tga_error();
}
print_tga_data(img);
write_tga_image(img, argv[2]);
free_tga_image(img);
fclose(img_file);
return 0;