comparison system/visarc.cc @ 0:223b71206888

Initial import
author thib
date Fri, 01 Aug 2008 16:32:45 +0000
parents
children 3a6aaeab7b4e
comparison
equal deleted inserted replaced
-1:000000000000 0:223b71206888
1 #define CMDNAME "visarc"
2 #define VERSION "1.00"
3
4 /*****************************************
5 ** Visual Arts の圧縮書庫ファイルを
6 ** 展開する
7 **
8 ** usage : visarc x <arcfile> <file> [<file> ...]
9 ** visarc l <arcfile>
10 ** visarc g <arcfile> <graphic file>
11 ** visarc m <arcfile> <mask file>
12 **
13 ******************************************
14 */
15 /*
16 *
17 * Copyright (C) 2000- Kazunori Ueno(JAGARL) <jagarl@creator.club.ne.jp>
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 *
33 */
34
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38
39 #include <stdio.h>
40 #include <unistd.h>
41 #include <string.h>
42
43 // use only file subsystem
44 #include "file.h"
45 #include "file_impl.h"
46 // #include "file.cc"
47
48 #ifdef HAVE_LIBPNG
49 #include <png.h>
50 #endif
51
52 void usage(void) {
53 fprintf(stderr, "usage : visarc <cmd> <arcfile> [<file1> [<file2> [...] ]]\n");
54 fprintf(stderr, " cmd : x : extract\n");
55 fprintf(stderr, " l : list all files\n");
56 fprintf(stderr, "\n");
57 #ifdef HAVE_LIBPNG
58 fprintf(stderr, "usage2: visarc <cmd> <pdt-file> [<output-file>]\n");
59 fprintf(stderr, " cmd p : unpack pdt file and save as png file\n");
60 #endif /* HAVE_LIBPNG */
61 fprintf(stderr, "\n");
62 }
63
64 void List(char* path) {
65 ARCFILE* file;
66 FILE* f = fopen(path, "rb");
67 if (f == 0) return;
68 char header[32];
69 fread(header, 32, 1, f);
70 fclose(f);
71 char magic_raf[8] = {'C','A','P','F',1,0,0,0};
72 if (strncmp(header, "PACL", 4) == 0) file = new ARCFILE(path);
73 else file = new SCN2kFILE(path);
74 file->Init();
75 file->ListFiles(stdout);
76 delete file;
77 return;
78 }
79
80 void ExtractOne(ARCFILE* arc, char* file) {
81 ARCINFO* info = arc->Find(file,"");
82 if (info == 0) {
83 fprintf(stderr, "Cannot find file %s in archive\n",file);
84 return;
85 }
86 FILE* out = fopen(file, "w");
87 if (out == 0) {
88 delete info;
89 fprintf(stderr, "Cannot open output file %s\n",file);
90 return;
91 }
92
93 fprintf(stdout, "Extracting %s ... ",file);
94 int size = info->Size();
95 const char* data = info->Read();
96 fwrite(data, size, 1, out);
97 fclose(out);
98 fprintf(stdout, "done\n");
99 delete info;
100 return;
101 }
102
103 void Extract(char* path, char** files, int fnum) {
104 ARCFILE* file;
105 FILE* f = fopen(path, "rb");
106 if (f == 0) return;
107 char header[32];
108 fread(header, 32, 1, f);
109 fclose(f);
110 char magic_raf[8] = {'C','A','P','F',1,0,0,0};
111 if (strncmp(header, "PACL", 4) == 0) file = new ARCFILE(path);
112 else file = new SCN2kFILE(path);
113 file->Init();
114 if (files != 0 && fnum != 0) {
115 int i; for (i=0; i<fnum; i++) {
116 ExtractOne(file, files[i]);
117 }
118 } else {
119 file->InitList();
120 char* path; while( (path=file->ListItem()) != 0) {
121 ExtractOne(file, path);
122 }
123 }
124 delete file;
125 return;
126 }
127
128 void ChangeExt(char* path, char* new_ext, char* buf) {
129 char* name = strrchr(path, DIR_SPLIT);
130 if (name == 0) name = path;
131 else name++;
132 int path_len = name - path;
133
134 char* ext = strrchr(name, '.');
135 int ext_len;
136 if (ext) ext_len = ext - name;
137 else ext_len = strlen(name);
138
139 strncpy(buf, path, path_len+ext_len);
140 strcpy(buf+path_len+ext_len, new_ext);
141 }
142
143 char* ReadFile(char* fname, int* len) {
144 FILE* in = fopen(fname, "rb");
145 if (in == 0) return 0;
146 fseek(in,0,2); size_t s = ftell(in); fseek(in,0,0);
147 char* buf = new char[s];
148 fread(buf,s,1,in);
149 fclose(in);
150 if (len) *len = s;
151 return buf;
152 }
153
154
155 #ifdef HAVE_LIBPNG
156 void create_png(FILE* stream, char* path, char* desc, int width, int height, char* data) {
157 png_structp png_ptr;
158 png_infop info_ptr;
159
160 /* create struct */
161 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
162 if (png_ptr == NULL) return;
163
164 /* initialize information */
165 info_ptr = png_create_info_struct(png_ptr);
166 if (info_ptr == NULL) {
167 png_destroy_write_struct(&png_ptr, (png_infop*)NULL);
168 return;
169 }
170
171 if (setjmp(png_jmpbuf(png_ptr))) {
172 /* error occured !! */
173 png_destroy_write_struct(&png_ptr,&info_ptr);
174 fprintf(stderr, "Get error while processing PNG from file %s\n",path);
175 return;
176 }
177
178 /* initialize I/O (for stream) */
179 png_init_io(png_ptr, stream);
180
181 /* initialize headers */
182 png_set_IHDR(png_ptr, info_ptr,
183 width, height, 8 /* bit_dept */,
184 PNG_COLOR_TYPE_RGB_ALPHA,
185 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
186 /* create text information */
187 png_text info_text[3];
188 info_text[0].key = "Title";
189 info_text[0].text= path;
190 info_text[0].compression = PNG_TEXT_COMPRESSION_NONE;
191 info_text[1].key = "Author";
192 info_text[1].text= CMDNAME " version " VERSION;
193 info_text[1].compression = PNG_TEXT_COMPRESSION_NONE;
194 info_text[2].key = "Description";
195 info_text[2].text= desc;
196 info_text[2].compression = PNG_TEXT_COMPRESSION_NONE;
197 png_set_text(png_ptr, info_ptr, info_text, 3);
198
199 /* write information */
200 png_write_info(png_ptr, info_ptr);
201
202 /* write body */
203 /* rgba image ; input/output is 32bpp.*/
204 char* row = new char[width*4];
205 int i; for (i=0; i<height; i++) {
206 char* row_ptr = row;
207 int j; for (j=0; j<width; j++) {
208 row_ptr[0] = data[2];
209 row_ptr[1] = data[1];
210 row_ptr[2] = data[0];
211 row_ptr[3] = data[3];
212 row_ptr += 4; data += 4;
213 }
214 png_write_rows(png_ptr, (png_byte**)&row, 1);
215 }
216 png_write_end(png_ptr, info_ptr);
217 png_destroy_write_struct(&png_ptr, &info_ptr);
218 return;
219 }
220
221 void ExtractPngRgbaGraphic(char* path,char* outpath = 0) {
222 char buf[1024]; char* fname = buf;
223 int len;
224 char* dat = ReadFile(path, &len);
225 if (dat == 0) {
226 fprintf(stderr, "Cannot open PDT file : %s\n",path);
227 return;
228 }
229 GRPCONV* conv = GRPCONV::AssignConverter(dat, len, path);
230 if (conv == 0) {
231 fprintf(stderr, "Invalid format\n");
232 return;
233 }
234 bool masked = conv->IsMask();
235 char* data = new char[conv->Width() * conv->Height() * 4 + 1024];
236 if (! conv->Read(data)) {
237 fprintf(stderr, "Insufficient memory\n");
238 delete conv;
239 return;
240 }
241 if (! masked) {
242 for (int i = 0; i < conv->Width() * conv->Height(); i++) {
243 data[4*i+3] = 0xff; // 不透明度を最大にする
244 }
245 }
246 if (outpath == 0) ChangeExt(path,".png", buf); // path をつくる
247 else fname = outpath;
248 FILE* out = fopen(fname, "wb"); // ファイルを開く
249 if (out == 0) {
250 fprintf(stderr, "Cannot open raw file : %s\n",buf);
251 delete conv;
252 return;
253 }
254 create_png(out, path, "", conv->Width(), conv->Height(), data);
255 fclose(out);
256
257 delete conv;
258 }
259 #endif /* HAVE_LIBPNG */
260
261 int main(int argc, char* argv[]) {
262 int i;
263 fprintf(stderr, "%s version %s\n", CMDNAME, VERSION);
264 if (argc < 3) {
265 usage(); return -1;
266 }
267 if (strlen(argv[1]) != 1) {
268 usage(); return -1;
269 }
270 for (i=2; i<argc; i++) {
271 /* option を削る */
272 argc--;
273 int j; for (j=i; j<argc; j++) argv[j] = argv[j+1];
274 }
275 switch(argv[1][0]) {
276 case 'x': case 'X':
277 if (argc < 4) Extract(argv[2], 0, -1);
278 else Extract(argv[2], argv+3, argc-3);
279 break;
280 case 'l': case 'L':
281 List(argv[2]);
282 break;
283 #ifdef HAVE_LIBPNG
284 case 'p': case 'P':
285 case 'a': case 'A':
286 if (argc < 4)
287 ExtractPngRgbaGraphic(argv[2]);
288 else
289 ExtractPngRgbaGraphic(argv[2],argv[3]);
290 break;
291 #endif /* HAVE_LIBPNG */
292 default:
293 usage(); return -1;
294 }
295 return 0;
296 }