• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javaandroidc++linuxc#windowsobjective-ccocoaqt誰得pythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

swfから画像を抽出するコマンドラインアプリケーション


Commit MetaInfo

Revisionc903716e127aee82ea2f5217dc79d3461ba72fd3 (tree)
Zeit2016-09-14 00:20:56
Autormasakih <masakih@user...>
Commitermasakih

Log Message

first commit.

Ändern Zusammenfassung

Diff

--- a/KanColleGraphicDivider.xcodeproj/project.pbxproj
+++ b/KanColleGraphicDivider.xcodeproj/project.pbxproj
@@ -8,6 +8,7 @@
88
99 /* Begin PBXBuildFile section */
1010 F44C14BB1D84F07300ADE497 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F44C14BA1D84F07300ADE497 /* main.m */; };
11+ F44C14C41D85083E00ADE497 /* HMZlibData.m in Sources */ = {isa = PBXBuildFile; fileRef = F44C14C31D85083E00ADE497 /* HMZlibData.m */; };
1112 /* End PBXBuildFile section */
1213
1314 /* Begin PBXCopyFilesBuildPhase section */
@@ -25,6 +26,9 @@
2526 /* Begin PBXFileReference section */
2627 F44C14B71D84F07300ADE497 /* KanColleGraphicDivider */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = KanColleGraphicDivider; sourceTree = BUILT_PRODUCTS_DIR; };
2728 F44C14BA1D84F07300ADE497 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
29+ F44C14C11D84F27500ADE497 /* SWFStructure.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SWFStructure.h; sourceTree = "<group>"; };
30+ F44C14C21D85083E00ADE497 /* HMZlibData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HMZlibData.h; sourceTree = "<group>"; };
31+ F44C14C31D85083E00ADE497 /* HMZlibData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HMZlibData.m; sourceTree = "<group>"; };
2832 /* End PBXFileReference section */
2933
3034 /* Begin PBXFrameworksBuildPhase section */
@@ -58,6 +62,9 @@
5862 isa = PBXGroup;
5963 children = (
6064 F44C14BA1D84F07300ADE497 /* main.m */,
65+ F44C14C11D84F27500ADE497 /* SWFStructure.h */,
66+ F44C14C21D85083E00ADE497 /* HMZlibData.h */,
67+ F44C14C31D85083E00ADE497 /* HMZlibData.m */,
6168 );
6269 path = KanColleGraphicDivider;
6370 sourceTree = "<group>";
@@ -119,6 +126,7 @@
119126 buildActionMask = 2147483647;
120127 files = (
121128 F44C14BB1D84F07300ADE497 /* main.m in Sources */,
129+ F44C14C41D85083E00ADE497 /* HMZlibData.m in Sources */,
122130 );
123131 runOnlyForDeploymentPostprocessing = 0;
124132 };
@@ -209,6 +217,7 @@
209217 F44C14BF1D84F07300ADE497 /* Debug */ = {
210218 isa = XCBuildConfiguration;
211219 buildSettings = {
220+ OTHER_LDFLAGS = "-lz";
212221 PRODUCT_NAME = "$(TARGET_NAME)";
213222 };
214223 name = Debug;
@@ -216,6 +225,7 @@
216225 F44C14C01D84F07300ADE497 /* Release */ = {
217226 isa = XCBuildConfiguration;
218227 buildSettings = {
228+ OTHER_LDFLAGS = "-lz";
219229 PRODUCT_NAME = "$(TARGET_NAME)";
220230 };
221231 name = Release;
--- /dev/null
+++ b/KanColleGraphicDivider.xcodeproj/xcuserdata/masaki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
@@ -0,0 +1,5 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<Bucket
3+ type = "1"
4+ version = "2.0">
5+</Bucket>
--- a/KanColleGraphicDivider.xcodeproj/xcuserdata/masaki.xcuserdatad/xcschemes/KanColleGraphicDivider.xcscheme
+++ b/KanColleGraphicDivider.xcodeproj/xcuserdata/masaki.xcuserdatad/xcschemes/KanColleGraphicDivider.xcscheme
@@ -46,7 +46,8 @@
4646 selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
4747 selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
4848 launchStyle = "0"
49- useCustomWorkingDirectory = "NO"
49+ useCustomWorkingDirectory = "YES"
50+ customWorkingDirectory = "/Users/masaki/Desktop/KanColle-Limited-Graphics"
5051 ignoresPersistentStateOnLaunch = "NO"
5152 debugDocumentVersioning = "YES"
5253 debugServiceExtension = "internal"
@@ -61,6 +62,12 @@
6162 ReferencedContainer = "container:KanColleGraphicDivider.xcodeproj">
6263 </BuildableReference>
6364 </BuildableProductRunnable>
65+ <CommandLineArguments>
66+ <CommandLineArgument
67+ argument = "2016HarunaKaiMizugi.swf"
68+ isEnabled = "YES">
69+ </CommandLineArgument>
70+ </CommandLineArguments>
6471 <AdditionalOptions>
6572 </AdditionalOptions>
6673 </LaunchAction>
--- /dev/null
+++ b/KanColleGraphicDivider/HMZlibData.h
@@ -0,0 +1,16 @@
1+//
2+// HMZlibData.h
3+// KanColleGraphicDivider
4+//
5+// Created by Hori,Masaki on 2016/09/11.
6+// Copyright © 2016年 Hori,Masaki. All rights reserved.
7+//
8+
9+#import <Foundation/Foundation.h>
10+
11+@interface NSData (HMZlibData)
12+
13+- (NSData *)deflate:(int)compressionLevel;
14+- (NSData *)inflate;
15+
16+@end
--- /dev/null
+++ b/KanColleGraphicDivider/HMZlibData.m
@@ -0,0 +1,63 @@
1+//
2+// HMZlibData.m
3+// KanColleGraphicDivider
4+//
5+// Created by Hori,Masaki on 2016/09/11.
6+// Copyright © 2016年 Hori,Masaki. All rights reserved.
7+//
8+
9+#import "HMZlibData.h"
10+#import <zlib.h>
11+
12+
13+@implementation NSData (HMZlibData)
14+
15+- (z_stream)initialized_zStream {
16+ z_stream zStream;
17+ zStream.zalloc = Z_NULL;
18+ zStream.zfree = Z_NULL;
19+ zStream.opaque = Z_NULL;
20+ return zStream;
21+}
22+
23+- (NSData *)deflate:(int)compressionLevel {
24+ z_stream zStream = [self initialized_zStream];
25+ Bytef buffer[131072];
26+ deflateInit(&zStream, compressionLevel);
27+ zStream.next_in = (Bytef *)self.bytes;
28+ zStream.avail_in = (UInt)self.length;
29+ int retval = Z_OK;
30+ NSMutableData *ret = [NSMutableData dataWithCapacity:0];
31+ do {
32+ zStream.next_out = buffer;
33+ zStream.avail_out = sizeof(buffer);
34+ retval = deflate(&zStream, Z_FINISH);
35+ size_t length = sizeof(buffer) - zStream.avail_out;
36+ if (length > 0)
37+ [ret appendBytes:buffer length:length];
38+ } while (zStream.avail_out != sizeof(buffer));
39+ deflateEnd(&zStream);
40+ return ret;
41+}
42+
43+- (NSData *)inflate {
44+ z_stream zStream = [self initialized_zStream];
45+ Bytef buffer[131072];
46+ inflateInit(&zStream);
47+ zStream.next_in = (Bytef *)self.bytes;
48+ zStream.avail_in = (UInt)self.length;
49+ int retval = Z_OK;
50+ NSMutableData *ret = [NSMutableData dataWithCapacity:0];
51+ do {
52+ zStream.next_out = buffer;
53+ zStream.avail_out = sizeof(buffer);
54+ retval = inflate(&zStream, Z_FINISH);
55+ size_t length = sizeof(buffer) - zStream.avail_out;
56+ if (length > 0)
57+ [ret appendBytes:buffer length:length];
58+ } while (zStream.avail_out != sizeof(buffer));
59+ inflateEnd(&zStream);
60+ return ret;
61+}
62+
63+@end
--- /dev/null
+++ b/KanColleGraphicDivider/SWFStructure.h
@@ -0,0 +1,32 @@
1+//
2+// SWFStructure.h
3+// KanColleGraphicDivider
4+//
5+// Created by Hori,Masaki on 2016/09/11.
6+// Copyright © 2016年 Hori,Masaki. All rights reserved.
7+//
8+
9+#ifndef SWFStructure_h
10+#define SWFStructure_h
11+
12+
13+#pragma pack(1)
14+
15+typedef struct _HMSWFHeader {
16+ char type[3];
17+ char version;
18+ union {
19+ char fileSize[4];
20+ int f;
21+ } f;
22+} HMSWFHeader;
23+
24+typedef struct _HMSWFTag {
25+ UInt16 tagAndLength;
26+ UInt32 extraLength;
27+} HMSWFTag;
28+
29+#pragma pack()
30+
31+
32+#endif /* SWFStructure_h */
--- a/KanColleGraphicDivider/main.m
+++ b/KanColleGraphicDivider/main.m
@@ -6,12 +6,239 @@
66 // Copyright © 2016年 Hori,Masaki. All rights reserved.
77 //
88
9-#import <Foundation/Foundation.h>
9+#import <Cocoa/Cocoa.h>
10+#include "SWFStructure.h"
11+#import "HMZlibData.h"
12+
13+static NSString *sCurrentDir = nil;
14+
15+void printLog(const char *fmt, ...) {
16+#if 0
17+ va_list ap;
18+ va_start(ap, fmt);
19+ vfprintf(stderr, fmt, ap);
20+ va_end(ap);
21+#endif
22+}
23+
24+void printHex(const unsigned char *p) {
25+ for(int i=0;i<1;i++) {
26+ for(int j=0;j<16;j++) {
27+ printLog("%02x ", *p++);
28+ }
29+ printLog("\n");
30+ }
31+}
32+
33+void storeImage(const unsigned char *p, UInt32 length, int tagCount) {
34+ @autoreleasepool {
35+ printLog("#### TYPE IS PICTURE ####\n\n");
36+ if(length != 0) {
37+ NSData *pic = [NSData dataWithBytes:p length:length];
38+ NSImage *pict = [[NSImage alloc] initWithData:pic];
39+ if(!pict) {
40+ fprintf(stderr, "Can not create image from data.\n");
41+ } else {
42+ NSString *path = [NSString stringWithFormat:@"d%d.jpg", tagCount];
43+ path = [sCurrentDir stringByAppendingPathComponent:path];
44+ NSURL *url = [NSURL fileURLWithPath:path];
45+ [pic writeToURL:url atomically:YES];
46+ }
47+ }
48+ }
49+}
50+
51+void storeDefineBitsJPEG3(const unsigned char *p, UInt32 length, int tagCount) {
52+ UInt32 contentLength = length - 6;
53+ UInt32 imageSize = *(UInt32 *)(p + 2);
54+ p += 6;
55+
56+ if(imageSize == contentLength) {
57+ storeImage(p, contentLength, tagCount);
58+ return;
59+ }
60+
61+ // JPEGを取出し
62+ NSData *pic = [NSData dataWithBytes:p length:imageSize];
63+ NSImage *pict = [[NSImage alloc] initWithData:pic];
64+ if(!pict) {
65+ fprintf(stderr, "Can not create image from data.\n");
66+ return;
67+ }
68+
69+ NSSize size = pict.size;
70+
71+ // アルファチャンネルの取出し
72+ NSData *alpha = [NSData dataWithBytes:p + imageSize length:contentLength - imageSize];
73+ alpha = [alpha inflate];
74+
75+ unsigned char *pp = (unsigned char *)alpha.bytes;
76+ NSBitmapImageRep *alphaImageRef = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&pp
77+ pixelsWide:size.width
78+ pixelsHigh:size.height
79+ bitsPerSample:8
80+ samplesPerPixel:1
81+ hasAlpha:NO
82+ isPlanar:NO
83+ colorSpaceName:NSDeviceWhiteColorSpace
84+ bytesPerRow:size.width
85+ bitsPerPixel:0];
86+ if(!alphaImageRef) {
87+ fprintf(stderr, "Can not create alpha image from data.\n");
88+ return;
89+ }
90+
91+ // 透過画像の作成
92+ NSImage *image = [[NSImage alloc] initWithSize:size];
93+ [image lockFocus];
94+ {
95+ NSRect rect = NSMakeRect(0, 0, size.width, size.height);
96+
97+ CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
98+ CGContextSaveGState(context);
99+ CGContextClipToMask(context, NSRectToCGRect(rect), alphaImageRef.CGImage);
100+ [pict drawAtPoint:NSZeroPoint
101+ fromRect:rect
102+ operation:NSCompositeCopy
103+ fraction:1.0];
104+
105+ CGContextRestoreGState(context);
106+ }
107+ [image unlockFocus];
108+
109+ // PNGで保存
110+ NSData *tiffData = image.TIFFRepresentation;
111+ if(!tiffData) {
112+ fprintf(stderr, "Can not create masked image.\n");
113+ return;
114+ }
115+
116+ NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithData:tiffData];
117+ NSData *imageData = [rep representationUsingType:NSPNGFileType
118+ properties:@{}];
119+ NSString *path = [NSString stringWithFormat:@"d%d.png", tagCount];
120+ path = [sCurrentDir stringByAppendingPathComponent:path];
121+ NSURL *url = [NSURL fileURLWithPath:path];
122+ [imageData writeToURL:url atomically:YES];
123+}
10124
11125 int main(int argc, const char * argv[]) {
12126 @autoreleasepool {
13- // insert code here...
14- NSLog(@"Hello, World!");
127+ NSProcessInfo *pInfo = [NSProcessInfo processInfo];
128+ NSArray<NSString *> *args = pInfo.arguments;
129+ if(args.count < 2) {
130+ fprintf(stderr, "Few argument\n");
131+ exit(-1);
132+ }
133+
134+ NSFileManager *fm = [NSFileManager defaultManager];
135+ sCurrentDir = fm.currentDirectoryPath;
136+
137+ NSString *filePath = args[1];
138+ if(![filePath hasPrefix:@"/"]) {
139+ filePath = [sCurrentDir stringByAppendingPathComponent:filePath];
140+ }
141+
142+ NSURL *url = [NSURL fileURLWithPath:filePath];
143+ NSData *data = [NSData dataWithContentsOfURL:url];
144+ if(!data) {
145+ fprintf(stderr, "Can not open %s.\n", args[1].UTF8String);
146+ exit(-1);
147+ }
148+
149+ printHex(data.bytes);
150+
151+ // ヘッダの処理開始
152+ const HMSWFHeader *header = data.bytes;
153+ printLog("type\t%c%c%c\n", header->type[0], header->type[1], header->type[2]);
154+ printLog("version\t%d\n", header->version);
155+ printLog("file size\t0x%x (%d)\n", header->f.f, header->f.f);
156+ data = [data subdataWithRange:NSMakeRange(8, data.length - 8)];
157+ printHex(data.bytes);
158+
159+ // シグニチャがCの時はコンテントはzlibで圧縮されている
160+ if(header->type[0] == 'C') {
161+ data = [data inflate];
162+ printHex(data.bytes);
163+ }
164+
165+ const unsigned char *p = data.bytes;
166+
167+ // RECT: 上位5bitsが各要素のサイズを表す 要素は4つ
168+ unsigned short size = *p;
169+ size >>= 3;
170+ printLog("size -> %u (%x)\n", size, size);
171+ int offset = size * 4;
172+ offset += 5; // 上位5bit分
173+ int div = offset / 8;
174+ int mod = offset % 8;
175+ offset = div + (mod == 0 ? 0 : 1); // アライメント
176+ printLog("offset -> %d\n", offset);
177+ p += offset;
178+
179+ // fps: 8.8 fixed number.
180+ UInt8 fpsE = *(UInt8 *)p;
181+ p += 1;
182+ UInt8 fps = *(UInt8 *)p;
183+ p += 1;
184+ printLog("fps -> %u.%u\n", fps, fpsE);
185+
186+ // frame count
187+ UInt16 frameCount = *(UInt16 *)p;
188+ printLog("frame count -> %u\n", frameCount);
189+ p += 2;
190+
191+ // タグの処理開始
192+ int tagCount = 0;
193+ while(1) {
194+ printHex(p);
195+
196+ HMSWFTag *tagP = (HMSWFTag *)p;
197+ p += 2;
198+ printLog("tag and length -> 0x%04x\n", tagP->tagAndLength);
199+ UInt32 tag = tagP->tagAndLength >> 6;
200+ UInt32 length = tagP->tagAndLength & 0x3F;
201+ if(length == 0x3F) {
202+ length = tagP->extraLength;
203+ p += 4;
204+ }
205+ printLog("tag -> %u\nlength -> %u\n", tag, length);
206+
207+ // tag == 0 終了タグ
208+ if(tag == 0) break;
209+
210+ // 画像の時の処理
211+ switch(tag) {
212+ case 6:
213+ if(length != 0) {
214+ storeImage(p + 2, length - 2, tagCount);
215+ }
216+ break;
217+ case 35:
218+ if(length != 0) {
219+ storeDefineBitsJPEG3(p, length, tagCount);
220+ }
221+ break;
222+ case 8:
223+ case 21:
224+ case 20:
225+ case 36:
226+ case 90:
227+ storeImage(p, length, tagCount);
228+ break;
229+ }
230+
231+ p += length;
232+ tagCount++;
233+
234+ if(tagCount > 200) {
235+ exit(-1);
236+ }
237+ }
238+
239+ printLog("tag Count -> %d\n", tagCount);
240+
15241 }
16242 return 0;
17243 }
244+