swfから画像を抽出するコマンドラインアプリケーション
Revisión | e934d6bc8216331c532b2f8681f92bd2d0c24fc5 (tree) |
---|---|
Tiempo | 2016-09-20 20:55:23 |
Autor | masakih <masakih@user...> |
Commiter | masakih |
複数のswfファイルを処理出来るようにした
@@ -304,12 +304,125 @@ void storeBitsLossless2(const unsigned char *p, UInt32 length) { | ||
304 | 304 | saveImageAsPNG(imageRef, charactorID); |
305 | 305 | } |
306 | 306 | |
307 | +void extractImagesFromSWFFile(const char *filename) { | |
308 | + | |
309 | + NSString *filePath = [NSString stringWithFormat:@"%s", filename]; | |
310 | + if(![filePath hasPrefix:@"/"]) { | |
311 | + NSFileManager *fm = [NSFileManager defaultManager]; | |
312 | + filePath = [fm.currentDirectoryPath stringByAppendingPathComponent:filePath]; | |
313 | + } | |
314 | + | |
315 | + NSURL *url = [NSURL fileURLWithPath:filePath]; | |
316 | + NSData *data = [NSData dataWithContentsOfURL:url]; | |
317 | + if(!data) { | |
318 | + fprintf(stderr, "Can not open %s.\n", filename); | |
319 | + return; | |
320 | + } | |
321 | + | |
322 | + sOriginalName = [filePath lastPathComponent]; | |
323 | + sOriginalName = [sOriginalName stringByDeletingPathExtension]; | |
324 | + | |
325 | + printHex(data.bytes); | |
326 | + | |
327 | + // ヘッダの処理開始 | |
328 | + const HMSWFHeader *header = data.bytes; | |
329 | + printLog("type\t%c%c%c\n", header->type[0], header->type[1], header->type[2]); | |
330 | + printLog("version\t%d\n", header->version); | |
331 | + printLog("file size\t0x%x (%d)\n", header->f.f, header->f.f); | |
332 | + data = [data subdataWithRange:NSMakeRange(8, data.length - 8)]; | |
333 | + printHex(data.bytes); | |
334 | + | |
335 | + // シグニチャがCの時はコンテントはzlibで圧縮されている | |
336 | + if(header->type[0] == 'C') { | |
337 | + data = [data inflate]; | |
338 | + printHex(data.bytes); | |
339 | + } | |
340 | + | |
341 | + const unsigned char *p = data.bytes; | |
342 | + | |
343 | + // RECT: 上位5bitsが各要素のサイズを表す 要素は4つ | |
344 | + UInt8 size = *(UInt8 *)p; | |
345 | + size >>= 3; | |
346 | + printLog("size -> %u (%x)\n", size, size); | |
347 | + int offset = size * 4; | |
348 | + offset += 5; // 上位5bit分 | |
349 | + // bit -> byte | |
350 | + int div = offset / 8; | |
351 | + int mod = offset % 8; | |
352 | + offset = div + (mod == 0 ? 0 : 1); // アライメント | |
353 | + printLog("offset -> %d\n", offset); | |
354 | + p += offset; | |
355 | + | |
356 | + // fps: 8.8 fixed number. | |
357 | + printLog("fps -> %u.%u\n", *(UInt8 *)(p + 1), *(UInt8 *)p); | |
358 | + p += 2; | |
359 | + | |
360 | + // frame count | |
361 | + printLog("frame count -> %u\n", *(UInt16 *)p); | |
362 | + p += 2; | |
363 | + | |
364 | + // タグの処理開始 | |
365 | + int tagCount = 0; | |
366 | + while(1) { | |
367 | + printHex(p); | |
368 | + | |
369 | + HMSWFTag *tagP = (HMSWFTag *)p; | |
370 | + p += 2; | |
371 | + printLog("tag and length -> 0x%04x\n", tagP->tagAndLength); | |
372 | + UInt32 tag = tagP->tagAndLength >> 6; | |
373 | + UInt32 length = tagP->tagAndLength & 0x3F; | |
374 | + if(length == 0x3F) { | |
375 | + length = tagP->extraLength; | |
376 | + p += 4; | |
377 | + } | |
378 | + printLog("tag -> %u\nlength -> %u\n", tag, length); | |
379 | + | |
380 | + // tag == 0 終了タグ | |
381 | + if(tag == 0) break; | |
382 | + | |
383 | + // 画像の時の処理 | |
384 | + switch(tag) { | |
385 | + case tagBits: | |
386 | + @autoreleasepool { | |
387 | + storeImage(p + 2, length - 2, *(UInt16 *)p); | |
388 | + } | |
389 | + break; | |
390 | + case tagBitsJPEG3: | |
391 | + @autoreleasepool { | |
392 | + storeBitsJPEG3(p, length); | |
393 | + } | |
394 | + break; | |
395 | + case tagBitsLossless2: | |
396 | + @autoreleasepool { | |
397 | + storeBitsLossless2(p, length); | |
398 | + } | |
399 | + break; | |
400 | + case tagBitsJPEG2: | |
401 | + case tagBitsLossless: | |
402 | + case tagBitsJPEG4: | |
403 | + case tagJPEGTables: | |
404 | + if(length > 0) { | |
405 | + fprintf(stderr, "Not supported type. (tag=%d)\n", tag); | |
406 | + } | |
407 | + break; | |
408 | + } | |
409 | + | |
410 | + p += length; | |
411 | + tagCount++; | |
412 | + | |
413 | + if(tagCount > 200) { | |
414 | + return; | |
415 | + } | |
416 | + } | |
417 | + | |
418 | + printLog("tag Count -> %d\n", tagCount); | |
419 | +} | |
420 | + | |
307 | 421 | int main(int argc, char * const *argv) { |
308 | 422 | @autoreleasepool { |
309 | 423 | |
310 | 424 | // 引数の処理 |
311 | 425 | int opt; |
312 | - char *filename = NULL; | |
313 | 426 | char *oFilename = NULL; |
314 | 427 | char *charactorid = NULL; |
315 | 428 |
@@ -344,9 +457,7 @@ int main(int argc, char * const *argv) { | ||
344 | 457 | } |
345 | 458 | } |
346 | 459 | |
347 | - if(optind < argc) { | |
348 | - filename = argv[optind]; | |
349 | - } else { | |
460 | + if(optind >= argc) { | |
350 | 461 | usage(EXIT_FAILURE, stderr); |
351 | 462 | } |
352 | 463 |
@@ -374,118 +485,11 @@ int main(int argc, char * const *argv) { | ||
374 | 485 | } |
375 | 486 | } |
376 | 487 | |
377 | - NSString *filePath = [NSString stringWithFormat:@"%s", filename]; | |
378 | - if(![filePath hasPrefix:@"/"]) { | |
379 | - NSFileManager *fm = [NSFileManager defaultManager]; | |
380 | - filePath = [fm.currentDirectoryPath stringByAppendingPathComponent:filePath]; | |
381 | - } | |
382 | - | |
383 | - NSURL *url = [NSURL fileURLWithPath:filePath]; | |
384 | - NSData *data = [NSData dataWithContentsOfURL:url]; | |
385 | - if(!data) { | |
386 | - fprintf(stderr, "Can not open %s.\n", filename); | |
387 | - exit(EXIT_FAILURE); | |
388 | - } | |
389 | - | |
390 | - sOriginalName = [filePath lastPathComponent]; | |
391 | - sOriginalName = [sOriginalName stringByDeletingPathExtension]; | |
392 | - | |
393 | - | |
394 | - printHex(data.bytes); | |
395 | - | |
396 | - // ヘッダの処理開始 | |
397 | - const HMSWFHeader *header = data.bytes; | |
398 | - printLog("type\t%c%c%c\n", header->type[0], header->type[1], header->type[2]); | |
399 | - printLog("version\t%d\n", header->version); | |
400 | - printLog("file size\t0x%x (%d)\n", header->f.f, header->f.f); | |
401 | - data = [data subdataWithRange:NSMakeRange(8, data.length - 8)]; | |
402 | - printHex(data.bytes); | |
403 | - | |
404 | - // シグニチャがCの時はコンテントはzlibで圧縮されている | |
405 | - if(header->type[0] == 'C') { | |
406 | - data = [data inflate]; | |
407 | - printHex(data.bytes); | |
408 | - } | |
409 | - | |
410 | - const unsigned char *p = data.bytes; | |
411 | - | |
412 | - // RECT: 上位5bitsが各要素のサイズを表す 要素は4つ | |
413 | - UInt8 size = *(UInt8 *)p; | |
414 | - size >>= 3; | |
415 | - printLog("size -> %u (%x)\n", size, size); | |
416 | - int offset = size * 4; | |
417 | - offset += 5; // 上位5bit分 | |
418 | - // bit -> byte | |
419 | - int div = offset / 8; | |
420 | - int mod = offset % 8; | |
421 | - offset = div + (mod == 0 ? 0 : 1); // アライメント | |
422 | - printLog("offset -> %d\n", offset); | |
423 | - p += offset; | |
424 | - | |
425 | - // fps: 8.8 fixed number. | |
426 | - printLog("fps -> %u.%u\n", *(UInt8 *)(p + 1), *(UInt8 *)p); | |
427 | - p += 2; | |
428 | - | |
429 | - // frame count | |
430 | - printLog("frame count -> %u\n", *(UInt16 *)p); | |
431 | - p += 2; | |
432 | - | |
433 | - // タグの処理開始 | |
434 | - int tagCount = 0; | |
435 | - while(1) { | |
436 | - printHex(p); | |
437 | - | |
438 | - HMSWFTag *tagP = (HMSWFTag *)p; | |
439 | - p += 2; | |
440 | - printLog("tag and length -> 0x%04x\n", tagP->tagAndLength); | |
441 | - UInt32 tag = tagP->tagAndLength >> 6; | |
442 | - UInt32 length = tagP->tagAndLength & 0x3F; | |
443 | - if(length == 0x3F) { | |
444 | - length = tagP->extraLength; | |
445 | - p += 4; | |
446 | - } | |
447 | - printLog("tag -> %u\nlength -> %u\n", tag, length); | |
448 | - | |
449 | - // tag == 0 終了タグ | |
450 | - if(tag == 0) break; | |
451 | - | |
452 | - // 画像の時の処理 | |
453 | - switch(tag) { | |
454 | - case tagBits: | |
455 | - @autoreleasepool { | |
456 | - storeImage(p + 2, length - 2, *(UInt16 *)p); | |
457 | - } | |
458 | - break; | |
459 | - case tagBitsJPEG3: | |
460 | - @autoreleasepool { | |
461 | - storeBitsJPEG3(p, length); | |
462 | - } | |
463 | - break; | |
464 | - case tagBitsLossless2: | |
465 | - @autoreleasepool { | |
466 | - storeBitsLossless2(p, length); | |
467 | - } | |
468 | - break; | |
469 | - case tagBitsJPEG2: | |
470 | - case tagBitsLossless: | |
471 | - case tagBitsJPEG4: | |
472 | - case tagJPEGTables: | |
473 | - if(length > 0) { | |
474 | - fprintf(stderr, "Not supported type. (tag=%d)\n", tag); | |
475 | - } | |
476 | - break; | |
477 | - } | |
478 | - | |
479 | - p += length; | |
480 | - tagCount++; | |
488 | + for(int filePos = optind; filePos < argc; filePos++) { | |
489 | + const char *filename = argv[filePos]; | |
481 | 490 | |
482 | - if(tagCount > 200) { | |
483 | - exit(-1); | |
484 | - } | |
491 | + extractImagesFromSWFFile(filename); | |
485 | 492 | } |
486 | - | |
487 | - printLog("tag Count -> %d\n", tagCount); | |
488 | - | |
489 | 493 | } |
490 | 494 | return 0; |
491 | 495 | } |