From: bogglez <bo...@us...> - 2017-03-09 20:50:18
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via d0be8ed7e09cc721d45d4ba38266d0a10e07598e (commit) via df9dfa1a494c9ba871318eee506683c3557be9e2 (commit) via ee28c5cfb5cbd98a4f29393f8d157b4e67674aab (commit) from 8b2a2967d2d77973b50c5fa01fcb27932f70d522 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d0be8ed7e09cc721d45d4ba38266d0a10e07598e Author: bogglez <bo...@pr...> Date: Thu Mar 9 21:49:43 2017 +0100 dcbumpgen: check errors - check dimensions power of two - check fopen - check 2 mallocs - check fwrite - cleanup ressources at end of function commit df9dfa1a494c9ba871318eee506683c3557be9e2 Author: bogglez <bo...@pr...> Date: Thu Mar 9 21:44:28 2017 +0100 dcbumpgen: use readpng code from vqenc, io errors commit ee28c5cfb5cbd98a4f29393f8d157b4e67674aab Author: bogglez <bo...@pr...> Date: Thu Mar 9 21:39:26 2017 +0100 dcbumpgen: add man page ----------------------------------------------------------------------- Summary of changes: utils/dcbumpgen/dcbumpgen.1 | 30 ++++++++++ utils/dcbumpgen/dcbumpgen.c | 61 +++++++++++++------- utils/dcbumpgen/get_image_png.c | 121 ++++++++++++++++++++-------------------- utils/dcbumpgen/readpng.c | 79 ++++++++++++++------------ utils/dcbumpgen/readpng.h | 10 ++-- 5 files changed, 179 insertions(+), 122 deletions(-) create mode 100644 utils/dcbumpgen/dcbumpgen.1 diff --git a/utils/dcbumpgen/dcbumpgen.1 b/utils/dcbumpgen/dcbumpgen.1 new file mode 100644 index 0000000..982ee26 --- /dev/null +++ b/utils/dcbumpgen/dcbumpgen.1 @@ -0,0 +1,30 @@ +.TH DCBUMPGEN 1 "Mar 2017" "Version 1.0" +.SH NAME +dcbumpgen \- dcbumpgen a Dreamcast executable +.SH SYNOPSIS +.B dcbumpgen +.IR from +.IR to + +.SH DESCRIPTION +.B dcbumpgen +is used to generate SEGA Dreamcast PVR bumpmap textures. + +.SH EXAMPLES + +.EX +.B + dcbumpgen infile.png outfile.raw +.EE + +.EX +.B + dcbumpgen infile.jpg outfile.raw +.EE + +.SH AUTHOR +This manual page was initially written by Stefan Galowicz <bo...@pr...>, +for the KOS project. +.TP +The program has been initially written by Frederik Ehnbom in 2005. +.SH SEE ALSO diff --git a/utils/dcbumpgen/dcbumpgen.c b/utils/dcbumpgen/dcbumpgen.c index 7f3d241..b91b7d0 100644 --- a/utils/dcbumpgen/dcbumpgen.c +++ b/utils/dcbumpgen/dcbumpgen.c @@ -35,41 +35,61 @@ */ #include "get_image.h" -void printUsage() { +static void printUsage() { printf("dcbumpgen - Dreamcast bumpmap generator v0.1\n"); printf("Copyright (c) 2005 Fredrik Ehnbom\n"); printf("usage: dcbumpgen <infile.png/.jpg> <outfile.raw>\n"); } +static int isPowerOfTwo(unsigned x) +{ + return x && !(x & (x-1)); +} + /* twiddling stuff copied from kmgenc.c */ #define TWIDTAB(x) ( (x&1)|((x&2)<<1)|((x&4)<<2)|((x&8)<<3)|((x&16)<<4)| \ ((x&32)<<5)|((x&64)<<6)|((x&128)<<7)|((x&256)<<8)|((x&512)<<9) ) #define TWIDOUT(x, y) ( TWIDTAB((y)) | (TWIDTAB((x)) << 1) ) #define MIN(a, b) ( (a)<(b)? (a):(b) ) +#define ERROR(...) { ret = 1; fprintf(stderr, __VA_ARGS__); goto cleanup; } + int main(int argc, char **argv) { - image_t img; - FILE *fp; + int ret = 0; int y, x; - unsigned char *buffer; int imgpos, dest; + image_t img = {0}; + FILE *fp = 0; + unsigned char *buffer = 0; + short * twidbuffer = 0; if (argc != 3) { printUsage(); - exit(1); + return 0; } if (get_image(argv[1], &img) < 0) { - fprintf(stderr, "couldn't open %s\n", argv[1]); - return -1; + ERROR("Cannot open %s\n", argv[1]); } - /* TODO: - * - error-checking for missing files and other file failures - * - check that image is power of two - */ fp = fopen(argv[2], "wb"); + if(!fp) { + ERROR("Cannot open file %s!\n", argv[2]); + } + buffer = malloc(2 * img.w * img.h); + if(!buffer) { + ERROR("Cannot allocate memory for image data!\n"); + } + + twidbuffer = malloc(2 * img.w * img.h); + if(!buffer) { + ERROR("Cannot allocate memory for twiddle buffer!\n"); + } + + if(!isPowerOfTwo(img.w) || !isPowerOfTwo(img.h)) { + ERROR("Image dimensions %ux%u are not a power of two!\n", img.w, img.h); + } imgpos = 1; /* 1 to skip the alpha-channel */ dest = 0; @@ -101,7 +121,6 @@ int main(int argc, char **argv) { int min = MIN(img.w, img.h); int mask = min-1; short *sbuffer = (short*) buffer; - short *twidbuffer = malloc(2 * img.w * img.h); for (y=0; y<img.h; y++) { int yout = y; for (x=0; x<img.w; x++) { @@ -110,14 +129,16 @@ int main(int argc, char **argv) { } } - fwrite(twidbuffer, 1, 2* img.w * img.h, fp); - fclose(fp); - - free(buffer); - free(twidbuffer); - if (img.data) { - free(img.data); + if(fwrite(twidbuffer, 2* img.w * img.h, 1, fp) != 1) { + ERROR("Cannot write twiddle buffer!\n"); } - return 0; + +cleanup: + if(fp) fclose(fp); + if(buffer) free(buffer); + if(twidbuffer) free(twidbuffer); + if(img.data) free(img.data); + + return ret; } diff --git a/utils/dcbumpgen/get_image_png.c b/utils/dcbumpgen/get_image_png.c index aec635d..3668167 100644 --- a/utils/dcbumpgen/get_image_png.c +++ b/utils/dcbumpgen/get_image_png.c @@ -8,8 +8,8 @@ */ #include <assert.h> -#include <stdlib.h> #include <png.h> +#include <stdlib.h> #include "readpng.h" #include "get_image.h" @@ -17,79 +17,78 @@ /* not to be used outside of here */ void _png_copy_texture(uint8 *buffer, uint8 *temp_tex, - uint32 channels, uint32 stride, - uint32 w, uint32 h) -{ - uint32 i,j; - uint8 *ourbuffer; - uint8 *pRow; - - for(i = 0; i < h; i++) { - pRow = &buffer[i*stride]; - ourbuffer = &temp_tex[i*w*4]; - - if (channels == 3) { - for (j=0; j<w; j++) { - ourbuffer[j*4+0] = 0xff; - ourbuffer[j*4+1] = pRow[j*3+0]; - ourbuffer[j*4+2] = pRow[j*3+1]; - ourbuffer[j*4+3] = pRow[j*3+2]; - } - } - else if (channels == 4) { - for (j=0; j<w; j++) { - ourbuffer[j*4+0] = pRow[j*4+3]; - ourbuffer[j*4+1] = pRow[j*4+0]; - ourbuffer[j*4+2] = pRow[j*4+1]; - ourbuffer[j*4+3] = pRow[j*4+2]; - } + uint32 channels, uint32 stride, + uint32 w, uint32 h) { + uint32 i, j; + uint8 *ourbuffer; + uint8 *pRow; + + for(i = 0; i < h; i++) { + pRow = &buffer[i * stride]; + ourbuffer = &temp_tex[i * w * 4]; + + if(channels == 3) { + for(j = 0; j < w; j++) { + ourbuffer[j * 4 + 0] = 0xff; + ourbuffer[j * 4 + 1] = pRow[j * 3]; + ourbuffer[j * 4 + 2] = pRow[j * 3 + 1]; + ourbuffer[j * 4 + 3] = pRow[j * 3 + 2]; + } + } + else if(channels == 4) { + for(j = 0; j < w; j++) { + ourbuffer[j * 4 + 0] = pRow[j * 4 + 3]; + ourbuffer[j * 4 + 1] = pRow[j * 4 + 0]; + ourbuffer[j * 4 + 2] = pRow[j * 4 + 1]; + ourbuffer[j * 4 + 3] = pRow[j * 4 + 2]; + } + } } - } } int get_image_png(const char * filename, image_t * image) { - uint8 *temp_tex; + uint8 *temp_tex; - /* More stuff */ - uint8 *buffer; /* Output row buffer */ - uint32 row_stride; /* physical row width in output buffer */ - uint32 channels; /* 3 for RGB 4 for RGBA */ + /* More stuff */ + uint8 *buffer; /* Output row buffer */ + uint32 row_stride; /* physical row width in output buffer */ + uint32 channels; /* 3 for RGB 4 for RGBA */ - FILE *infile; /* source file */ + FILE *infile; /* source file */ - assert( image != NULL ); + assert(image != NULL); - if ((infile = fopen(filename, "rb")) == 0) { - printf("png_to_texture: can't open %s\n", filename); - return -1; - } + if((infile = fopen(filename, "rb")) == 0) { + printf("png_to_texture: can't open %s\n", filename); + return -1; + } - /* Step 1: Initialize loader */ - if (readpng_init(infile)) { - fclose(infile); - return -2; - } + /* Step 1: Initialize loader */ + if(readpng_init(infile)) { + fclose(infile); + return -2; + } - /* Step 1.5: Create output kos_img_t */ - /* rv = (kos_img_t *)malloc(sizeof(kos_img_t)); */ + /* Step 1.5: Create output kos_img_t */ + /* rv = (kos_img_t *)malloc(sizeof(kos_img_t)); */ - /* Step 2: Read file */ - buffer = readpng_get_image(&channels, &row_stride, &image->w, &image->h); - temp_tex = (uint8 *)malloc(sizeof(uint8) * 4 * image->w * image->h); - image->data = (unsigned char *)temp_tex; - image->bpp = 4; - image->stride = image->w*4; + /* Step 2: Read file */ + buffer = readpng_get_image(&channels, &row_stride, &image->w, &image->h); + temp_tex = (uint8 *)malloc(sizeof(uint8) * 4 * image->w * image->h); + image->data = (unsigned char *)temp_tex; + image->bpp = 4; + image->stride = image->w * 4; - _png_copy_texture(buffer, temp_tex, - channels, row_stride, - image->w, image->h); + _png_copy_texture(buffer, temp_tex, + channels, row_stride, + image->w, image->h); - /* Step 3: Finish decompression */ - free(buffer); - readpng_cleanup(); + /* Step 3: Finish decompression */ + free(buffer); + readpng_cleanup(); - fclose(infile); + fclose(infile); - /* And we're done! */ - return 0; + /* And we're done! */ + return 0; } diff --git a/utils/dcbumpgen/readpng.c b/utils/dcbumpgen/readpng.c index f9372d7..788f100 100644 --- a/utils/dcbumpgen/readpng.c +++ b/utils/dcbumpgen/readpng.c @@ -3,7 +3,6 @@ readpng.c Copyright (C)2002 Jeffrey McBeth - $Id: readpng.c,v 1.1 2003/04/24 03:19:42 bardtx Exp $ */ /* Modified for vqenc by Dan Potter */ @@ -11,43 +10,46 @@ #include <stdio.h> #include <stdlib.h> -#include <png.h> /* libpng header */ +#include <png.h> /* libpng header; includes zlib.h */ #include <zlib.h> #include "readpng.h" /* typedefs, common macros, public prototypes */ static png_structp png_ptr = NULL; static png_infop info_ptr = NULL; -void readpng_version_info(void) -{ +void readpng_version_info(void) { fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n", - PNG_LIBPNG_VER_STRING, png_libpng_ver); + PNG_LIBPNG_VER_STRING, png_libpng_ver); fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n", - ZLIB_VERSION, zlib_version); + ZLIB_VERSION, zlib_version); } -/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */ +/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 3 for io, 4 for no mem */ -uint32 readpng_init(FILE *infile) -{ +uint32 readpng_init(FILE *infile) { uint8 sig[8]; /* first do a quick check that the file really is a PNG image; could * have used slightly more general png_sig_cmp() function instead */ - fread(sig, 1, 8, infile); - if (!png_check_sig(sig, 8)) + if(fread(sig, 8, 1, infile) != 1) { + return 3; + } + + if(!png_check_sig(sig, 8)) return 1; /* bad signature */ /* could pass pointers to user-defined error handlers instead of NULLs: */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) + + if(!png_ptr) return 4; /* out of memory */ info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { + + if(!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return 4; /* out of memory */ } @@ -62,39 +64,42 @@ uint32 readpng_init(FILE *infile) return 0; } -uint8 *readpng_get_image(uint32 *pChannels, uint32 *pRowbytes, uint32 *pWidth, uint32 *pHeight) -{ - png_uint_32 width, height; - int bit_depth, color_type; - uint8 *image_data = NULL; - png_uint_32 i, rowbytes; - png_bytepp row_pointers = NULL; +uint8 *readpng_get_image(uint32 *pChannels, uint32 *pRowbytes, int *pWidth, int *pHeight) { + png_uint_32 width, height; + int bit_depth, color_type; + uint8 *image_data = NULL; + png_uint_32 i, rowbytes; + png_bytepp row_pointers = NULL; /* alternatively, could make separate calls to png_get_image_width(), * etc., but want bit_depth and color_type for later [don't care about * compression_type and filter_type => NULLs] */ - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, - NULL, NULL, NULL); + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, + NULL, NULL, NULL); - *pWidth = width; - *pHeight = height; + *pWidth = (int)width; + *pHeight = (int)height; /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits, * transparency chunks to full alpha channel; strip 16-bit-per-sample * images to 8 bits per sample; and convert grayscale to RGB[A] */ - if (color_type == PNG_COLOR_TYPE_PALETTE) + if(color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + + if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand(png_ptr); - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + + if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); - if (bit_depth == 16) + + if(bit_depth == 16) png_set_strip_16(png_ptr); - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + + if(color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); /* all transformations have been registered; now update info_ptr data, @@ -105,11 +110,12 @@ uint8 *readpng_get_image(uint32 *pChannels, uint32 *pRowbytes, uint32 *pWidth, u *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr); *pChannels = (int)png_get_channels(png_ptr, info_ptr); - if ((image_data = (uint8 *)malloc(rowbytes*height)) == NULL) { + if((image_data = (uint8 *)malloc(rowbytes * height)) == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } - if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { + + if((row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep))) == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); free(image_data); image_data = NULL; @@ -121,8 +127,8 @@ uint8 *readpng_get_image(uint32 *pChannels, uint32 *pRowbytes, uint32 *pWidth, u /* set the individual row_pointers to point at the correct offsets */ - for (i = 0; i < height; ++i) - row_pointers[i] = image_data + i*rowbytes; + for(i = 0; i < height; ++i) + row_pointers[i] = image_data + i * rowbytes; /* now we can go ahead and just read the whole image */ @@ -137,9 +143,8 @@ uint8 *readpng_get_image(uint32 *pChannels, uint32 *pRowbytes, uint32 *pWidth, u } -void readpng_cleanup(void) -{ - if (png_ptr && info_ptr) { +void readpng_cleanup(void) { + if(png_ptr && info_ptr) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); png_ptr = NULL; info_ptr = NULL; diff --git a/utils/dcbumpgen/readpng.h b/utils/dcbumpgen/readpng.h index 8473a73..1c4a034 100644 --- a/utils/dcbumpgen/readpng.h +++ b/utils/dcbumpgen/readpng.h @@ -2,9 +2,11 @@ typedef unsigned short uint16; typedef unsigned char uint8; */ -#define uint32 unsigned int -#define uint16 unsigned short -#define uint8 unsigned char +#include <stdint.h> + +#define uint32 uint32_t +#define uint16 uint16_t +#define uint8 uint8_t #ifndef TRUE # define TRUE 1 @@ -33,6 +35,6 @@ uint32 readpng_init(FILE *infile); * The caller is responsible for freeing the memory */ uint8 *readpng_get_image(uint32 *pNumChannels, - uint32 *pRowBytes, uint32 *pWidth, uint32 *pHeight); + uint32 *pRowBytes, int *pWidth, int *pHeight); void readpng_cleanup(void); hooks/post-receive -- A pseudo Operating System for the Dreamcast. |