diff --git a/tools/croppa/Makefile b/tools/croppa/Makefile new file mode 100644 index 0000000..867f95b --- /dev/null +++ b/tools/croppa/Makefile @@ -0,0 +1,50 @@ +PROGRAM=./out/croppa +OBJS=out/croppa.o +LIBS=`GraphicsMagick-config --ldflags --libs` +EXTRA_CFLAGS=`GraphicsMagick-config --cppflags` + +include ../../shared/tools.mk + +TEST_IMAGE=../../assets/gigi_full.png +RESIZED_IMAGE=out/gigi.png +RESIZED_LACED=out/gigi_laced.png +REFERENCE_IMAGE=reference/gigi.png +REFERENCE_LACED=reference/gigi_laced.png +TEST_IMAGE2=../../assets/Amiga2000.png +RESIZED_IMAGE2=out/Amiga2000.png +REFERENCE_IMAGE2=reference/Amiga2000.png +RESIZED_LACED2=out/Amiga2000_laced.png +REFERENCE_LACED2=reference/Amiga2000_laced.png + +ODD_SIZE_IMAGE=../../assets/mr.png +REFERENCE_ODD_SIZE=reference/mr.png +ODD_SIZE=out/mr.png + + +$(RESIZED_IMAGE): $(TEST_IMAGE) $(PROGRAM) Makefile + $(PROGRAM) --width=320 --height=256 --blur=0.75 --input=$(TEST_IMAGE) --output=$(RESIZED_IMAGE) + +$(RESIZED_IMAGE2): $(TEST_IMAGE2) $(PROGRAM) Makefile + $(PROGRAM) --width=320 --height=256 --blur=0.75 --input=$(TEST_IMAGE2) --output=$(RESIZED_IMAGE2) + +$(RESIZED_LACED): $(TEST_IMAGE) $(PROGRAM) Makefile + $(PROGRAM) --width=320 --height=512 --interlaced --blur=0.75 --input=$(TEST_IMAGE) --output=$(RESIZED_LACED) + +$(RESIZED_LACED2): $(TEST_IMAGE2) $(PROGRAM) Makefile + $(PROGRAM) --width=320 --height=512 --interlaced --blur=0.75 --input=$(TEST_IMAGE2) --output=$(RESIZED_LACED2) + +$(ODD_SIZE): $(ODD_SIZE_IMAGE) $(PROGRAM) Makefile + $(PROGRAM) --width=320 --height=512 --interlaced --blur=0.75 --input=$(ODD_SIZE_IMAGE) --output=$(ODD_SIZE) + +test: $(RESIZED_IMAGE) $(RESIZED_LACED) $(RESIZED_IMAGE2) $(RESIZED_LACED2) $(ODD_SIZE) + diff $(RESIZED_IMAGE) $(REFERENCE_IMAGE) + diff $(RESIZED_LACED) $(REFERENCE_LACED) + diff $(RESIZED_IMAGE2) $(REFERENCE_IMAGE2) + diff $(RESIZED_LACED2) $(REFERENCE_LACED2) + diff $(ODD_SIZE) $(REFERENCE_ODD_SIZE) + @echo "______ ___ _____ _____ ___________ " + @echo "| ___ \/ _ \ / ___/ ___| ___| _ \ " + @echo "| |_/ / /_\ \\\\\ \`--.\ \`--.| |__ | | | | " + @echo "| __/| _ | \`--. \\\`--. \ __|| | | | " + @echo "| | | | | |/\__/ /\__/ / |___| |/ / " + @echo "\_| \_| |_/\____/\____/\____/|___/ " \ No newline at end of file diff --git a/tools/croppa/README.md b/tools/croppa/README.md new file mode 100644 index 0000000..75a7ad5 --- /dev/null +++ b/tools/croppa/README.md @@ -0,0 +1,69 @@ +croppa +====== + +Crop images + +usage +----- +``` + croppa: --input --output --x --y --width --height + options: + --dx (default: width) + --dy (default: height) + --rows (default: 1) + --cols (default: 1) + --verbose + --verbose +``` + +Crop will extract one or more images from a master image. + +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 width of the crop area in pixels. + +**--height** <height> + +Specify the height of the crop area in pixels. + +**--x** <x> + +Specify the x coordinate for the start of the crop in pixels. + +**--y** <x> + +Specify the y coordinate for the start of the crop in pixels. + + +options +------- + +**--dx <dx>** + +Specify the number of pixels added to x after each crop + +**--dy <dy>** + +Specify the number of pixels added to y after each crop + +**--rows <rows>** + +Specify the number rows of images that will be cropped (total number of images will be rows*cols) + +**--colss <cols>** + +Specify the number columns of images that will be cropped (total number of images will be rows*cols) + +**--verbose** + +Display debugging information diff --git a/tools/croppa/croppa.c b/tools/croppa/croppa.c new file mode 100644 index 0000000..27625c9 --- /dev/null +++ b/tools/croppa/croppa.c @@ -0,0 +1,236 @@ +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + int verbose; + int width; + int height; + int x; + int y; + int dx; + int dy; + int rows; + int cols; + char** argv; +} config_t; + +typedef struct { + Image *image; + Image *croppedImage; + ImageInfo *imageInfo; +} image_t; + +image_t image = {0}; +config_t config = { + .rows = 1, + .cols = 1, + .verbose = 0 +}; + +void +cleanup() +{ + if (image.image != (Image *) NULL) { + DestroyImage(image.image); + } + + 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 --x --y --width --height \n"\ + "options:\n"\ + " --dx (default: width)\n"\ + " --dy (default: height)\n"\ + " --rows (default: 1)\n"\ + " --cols (default: 1)\n"\ + " --verbose\n", config.argv[0]); + exit(1); +} + +int +main(int argc, char **argv) +{ + int c; + char* inputFile = 0; + char* outputFile = 0; + + ExceptionInfo exception; + + config.argv = argv; + + InitializeMagick(NULL); + image.imageInfo=CloneImageInfo(0); + GetExceptionInfo(&exception); + + while (1) { + static struct option long_options[] = { + {"verbose", no_argument, &config.verbose, 1}, + {"width", required_argument, 0, 'w'}, + {"height", required_argument, 0, 'h'}, + {"output", required_argument, 0, 'o'}, + {"input", required_argument, 0, 'i'}, + {"x", required_argument, 0, 'x'}, + {"y", required_argument, 0, 'y'}, + {"dx", required_argument, 0, 'd'}, + {"dy", required_argument, 0, 'f'}, + {"rows", required_argument, 0, 'r'}, + {"cols", required_argument, 0, 'c'}, + {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 'x': + if (sscanf(optarg, "%d", &config.x) != 1) { + abort_("invalid x"); + } + break; + case 'y': + if (sscanf(optarg, "%d", &config.y) != 1) { + abort_("invalid x"); + } + break; + case 'd': + if (sscanf(optarg, "%d", &config.dx) != 1) { + abort_("invalid dx"); + } + break; + case 'f': + if (sscanf(optarg, "%d", &config.dy) != 1) { + abort_("invalid dy"); + } + break; + case 'r': + if (sscanf(optarg, "%d", &config.rows) != 1) { + abort_("invalid rows"); + } + break; + case 'c': + if (sscanf(optarg, "%d", &config.cols) != 1) { + abort_("invalid cols"); + } + break; + case '?': + usage(); + break; + default: + usage(); + break; + } + } + + + if (inputFile == 0 || outputFile == 0 || config.width == 0 || config.height == 0) { + usage(); + abort(); + } + + if (config.dx == 0 ) { + config.dx = config.width; + } + + if (config.dy == 0 ) { + config.dy = config.height; + } + + if (config.verbose) { + printf("x: %d, y: %d\n", config.x, config.y); + printf("dx: %d, dy: %d\n", config.dx, config.dy); + printf("width: %d, height: %d\n", config.width, config.height); + printf("rows: %d, cols: %d\n", config.rows, config.cols); + } + + (void) strcpy(image.imageInfo->filename, inputFile); + image.image = ReadImage(image.imageInfo, &exception); + if (image.image == (Image *) NULL) { + CatchException(&exception); + abort_("Failed to read image %s\n", inputFile); + } + + + for (int x = config.x, count = 0; x < config.x+(config.cols*config.dx); x += config.dx) { + for (int y = config.y; y < config.y+(config.rows*config.dy); y += config.dy, count++) { + RectangleInfo rect = { + .x = x, + .y = y, + .width = config.width, + .height = config.height + }; + + if (config.verbose) { + printf("row %d cols %d %ld %ld %ld %ld\n", (y-config.y)/config.dy, (x-config.x)/config.dx, rect.x, rect.y, rect.width, rect.height); + } + + image.croppedImage = CropImage(image.image, &rect, &exception); + + if (config.rows > 1 || config.cols > 1) { + sprintf(image.croppedImage->filename, "%d-%s", count, outputFile); + } else { + strcpy(image.croppedImage->filename, outputFile); + } + + if (!WriteImage(image.imageInfo, image.croppedImage)) { + CatchException(&image.croppedImage->exception); + abort_("Failed to write image %d\n", outputFile); + } + } + } + + cleanup(); + + return 0; +}