/* Concatenate PNG files from top to bottom. ./concat_png_tb input.png... > output.png */ #include #include #include #include #include #include #ifdef _WIN32 #include #include #endif #include"png_cache.h" int main(int argc, char **argv) { ImageCache *cache = NULL, *input; png_image output_image; png_bytep output_pixels; unsigned int y, offset; int i; if( argc < 2 ) return printf("%s [...] > output.png\n", *argv); if( isatty(STDOUT_FILENO) ) { fputs("Output should be redirected to a PNG file.\n", stderr); return 1; } #ifdef _WIN32 setmode(STDIN_FILENO, O_BINARY); setmode(STDOUT_FILENO, O_BINARY); #endif /* Load images and determine output size. */ memset(&output_image, 0, sizeof(png_image)); output_image.version = PNG_IMAGE_VERSION; output_image.format = PNG_FORMAT_RGBA; for(i = 1; i < argc; i++) { input = LoadImage(argv[i], &cache); if( input == NULL ) { FreeImageCache(&cache); return 1; } if( output_image.width < input->image.width ) output_image.width = input->image.width; output_image.height += input->image.height; if( output_image.height >= 0x8000 ) { fputs("Output size too large\n", stderr); FreeImageCache(&cache); return 1; } } /* Allocate output pixels. */ assert(PNG_IMAGE_SIZE(output_image) == output_image.width * output_image.height * 4); output_pixels = (png_bytep)calloc(1, PNG_IMAGE_SIZE(output_image)); if( output_pixels == NULL ) { fputs("Out of memory.\n", stderr); FreeImageCache(&cache); return 1; } /* Copy pixels. */ offset = 0; for(i = 1; i < argc; i++) { input = LoadImage(argv[i], &cache); assert(input != NULL); for(y = 0; y < input->image.height; y++) { memcpy(output_pixels + offset + y * output_image.width * 4, input->pixels + y * input->image.width * 4, input->image.width * 4); } offset += output_image.width * input->image.height * 4; } /* Write output. */ if( !png_image_write_to_stdio( &output_image, stdout, 0, output_pixels, 0, NULL) ) { fputs("Error writing output.\n", stderr); return 1; } free(output_pixels); FreeImageCache(&cache); return 0; }