それでは始めましょう。
最初に必要なのは、カットライン付きの画像を表示するカスタム画像ビューです。
@interface MyImageView : NSImageView { int vSize; int hSize; } @property int vSize; @property int hSize; @end * This source code was highlighted with Source Code Highlighter .
@interface MyImageView : NSImageView { int vSize; int hSize; } @property int vSize; @property int hSize; @end * This source code was highlighted with Source Code Highlighter .
@interface MyImageView : NSImageView { int vSize; int hSize; } @property int vSize; @property int hSize; @end * This source code was highlighted with Source Code Highlighter .
@interface MyImageView : NSImageView { int vSize; int hSize; } @property int vSize; @property int hSize; @end * This source code was highlighted with Source Code Highlighter .
@interface MyImageView : NSImageView { int vSize; int hSize; } @property int vSize; @property int hSize; @end * This source code was highlighted with Source Code Highlighter .
@interface MyImageView : NSImageView { int vSize; int hSize; } @property int vSize; @property int hSize; @end * This source code was highlighted with Source Code Highlighter .
@interface MyImageView : NSImageView { int vSize; int hSize; } @property int vSize; @property int hSize; @end * This source code was highlighted with Source Code Highlighter .
@interface MyImageView : NSImageView { int vSize; int hSize; } @property int vSize; @property int hSize; @end * This source code was highlighted with Source Code Highlighter .
@interface MyImageView : NSImageView { int vSize; int hSize; } @property int vSize; @property int hSize; @end * This source code was highlighted with Source Code Highlighter .
@interface MyImageView : NSImageView { int vSize; int hSize; } @property int vSize; @property int hSize; @end * This source code was highlighted with Source Code Highlighter .
MyImageViewクラスのメソッドの実装に移りましょう。 メソッドの再定義-(id)initWithCoder:(NSCoder *)コーダーは、クラスのインスタンスの作成をカスタマイズします。
*このソースコードは、 ソースコードハイライターで強調表示されました。
- if (self = [super initWithCoder:coder])
- {
- [self setEditable:YES];
- hSize = 1;
- vSize = 1;
- }
- 自己を返す ;
次に、-(void)drawRect:(NSRect)dirtyRectメソッドを再定義して、カットラインを表示します。
*このソースコードは、 ソースコードハイライターで強調表示されました。
- [super drawRect:dirtyRect];
- NSImage * img = [自己画像];
- CGContextRef context =(CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
- NSRect selfRect = [自己境界];
- if (!img)
- {
- static NSString * idleText = @ "ここに画像をドラッグするだけ!" ;
- NSFont * myFont = [NSFont fontWithName: @ "Arial"サイズ:16];
- NSMutableParagraphStyle * ps = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
- [ps setAlignment:NSCenterTextAlignment];
- NSDictionary * attsDict = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSColor blackColor]、NSForegroundColorAttributeName、
- myFont、NSFontAttributeName、
- nil];
- NSSize textSize = [idleText sizeWithAttributes:attsDict];
- [idleText drawAtPoint:NSMakePoint((selfRect.size.width-textSize.width)/ 2、(selfRect.size.height-textSize.height)/ 2)withAttributes:attsDict];
- 帰る
- }
- //スライスの正しい描画線のアスペクト比を計算します
- float aspectRatioImg = [imgサイズ] .width / [imgサイズ] .height;
- float aspectRatioView = selfRect.size.width / selfRect.size.height;
- NSRect scaledRect = selfRect;
- if (aspectRatioImg> aspectRatioView)
- {
- scaledRect.size.height = scaledRect.size.width / aspectRatioImg;
- scaledRect.origin.y =(selfRect.size.height-scaledRect.size.height)/ 2;
- }
- 他に
- {
- scaledRect.size.width = scaledRect.size.height * aspectRatioImg;
- scaledRect.origin.x =(selfRect.size.width-scaledRect.size.width)/ 2;
- }
- //線の色と幅を設定します
- CGContextSetRGBStrokeColor(コンテキスト、1.f、1.f、0.f、1.f);
- CGContextSetLineWidth(コンテキスト、1.f);
- //線を引きます
- CGContextBeginPath(コンテキスト);
- //縦線
- for ( int i = 1; i <hSize; i ++)
- {
- int x = scaledRect.origin.x + i * scaledRect.size.width / hSize;
- CGContextMoveToPoint(context、x、scaledRect.origin.y);
- CGContextAddLineToPoint(context、x、scaledRect.origin.y + scaledRect.size.height);
- }
- //水平線
- for ( int j = 1; j <vSize; j ++)
- {
- int y = scaledRect.origin.y + j * scaledRect.size.height / vSize;
- CGContextMoveToPoint(context、scaledRect.origin.x、y);
- CGContextAddLineToPoint(context、scaledRect.origin.x + scaledRect.size.width、y);
- }
- CGContextClosePath(コンテキスト);
- CGContextStrokePath(コンテキスト);
すべてのプロパティに対して合成を処方することを忘れないでください!
大きな画像をすばやくカットするには、特にMacOS Xがこのための多くのツールを提供するため、アプリケーションをマルチスレッドにします。 NSOperationクラスを使用します。これは、MacOS Xでバージョン10.5以降に登場しました。 NSOperation-マルチスレッドは簡単なことではありません。
NSOperationの下位クラスを作成し、-mainメソッドをオーバーライドします。 操作の開始時に呼び出されます。 クラスインターフェイス:
*このソースコードは、 ソースコードハイライターで強調表示されました。
- @interface ImageSliceOperation:NSOperation
- {
- NSImage * image; //大きな画像
- NSRect rect; //スライスの長方形
- NSURL * url; //スライスを保存するURL
- }
- -(id)initWithImage:(NSImage *)anImage rect:(NSRect)aRect url:(NSURL *)anUrl;
- -( void )メイン;
- @end
そして、クラスの実装:
*このソースコードは、 ソースコードハイライターで強調表示されました。
- @implementation ImageSliceOperation
- -(id)initWithImage:(NSImage *)anImage rect:(NSRect)aRect url:(NSURL *)anUrl
- {
- self = [super init];
- if (self)
- {
- image = [anImage retain];
- rect = aRect;
- url = [anUrl copy];
- }
- 自己を返す ;
- }
- -( void )メイン
- {
- NSImage * target = [[NSImage alloc] initWithSize:NSMakeSize(rect.size.width、rect.size.height)];
- [ターゲットlockFocus];
- [image drawInRect:NSMakeRect(0,0、rect.size.width、rect.size.height)
- fromRect:rect
- 操作:NSCompositeCopy
- 分数:1.0];
- [ターゲットunlockFocus];
- NSData * imageData = [ターゲットTIFFRepresentation];
- NSBitmapImageRep * imageRep = [NSBitmapImageRep imageRepWithData:imageData];
- NSDictionary * imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:1.0] forKey:NSImageCompressionFactor];
- imageData = [imageRep representationUsingType:NSJPEGFileTypeプロパティ:imageProps];
- //ファイルにデータを書き込みます
- [imageData writeToURL:url atomically:NO];
- [対象リリース];
- }
- -( void )dealloc
- {
- [画像リリース];
- [URLリリース];
- [super dealloc];
- }
- @end
ここで、MainViewクラスを作成します。
*このソースコードは、 ソースコードハイライターで強調表示されました。
- @interface MainView:NSView
- {
- IBOutlet MyImageView * imageView;
- IBOutlet NSTextField * hPartsLabel;
- IBOutlet NSTextField * vPartsLabel;
- IBOutlet NSButton * startButton;
- IBOutlet NSProgressIndicator * progressIndicator;
- NSOperationQueue *キュー;
- }
- -(IBAction)startButtonPressed:(id)sender;
- //スライダーをラベルにバインドします
- -(IBAction)hPartsSliderMoved:(id)sender;
- -(IBAction)vPartsSliderMoved:(id)sender;
- -( void )splitImage:(NSArray *)anArray;
- @end
*このソースコードは、 ソースコードハイライターで強調表示されました。
- @implementation MainView
- -(id)initWithCoder:(NSCoder *)コーダー
- {
- self = [super initWithCoder:coder];
- if (self)
- {
- queue = [[NSOperationQueue alloc] init];
- [キューsetMaxConcurrentOperationCount:4];
- }
- 自己を返す ;
- }
- -(IBAction)startButtonPressed:(id)送信者
- {
- if (![imageView image])
- {
- NSAlert * alert = [[NSAlert alloc] init];
- [アラートaddButtonWithTitle: @ "OK" ];
- [アラートsetMessageText: @ "エラー!" ];
- [アラートsetInformativeText: @ "事前にファイルを開く必要があります。" ];
- [アラートsetAlertStyle:NSCriticalAlertStyle];
- [アラートrunModal];
- [アラートリリース];
- 帰る
- }
- NSOpenPanel * saveDlg = [NSOpenPanel openPanel]; //宛先を選択します
- [saveDlg setCanCreateDirectories:YES];
- [saveDlg setCanChooseDirectories:YES];
- [saveDlg setCanChooseFiles:NO];
- int result = [saveDlg runModal];
- if (結果== NSOKButton)
- {
- NSURL * dirURL = [saveDlg directoryURL];
- NSArray * argArray = [NSArray arrayWithObjects:dirURL、
- [imageView image]、
- [NSNumber numberWithInt:[vPartsLabel intValue]]、
- [NSNumber numberWithInt:[hPartsLabel intValue]]、
- nil];
- [NSThread detachNewThreadSelector:@selector(splitImage :) toTarget:self withObject:argArray];
- }
- }
- -(IBAction)hPartsSliderMoved:(id)sender
- {
- int val = [sender intValue];
- [hPartsLabel setStringValue:[NSString stringWithFormat: @ "%i" 、val]];
- imageView.hSize = val;
- [imageView setNeedsDisplay:YES];
- }
- -(IBAction)vPartsSliderMoved:(id)送信者
- {
- int val = [sender intValue];
- [vPartsLabel setStringValue:[NSString stringWithFormat: @ "%i" 、val]];
- imageView.vSize = val;
- [imageView setNeedsDisplay:YES];
- }
- -( void )splitImage:(NSArray *)anArray // 0-リンク先URL; 1-画像。 2-vParts; 3-hParts
- {
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- [startButton setEnabled:NO];
- [progressIndicator setUsesThreadedAnimation:YES];
- [progressIndicator startAnimation:self];
- NSURL * anUrl = [anArray objectAtIndex:0];
- NSImage * anImage = [anArray objectAtIndex:1];
- int vParts = [[anArray objectAtIndex:2] intValue];
- int hParts = [[anArray objectAtIndex:3] intValue];
- int imgW = [anImage size] .width;
- int imgH = [anImage size] .height;
- int partW = imgW / hParts;
- int partH = imgH / vParts;
- for ( int i = 0; i <hParts; i ++)
- {
- for ( int j = 0; j <vParts; j ++)
- {
- int currentX = partW * i;
- int currentY = imgH-partH *(j + 1);
- NSRect rect = NSMakeRect(currentX、currentY、partW、partH);
- NSString * fileName = [NSString stringWithFormat: @ "%i_%i.jpg" 、i、j];
- NSURL * fileURL = [NSURL URLWithString:fileName relativeToURL:anUrl];
- ImageSliceOperation * op = [[ImageSliceOperation alloc] initWithImage:anImage rect:rect url:fileURL];
- [キューaddOperation:op];
- [opリリース];
- }
- }
- [キューwaitUntilAllOperationsAreFinished];
- [progressIndicator stopAnimation:self];
- [startButton setEnabled:YES];
- [プールリリース];
- }
- @end
splitImageメソッド:別のスレッドで呼び出され、インターフェイスがフリーズするのを防ぎます。 このメソッドは、ImageSliceOperationを作成してキューに追加し、メインアクションの実行中に進行状況インジケーターも表示します。
コードを記述する最後の手順は、アプリケーションデリゲートを作成することです。
*このソースコードは、 ソースコードハイライターで強調表示されました。
- @implementation iPictureSplitterAppDelegate
- -( void )applicationDidFinishLaunching:(NSNotification *)aNotification
- {
- //カスタム初期化用
- }
- -(IBAction)showAboutPanel:(id)sender
- {
- [aboutpanel orderfront:self];
- }
- @end
ユーティリティはほぼ準備完了です。 Interface Builderドキュメントを作成し、ウィンドウを作成し、その上にUI要素を配置し、それらをクラスのアウトレットに関連付けるだけです。
結果は次のようになります。
プロジェクトのソースコードはこちらからダウンロードできます 。