Wherein I watch too much Ashens
This commit is contained in:
		
							parent
							
								
									924ef3feb9
								
							
						
					
					
						commit
						0e0d60c9a6
					
				
					 6 changed files with 1218 additions and 9 deletions
				
			
		| 
						 | 
					@ -7,9 +7,18 @@
 | 
				
			||||||
#define CAMMY_SRAM_SCRATCH_2_SIZE      4
 | 
					#define CAMMY_SRAM_SCRATCH_2_SIZE      4
 | 
				
			||||||
#define CAMMY_SRAM_TILE_SIZE          16
 | 
					#define CAMMY_SRAM_TILE_SIZE          16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CAMMY_SRAM_TILE_WIDTH          8
 | 
				
			||||||
 | 
					#define CAMMY_SRAM_TILE_HEIGHT         8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CAMMY_SRAM_PHOTO_TILES_WIDTH  16
 | 
					#define CAMMY_SRAM_PHOTO_TILES_WIDTH  16
 | 
				
			||||||
#define CAMMY_SRAM_PHOTO_TILES_HEIGHT 14
 | 
					#define CAMMY_SRAM_PHOTO_TILES_HEIGHT 14
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CAMMY_SRAM_PHOTO_WIDTH \
 | 
				
			||||||
 | 
					    (CAMMY_SRAM_TILE_WIDTH * CAMMY_SRAM_PHOTO_TILES_WIDTH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CAMMY_SRAM_PHOTO_HEIGHT \
 | 
				
			||||||
 | 
					    (CAMMY_SRAM_TILE_HEIGHT * CAMMY_SRAM_PHOTO_TILES_HEIGHT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CAMMY_SRAM_THUMB_TILES_WIDTH   4
 | 
					#define CAMMY_SRAM_THUMB_TILES_WIDTH   4
 | 
				
			||||||
#define CAMMY_SRAM_THUMB_TILES_HEIGHT  4
 | 
					#define CAMMY_SRAM_THUMB_TILES_HEIGHT  4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,12 +34,12 @@ typedef struct _cammy_sram_tile {
 | 
				
			||||||
} cammy_sram_tile;
 | 
					} cammy_sram_tile;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct _cammy_sram_thumb {
 | 
					typedef struct _cammy_sram_thumb {
 | 
				
			||||||
    cammy_sram_tile rows[CAMMY_SRAM_THUMB_TILES_HEIGHT]
 | 
					    cammy_sram_tile tiles[CAMMY_SRAM_THUMB_TILES_HEIGHT]
 | 
				
			||||||
                         [CAMMY_SRAM_THUMB_TILES_WIDTH];
 | 
					                         [CAMMY_SRAM_THUMB_TILES_WIDTH];
 | 
				
			||||||
} cammy_sram_thumb;
 | 
					} cammy_sram_thumb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct _cammy_sram_photo {
 | 
					typedef struct _cammy_sram_photo {
 | 
				
			||||||
    cammy_sram_tile rows[CAMMY_SRAM_PHOTO_TILES_HEIGHT]
 | 
					    cammy_sram_tile tiles[CAMMY_SRAM_PHOTO_TILES_HEIGHT]
 | 
				
			||||||
                         [CAMMY_SRAM_PHOTO_TILES_WIDTH];
 | 
					                         [CAMMY_SRAM_PHOTO_TILES_WIDTH];
 | 
				
			||||||
} cammy_sram_photo;
 | 
					} cammy_sram_photo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,10 +5,14 @@ HEADER_SUBDIR	= cammy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CC		= $(CROSS)cc
 | 
					CC		= $(CROSS)cc
 | 
				
			||||||
CFLAGS		= $(CGFLAGS) -fPIC -Wall -O2 -I$(INCLUDE_PATH)
 | 
					CFLAGS		= $(CGFLAGS) -fPIC -Wall -O2 -I$(INCLUDE_PATH)
 | 
				
			||||||
LDFLAGS		=
 | 
					LDFLAGS		= -lz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HEADERS		= sram.h
 | 
					HEADERS		= sram.h
 | 
				
			||||||
