1 /*
2  * This file is part of the Scale2x project.
3  *
4  * Copyright (C) 2003 Andrea Mazzoleni
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 /*
22  * This is the source of a simple command line tool which uses the fast
23  * implementation of the Scale effects.
24  *
25  * You can find an high level description of the effects at :
26  *
27  * http://scale2x.sourceforge.net/
28  */
29 
30 #include "scalebit.h"
31 #include "file.h"
32 #include "portable.h"
33 
34 #include <zlib.h>
35 
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 
file_process(const char * file0,const char * file1,int opt_scale_x,int opt_scale_y,int opt_crc)40 int file_process(const char* file0, const char* file1, int opt_scale_x, int opt_scale_y, int opt_crc)
41 {
42 	unsigned pixel;
43 	unsigned width;
44 	unsigned height;
45 	unsigned char* src_ptr;
46 	unsigned src_slice;
47 	unsigned char* dst_ptr;
48 	unsigned dst_slice;
49 	int type;
50 	int channel;
51 	png_color* palette;
52 	unsigned palette_size;
53 
54 	if (file_read(file0, &src_ptr, &src_slice, &pixel, &width, &height, &type, &channel, &palette, &palette_size, 1) != 0) {
55 		goto err;
56 	}
57 
58 	if (scale_precondition(opt_scale_x * 100 + opt_scale_y, pixel, width, height) != 0) {
59 		fprintf(stderr, "Error in the size of the source bitmap. Generally this happen\n");
60 		fprintf(stderr, "when the bitmap is too small or when the width is not an exact\n");
61 		fprintf(stderr, "multiplier of 8 bytes.\n");
62 		goto err_src;
63 	}
64 
65 	dst_slice = width * pixel * opt_scale_x;
66 	dst_ptr = malloc(dst_slice * height * opt_scale_y);
67 	if (!dst_ptr) {
68 		fprintf(stderr, "Low memory.\n");
69 		goto err_src;
70 	}
71 
72 	scale(opt_scale_x * 100 + opt_scale_y, dst_ptr, dst_slice, src_ptr, src_slice, pixel, width, height);
73 
74 	if (file_write(file1, dst_ptr, dst_slice, pixel, width * opt_scale_x, height * opt_scale_y, type, channel, palette, palette_size) != 0) {
75 		goto err_dst;
76 	}
77 
78 	if (opt_crc) {
79 		unsigned crc = crc32(0, dst_ptr, dst_slice * height * opt_scale_y);
80 		printf("%08x\n", crc);
81 	}
82 
83 	free(dst_ptr);
84 	free(src_ptr);
85 	free(palette);
86 
87 	return 0;
88 
89 err_dst:
90 	free(dst_ptr);
91 err_src:
92 	free(src_ptr);
93 	free(palette);
94 err:
95 	return -1;
96 }
97 
version(void)98 void version(void) {
99 	printf(PACKAGE " v" VERSION " by Andrea Mazzoleni\n");
100 }
101 
usage(void)102 void usage(void) {
103 	version();
104 	printf("Fast implementation of the Scale2/3/4x effects\n");
105 #if defined(__GNUC__) && (defined(HAVE_MMX) || defined(__amd64__))
106 	printf("(using Pentium MMX optimization)\n");
107 #endif
108 	printf("\nSyntax: scalex [-k N] FROM.png TO.png\n");
109 	printf("\nOptions:\n");
110 	printf("\t-k N\tSelect the scale factor. 2, 2x3, 2x4, 3 or 4. (default 2).\n");
111 	printf("\nMore info at http://scale2x.sourceforge.net/\n");
112 	exit(EXIT_FAILURE);
113 }
114 
115 #ifdef HAVE_GETOPT_LONG
116 struct option long_options[] = {
117 	{"scale", 1, 0, 'k'},
118 	{"crc", 0, 0, 'c'},
119 	{"help", 0, 0, 'h'},
120 	{"version", 0, 0, 'v'},
121 	{0, 0, 0, 0}
122 };
123 #endif
124 
125 #define OPTIONS "k:chv"
126 
main(int argc,char * argv[])127 int main(int argc, char* argv[]) {
128 	int opt_scale_x = 2;
129 	int opt_scale_y = 2;
130 	int opt_crc = 0;
131 	int c;
132 
133 	opterr = 0;
134 
135 	while ((c =
136 #ifdef HAVE_GETOPT_LONG
137 		getopt_long(argc, argv, OPTIONS, long_options, 0))
138 #else
139 		getopt(argc, argv, OPTIONS))
140 #endif
141 	!= EOF) {
142 		switch (c) {
143 			case 'h' :
144 				usage();
145 				exit(EXIT_SUCCESS);
146 			case 'v' :
147 				version();
148 				exit(EXIT_SUCCESS);
149 			case 'k' :
150 				if (strcmp(optarg, "2") == 0) {
151 					opt_scale_x = 2;
152 					opt_scale_y = 2;
153 				} else if (strcmp(optarg, "3") == 0) {
154 					opt_scale_x = 3;
155 					opt_scale_y = 3;
156 				} else if (strcmp(optarg, "4") == 0) {
157 					opt_scale_x = 4;
158 					opt_scale_y = 4;
159 				} else {
160 					if (sscanf(optarg, "%dx%d", &opt_scale_x, &opt_scale_y) != 2
161 						|| opt_scale_x < 1
162 						|| opt_scale_y < 1
163 					) {
164 						printf("Invalid -k option. Valid values are 2, 2x3, 2x4, 3 and 4.\n");
165 						exit(EXIT_FAILURE);
166 					}
167 				}
168 				break;
169 			case 'c' :
170 				opt_crc = 1;
171 				break;
172 			default:
173 				printf("Unknown option `%c'.\n", (char)optopt);
174 				exit(EXIT_FAILURE);
175 		}
176 	}
177 
178 	if (optind + 2 != argc) {
179 		usage();
180 		exit(EXIT_FAILURE);
181 	}
182 
183 	if (file_process(argv[optind], argv[optind+1], opt_scale_x, opt_scale_y, opt_crc) != 0) {
184 		exit(EXIT_FAILURE);
185 	}
186 
187 	return EXIT_SUCCESS;
188 }
189 
190