/* disassemble1.c */
#include <stdio.h>
#include <stdlib.h>
/* note that this following line will probably not work for you,
* change it to:
* #include <png.h> */
#include PNGHEADER
void readSetup(char* filename, png_structp* png_ptr_read, png_infop* info_ptr_read);
void writePpmFromIDAT(png_structp png_ptr_read, png_infop info_ptr_read);
void writeSetup(FILE* image, png_structp* png_ptr_write, png_infop* info_ptr_write);
void writeSetup2(png_structp png_ptr_read, png_infop info_ptr_read,
png_structp png_ptr_write, png_infop info_ptr_write,
png_uint_32 width, png_uint_32 height);
void fatalError(char* str)
{
fprintf(stderr, "Fatal Error: %s\n", str);
exit(1);
}
int main(int argc, char** argv)
{
png_structp png_ptr_read;
png_infop info_ptr_read;
int count;
png_structp png_ptr_write;
png_infop info_ptr_write;
FILE* newImage;
char filename[512];
png_bytepp rowPointers;
png_uint_32 bytesPerRow;
png_uint_32 next_frame_width;
png_uint_32 next_frame_height;
png_uint_32 next_frame_x_offset;
png_uint_32 next_frame_y_offset;
png_uint_16 next_frame_delay_num;
png_uint_16 next_frame_delay_den;
png_byte next_frame_dispose_op;
png_byte next_frame_blend_op;
if(argc != 2)
fatalError("usage: dissasemble1 image.png");
readSetup(argv[1], &png_ptr_read, &info_ptr_read);
if(setjmp(png_ptr_read->jmpbuf))
fatalError("something didn't work, jump 1");
png_read_info(png_ptr_read, info_ptr_read);
if(!png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_acTL))
fatalError("source image must be animated");
rowPointers = png_malloc(png_ptr_read, sizeof(png_bytep) * info_ptr_read->height);
bytesPerRow = png_get_rowbytes(png_ptr_read, info_ptr_read);
for(count = 0; count < info_ptr_read->height; count++)
rowPointers[count] = png_malloc(png_ptr_read, bytesPerRow);
for(count = 0; count < png_get_num_frames(png_ptr_read, info_ptr_read); count++)
{
sprintf(filename, "extracted-%02d.png", count);
newImage = fopen(filename, "wb");
if(newImage == NULL)
fatalError("couldn't create png for writing");
writeSetup(newImage, &png_ptr_write, &info_ptr_write);
if(setjmp(png_ptr_write->jmpbuf))
fatalError("something didn't work, jump 2");
png_read_frame_head(png_ptr_read, info_ptr_read);
if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_fcTL))
{
png_get_next_frame_fcTL(png_ptr_read, info_ptr_read,
&next_frame_width, &next_frame_height,
&next_frame_x_offset, &next_frame_y_offset,
&next_frame_delay_num, &next_frame_delay_den,
&next_frame_dispose_op, &next_frame_blend_op);
}
else
{
/* the first frame doesn't have an fcTL so it's expected to be hidden,
* but we'll extract it anyway */
next_frame_width = png_get_image_width(png_ptr_read, info_ptr_read);
next_frame_height = png_get_image_height(png_ptr_read, info_ptr_read);
}
writeSetup2(png_ptr_read, info_ptr_read, png_ptr_write, info_ptr_write,
next_frame_width, next_frame_height);
png_write_info(png_ptr_write, info_ptr_write);
png_read_image(png_ptr_read, rowPointers);
png_write_image(png_ptr_write, rowPointers);
png_write_end(png_ptr_write, NULL);
png_destroy_write_struct(&png_ptr_write, &info_ptr_write);
fclose(newImage);
printf("extracted frame %d into %s\n", count, filename);
}
for(count = 0; count < info_ptr_read->height; count++)
png_free(png_ptr_read, rowPointers[count]);
png_free(png_ptr_read, rowPointers);
png_read_end(png_ptr_read, info_ptr_read);
png_destroy_read_struct(&png_ptr_read, &info_ptr_read, NULL);
printf("finished\n");
return 0;
}
void readSetup(char* filename, png_structp* png_ptr_read, png_infop* info_ptr_read)
{
FILE* image;
int rc;
png_byte pngSig[8];
image = fopen(filename, "rb");
if(image == NULL)
fatalError("couldn't open original png");
rc = fread(pngSig, 1, 8, image);
if(rc != 8)
fatalError("unable to read signature");
rc = png_check_sig(pngSig, 8);
if(rc == 0)
fatalError("invalid png signature");
*png_ptr_read = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(*png_ptr_read == NULL)
fatalError("unable to create read struct");
*info_ptr_read = png_create_info_struct(*png_ptr_read);
if(*info_ptr_read == NULL)
fatalError("unable to create info struct");
png_init_io(*png_ptr_read, image);
png_set_sig_bytes(*png_ptr_read, 8);
}
void writeSetup(FILE* image, png_structp* png_ptr_write, png_infop* info_ptr_write)
{
*png_ptr_write = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(*png_ptr_write == NULL)
fatalError("unable to create write struct");
*info_ptr_write = png_create_info_struct(*png_ptr_write);
if(*info_ptr_write == NULL)
fatalError("unable to create write struct");
png_init_io(*png_ptr_write, image);
}
void writeSetup2(png_structp png_ptr_read, png_infop info_ptr_read,
png_structp png_ptr_write, png_infop info_ptr_write,
png_uint_32 width, png_uint_32 height)
{
/* IHDR */
png_uint_32 garbage;
int bit_depth;
int colour_type;
int interlace_method;
int compression_method;
int filter_method;
/* PLTE */
png_colorp palette = NULL;
int palette_size = 0;
/* gAMA */
double gamma;
/* tRNS */
png_bytep trans;
int num_trans;
png_color_16p trans_values;
/* bKGD */
png_color_16p background;
png_get_IHDR(png_ptr_read, info_ptr_read, &garbage, &garbage,
&bit_depth, &colour_type, &interlace_method,
&compression_method, &filter_method);
png_set_IHDR(png_ptr_write, info_ptr_write, width, height,
bit_depth, colour_type, interlace_method,
compression_method, filter_method);
if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_PLTE))
{
png_get_PLTE(png_ptr_read, info_ptr_read, &palette, &palette_size);
png_set_PLTE(png_ptr_write, info_ptr_write, palette, palette_size);
}
if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_gAMA))
{
png_get_gAMA(png_ptr_read, info_ptr_read, &gamma);
png_set_gAMA(png_ptr_write, info_ptr_write, gamma);
}
if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_tRNS))
{
png_get_tRNS(png_ptr_read, info_ptr_read, &trans, &num_trans, &trans_values);
png_set_tRNS(png_ptr_write, info_ptr_write, trans, num_trans, trans_values);
}
if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_bKGD))
{
png_get_bKGD(png_ptr_read, info_ptr_read, &background);
png_set_bKGD(png_ptr_write, info_ptr_write, background);
}
} |