OBJS		= sram.o test.o
 | 
					HEADERS_LOCAL	= pnglite.h
 | 
				
			||||||
 | 
					HEADERS_BUILD	= $(HEADERS_LOCAL) \
 | 
				
			||||||
 | 
							  $(addprefix $(INCLUDE_PATH)/$(HEADER_SUBDIR)/,$(HEADERS))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OBJS		= sram.o pnglite.o test.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PROGRAM		= test
 | 
					PROGRAM		= test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										862
									
								
								src/pnglite.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										862
									
								
								src/pnglite.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,862 @@
 | 
				
			||||||
 | 
					/*  pnglite.c - pnglite library
 | 
				
			||||||
 | 
					    For conditions of distribution and use, see copyright notice in pnglite.h
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					#define DO_CRC_CHECKS 1
 | 
				
			||||||
 | 
					#define USE_ZLIB 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if USE_ZLIB
 | 
				
			||||||
 | 
					#include <zlib.h>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#include "zlite.h"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include "pnglite.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static png_alloc_t png_alloc;
 | 
				
			||||||
 | 
					static png_free_t png_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static size_t file_read(png_t* png, void* out, size_t size, size_t numel)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						size_t result;
 | 
				
			||||||
 | 
						if(png->read_fun)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							result = png->read_fun(out, size, numel, png->user_pointer);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if(!out)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								result = fseek(png->user_pointer, (long)(size*numel), SEEK_CUR);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								result = fread(out, size, numel, png->user_pointer);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static size_t file_write(png_t* png, void* p, size_t size, size_t numel)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						size_t result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(png->write_fun)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							result = png->write_fun(p, size, numel, png->user_pointer);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							result = fwrite(p, size, numel, png->user_pointer);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int file_read_ul(png_t* png, unsigned *out)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char buf[4];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(file_read(png, buf, 1, 4) != 4)
 | 
				
			||||||
 | 
							return PNG_FILE_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*out = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int file_write_ul(png_t* png, unsigned in)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char buf[4];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buf[0] = (in>>24) & 0xff;
 | 
				
			||||||
 | 
						buf[1] = (in>>16) & 0xff;
 | 
				
			||||||
 | 
						buf[2] = (in>>8) & 0xff;
 | 
				
			||||||
 | 
						buf[3] = (in) & 0xff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(file_write(png, buf, 1, 4) != 4)
 | 
				
			||||||
 | 
							return PNG_FILE_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned get_ul(unsigned char* buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned result;
 | 
				
			||||||
 | 
						unsigned char foo[4];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(foo, buf, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result = (foo[0]<<24) | (foo[1]<<16) | (foo[2]<<8) | foo[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned set_ul(unsigned char* buf, unsigned in)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						buf[0] = (in>>24) & 0xff;
 | 
				
			||||||
 | 
						buf[1] = (in>>16) & 0xff;
 | 
				
			||||||
 | 
						buf[2] = (in>>8) & 0xff;
 | 
				
			||||||
 | 
						buf[3] = (in) & 0xff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_init(png_alloc_t pngalloc, png_free_t pngfree)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if(pngalloc)
 | 
				
			||||||
 | 
							png_alloc = pngalloc;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							png_alloc = &malloc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(pngfree)
 | 
				
			||||||
 | 
							png_free = pngfree;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							png_free = &free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_get_bpp(png_t* png)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int bpp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch(png->color_type)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case PNG_GREYSCALE:
 | 
				
			||||||
 | 
							bpp = 1; break;
 | 
				
			||||||
 | 
						case PNG_TRUECOLOR:
 | 
				
			||||||
 | 
							bpp = 3; break;
 | 
				
			||||||
 | 
						case PNG_INDEXED:
 | 
				
			||||||
 | 
							bpp = 1; break;
 | 
				
			||||||
 | 
						case PNG_GREYSCALE_ALPHA:
 | 
				
			||||||
 | 
							bpp = 2; break;
 | 
				
			||||||
 | 
						case PNG_TRUECOLOR_ALPHA:
 | 
				
			||||||
 | 
							bpp = 4; break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return PNG_FILE_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bpp *= png->depth/8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return bpp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_read_ihdr(png_t* png)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned length;
 | 
				
			||||||
 | 
					#if DO_CRC_CHECKS
 | 
				
			||||||
 | 
						unsigned orig_crc;
 | 
				
			||||||
 | 
						unsigned calc_crc;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						unsigned char ihdr[13+4];		 /* length should be 13, make room for type (IHDR) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file_read_ul(png, &length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(length != 13)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf("%d\n", length);
 | 
				
			||||||
 | 
							return PNG_CRC_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(file_read(png, ihdr, 1, 13+4) != 13+4)
 | 
				
			||||||
 | 
							return PNG_EOF_ERROR;
 | 
				
			||||||
 | 
					#if DO_CRC_CHECKS
 | 
				
			||||||
 | 
						file_read_ul(png, &orig_crc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						calc_crc = crc32(0L, 0, 0);
 | 
				
			||||||
 | 
						calc_crc = crc32(calc_crc, ihdr, 13+4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(orig_crc != calc_crc)
 | 
				
			||||||
 | 
							return PNG_CRC_ERROR;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						file_read_ul(png);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png->width = get_ul(ihdr+4);
 | 
				
			||||||
 | 
						png->height = get_ul(ihdr+8);
 | 
				
			||||||
 | 
						png->depth = ihdr[12];
 | 
				
			||||||
 | 
						png->color_type = ihdr[13];
 | 
				
			||||||
 | 
						png->compression_method = ihdr[14];
 | 
				
			||||||
 | 
						png->filter_method = ihdr[15];
 | 
				
			||||||
 | 
						png->interlace_method = ihdr[16];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(png->color_type == PNG_INDEXED)
 | 
				
			||||||
 | 
							return PNG_NOT_SUPPORTED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(png->depth != 8 && png->depth != 16)
 | 
				
			||||||
 | 
							return PNG_NOT_SUPPORTED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(png->interlace_method)
 | 
				
			||||||
 | 
							return PNG_NOT_SUPPORTED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_write_ihdr(png_t* png)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char ihdr[13+4];
 | 
				
			||||||
 | 
						unsigned char *p = ihdr;
 | 
				
			||||||
 | 
						unsigned crc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file_write(png, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 1, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file_write_ul(png, 13);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*p = 'I';			p++;
 | 
				
			||||||
 | 
						*p = 'H';			p++;
 | 
				
			||||||
 | 
						*p = 'D';			p++;
 | 
				
			||||||
 | 
						*p = 'R';			p++;
 | 
				
			||||||
 | 
						set_ul(p, png->width);		p+=4;
 | 
				
			||||||
 | 
						set_ul(p, png->height);		p+=4;
 | 
				
			||||||
 | 
						*p = png->depth;		p++;
 | 
				
			||||||
 | 
						*p = png->color_type;		p++;
 | 
				
			||||||
 | 
						*p = 0;				p++;
 | 
				
			||||||
 | 
						*p = 0;				p++;
 | 
				
			||||||
 | 
						*p = 0;				p++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file_write(png, ihdr, 1, 13+4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						crc = crc32(0L, 0, 0);
 | 
				
			||||||
 | 
						crc = crc32(crc, ihdr, 13+4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file_write_ul(png, crc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void png_print_info(png_t* png)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						printf("PNG INFO:\n");
 | 
				
			||||||
 | 
						printf("\twidth:\t\t%d\n", png->width);
 | 
				
			||||||
 | 
						printf("\theight:\t\t%d\n", png->height);
 | 
				
			||||||
 | 
						printf("\tdepth:\t\t%d\n", png->depth);
 | 
				
			||||||
 | 
						printf("\tcolor:\t\t");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch(png->color_type)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case PNG_GREYSCALE:		printf("greyscale\n"); break;
 | 
				
			||||||
 | 
						case PNG_TRUECOLOR:		printf("truecolor\n"); break;
 | 
				
			||||||
 | 
						case PNG_INDEXED:		printf("palette\n"); break;
 | 
				
			||||||
 | 
						case PNG_GREYSCALE_ALPHA:	printf("greyscale with alpha\n"); break;
 | 
				
			||||||
 | 
						case PNG_TRUECOLOR_ALPHA:	printf("truecolor with alpha\n"); break;
 | 
				
			||||||
 | 
						default:			printf("unknown, this is not good\n"); break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printf("\tcompression:\t%s\n",	png->compression_method?"unknown, this is not good":"inflate/deflate");
 | 
				
			||||||
 | 
						printf("\tfilter:\t\t%s\n",	png->filter_method?"unknown, this is not good":"adaptive");
 | 
				
			||||||
 | 
						printf("\tinterlace:\t%s\n",	png->interlace_method?"interlace":"no interlace");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_open_read(png_t* png, png_read_callback_t read_fun, void* user_pointer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char header[8];
 | 
				
			||||||
 | 
						int result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png->read_fun = read_fun;
 | 
				
			||||||
 | 
						png->write_fun = 0;
 | 
				
			||||||
 | 
						png->user_pointer = user_pointer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!read_fun && !user_pointer)
 | 
				
			||||||
 | 
							return PNG_WRONG_ARGUMENTS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(file_read(png, header, 1, 8) != 8)
 | 
				
			||||||
 | 
							return PNG_EOF_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(memcmp(header, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) != 0)
 | 
				
			||||||
 | 
							return PNG_HEADER_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result = png_read_ihdr(png);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png->bpp = (unsigned char)png_get_bpp(png);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_open_write(png_t* png, png_write_callback_t write_fun, void* user_pointer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						png->write_fun = write_fun;
 | 
				
			||||||
 | 
						png->read_fun = 0;
 | 
				
			||||||
 | 
						png->user_pointer = user_pointer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!write_fun && !user_pointer)
 | 
				
			||||||
 | 
							return PNG_WRONG_ARGUMENTS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_open(png_t* png, png_read_callback_t read_fun, void* user_pointer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return png_open_read(png, read_fun, user_pointer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_open_file_read(png_t *png, const char* filename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						FILE* fp = fopen(filename, "rb");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!fp)
 | 
				
			||||||
 | 
							return PNG_FILE_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return png_open_read(png, 0, fp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_open_file_write(png_t *png, const char* filename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						FILE* fp = fopen(filename, "wb");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!fp)
 | 
				
			||||||
 | 
							return PNG_FILE_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return png_open_write(png, 0, fp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_open_file(png_t *png, const char* filename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return png_open_file_read(png, filename);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_close_file(png_t* png)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						fclose(png->user_pointer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_init_deflate(png_t* png, unsigned char* data, int datalen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						z_stream *stream;
 | 
				
			||||||
 | 
						png->zs = png_alloc(sizeof(z_stream));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stream = png->zs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!stream)
 | 
				
			||||||
 | 
							return PNG_MEMORY_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(stream, 0, sizeof(z_stream));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(deflateInit(stream, Z_DEFAULT_COMPRESSION) != Z_OK)
 | 
				
			||||||
 | 
							return PNG_ZLIB_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stream->next_in = data;
 | 
				
			||||||
 | 
						stream->avail_in = datalen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_init_inflate(png_t* png)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if USE_ZLIB
 | 
				
			||||||
 | 
						z_stream *stream;
 | 
				
			||||||
 | 
						png->zs = png_alloc(sizeof(z_stream));
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						zl_stream *stream;
 | 
				
			||||||
 | 
						png->zs = png_alloc(sizeof(zl_stream));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stream = png->zs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!stream)
 | 
				
			||||||
 | 
							return PNG_MEMORY_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if USE_ZLIB
 | 
				
			||||||
 | 
						memset(stream, 0, sizeof(z_stream));
 | 
				
			||||||
 | 
						if(inflateInit(stream) != Z_OK)
 | 
				
			||||||
 | 
							return PNG_ZLIB_ERROR;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						memset(stream, 0, sizeof(zl_stream));
 | 
				
			||||||
 | 
						if(z_inflateInit(stream) != Z_OK)
 | 
				
			||||||
 | 
							return PNG_ZLIB_ERROR;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stream->next_out = png->png_data;
 | 
				
			||||||
 | 
						stream->avail_out = png->png_datalen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_end_deflate(png_t* png)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						z_stream *stream = png->zs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!stream)
 | 
				
			||||||
 | 
							return PNG_MEMORY_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						deflateEnd(stream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png_free(png->zs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_end_inflate(png_t* png)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if USE_ZLIB
 | 
				
			||||||
 | 
						z_stream *stream = png->zs;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						zl_stream *stream = png->zs;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!stream)
 | 
				
			||||||
 | 
							return PNG_MEMORY_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if USE_ZLIB
 | 
				
			||||||
 | 
						if(inflateEnd(stream) != Z_OK)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						if(z_inflateEnd(stream) != Z_OK)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf("ZLIB says: %s\n", stream->msg);
 | 
				
			||||||
 | 
							return PNG_ZLIB_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png_free(png->zs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_inflate(png_t* png, unsigned char* data, int len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int result;
 | 
				
			||||||
 | 
					#if USE_ZLIB
 | 
				
			||||||
 | 
						z_stream *stream = png->zs;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						zl_stream *stream = png->zs;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!stream)
 | 
				
			||||||
 | 
							return PNG_MEMORY_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stream->next_in = data;
 | 
				
			||||||
 | 
						stream->avail_in = len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if USE_ZLIB
 | 
				
			||||||
 | 
						result = inflate(stream, Z_SYNC_FLUSH);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						result = z_inflate(stream);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(result != Z_STREAM_END && result != Z_OK)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf("%s\n", stream->msg);
 | 
				
			||||||
 | 
							return PNG_ZLIB_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(stream->avail_in != 0)
 | 
				
			||||||
 | 
							return PNG_ZLIB_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_deflate(png_t* png, char* outdata, int outlen, int *outwritten)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						z_stream *stream = png->zs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!stream)
 | 
				
			||||||
 | 
							return PNG_MEMORY_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stream->next_out = (unsigned char*)outdata;
 | 
				
			||||||
 | 
						stream->avail_out = outlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result = deflate(stream, Z_SYNC_FLUSH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*outwritten = outlen - stream->avail_out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(result != Z_STREAM_END && result != Z_OK)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf("%s\n", stream->msg);
 | 
				
			||||||
 | 
							return PNG_ZLIB_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_write_idats(png_t* png, unsigned char* data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char *chunk;
 | 
				
			||||||
 | 
						unsigned long written;
 | 
				
			||||||
 | 
						unsigned long crc;
 | 
				
			||||||
 | 
						unsigned size = png->width * png->height * png->bpp + png->height;
 | 
				
			||||||
 | 
						unsigned chunk_size = compressBound(size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						(void)png_init_deflate;
 | 
				
			||||||
 | 
						(void)png_end_deflate;
 | 
				
			||||||
 | 
						(void)png_deflate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						chunk = png_alloc(chunk_size + 4);
 | 
				
			||||||
 | 
						memcpy(chunk, "IDAT", 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						written = chunk_size;
 | 
				
			||||||
 | 
						compress(chunk+4, &written, data, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						crc = crc32(0L, Z_NULL, 0);
 | 
				
			||||||
 | 
						crc = crc32(crc, chunk, written+4);
 | 
				
			||||||
 | 
						set_ul(chunk+written+4, crc);
 | 
				
			||||||
 | 
						file_write_ul(png, written);
 | 
				
			||||||
 | 
						file_write(png, chunk, 1, written+8);
 | 
				
			||||||
 | 
						png_free(chunk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file_write_ul(png, 0);
 | 
				
			||||||
 | 
						file_write(png, "IEND", 1, 4);
 | 
				
			||||||
 | 
						crc = crc32(0L, (const unsigned char *)"IEND", 4);
 | 
				
			||||||
 | 
						file_write_ul(png, crc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_read_idat(png_t* png, unsigned length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if DO_CRC_CHECKS
 | 
				
			||||||
 | 
						unsigned orig_crc;
 | 
				
			||||||
 | 
						unsigned calc_crc;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!png->readbuf || png->readbuflen < length)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (png->readbuf)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								png_free(png->readbuf);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							png->readbuf = png_alloc(length);
 | 
				
			||||||
 | 
							png->readbuflen = length;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!png->readbuf)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return PNG_MEMORY_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(file_read(png, png->readbuf, 1, length) != length)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return PNG_FILE_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if DO_CRC_CHECKS
 | 
				
			||||||
 | 
						calc_crc = crc32(0L, Z_NULL, 0);
 | 
				
			||||||
 | 
						calc_crc = crc32(calc_crc, (unsigned char*)"IDAT", 4);
 | 
				
			||||||
 | 
						calc_crc = crc32(calc_crc, (unsigned char*)png->readbuf, length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file_read_ul(png, &orig_crc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(orig_crc != calc_crc)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return PNG_CRC_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						file_read_ul(png);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return png_inflate(png, png->readbuf, length);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_process_chunk(png_t* png)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int result = PNG_NO_ERROR;
 | 
				
			||||||
 | 
						unsigned type;
 | 
				
			||||||
 | 
						unsigned length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file_read_ul(png, &length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(file_read(png, &type, 1, 4) != 4)
 | 
				
			||||||
 | 
							return PNG_FILE_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(type == *(unsigned int*)"IDAT")	/* if we found an idat, all other idats should be followed with no other chunks in between */
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if(!png->png_data) /* first IDAT */
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								png->png_datalen = png->width * png->height * png->bpp + png->height;
 | 
				
			||||||
 | 
								png->png_data = png_alloc(png->png_datalen);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(!png->png_data)
 | 
				
			||||||
 | 
								return PNG_MEMORY_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(!png->zs)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								result = png_init_inflate(png);
 | 
				
			||||||
 | 
								if(result != PNG_NO_ERROR)
 | 
				
			||||||
 | 
									return result;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return png_read_idat(png, length);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if(type == *(unsigned int*)"IEND")
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return PNG_DONE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							file_read(png, 0, 1, length + 4); /* unknown chunk */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void png_filter_sub(int stride, unsigned char* in, unsigned char* out, int len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						unsigned char a = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for(i = 0; i < len; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if(i >= stride)
 | 
				
			||||||
 | 
								a = out[i - stride];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							out[i] = in[i] + a;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void png_filter_up(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(prev_line)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
					        for(i = 0; i < len; i++)
 | 
				
			||||||
 | 
							out[i] = in[i] + prev_line[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							memcpy(out, in, len);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void png_filter_average(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						unsigned char a = 0;
 | 
				
			||||||
 | 
						unsigned char b = 0;
 | 
				
			||||||
 | 
						unsigned int sum = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for(i = 0; i < len; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if(prev_line)
 | 
				
			||||||
 | 
								b = prev_line[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(i >= stride)
 | 
				
			||||||
 | 
								a = out[i - stride];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sum = a;
 | 
				
			||||||
 | 
							sum += b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							out[i] = (char)(in[i] + sum/2);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned char png_paeth(unsigned char a, unsigned char b, unsigned char c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int p = (int)a + b - c;
 | 
				
			||||||
 | 
						int pa = abs(p - a);
 | 
				
			||||||
 | 
						int pb = abs(p - b);
 | 
				
			||||||
 | 
						int pc = abs(p - c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int pr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(pa <= pb && pa <= pc)
 | 
				
			||||||
 | 
							pr = a;
 | 
				
			||||||
 | 
						else if(pb <= pc)
 | 
				
			||||||
 | 
							pr = b;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							pr = c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (char)pr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void png_filter_paeth(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						unsigned char a;
 | 
				
			||||||
 | 
						unsigned char b;
 | 
				
			||||||
 | 
						unsigned char c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for(i = 0; i < len; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if(prev_line && i >= stride)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								a = out[i - stride];
 | 
				
			||||||
 | 
								b = prev_line[i];
 | 
				
			||||||
 | 
								c = prev_line[i - stride];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if(prev_line)
 | 
				
			||||||
 | 
									b = prev_line[i];
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									b = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(i >= stride)
 | 
				
			||||||
 | 
									a = out[i - stride];
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									a = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								c = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							out[i] = in[i] + png_paeth(a, b, c);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_filter(png_t* png, unsigned char* data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int png_unfilter(png_t* png, unsigned char* data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned i;
 | 
				
			||||||
 | 
						unsigned pos = 0;
 | 
				
			||||||
 | 
						unsigned outpos = 0;
 | 
				
			||||||
 | 
						unsigned char *filtered = png->png_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int stride = png->bpp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while(pos < png->png_datalen)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							unsigned char filter = filtered[pos];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pos++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(png->depth == 16)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								for(i = 0; i < png->width * stride; i+=2)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									*(short*)(filtered+pos+i) = (filtered[pos+i] << 8) | filtered[pos+i+1];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch(filter)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							case 0: /* none */
 | 
				
			||||||
 | 
								memcpy(data+outpos, filtered+pos, png->width * stride);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 1: /* sub */
 | 
				
			||||||
 | 
								png_filter_sub(stride, filtered+pos, data+outpos, png->width * stride);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 2: /* up */
 | 
				
			||||||
 | 
								if(outpos)
 | 
				
			||||||
 | 
									png_filter_up(stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									png_filter_up(stride, filtered+pos, data+outpos, 0, png->width*stride);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 3: /* average */
 | 
				
			||||||
 | 
								if(outpos)
 | 
				
			||||||
 | 
									png_filter_average(stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									png_filter_average(stride, filtered+pos, data+outpos, 0, png->width*stride);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 4: /* paeth */
 | 
				
			||||||
 | 
								if(outpos)
 | 
				
			||||||
 | 
									png_filter_paeth(stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									png_filter_paeth(stride, filtered+pos, data+outpos, 0, png->width*stride);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return PNG_UNKNOWN_FILTER;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							outpos += png->width * stride;
 | 
				
			||||||
 | 
							pos += png->width * stride;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_get_data(png_t* png, unsigned char* data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int result = PNG_NO_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png->zs = NULL;
 | 
				
			||||||
 | 
						png->png_datalen = 0;
 | 
				
			||||||
 | 
						png->png_data = NULL;
 | 
				
			||||||
 | 
						png->readbuf = NULL;
 | 
				
			||||||
 | 
						png->readbuflen = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while(result == PNG_NO_ERROR)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							result = png_process_chunk(png);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (png->readbuf)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							png_free(png->readbuf);
 | 
				
			||||||
 | 
							png->readbuflen = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (png->zs)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							png_end_inflate(png);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(result != PNG_DONE)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							png_free(png->png_data);
 | 
				
			||||||
 | 
							return result;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result = png_unfilter(png, data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png_free(png->png_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_set_data(png_t* png, unsigned width, unsigned height, char depth, int color, unsigned char* data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						unsigned char *filtered;
 | 
				
			||||||
 | 
						png->width = width;
 | 
				
			||||||
 | 
						png->height = height;
 | 
				
			||||||
 | 
						png->depth = depth;
 | 
				
			||||||
 | 
						png->color_type = color;
 | 
				
			||||||
 | 
						png->bpp = png_get_bpp(png);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						filtered = png_alloc(width * height * png->bpp + height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for(i = 0; i < png->height; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							filtered[i*png->width*png->bpp+i] = 0;
 | 
				
			||||||
 | 
							memcpy(&filtered[i*png->width*png->bpp+i+1], data + i * png->width*png->bpp, png->width*png->bpp);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png_filter(png, filtered);
 | 
				
			||||||
 | 
						png_write_ihdr(png);
 | 
				
			||||||
 | 
						png_write_idats(png, filtered);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png_free(filtered);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return PNG_NO_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char* png_error_string(int error)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch(error)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case PNG_NO_ERROR:
 | 
				
			||||||
 | 
							return "No error";
 | 
				
			||||||
 | 
						case PNG_FILE_ERROR:
 | 
				
			||||||
 | 
							return "Unknown file error.";
 | 
				
			||||||
 | 
						case PNG_HEADER_ERROR:
 | 
				
			||||||
 | 
							return "No PNG header found. Are you sure this is a PNG?";
 | 
				
			||||||
 | 
						case PNG_IO_ERROR:
 | 
				
			||||||
 | 
							return "Failure while reading file.";
 | 
				
			||||||
 | 
						case PNG_EOF_ERROR:
 | 
				
			||||||
 | 
							return "Reached end of file.";
 | 
				
			||||||
 | 
						case PNG_CRC_ERROR:
 | 
				
			||||||
 | 
							return "CRC or chunk length error.";
 | 
				
			||||||
 | 
						case PNG_MEMORY_ERROR:
 | 
				
			||||||
 | 
							return "Could not allocate memory.";
 | 
				
			||||||
 | 
						case PNG_ZLIB_ERROR:
 | 
				
			||||||
 | 
							return "zlib reported an error.";
 | 
				
			||||||
 | 
						case PNG_UNKNOWN_FILTER:
 | 
				
			||||||
 | 
							return "Unknown filter method used in scanline.";
 | 
				
			||||||
 | 
						case PNG_DONE:
 | 
				
			||||||
 | 
							return "PNG done";
 | 
				
			||||||
 | 
						case PNG_NOT_SUPPORTED:
 | 
				
			||||||
 | 
							return "The PNG is unsupported by pnglite, too bad for you!";
 | 
				
			||||||
 | 
						case PNG_WRONG_ARGUMENTS:
 | 
				
			||||||
 | 
							return "Wrong combination of arguments passed to png_open. You must use either a read_function or supply a file pointer to use.";
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return "Unknown error.";
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										232
									
								
								src/pnglite.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								src/pnglite.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,232 @@
 | 
				
			||||||
 | 
					/*  pnglite.h - Interface for pnglite library
 | 
				
			||||||
 | 
						Copyright (c) 2007 Daniel Karling
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						This software is provided 'as-is', without any express or implied
 | 
				
			||||||
 | 
						warranty. In no event will the authors be held liable for any damages
 | 
				
			||||||
 | 
						arising from the use of this software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Permission is granted to anyone to use this software for any purpose,
 | 
				
			||||||
 | 
						including commercial applications, and to alter it and redistribute it
 | 
				
			||||||
 | 
						freely, subject to the following restrictions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						1. The origin of this software must not be misrepresented; you must not
 | 
				
			||||||
 | 
						   claim that you wrote the original software. If you use this software
 | 
				
			||||||
 | 
						   in a product, an acknowledgment in the product documentation would be
 | 
				
			||||||
 | 
						   appreciated but is not required.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						2. Altered source versions must be plainly marked as such, and must not be
 | 
				
			||||||
 | 
						   misrepresented as being the original software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						3. This notice may not be removed or altered from any source
 | 
				
			||||||
 | 
						   distribution.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Daniel Karling
 | 
				
			||||||
 | 
						daniel.karling@gmail.com
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _PNGLITE_H_
 | 
				
			||||||
 | 
					#define _PNGLITE_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C"{
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						Enumerations for pnglite.
 | 
				
			||||||
 | 
						Negative numbers are error codes and 0 and up are okay responses.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PNG_DONE			= 1,
 | 
				
			||||||
 | 
						PNG_NO_ERROR			= 0,
 | 
				
			||||||
 | 
						PNG_FILE_ERROR			= -1,
 | 
				
			||||||
 | 
						PNG_HEADER_ERROR		= -2,
 | 
				
			||||||
 | 
						PNG_IO_ERROR			= -3,
 | 
				
			||||||
 | 
						PNG_EOF_ERROR			= -4,
 | 
				
			||||||
 | 
						PNG_CRC_ERROR			= -5,
 | 
				
			||||||
 | 
						PNG_MEMORY_ERROR		= -6,
 | 
				
			||||||
 | 
						PNG_ZLIB_ERROR			= -7,
 | 
				
			||||||
 | 
						PNG_UNKNOWN_FILTER		= -8,
 | 
				
			||||||
 | 
						PNG_NOT_SUPPORTED		= -9,
 | 
				
			||||||
 | 
						PNG_WRONG_ARGUMENTS		= -10
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						The five different kinds of color storage in PNG files.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PNG_GREYSCALE			= 0,
 | 
				
			||||||
 | 
						PNG_TRUECOLOR			= 2,
 | 
				
			||||||
 | 
						PNG_INDEXED			= 3,
 | 
				
			||||||
 | 
						PNG_GREYSCALE_ALPHA		= 4,
 | 
				
			||||||
 | 
						PNG_TRUECOLOR_ALPHA		= 6
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						Typedefs for callbacks.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef unsigned (*png_write_callback_t)(void* input, size_t size, size_t numel, void* user_pointer);
 | 
				
			||||||
 | 
					typedef unsigned (*png_read_callback_t)(void* output, size_t size, size_t numel, void* user_pointer);
 | 
				
			||||||
 | 
					typedef void (*png_free_t)(void* p);
 | 
				
			||||||
 | 
					typedef void * (*png_alloc_t)(size_t s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						void*				zs;				/* pointer to z_stream */
 | 
				
			||||||
 | 
						png_read_callback_t		read_fun;
 | 
				
			||||||
 | 
						png_write_callback_t		write_fun;
 | 
				
			||||||
 | 
						void*				user_pointer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned char*			png_data;
 | 
				
			||||||
 | 
						unsigned			png_datalen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned			width;
 | 
				
			||||||
 | 
						unsigned			height;
 | 
				
			||||||
 | 
						unsigned char			depth;
 | 
				
			||||||
 | 
						unsigned char			color_type;
 | 
				
			||||||
 | 
						unsigned char			compression_method;
 | 
				
			||||||
 | 
						unsigned char			filter_method;
 | 
				
			||||||
 | 
						unsigned char			interlace_method;
 | 
				
			||||||
 | 
						unsigned char			bpp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned char*			readbuf;
 | 
				
			||||||
 | 
						unsigned			readbuflen;
 | 
				
			||||||
 | 
					} png_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						Function: png_init
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						This function initializes pnglite. The parameters can be used to set your own memory allocation routines following these formats:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> void* (*custom_alloc)(size_t s)
 | 
				
			||||||
 | 
						> void (*custom_free)(void* p)
 | 
				
			||||||
 | 
						Parameters:
 | 
				
			||||||
 | 
							pngalloc - Pointer to custom allocation routine. If 0 is passed, malloc from libc will be used.
 | 
				
			||||||
 | 
							pngfree - Pointer to custom free routine. If 0 is passed, free from libc will be used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Returns:
 | 
				
			||||||
 | 
							Always returns PNG_NO_ERROR.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_init(png_alloc_t pngalloc, png_free_t pngfree);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						Function: png_open_file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						This function is used to open a png file with the internal file IO system. This function should be used instead of
 | 
				
			||||||
 | 
						png_open if no custom read function is used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Parameters:
 | 
				
			||||||
 | 
							png - Empty png_t struct.
 | 
				
			||||||
 | 
							filename - Filename of the file to be opened.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Returns:
 | 
				
			||||||
 | 
							PNG_NO_ERROR on success, otherwise an error code.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_open_file(png_t *png, const char* filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_open_file_read(png_t *png, const char* filename);
 | 
				
			||||||
 | 
					int png_open_file_write(png_t *png, const char* filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						Function: png_open
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						This function reads or writes a png from/to the specified callback. The callbacks should be of the format:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> size_t (*png_write_callback_t)(void* input, size_t size, size_t numel, void* user_pointer);
 | 
				
			||||||
 | 
						> size_t (*png_read_callback_t)(void* output, size_t size, size_t numel, void* user_pointer).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Only one callback has to be specified. The read callback in case of PNG reading, otherwise the write callback.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Writing:
 | 
				
			||||||
 | 
						The callback will be called like fwrite.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Reading:
 | 
				
			||||||
 | 
						The callback will be called each time pnglite needs more data. The callback should read as much data as requested,
 | 
				
			||||||
 | 
						or return 0. This should always be possible if the PNG is sane.	If the output-buffer is a null-pointer the callback
 | 
				
			||||||
 | 
						should only skip ahead the specified number of elements. If the callback is a null-pointer the user_pointer will be
 | 
				
			||||||
 | 
						treated as a file pointer (use png_open_file instead).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Parameters:
 | 
				
			||||||
 | 
							png - png_t struct
 | 
				
			||||||
 | 
							read_fun - Callback function for reading.
 | 
				
			||||||
 | 
							user_pointer - User pointer to be passed to read_fun.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Returns:
 | 
				
			||||||
 | 
							PNG_NO_ERROR on success, otherwise an error code.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_open(png_t* png, png_read_callback_t read_fun, void* user_pointer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_open_read(png_t* png, png_read_callback_t read_fun, void* user_pointer);
 | 
				
			||||||
 | 
					int png_open_write(png_t* png, png_write_callback_t write_fun, void* user_pointer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						Function: png_print_info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						This function prints some info about the opened png file to stdout.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Parameters:
 | 
				
			||||||
 | 
							png - png struct to get info from.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void png_print_info(png_t* png);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						Function: png_error_string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						This function translates an error code to a human readable string.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Parameters:
 | 
				
			||||||
 | 
							error - Error code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Returns:
 | 
				
			||||||
 | 
							Pointer to string.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char* png_error_string(int error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						Function: png_get_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						This function decodes the opened png file and stores the result in data. data should be big enough to hold the decoded png. Required size will be:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> width*height*(bytes per pixel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Parameters:
 | 
				
			||||||
 | 
							data - Where to store result.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Returns:
 | 
				
			||||||
 | 
							PNG_NO_ERROR on success, otherwise an error code.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_get_data(png_t* png, unsigned char* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_set_data(png_t* png, unsigned width, unsigned height, char depth, int color, unsigned char* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						Function: png_close_file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Closes an open png file pointer. Should only be used when the png has been opened with png_open_file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Parameters:
 | 
				
			||||||
 | 
							png - png to close.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Returns:
 | 
				
			||||||
 | 
							PNG_NO_ERROR
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int png_close_file(png_t* png);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@ cammy_sram *cammy_sram_open(const char *file) {
 | 
				
			||||||
        goto error_malloc_sram;
 | 
					        goto error_malloc_sram;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((sram->fd = open(file, O_RDONLY)) < 0) {
 | 
					    if ((sram->fd = open(file, O_RDWR)) < 0) {
 | 
				
			||||||
        goto error_open;
 | 
					        goto error_open;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										106
									
								
								src/test.c
									
										
									
									
									
								
							
							
						
						
									
										106
									
								
								src/test.c
									
										
									
									
									
								
							| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <stdarg.h>
 | 
					#include <stdarg.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include "pnglite.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <cammy/sram.h>
 | 
					#include <cammy/sram.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,16 +17,61 @@ static void usage(int argc, char **argv, const char *message, ...) {
 | 
				
			||||||
         fprintf(stderr, "\n");
 | 
					         fprintf(stderr, "\n");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "usage: %s file.sav\n", argv[0]);
 | 
					    fprintf(stderr, "usage: %s file.sav frame1..30 photo.png\n", argv[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    exit(1);
 | 
					    exit(1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint8_t *buf_malloc(png_t *png) {
 | 
				
			||||||
 | 
					    return malloc(4 * png->width * png->height);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void image_copy(cammy_sram_frame *frame, uint8_t *buf) {
 | 
				
			||||||
 | 
					    size_t x, y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset(&frame->photo, '\0', sizeof(cammy_sram_photo));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (y=0; y<CAMMY_SRAM_PHOTO_HEIGHT; y++) {
 | 
				
			||||||
 | 
					        for (x=0; x<CAMMY_SRAM_PHOTO_WIDTH; x++) {
 | 
				
			||||||
 | 
					            uint8_t r = buf[4*CAMMY_SRAM_PHOTO_WIDTH*y+4*x],
 | 
				
			||||||
 | 
					                    g = buf[4*CAMMY_SRAM_PHOTO_WIDTH*y+4*x+1],
 | 
				
			||||||
 | 
					                    b = buf[4*CAMMY_SRAM_PHOTO_WIDTH*y+4*x+2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            float avg = 255.0 - ((float)r + (float)g + (float)b) / 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            uint8_t value = (uint8_t)(avg / 64.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            cammy_sram_tile *tile = &frame->photo.tiles[y>>3][x>>3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int tile_x = x & 7,
 | 
				
			||||||
 | 
					                tile_y = y & 7;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            tile->data[2*tile_y]   |= ((value & 0x02) >> 1) << (7 - tile_x);
 | 
				
			||||||
 | 
					            tile->data[2*tile_y+1] |=  (value & 0x01)       << (7 - tile_x);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char **argv) {
 | 
					int main(int argc, char **argv) {
 | 
				
			||||||
    cammy_sram *sram;
 | 
					    cammy_sram *sram;
 | 
				
			||||||
 | 
					    png_t *png;
 | 
				
			||||||
 | 
					    int frame = 0;
 | 
				
			||||||
 | 
					    uint8_t *buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (argc != 2) {
 | 
					    int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (argc < 2) {
 | 
				
			||||||
        usage(argc, argv, "No save file provided");
 | 
					        usage(argc, argv, "No save file provided");
 | 
				
			||||||
 | 
					    } else if (argc < 3) {
 | 
				
			||||||
 | 
					        usage(argc, argv, "No frame number provided");
 | 
				
			||||||
 | 
					    } else if (argc < 4) {
 | 
				
			||||||
 | 
					        usage(argc, argv, "No photo provided");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    frame = atoi(argv[2]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (frame < 1 || frame > CAMMY_SRAM_FRAME_COUNT) {
 | 
				
			||||||
 | 
					        usage(argc, argv, "Invalid frame number");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((sram = cammy_sram_open(argv[1])) == NULL) {
 | 
					    if ((sram = cammy_sram_open(argv[1])) == NULL) {
 | 
				
			||||||
| 
						 | 
					@ -35,10 +81,66 @@ int main(int argc, char **argv) {
 | 
				
			||||||
        goto error_sram_open;
 | 
					        goto error_sram_open;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    png_init(malloc, free);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((png = malloc(sizeof(*png))) == NULL) {
 | 
				
			||||||
 | 
					        goto error_malloc_png;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((error = png_open_file_read(png, argv[3])) < 0) {
 | 
				
			||||||
 | 
					        fprintf(stderr, "%s: %s: %s: %s\n",
 | 
				
			||||||
 | 
					            argv[0], "png_open_file_read()", argv[3], png_error_string(error));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        goto error_png_open_file_read;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (png->width  != CAMMY_SRAM_PHOTO_WIDTH
 | 
				
			||||||
 | 
					     || png->height != CAMMY_SRAM_PHOTO_HEIGHT) {
 | 
				
			||||||
 | 
					        fprintf(stderr, "%s: %s: %s\n",
 | 
				
			||||||
 | 
					            argv[0], argv[3], "Invalid image dimensions");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        goto error_invalid_dimensions;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((buf = buf_malloc(png)) == NULL) {
 | 
				
			||||||
 | 
					        fprintf(stderr, "%s: %s: %s\n",
 | 
				
			||||||
 | 
					            argv[0], "malloc()", strerror(errno));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        goto error_buf_malloc;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((error = png_get_data(png, buf)) < 0) {
 | 
				
			||||||
 | 
					        fprintf(stderr, "%s: %s: %s: %s\n",
 | 
				
			||||||
 | 
					            argv[0], "png_get_data()", argv[3], png_error_string(error));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        goto error_png_get_data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    image_copy(&sram->data->frames[frame], buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    png_close_file(png);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free(png);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cammy_sram_close(sram);
 | 
					    cammy_sram_close(sram);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					error_png_get_data:
 | 
				
			||||||
 | 
					    free(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					error_buf_malloc:
 | 
				
			||||||
 | 
					error_invalid_dimensions:
 | 
				
			||||||
 | 
					    png_close_file(png);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					error_png_open_file_read:
 | 
				
			||||||
 | 
					    free(png);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					error_malloc_png:
 | 
				
			||||||
 | 
					    cammy_sram_close(sram);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
error_sram_open:
 | 
					error_sram_open:
 | 
				
			||||||
    return 1;
 | 
					    return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue