diff --git a/tools/resize/README.md b/tools/resize/README.md new file mode 100644 index 0000000..a97d0a7 --- /dev/null +++ b/tools/resize/README.md @@ -0,0 +1,65 @@ +resize +====== + +Nicely resize images + +usage +----- +``` + rezize: --input --output --width --height + options: + --blur + --interlaced + --verbose +``` + +resize will resize images using filtering to try and make the resampled output still look good. It currently is hard coded to use a BesselFilter. Although by hacking the source you could use any of these filters: + + * BoxFilter + * TriangleFilter + * HermiteFilter + * HanningFilter + * HammingFilter + * BlackmanFilter + * GaussianFilter + * QuadraticFilter + * CubicFilter + * CatromFilter + * MitchellFilter + * LanczosFilter + * BesselFilter + * SincFilter + + +mandatory arguments +------------------- +**--input** <input.png> + +Specify the filename of the image to be resized. + +**--output** <output.png> + +Specify the filename of the resized image file. + +**--width** <width> + +Specify the new width in pixels. + +**--height** <height> + +Specify the new height in pixels. + +options +------- + +**--interlaced** + +Generated output suitable for an interlaced display. The aspect ratio will be adjusted for double the vertical resolution. Specify the dimensions of the bitplane data (eg --width=320 --height=512). + +**--blur** <blur> + +Specify the blur factor to be applied. 0 is no blur. 0.75 looks good for most reductions. + +**--verbose** + +Display debugging information diff --git a/tools/resize/resize.c b/tools/resize/resize.c index f10f7ba..6d275d6 100644 --- a/tools/resize/resize.c +++ b/tools/resize/resize.c @@ -4,59 +4,162 @@ #include #include #include +#include + +typedef struct { + int verbose; + int width; + int height; + int interlaced; + float blur; + char** argv; +} config_t; + +typedef struct { + Image *image; + Image *resizeImage; + Image *croppedImage; + ImageInfo *imageInfo; +} image_t; + +image_t image = {0}; +config_t config = {.blur = 0.75}; + +void +cleanup() +{ + if (image.image != (Image *) NULL) { + DestroyImage(image.image); + } + + if (image.resizeImage != (Image *)NULL) { + DestroyImage(image.resizeImage); + } + + if (image.croppedImage != (Image *)NULL) { + DestroyImage(image.croppedImage); + } + + if (image.imageInfo != (ImageInfo *) NULL) { + DestroyImageInfo(image.imageInfo); + } + DestroyMagick(); +} + +void +abort_(const char * s, ...) +{ + fprintf(stderr, "%s: ", config.argv[0]); + va_list args; + va_start(args, s); + vfprintf(stderr, s, args); + fprintf(stderr, "\n"); + va_end(args); + cleanup(); + exit(1); +} + +void +usage() +{ + fprintf(stderr, + "%s: --input --output --width --height \n"\ + "options:\n"\ + " --blur \n"\ + " --interlaced\n"\ + " --verbose\n", config.argv[0]); + exit(1); +} int main(int argc, char **argv) { - Image *image = 0, *resizeImage = 0, *croppedImage = 0; - char infile[MaxTextExtent]; - char outfile[MaxTextExtent]; - int arg = 1, exit_status = 0; - ImageInfo *imageInfo; + int c; + char* inputFile = 0; + char* outputFile = 0; + ExceptionInfo exception; + config.argv = argv; + InitializeMagick(NULL); - imageInfo=CloneImageInfo(0); + image.imageInfo=CloneImageInfo(0); GetExceptionInfo(&exception); -#if 0 - const int targetWidth = 320; - const int targetHeight = 256; - const int interlaced = 0; - const float blur = 0.75; -#else - const int targetWidth = 320; - const int targetHeight = 512; - const int interlaced = 1; - const float blur = 0.75; -#endif + while (1) { + static struct option long_options[] = { + {"verbose", no_argument, &config.verbose, 1}, + {"interlaced", no_argument, &config.interlaced, 1}, + {"width", required_argument, 0, 'w'}, + {"height", required_argument, 0, 'h'}, + {"blur", required_argument, 0, 'b'}, + {"output", required_argument, 0, 'o'}, + {"input", required_argument, 0, 'i'}, + {0, 0, 0, 0} + }; + + int option_index = 0; + + + c = getopt_long (argc, argv, "o:i:w:h:b:", long_options, &option_index); + + if (c == -1) + break; + + switch (c) { + case 0: + break; + case 'i': + inputFile = optarg; + break; + case 'o': + outputFile = optarg; + break; + case 'w': + if (sscanf(optarg, "%d", &config.width) != 1) { + abort_("invalid width"); + } + break; + case 'h': + if (sscanf(optarg, "%d", &config.height) != 1) { + abort_("invalid height"); + } + break; + case 'b': + if (sscanf(optarg, "%f", &config.blur) != 1) { + abort_("invalid height"); + } + break; + case '?': + usage(); + break; + default: + usage(); + break; + } + } + - if (argc != 3) { - (void) fprintf ( stderr, "Usage: %s infile outfile\n", argv[0] ); - (void) fflush(stderr); - exit_status = 1; - goto program_exit; + if (inputFile == 0 || outputFile == 0 || config.width == 0 || config.height == 0) { + usage(); + abort(); } - (void) strncpy(infile, argv[arg], MaxTextExtent-1 ); - arg++; - (void) strncpy(outfile, argv[arg], MaxTextExtent-1 ); - (void) strcpy(imageInfo->filename, infile); - image = ReadImage(imageInfo, &exception); - if (image == (Image *) NULL) { + (void) strcpy(image.imageInfo->filename, inputFile); + image.image = ReadImage(image.imageInfo, &exception); + if (image.image == (Image *) NULL) { CatchException(&exception); - exit_status = 1; - goto program_exit; + abort_("Failed to read image %s\n", inputFile); } - int width = image->columns; - int height = image->rows; + int width = image.image->columns; + int height = image.image->rows; - float scale = (float)height/(float)targetHeight; + float scale = (float)height/(float)config.height; int newWidth = width/scale; - resizeImage=ResizeImage(image, newWidth/(interlaced?2:1), targetHeight, + image.resizeImage=ResizeImage(image.image, newWidth/(config.interlaced?2:1), config.height, //GaussianFilter, //BoxFilter, //TriangleFilter, @@ -72,39 +175,25 @@ main(int argc, char **argv) //LanczosFilter, BesselFilter, //SincFilter, - blur, &exception); + config.blur, &exception); RectangleInfo rect = { - .x = ((newWidth/(interlaced?2:1))-targetWidth)/2, + .x = ((newWidth/(config.interlaced?2:1))-config.width)/2, .y = 0, - .width = targetWidth, - .height = targetHeight + .width = config.width, + .height = config.height }; - croppedImage = CropImage(resizeImage, &rect, &exception); + image.croppedImage = CropImage(image.resizeImage, &rect, &exception); - (void) strcpy(croppedImage->filename, outfile); - if (!WriteImage (imageInfo, croppedImage)) - { - CatchException(&croppedImage->exception); - exit_status = 1; - goto program_exit; - } + strcpy(image.croppedImage->filename, outputFile); - program_exit: + if (!WriteImage(image.imageInfo, image.croppedImage)) { + CatchException(&image.croppedImage->exception); + abort_("Failed to write image %d\n", outputFile); + } - if (image != (Image *) NULL) - DestroyImage(image); + cleanup(); - if (resizeImage != (Image *)NULL) - DestroyImage(resizeImage); - - if (croppedImage != (Image *)NULL) - DestroyImage(croppedImage); - - if (imageInfo != (ImageInfo *) NULL) - DestroyImageInfo(imageInfo); - DestroyMagick(); - - return exit_status; + return 0; }