From aaa244b52c02c12570c2f940e7067e0e3e3648a6 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Mon, 25 Apr 2011 15:22:27 +0400 Subject: [PATCH 01/40] Added tilesInfo to TileOperation. --- TileOperation.h | 11 ++++++++++- TileOperation.m | 20 +++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/TileOperation.h b/TileOperation.h index 611c612..b26f5f2 100644 --- a/TileOperation.h +++ b/TileOperation.h @@ -20,7 +20,7 @@ @interface TileOperation : NSOperation { - + } @property (assign) NSObject *delegate; @property (retain) NSBitmapImageRep *imageRep; @@ -29,4 +29,13 @@ @property NSUInteger tileHeight; @property NSUInteger tileWidth; @property TileCutterOutputPrefs outputFormat; + +/* array of tiles info, + * each item = NSDictionary { + * NSString *name - output filename of tile + * NSString from CGRect of that tile in source Image + */ +@property (readwrite, retain)NSMutableArray *tilesInfo; + + @end diff --git a/TileOperation.m b/TileOperation.m index 9110351..b58a1b2 100644 --- a/TileOperation.m +++ b/TileOperation.m @@ -13,6 +13,7 @@ @implementation TileOperation @synthesize delegate, imageRep, row, baseFilename, tileHeight, tileWidth, outputFormat; +@synthesize tilesInfo; #pragma mark - - (void)informDelegateOfError:(NSString *)message { @@ -65,9 +66,14 @@ - (void)main extension = @"jpg"; fileType = NSJPEGFileType; break; - } + } + // Get Tile Count for this Operation int tileColCount = [imageRep columnsWithTileWidth:tileWidth]; + + // Create tilesInfo Array for holding this Operation Tiles Info + self.tilesInfo = [NSMutableArray arrayWithCapacity: tileColCount]; + for (int column = 0; column < tileColCount; column++) { NSImage *subImage = [imageRep subImageWithTileWidth:(float)tileWidth tileHeight:(float)tileHeight column:column row:row]; @@ -98,6 +104,17 @@ - (void)main NSString *outPath = [NSString stringWithFormat:@"%@_%d_%d.%@", baseFilename, row, column, extension]; [bitmapData writeToFile:outPath atomically:YES]; + + // Add created Tile Info to tilesInfo array + NSRect tileRect = NSRectFromCGRect( CGRectMake(column * tileWidth, + row * tileHeight, + tileWidth, + tileHeight)); + NSDictionary *tileInfoDict = [NSDictionary dictionaryWithObjectsAndKeys: + [outPath lastPathComponent], @"Name", + NSStringFromRect(tileRect), @"Rect", + nil]; + [(NSMutableArray *)self.tilesInfo addObject: tileInfoDict ]; if ([delegate respondsToSelector:@selector(operationDidFinishTile:)]) [delegate performSelectorOnMainThread:@selector(operationDidFinishTile:) @@ -124,6 +141,7 @@ - (void)dealloc delegate = nil; [imageRep release], imageRep = nil; [baseFilename release], baseFilename = nil; + self.tilesInfo = nil; [super dealloc]; } From 9a4c068117e606af8a2b7d079126b78da10205c1 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Mon, 25 Apr 2011 15:38:09 +0400 Subject: [PATCH 02/40] Added allTilesInfo, that holds info about all tiles from last save. --- Tile_CutterAppDelegate.h | 2 ++ Tile_CutterAppDelegate.m | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/Tile_CutterAppDelegate.h b/Tile_CutterAppDelegate.h index 596a057..f2f6dd4 100644 --- a/Tile_CutterAppDelegate.h +++ b/Tile_CutterAppDelegate.h @@ -25,6 +25,8 @@ @property (retain) IBOutlet NSString *baseFilename; @property (nonatomic, retain) NSOperationQueue *queue; +@property(readwrite, retain) NSArray *allTilesInfo; + - (IBAction)saveButtonPressed:(id)sender; - (IBAction)openSelected:(id)sender; @end diff --git a/Tile_CutterAppDelegate.m b/Tile_CutterAppDelegate.m index f901c2a..fd2674a 100644 --- a/Tile_CutterAppDelegate.m +++ b/Tile_CutterAppDelegate.m @@ -28,6 +28,7 @@ - (void)delayAlert:(NSString *)message; @implementation Tile_CutterAppDelegate @synthesize window, tileCutterView, widthTextField, heightTextField, rowBar, columnBar, progressWindow, progressLabel, baseFilename, queue; +@synthesize allTilesInfo; - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename { @@ -78,6 +79,8 @@ - (void)saveThread tileRowCount = [image rowsWithTileHeight:tileHeight]; tileColCount = [image columnsWithTileWidth:tileWidth]; + + self.allTilesInfo = [NSMutableArray arrayWithCapacity: tileRowCount * tileColCount]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; TileCutterOutputPrefs outputFormat = (TileCutterOutputPrefs)[defaults integerForKey:@"OutputFormat"]; @@ -161,6 +164,7 @@ - (IBAction)openSelected:(id)sender } - (void)dealloc { + self.allTilesInfo = nil; [columnBar release], columnBar = nil; [rowBar release], rowBar = nil; [progressWindow release], progressWindow = nil; @@ -195,6 +199,8 @@ - (void)operationDidFinishTile:(TileOperation *)op // [progressLabel setStringValue:[NSString stringWithFormat:@"Processing row %d, column %d", progressRow, progressCol]]; [self performSelectorOnMainThread:@selector(updateProgress) withObject:nil waitUntilDone:NO]; + + [(NSMutableArray *)self.allTilesInfo addObjectsFromArray: op.tilesInfo]; } - (void)delayAlert:(NSString *)message { From 6b02814bbe5ec123d6dced03d7268474e16767c7 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Mon, 25 Apr 2011 15:49:23 +0400 Subject: [PATCH 03/40] Added autosaving plist file. A lot of duplicates now. --- Tile_CutterAppDelegate.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tile_CutterAppDelegate.m b/Tile_CutterAppDelegate.m index fd2674a..d300f3f 100644 --- a/Tile_CutterAppDelegate.m +++ b/Tile_CutterAppDelegate.m @@ -177,7 +177,10 @@ - (void)dealloc - (void)updateProgress { if (progressRow >= tileRowCount) + { + [self.allTilesInfo writeToFile:[NSString stringWithFormat:@"%@.plist", baseFilename] atomically:YES]; [NSApp endSheet:progressWindow]; + } // [rowBar setDoubleValue:(double)progressRow]; // [columnBar setDoubleValue:(double)progressCol]; From 44cac0ffcd94ef79c341eb78bce938c37b9b0b56 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Mon, 25 Apr 2011 15:59:12 +0400 Subject: [PATCH 04/40] Fixed duplicates in Plist file. --- Tile_CutterAppDelegate.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Tile_CutterAppDelegate.m b/Tile_CutterAppDelegate.m index d300f3f..90c83d9 100644 --- a/Tile_CutterAppDelegate.m +++ b/Tile_CutterAppDelegate.m @@ -202,9 +202,14 @@ - (void)operationDidFinishTile:(TileOperation *)op // [progressLabel setStringValue:[NSString stringWithFormat:@"Processing row %d, column %d", progressRow, progressCol]]; [self performSelectorOnMainThread:@selector(updateProgress) withObject:nil waitUntilDone:NO]; - +} + +- (void)operationDidFinishSuccessfully:(TileOperation *)op +{ [(NSMutableArray *)self.allTilesInfo addObjectsFromArray: op.tilesInfo]; + op.tilesInfo = nil; } + - (void)delayAlert:(NSString *)message { NSAlert *alert = [[[NSAlert alloc] init] autorelease]; From 7020f53520bdb347783b2bd708aa5b1b0b0d5e26 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Tue, 26 Apr 2011 16:23:42 +0400 Subject: [PATCH 05/40] Fixed PLIST output size for any source Image Sizes. --- TileOperation.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TileOperation.m b/TileOperation.m index b58a1b2..97991f0 100644 --- a/TileOperation.m +++ b/TileOperation.m @@ -108,8 +108,8 @@ - (void)main // Add created Tile Info to tilesInfo array NSRect tileRect = NSRectFromCGRect( CGRectMake(column * tileWidth, row * tileHeight, - tileWidth, - tileHeight)); + [subImage size].width, + [subImage size].height)); NSDictionary *tileInfoDict = [NSDictionary dictionaryWithObjectsAndKeys: [outPath lastPathComponent], @"Name", NSStringFromRect(tileRect), @"Rect", From 04f443fa4c50f2d7075a8b07501f36f489a784ca Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Tue, 26 Apr 2011 16:54:07 +0400 Subject: [PATCH 06/40] Added 'Skip Transparent Tiles' checkbox to main View. --- English.lproj/MainMenu.xib | 700 +++++++++++++++++++++++++++++++++++-- TileCutterView.h | 1 + TileCutterView.m | 1 + 3 files changed, 675 insertions(+), 27 deletions(-) diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index de94f31..ba952d9 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -2,7 +2,7 @@ 1060 - 10H574 + 10J869 823 1038.35 461.00 @@ -12,10 +12,10 @@ YES - - + - + + YES @@ -1224,7 +1224,7 @@ 13 2 - {{142, 445}, {524, 431}} + {{142, 420}, {524, 456}} 1948778496 Tile Cutter NSWindow @@ -1239,7 +1239,7 @@ 292 - {{20, 17}, {48, 22}} + {{20, 42}, {48, 22}} YES YES @@ -1346,7 +1346,7 @@ 292 - {{73, 22}, {12, 17}} + {{73, 47}, {12, 17}} YES @@ -1375,7 +1375,7 @@ 292 - {{90, 17}, {48, 22}} + {{90, 42}, {48, 22}} YES YES @@ -1441,7 +1441,7 @@ 289 - {{441, 11}, {69, 32}} + {{441, 36}, {69, 32}} YES @@ -1468,7 +1468,7 @@ NSColor pasteboard type - {{395, 16}, {44, 23}} + {{395, 41}, {44, 23}} YES YES @@ -1480,7 +1480,7 @@ 289 - {{307, 20}, {83, 17}} + {{307, 45}, {83, 17}} YES @@ -1508,7 +1508,7 @@ NeXT TIFF v4.0 pasteboard type - {{20, 47}, {484, 367}} + {{20, 72}, {484, 367}} YES @@ -1524,7 +1524,7 @@ 289 - {{195, 20}, {103, 18}} + {{195, 45}, {103, 18}} YES @@ -1535,11 +1535,11 @@ 1211912703 2 - + NSImage NSSwitch - + NSSwitch @@ -1548,8 +1548,30 @@ 25 + + + 289 + {{195, 25}, {194, 18}} + + YES + + -2080244224 + 0 + Skip Transparent Tiles + + + 1211912703 + 2 + + + + + 200 + 25 + + - {524, 431} + {524, 456} {{0, 0}, {1920, 1058}} @@ -1561,6 +1583,10 @@ NSFontManager + + YES + skipTransparentTiles + YES @@ -2683,6 +2709,30 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 647 + + + valueChanged: + + + + 654 + + + + value: values.skipTransparentTiles + + + + + + value: values.skipTransparentTiles + value + values.skipTransparentTiles + 2 + + + 656 + @@ -3175,6 +3225,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + @@ -3906,6 +3957,20 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + + 652 + + + YES + + + + + + 653 + + + @@ -4178,6 +4243,9 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 610.IBPluginDependency 612.IBPluginDependency 639.IBViewBoundsToFrameTransform + 652.IBPluginDependency + 652.IBViewBoundsToFrameTransform + 653.IBPluginDependency 72.IBPluginDependency 72.ImportedFromIB2 79.IBPluginDependency @@ -4290,7 +4358,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA com.apple.InterfaceBuilder.CocoaPlugin {{525, 802}, {197, 73}} - {{194, 943}, {441, 20}} + {{839, 736}, {441, 20}} com.apple.InterfaceBuilder.CocoaPlugin {74, 862} @@ -4315,10 +4383,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA com.apple.InterfaceBuilder.CocoaPlugin - {{753, 18}, {524, 431}} + {{354, 165}, {524, 456}} com.apple.InterfaceBuilder.CocoaPlugin - {{753, 18}, {524, 431}} + {{354, 165}, {524, 456}} {{33, 99}, {480, 360}} @@ -4450,31 +4518,31 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA com.apple.InterfaceBuilder.CocoaPlugin - P4AAAL+AAABDEAAAwbAAAA + P4AAAL+AAABDQwAAwnQAAA com.apple.InterfaceBuilder.CocoaPlugin - {{206, 760}, {207, 183}} + {{851, 553}, {207, 183}} com.apple.InterfaceBuilder.CocoaPlugin {{23, 794}, {245, 183}} - {{588, 803}, {456, 105}} + {{824, 651}, {456, 105}} com.apple.InterfaceBuilder.CocoaPlugin - {{588, 803}, {456, 105}} + {{824, 651}, {456, 105}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{201, 522}, {310, 176}} + {{329, 522}, {310, 176}} com.apple.InterfaceBuilder.CocoaPlugin - {{201, 522}, {310, 176}} + {{329, 522}, {310, 176}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - P4AAAL+AAABBkAAAwuAAAA + P4AAAL+AAABB0AAAwuAAAA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -4482,6 +4550,11 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA AUHIAABB0AAAA com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDEAAAwbAAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -4513,7 +4586,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - 647 + 656 @@ -4539,6 +4612,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA guideCheckbox guideColorWell saveButton + skipCheckbox tileHeightField tileWidthField @@ -4547,6 +4621,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSButton NSColorWell NSButton + NSButton NSTextField NSTextField @@ -4558,6 +4633,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA guideCheckbox guideColorWell saveButton + skipCheckbox tileHeightField tileWidthField @@ -4575,6 +4651,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA saveButton NSButton + + skipCheckbox + NSButton + tileHeightField NSTextField @@ -4712,6 +4792,572 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + + YES + + NSActionCell + NSCell + + IBFrameworkSource + AppKit.framework/Headers/NSActionCell.h + + + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSBox + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSBox.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSButton + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSButton.h + + + + NSButtonCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSButtonCell.h + + + + NSCell + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSCell.h + + + + NSColorWell + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSColorWell.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSController + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSController.h + + + + NSFontManager + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSImageCell + NSCell + + IBFrameworkSource + AppKit.framework/Headers/NSImageCell.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSNumberFormatter + NSFormatter + + IBFrameworkSource + Foundation.framework/Headers/NSNumberFormatter.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSProgressIndicator + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSProgressIndicator.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSString + + + + NSString + + IBFrameworkSource + AppKit.framework/Headers/NSStringDrawing.h + + + + NSString + + IBFrameworkSource + Foundation.framework/Headers/NSPathUtilities.h + + + + NSString + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSString.h + + + + NSString + + + + NSTableView + NSControl + + + + NSText + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSTextField + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSTextField.h + + + + NSTextFieldCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSTextFieldCell.h + + + + NSTextView + NSText + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSUserDefaultsController + NSController + + IBFrameworkSource + AppKit.framework/Headers/NSUserDefaultsController.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + 0 IBCocoaFramework diff --git a/TileCutterView.h b/TileCutterView.h index 4264348..14a7202 100644 --- a/TileCutterView.h +++ b/TileCutterView.h @@ -19,6 +19,7 @@ @property (nonatomic, retain) IBOutlet NSColorWell *guideColorWell; @property (nonatomic, retain) NSImage *image; @property (nonatomic, retain) IBOutlet NSButton *guideCheckbox; +@property (nonatomic, retain) IBOutlet NSButton *skipCheckbox; @property (nonatomic, retain) IBOutlet NSButton *saveButton; - (IBAction) valueChanged:(id)sender; @end diff --git a/TileCutterView.m b/TileCutterView.m index a9f827b..65e0300 100644 --- a/TileCutterView.m +++ b/TileCutterView.m @@ -11,6 +11,7 @@ @implementation TileCutterView @synthesize filename, tileWidthField, tileHeightField, guideColorWell, image, guideCheckbox, saveButton; +@synthesize skipCheckbox; - (id)initWithFrame:(NSRect)frame { From b14320bb7e137190cdabb19196bd8cb61fa659fd Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Tue, 26 Apr 2011 16:54:57 +0400 Subject: [PATCH 07/40] Added skipTransparentTiles property to tile Operation. --- TileOperation.h | 1 + TileOperation.m | 1 + Tile_CutterAppDelegate.m | 1 + 3 files changed, 3 insertions(+) diff --git a/TileOperation.h b/TileOperation.h index b26f5f2..6e97b39 100644 --- a/TileOperation.h +++ b/TileOperation.h @@ -29,6 +29,7 @@ @property NSUInteger tileHeight; @property NSUInteger tileWidth; @property TileCutterOutputPrefs outputFormat; +@property (readwrite) BOOL skipTransparentTiles; /* array of tiles info, * each item = NSDictionary { diff --git a/TileOperation.m b/TileOperation.m index 97991f0..ffac6b8 100644 --- a/TileOperation.m +++ b/TileOperation.m @@ -14,6 +14,7 @@ @implementation TileOperation @synthesize delegate, imageRep, row, baseFilename, tileHeight, tileWidth, outputFormat; @synthesize tilesInfo; +@synthesize skipTransparentTiles; #pragma mark - - (void)informDelegateOfError:(NSString *)message { diff --git a/Tile_CutterAppDelegate.m b/Tile_CutterAppDelegate.m index 90c83d9..a6d24c9 100644 --- a/Tile_CutterAppDelegate.m +++ b/Tile_CutterAppDelegate.m @@ -96,6 +96,7 @@ - (void)saveThread op.baseFilename = baseFilename; op.delegate = self; op.outputFormat = outputFormat; + op.skipTransparentTiles = ( [tileCutterView.skipCheckbox intValue] != 0 ) ? YES : NO; [queue addOperation:op]; [op release]; } From 24de796bfa3fcf83cf29368d390fd816d0cfe477 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Tue, 26 Apr 2011 17:24:01 +0400 Subject: [PATCH 08/40] Fixed skip checkbox binding. --- English.lproj/MainMenu.xib | 88 +++++++++++++++++++++----------------- Tile_CutterAppDelegate.m | 5 ++- 2 files changed, 52 insertions(+), 41 deletions(-) diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index ba952d9..1d65f2f 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -1535,11 +1535,11 @@ 1211912703 2 - + NSImage NSSwitch - + NSSwitch @@ -1548,22 +1548,22 @@ 25 - + 289 {{195, 25}, {194, 18}} YES - + -2080244224 0 Skip Transparent Tiles - + 1211912703 2 - - + + 200 @@ -2713,17 +2713,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA valueChanged: - + 654 value: values.skipTransparentTiles - + - + value: values.skipTransparentTiles value @@ -2733,6 +2733,14 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 656 + + + skipCheckbox + + + + 657 + @@ -3225,7 +3233,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - + @@ -3959,17 +3967,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 652 - + YES - + 653 - - + + @@ -4383,10 +4391,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA com.apple.InterfaceBuilder.CocoaPlugin - {{354, 165}, {524, 456}} + {{420, -31}, {524, 456}} com.apple.InterfaceBuilder.CocoaPlugin - {{354, 165}, {524, 456}} + {{420, -31}, {524, 456}} {{33, 99}, {480, 360}} @@ -4586,7 +4594,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - 656 + 657 @@ -4805,21 +4813,21 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSApplication NSResponder - + IBFrameworkSource AppKit.framework/Headers/NSApplication.h NSApplication - + IBFrameworkSource AppKit.framework/Headers/NSApplicationScripting.h NSApplication - + IBFrameworkSource AppKit.framework/Headers/NSColorPanel.h @@ -4896,7 +4904,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSControl NSView - + IBFrameworkSource AppKit.framework/Headers/NSControl.h @@ -4912,7 +4920,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSFontManager NSObject - + IBFrameworkSource AppKit.framework/Headers/NSFontManager.h @@ -4944,7 +4952,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSMenu NSObject - + IBFrameworkSource AppKit.framework/Headers/NSMenu.h @@ -4952,7 +4960,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSMenuItem NSObject - + IBFrameworkSource AppKit.framework/Headers/NSMenuItem.h @@ -4982,19 +4990,19 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSObject - + NSObject - + NSObject - + NSObject - + NSObject @@ -5012,7 +5020,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSObject - + NSObject @@ -5030,7 +5038,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSObject - + NSObject @@ -5048,7 +5056,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSObject - + IBFrameworkSource AppKit.framework/Headers/NSPasteboard.h @@ -5062,7 +5070,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSObject - + IBFrameworkSource AppKit.framework/Headers/NSTableView.h @@ -5076,7 +5084,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSObject - + IBFrameworkSource AppKit.framework/Headers/NSView.h @@ -5195,7 +5203,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSObject - + IBFrameworkSource Foundation.framework/Headers/NSURL.h @@ -5239,7 +5247,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSString - + NSString @@ -5265,12 +5273,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSString - + NSTableView NSControl - + NSText @@ -5321,7 +5329,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSView - + NSView @@ -5333,7 +5341,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSView NSResponder - + NSWindow diff --git a/Tile_CutterAppDelegate.m b/Tile_CutterAppDelegate.m index a6d24c9..e284bb0 100644 --- a/Tile_CutterAppDelegate.m +++ b/Tile_CutterAppDelegate.m @@ -96,7 +96,10 @@ - (void)saveThread op.baseFilename = baseFilename; op.delegate = self; op.outputFormat = outputFormat; - op.skipTransparentTiles = ( [tileCutterView.skipCheckbox intValue] != 0 ) ? YES : NO; + if (![tileCutterView.skipCheckbox intValue]) + op.skipTransparentTiles = NO; + else + op.skipTransparentTiles = YES; [queue addOperation:op]; [op release]; } From 3c939cd7a4dee4f6fb9c3d0bed23a9b5dc5e69ff Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Tue, 26 Apr 2011 18:11:39 +0400 Subject: [PATCH 09/40] Added isAbsoluteTransparent method to NSBitmapImageRep --- TileOperation.m | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/TileOperation.m b/TileOperation.m index ffac6b8..1858095 100644 --- a/TileOperation.m +++ b/TileOperation.m @@ -11,6 +11,35 @@ #import "NSInvocation-MCUtilities.h" #import "NSBitmapImageRep-Tile.h" +@interface NSBitmapImageRep (Extension) + +- (BOOL) isAbsoluteTransparent; + +@end + +@implementation NSBitmapImageRep (Extension) + +- (BOOL) isAbsoluteTransparent +{ + NSSize s = [self size]; + + for (int i = 0; i < s.width; ++i) + { + for (int j = 0; j < s.height; ++j) + { + NSColor *col = [self colorAtX:i y:j]; + + if ([col alphaComponent] != 0.0f) + return NO; + } + } + + return YES; +} + +@end + + @implementation TileOperation @synthesize delegate, imageRep, row, baseFilename, tileHeight, tileWidth, outputFormat; @synthesize tilesInfo; From e211bdeaf0fba2d0e88c253374dfdf4a82cd95ee Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Tue, 26 Apr 2011 18:12:34 +0400 Subject: [PATCH 10/40] Added transparent tiles analyzed save if skipTransparentTiles is set --- TileOperation.m | 67 +++++++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/TileOperation.m b/TileOperation.m index 1858095..645aaca 100644 --- a/TileOperation.m +++ b/TileOperation.m @@ -114,37 +114,50 @@ - (void)main goto finish; } - NSArray * representations = [subImage representations]; - - if ([self isCancelled]) - goto finish; - - NSData *bitmapData = [NSBitmapImageRep representationOfImageRepsInArray:representations - usingType:fileType properties:nil]; - - if (bitmapData == nil) - { - [self informDelegateOfError:NSLocalizedString(@"Error retrieving bitmap data from result", @"")]; - goto finish; - } - - + NSArray * representations = [subImage representations]; + NSBitmapImageRep *subBitmapRep = nil; + if ( [representations count] ) + subBitmapRep = [representations objectAtIndex: 0]; + if ([self isCancelled]) goto finish; - NSString *outPath = [NSString stringWithFormat:@"%@_%d_%d.%@", baseFilename, row, column, extension]; - [bitmapData writeToFile:outPath atomically:YES]; - // Add created Tile Info to tilesInfo array - NSRect tileRect = NSRectFromCGRect( CGRectMake(column * tileWidth, - row * tileHeight, - [subImage size].width, - [subImage size].height)); - NSDictionary *tileInfoDict = [NSDictionary dictionaryWithObjectsAndKeys: - [outPath lastPathComponent], @"Name", - NSStringFromRect(tileRect), @"Rect", - nil]; - [(NSMutableArray *)self.tilesInfo addObject: tileInfoDict ]; + + // Analyze do we need this tile saved + BOOL curTileNeeded = ! (self.skipTransparentTiles && [subBitmapRep isAbsoluteTransparent]); + + // save if yes + if ( curTileNeeded ) + { + NSData *bitmapData = [NSBitmapImageRep representationOfImageRepsInArray:representations + usingType:fileType properties:nil]; + + + if (bitmapData == nil) + { + [self informDelegateOfError:NSLocalizedString(@"Error retrieving bitmap data from result", @"")]; + goto finish; + } + + + if ([self isCancelled]) + goto finish; + + NSString *outPath = [NSString stringWithFormat:@"%@_%d_%d.%@", baseFilename, row, column, extension]; + [bitmapData writeToFile:outPath atomically:YES]; + + // Add created Tile Info to tilesInfo array + NSRect tileRect = NSRectFromCGRect( CGRectMake(column * tileWidth, + row * tileHeight, + [subImage size].width, + [subImage size].height)); + NSDictionary *tileInfoDict = [NSDictionary dictionaryWithObjectsAndKeys: + [outPath lastPathComponent], @"Name", + NSStringFromRect(tileRect), @"Rect", + nil]; + [(NSMutableArray *)self.tilesInfo addObject: tileInfoDict ]; + } if ([delegate respondsToSelector:@selector(operationDidFinishTile:)]) [delegate performSelectorOnMainThread:@selector(operationDidFinishTile:) From aa2efb73f04ff1dbe1821ae6f5e1f2b22d9e6b85 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Wed, 27 Apr 2011 14:25:44 +0400 Subject: [PATCH 11/40] Added source image info to the Plist output. --- Tile_CutterAppDelegate.h | 1 + Tile_CutterAppDelegate.m | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Tile_CutterAppDelegate.h b/Tile_CutterAppDelegate.h index f2f6dd4..8fcf196 100644 --- a/Tile_CutterAppDelegate.h +++ b/Tile_CutterAppDelegate.h @@ -26,6 +26,7 @@ @property (nonatomic, retain) NSOperationQueue *queue; @property(readwrite, retain) NSArray *allTilesInfo; +@property(readwrite, retain) NSDictionary *imageInfo; - (IBAction)saveButtonPressed:(id)sender; - (IBAction)openSelected:(id)sender; diff --git a/Tile_CutterAppDelegate.m b/Tile_CutterAppDelegate.m index e284bb0..f907b82 100644 --- a/Tile_CutterAppDelegate.m +++ b/Tile_CutterAppDelegate.m @@ -29,6 +29,7 @@ @implementation Tile_CutterAppDelegate @synthesize window, tileCutterView, widthTextField, heightTextField, rowBar, columnBar, progressWindow, progressLabel, baseFilename, queue; @synthesize allTilesInfo; +@synthesize imageInfo; - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename { @@ -80,6 +81,10 @@ - (void)saveThread tileRowCount = [image rowsWithTileHeight:tileHeight]; tileColCount = [image columnsWithTileWidth:tileWidth]; + self.imageInfo = [NSDictionary dictionaryWithObjectsAndKeys: + [tileCutterView.filename lastPathComponent], @"Filename", + NSStringFromSize([image size]), @"Size", nil]; + self.allTilesInfo = [NSMutableArray arrayWithCapacity: tileRowCount * tileColCount]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; @@ -182,7 +187,11 @@ - (void)updateProgress { if (progressRow >= tileRowCount) { - [self.allTilesInfo writeToFile:[NSString stringWithFormat:@"%@.plist", baseFilename] atomically:YES]; + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: + self.imageInfo, @"Source", + self.allTilesInfo, @"Tiles", nil]; + + [dict writeToFile:[NSString stringWithFormat:@"%@.plist", baseFilename] atomically:YES]; [NSApp endSheet:progressWindow]; } From 758b8e2ec80840b00ec498a4f0bc6dd0d559c525 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 19:48:07 +0400 Subject: [PATCH 12/40] Added commandLine tool target --- Tile Cutter.xcodeproj/project.pbxproj | 92 +++++++++++++++++ cmdToolMain.m | 141 ++++++++++++++++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 cmdToolMain.m diff --git a/Tile Cutter.xcodeproj/project.pbxproj b/Tile Cutter.xcodeproj/project.pbxproj index e1c5075..dfb08d9 100644 --- a/Tile Cutter.xcodeproj/project.pbxproj +++ b/Tile Cutter.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 1FFB9979127C874900BE5A73 /* NSInvocation-MCUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FFB9978127C874900BE5A73 /* NSInvocation-MCUtilities.m */; }; 1FFB9A18127CAD9F00BE5A73 /* NSBitmapImageRep-Tile.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FFB9A17127CAD9F00BE5A73 /* NSBitmapImageRep-Tile.m */; }; 256AC3DA0F4B6AC300CF3369 /* Tile_CutterAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 256AC3D90F4B6AC300CF3369 /* Tile_CutterAppDelegate.m */; }; + 6DA78C0D1369BEE1000EA884 /* cmdToolMain.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DA78C0C1369BEE1000EA884 /* cmdToolMain.m */; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; @@ -47,11 +48,20 @@ 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 6DA78C071369BEB0000EA884 /* tileCutter */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tileCutter; sourceTree = BUILT_PRODUCTS_DIR; }; + 6DA78C0C1369BEE1000EA884 /* cmdToolMain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = cmdToolMain.m; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Tile_Cutter-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Tile_Cutter-Info.plist"; sourceTree = ""; }; 8D1107320486CEB800E47090 /* Tile Cutter.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Tile Cutter.app"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 6DA78C051369BEB0000EA884 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8D11072E0486CEB800E47090 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -106,6 +116,7 @@ isa = PBXGroup; children = ( 8D1107320486CEB800E47090 /* Tile Cutter.app */, + 6DA78C071369BEB0000EA884 /* tileCutter */, ); name = Products; sourceTree = ""; @@ -127,6 +138,7 @@ children = ( 256AC3F00F4B6AF500CF3369 /* Tile_Cutter_Prefix.pch */, 29B97316FDCFA39411CA2CEA /* main.m */, + 6DA78C0C1369BEE1000EA884 /* cmdToolMain.m */, ); name = "Other Sources"; sourceTree = ""; @@ -155,6 +167,22 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 6DA78C061369BEB0000EA884 /* tileCutter */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6DA78C0B1369BECE000EA884 /* Build configuration list for PBXNativeTarget "tileCutter" */; + buildPhases = ( + 6DA78C041369BEB0000EA884 /* Sources */, + 6DA78C051369BEB0000EA884 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = tileCutter; + productName = tileCutter; + productReference = 6DA78C071369BEB0000EA884 /* tileCutter */; + productType = "com.apple.product-type.tool"; + }; 8D1107260486CEB800E47090 /* Tile Cutter */ = { isa = PBXNativeTarget; buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Tile Cutter" */; @@ -193,6 +221,7 @@ projectRoot = ""; targets = ( 8D1107260486CEB800E47090 /* Tile Cutter */, + 6DA78C061369BEB0000EA884 /* tileCutter */, ); }; /* End PBXProject section */ @@ -212,6 +241,14 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 6DA78C041369BEB0000EA884 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6DA78C0D1369BEE1000EA884 /* cmdToolMain.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8D11072C0486CEB800E47090 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -249,6 +286,52 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 6DA78C091369BEB0000EA884 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INSTALL_PATH = /usr/local/bin; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = tileCutter; + }; + name = Debug; + }; + 6DA78C0A1369BEB0000EA884 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INSTALL_PATH = /usr/local/bin; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = tileCutter; + ZERO_LINK = NO; + }; + name = Release; + }; C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -326,6 +409,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 6DA78C0B1369BECE000EA884 /* Build configuration list for PBXNativeTarget "tileCutter" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6DA78C091369BEB0000EA884 /* Debug */, + 6DA78C0A1369BEB0000EA884 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Tile Cutter" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/cmdToolMain.m b/cmdToolMain.m new file mode 100644 index 0000000..93b9df8 --- /dev/null +++ b/cmdToolMain.m @@ -0,0 +1,141 @@ +// +// cmdToolMain.m +// Tile Cutter +// +// Created by Stepan Generalov on 28.04.11. +// Copyright 2011 __MyCompanyName__. All rights reserved. +// + +#import + +#import +#import +#import + +void printUsageAndExit() +{ + printf("\nUsage: tileCutter [keepTransparentTiles] --tileWidth WIDTH --tileHeight HEIGHT\ +--inputFile INPUT.PNG --outputFile OUTPUT [--outputSuffix SUFFIX]\n\ +HEIGHT & WIDTH should be >= 1\n\ +output tiles file names will be in this format:\n\ +OUTPUT_X_Y-SUFFIX.png,\n\ +where X & Y is tile number\n\ +Output plist file will be:\n\ +OUTPUT.plist"); + exit(0); +} + +int main(int argc, char *argv[]) +{ + // Options Storage + int keepAllTiles = 0; + NSUInteger tileWidth = 0; + NSUInteger tileHeight = 0; + NSString *inputFilename = nil; + NSString *outputBaseFilename = nil; + NSString *outputSuffix = nil; + + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + + int c; + + if (argc <= 1) + { + [pool release]; + printUsageAndExit(); + } + + while (1) + { + struct option long_options[] = + { + /* These options set a flag. */ + {"skipTransparentTiles", no_argument, &keepAllTiles, 0}, + {"keepTransparentTiles", no_argument, &keepAllTiles, 1}, + /* These options don't set a flag. + We distinguish them by their indices. */ + {"tileWidth", required_argument, 0, 'w'}, + {"tileHeight", required_argument, 0, 'h'}, + {"inputFile", required_argument, 0, 'i'}, + {"outputFile", required_argument, 0, 'o'}, + {"outputSuffix", required_argument, 0, 's'}, + {0, 0, 0, 0} + }; + /* getopt_long stores the option index here. */ + int option_index = 0; + + c = getopt_long (argc, argv, "w:h:i:o:s:", + long_options, &option_index); + + /* Detect the end of the options. */ + if (c == -1) + break; + + switch (c) + { + case 0: + /* If this option set a flag, do nothing else now. */ + if (long_options[option_index].flag != 0) + break; + + // if this is unkown option - print usage and exit + [pool release]; + printUsageAndExit(); + + break; + + case 'w': + tileWidth = (NSUInteger)[[NSString stringWithCString: optarg encoding: NSUTF8StringEncoding] intValue]; + if (!tileWidth) + { + [pool release]; + printUsageAndExit(); + } + break; + + case 'h': + tileHeight = (NSUInteger)[[NSString stringWithCString: optarg encoding: NSUTF8StringEncoding] intValue]; + if (!tileHeight) + { + [pool release]; + printUsageAndExit(); + } + break; + + case 'i': + inputFilename = [NSString stringWithCString: optarg encoding: NSUTF8StringEncoding]; + break; + + case 'o': + outputBaseFilename = [NSString stringWithCString:optarg encoding: NSUTF8StringEncoding]; + break; + + case 's': + outputSuffix = [NSString stringWithCString:optarg encoding: NSUTF8StringEncoding]; + break; + + case '?': + /* getopt_long already printed an error message. */ + [pool release]; + printUsageAndExit(); + break; + + default: + abort (); + } + } + + + // We don't accept any nonOptions cmd line arguments + if (optind < argc) + { + [pool release]; + printUsageAndExit(); + } + + //TODO: process command line request + + [pool release]; + return 0; +} + From 83693bceac9a9aa76256abeafc7c1b5d8822fa2c Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 20:33:49 +0400 Subject: [PATCH 13/40] Moved Tiling Logics to TileCutterCore --- Tile Cutter.xcodeproj/project.pbxproj | 8 +++ TileCutterCore.h | 43 ++++++++++++ TileCutterCore.m | 97 +++++++++++++++++++++++++++ TileOperation.h | 1 + Tile_CutterAppDelegate.h | 6 +- Tile_CutterAppDelegate.m | 62 ++++++----------- 6 files changed, 173 insertions(+), 44 deletions(-) create mode 100644 TileCutterCore.h create mode 100644 TileCutterCore.m diff --git a/Tile Cutter.xcodeproj/project.pbxproj b/Tile Cutter.xcodeproj/project.pbxproj index dfb08d9..703513b 100644 --- a/Tile Cutter.xcodeproj/project.pbxproj +++ b/Tile Cutter.xcodeproj/project.pbxproj @@ -18,6 +18,8 @@ 1FFB9A18127CAD9F00BE5A73 /* NSBitmapImageRep-Tile.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FFB9A17127CAD9F00BE5A73 /* NSBitmapImageRep-Tile.m */; }; 256AC3DA0F4B6AC300CF3369 /* Tile_CutterAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 256AC3D90F4B6AC300CF3369 /* Tile_CutterAppDelegate.m */; }; 6DA78C0D1369BEE1000EA884 /* cmdToolMain.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DA78C0C1369BEE1000EA884 /* cmdToolMain.m */; }; + 6DA78C431369C5FE000EA884 /* TileCutterCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DA78C421369C5FE000EA884 /* TileCutterCore.m */; }; + 6DA78C441369C5FE000EA884 /* TileCutterCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DA78C421369C5FE000EA884 /* TileCutterCore.m */; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; @@ -50,6 +52,8 @@ 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 6DA78C071369BEB0000EA884 /* tileCutter */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tileCutter; sourceTree = BUILT_PRODUCTS_DIR; }; 6DA78C0C1369BEE1000EA884 /* cmdToolMain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = cmdToolMain.m; sourceTree = ""; }; + 6DA78C411369C5FE000EA884 /* TileCutterCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TileCutterCore.h; sourceTree = ""; }; + 6DA78C421369C5FE000EA884 /* TileCutterCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TileCutterCore.m; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Tile_Cutter-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Tile_Cutter-Info.plist"; sourceTree = ""; }; 8D1107320486CEB800E47090 /* Tile Cutter.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Tile Cutter.app"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -90,6 +94,8 @@ 1FFB9940127C847100BE5A73 /* TileOperation.m */, 1FFB9A16127CAD9F00BE5A73 /* NSBitmapImageRep-Tile.h */, 1FFB9A17127CAD9F00BE5A73 /* NSBitmapImageRep-Tile.m */, + 6DA78C411369C5FE000EA884 /* TileCutterCore.h */, + 6DA78C421369C5FE000EA884 /* TileCutterCore.m */, ); name = Classes; sourceTree = ""; @@ -246,6 +252,7 @@ buildActionMask = 2147483647; files = ( 6DA78C0D1369BEE1000EA884 /* cmdToolMain.m in Sources */, + 6DA78C431369C5FE000EA884 /* TileCutterCore.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -261,6 +268,7 @@ 1FFB9941127C847100BE5A73 /* TileOperation.m in Sources */, 1FFB9979127C874900BE5A73 /* NSInvocation-MCUtilities.m in Sources */, 1FFB9A18127CAD9F00BE5A73 /* NSBitmapImageRep-Tile.m in Sources */, + 6DA78C441369C5FE000EA884 /* TileCutterCore.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/TileCutterCore.h b/TileCutterCore.h new file mode 100644 index 0000000..0f9cc49 --- /dev/null +++ b/TileCutterCore.h @@ -0,0 +1,43 @@ +// +// TileCutterCore.h +// Tile Cutter +// +// Created by Stepan Generalov on 28.04.11. +// Copyright 2011 __MyCompanyName__. All rights reserved. +// + +#import +#import "TileOperation.h" + + +@interface TileCutterCore : NSObject +{} + +#pragma mark Public Properties + +// Properties of Tiling Operation +@property(readwrite) BOOL keepAllTiles; +@property(readwrite) NSUInteger tileWidth; +@property(readwrite) NSUInteger tileHeight; +@property(readwrite) TileCutterOutputPrefs outputFormat; +@property(readwrite, copy) NSString *inputFilename; +@property(readwrite, copy) NSString *outputBaseFilename; +@property(readwrite, copy) NSString *outputSuffix; + +// TileOperationDelegate messages will be forwarded after processing to this delegate +@property(readwrite, assign) id operationsDelegate; + +#pragma mark Public Methods + +- (void) startSavingTiles; + +#pragma mark Private Properties + +// Queue of Operations - used internally +@property(nonatomic, retain) NSOperationQueue *queue; + +// Info, prepared for output.plist - used internally +@property(readwrite, retain) NSArray *allTilesInfo; +@property(readwrite, retain) NSDictionary *imageInfo; + +@end diff --git a/TileCutterCore.m b/TileCutterCore.m new file mode 100644 index 0000000..8b1c938 --- /dev/null +++ b/TileCutterCore.m @@ -0,0 +1,97 @@ +// +// TileCutterCore.m +// Tile Cutter +// +// Created by Stepan Generalov on 28.04.11. +// Copyright 2011 __MyCompanyName__. All rights reserved. +// + +#import "TileCutterCore.h" + +@implementation TileCutterCore + +@synthesize keepAllTiles, tileWidth, tileHeight, inputFilename, + outputBaseFilename, outputSuffix, operationsDelegate, + queue, allTilesInfo, imageInfo, outputFormat; + +#pragma mark Public Methods + +- (id) init +{ + if ( (self == [super init]) ) + { + self.queue = [[[NSOperationQueue alloc] init] autorelease]; + self.outputFormat = NSPNGFileType; + self.outputSuffix = @""; + self.keepAllTiles = NO; + } +} + +- (void) dealloc +{ + self.queue = nil; + self.allTilesInfo = nil; + self.imageInfo = nil; + + [super dealloc]; +} + +- (void) startSavingTiles +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSImage *image = [[[NSImage alloc] initWithContentsOfFile: self.inputFilename] autorelease]; + + progressCol = 0; + progressRow = 0; + + tileRowCount = [image rowsWithTileHeight: self.tileHeight]; + tileColCount = [image columnsWithTileWidth: self.tileWidth]; + + self.imageInfo = [NSDictionary dictionaryWithObjectsAndKeys: + [self.inputFilename lastPathComponent], @"Filename", + NSStringFromSize([image size]), @"Size", nil]; + + self.allTilesInfo = [NSMutableArray arrayWithCapacity: tileRowCount * tileColCount]; + + for (int row = 0; row < tileRowCount; row++) + { + // Each row operation gets its own ImageRep to avoid contention + NSBitmapImageRep *imageRep = [[[NSBitmapImageRep alloc] initWithCGImage:[image CGImageForProposedRect:NULL context:NULL hints:nil]] autorelease]; + TileOperation *op = [[TileOperation alloc] init]; + op.row = row; + op.tileWidth = self.tileWidth; + op.tileHeight = self.tileHeight; + op.imageRep = imageRep; + op.baseFilename = outputBaseFilename; + op.delegate = self; + op.outputFormat = self.outputFormat; + op.skipTransparentTiles = (! self.keepAllTiles ); + [queue addOperation:op]; + [op release]; + } + + [pool drain]; +} + +- (void)operationDidFinishTile:(TileOperation *)op +{ + [self.delegate performSelector: _cmd withObject: op]; +} + +- (void)operationDidFinishSuccessfully:(TileOperation *)op +{ + [(NSMutableArray *)self.allTilesInfo addObjectsFromArray: op.tilesInfo]; + op.tilesInfo = nil; + + [self.delegate performSelector: _cmd withObject: op]; +} + + +- (void)operation:(TileOperation *)op didFailWithMessage:(NSString *)message +{ + [self.delegate performSelector: _cmd withObject: op]; +} + + +@end diff --git a/TileOperation.h b/TileOperation.h index 6e97b39..60d9521 100644 --- a/TileOperation.h +++ b/TileOperation.h @@ -7,6 +7,7 @@ // #import +//TODO: add suffix property @class TileOperation; diff --git a/Tile_CutterAppDelegate.h b/Tile_CutterAppDelegate.h index 8fcf196..e54af56 100644 --- a/Tile_CutterAppDelegate.h +++ b/Tile_CutterAppDelegate.h @@ -7,7 +7,7 @@ // #import -#import "TileOperation.h" +#import "TileCutterCore.h" @class TileCutterView; @interface Tile_CutterAppDelegate : NSObject @@ -23,10 +23,8 @@ @property (retain) IBOutlet NSWindow *progressWindow; @property (retain) IBOutlet NSTextField *progressLabel; @property (retain) IBOutlet NSString *baseFilename; -@property (nonatomic, retain) NSOperationQueue *queue; -@property(readwrite, retain) NSArray *allTilesInfo; -@property(readwrite, retain) NSDictionary *imageInfo; +@property (retain) TileCutterCore *tileCore; - (IBAction)saveButtonPressed:(id)sender; - (IBAction)openSelected:(id)sender; diff --git a/Tile_CutterAppDelegate.m b/Tile_CutterAppDelegate.m index f907b82..6d9f992 100644 --- a/Tile_CutterAppDelegate.m +++ b/Tile_CutterAppDelegate.m @@ -57,16 +57,17 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification [defaults setInteger:200 forKey:@"heightField"]; } - self.queue = [[[NSOperationQueue alloc] init] autorelease]; + self.tileCore = [TileCutterCore new]; + self.tileCore.delegate = self; } + - (void)saveThread { NSLog(@"Save thread started"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSImage *image = [[[NSImage alloc] initWithContentsOfFile:tileCutterView.filename] autorelease]; - - [rowBar setIndeterminate:NO]; + // Prepare GUI + [rowBar setIndeterminate:NO]; [columnBar setIndeterminate:NO]; [rowBar setMaxValue:(double)[image rowsWithTileHeight:[heightTextField floatValue]]]; [rowBar setMinValue:0.]; @@ -74,43 +75,24 @@ - (void)saveThread [columnBar setMinValue:0.]; [columnBar setMaxValue:(double)[image columnsWithTileWidth:[widthTextField floatValue]]]; [columnBar setDoubleValue:0.]; - - progressCol = 0; - progressRow = 0; - - tileRowCount = [image rowsWithTileHeight:tileHeight]; - tileColCount = [image columnsWithTileWidth:tileWidth]; - self.imageInfo = [NSDictionary dictionaryWithObjectsAndKeys: - [tileCutterView.filename lastPathComponent], @"Filename", - NSStringFromSize([image size]), @"Size", nil]; + // Setup Tile Core + self.tileCore.inputFilename = tileCutterView.filename + self.tileCore.tileWidth = tileWidth; + self.tileCore.tileHeight = tileHeight; + self.tileCore.outputFormat = (TileCutterOutputPrefs)[[NSUserDefaults standardUserDefaults] integerForKey:@"OutputFormat"]; + self.tileCore.outputBaseFilename = baseFilename; + if (![tileCutterView.skipCheckbox intValue]) + self.tileCore.keepAllTiles = YES; + else + self.tileCore.keepAllTiles = NO; - self.allTilesInfo = [NSMutableArray arrayWithCapacity: tileRowCount * tileColCount]; - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - TileCutterOutputPrefs outputFormat = (TileCutterOutputPrefs)[defaults integerForKey:@"OutputFormat"]; - for (int row = 0; row < tileRowCount; row++) - { - // Each row operation gets its own ImageRep to avoid contention - NSBitmapImageRep *imageRep = [[[NSBitmapImageRep alloc] initWithCGImage:[image CGImageForProposedRect:NULL context:NULL hints:nil]] autorelease]; - TileOperation *op = [[TileOperation alloc] init]; - op.row = row; - op.tileWidth = tileWidth; - op.tileHeight = tileHeight; - op.imageRep = imageRep; - op.baseFilename = baseFilename; - op.delegate = self; - op.outputFormat = outputFormat; - if (![tileCutterView.skipCheckbox intValue]) - op.skipTransparentTiles = NO; - else - op.skipTransparentTiles = YES; - [queue addOperation:op]; - [op release]; - } + // Start Tiling + [self.tileCore startSavingTiles]; [pool drain]; } + - (IBAction)saveButtonPressed:(id)sender { NSSavePanel *sp = [NSSavePanel savePanel]; @@ -152,6 +134,7 @@ - (void)delayPresentSheet //[queue setSuspended:YES]; [self performSelectorInBackground:@selector(saveThread) withObject:nil]; } + - (void)didEndSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { [sheet orderOut:self]; @@ -173,13 +156,12 @@ - (IBAction)openSelected:(id)sender } - (void)dealloc { - self.allTilesInfo = nil; + self.tileCore = nil; [columnBar release], columnBar = nil; [rowBar release], rowBar = nil; [progressWindow release], progressWindow = nil; [progressLabel release], progressLabel = nil; [baseFilename release], baseFilename = nil; - [queue release], queue = nil; [super dealloc]; } #pragma mark - @@ -219,8 +201,7 @@ - (void)operationDidFinishTile:(TileOperation *)op - (void)operationDidFinishSuccessfully:(TileOperation *)op { - [(NSMutableArray *)self.allTilesInfo addObjectsFromArray: op.tilesInfo]; - op.tilesInfo = nil; + } - (void)delayAlert:(NSString *)message @@ -232,6 +213,7 @@ - (void)delayAlert:(NSString *)message [alert setAlertStyle:NSCriticalAlertStyle]; [alert beginSheetModalForWindow:[self window] modalDelegate:nil didEndSelector:nil contextInfo:nil]; } + - (void)operation:(TileOperation *)op didFailWithMessage:(NSString *)message { [NSApp endSheet:progressWindow]; From 0d199836490c4a44480166df45a05ab3be329b9f Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 20:47:35 +0400 Subject: [PATCH 14/40] Moved more stuff to TileCutterCore. AppDelegate compiles OK --- TileCutterCore.h | 6 +++++ TileCutterCore.m | 16 ++++++++++++++ Tile_CutterAppDelegate.m | 47 +++++++++------------------------------- 3 files changed, 32 insertions(+), 37 deletions(-) diff --git a/TileCutterCore.h b/TileCutterCore.h index 0f9cc49..554c8b8 100644 --- a/TileCutterCore.h +++ b/TileCutterCore.h @@ -24,6 +24,12 @@ @property(readwrite, copy) NSString *outputBaseFilename; @property(readwrite, copy) NSString *outputSuffix; +// Properties of Global Tiling Operation Status +@property(readwrite) int tileRowCount; +@property(readwrite) int tileColCount; +@property(readwrite) int progressCol; +@property(readwrite) int progressRow; + // TileOperationDelegate messages will be forwarded after processing to this delegate @property(readwrite, assign) id operationsDelegate; diff --git a/TileCutterCore.m b/TileCutterCore.m index 8b1c938..2092c71 100644 --- a/TileCutterCore.m +++ b/TileCutterCore.m @@ -76,6 +76,22 @@ - (void) startSavingTiles - (void)operationDidFinishTile:(TileOperation *)op { + progressCol++; + if (progressCol >= tileColCount) + { + progressCol = 0; + progressRow++; + } + + if (progressRow >= tileRowCount) + { + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: + self.imageInfo, @"Source", + self.allTilesInfo, @"Tiles", nil]; + + [dict writeToFile:[NSString stringWithFormat:@"%@.plist", baseFilename] atomically:YES]; + } + [self.delegate performSelector: _cmd withObject: op]; } diff --git a/Tile_CutterAppDelegate.m b/Tile_CutterAppDelegate.m index 6d9f992..ca48cb3 100644 --- a/Tile_CutterAppDelegate.m +++ b/Tile_CutterAppDelegate.m @@ -16,20 +16,15 @@ @interface Tile_CutterAppDelegate() -{ - int tileHeight, tileWidth; - int tileRowCount, tileColCount; - int progressCol, progressRow; -} + - (void)delayAlert:(NSString *)message; + @end @implementation Tile_CutterAppDelegate -@synthesize window, tileCutterView, widthTextField, heightTextField, rowBar, columnBar, progressWindow, progressLabel, baseFilename, queue; -@synthesize allTilesInfo; -@synthesize imageInfo; +@synthesize window, tileCutterView, widthTextField, heightTextField, rowBar, columnBar, progressWindow, progressLabel, baseFilename; - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename { @@ -58,7 +53,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification } self.tileCore = [TileCutterCore new]; - self.tileCore.delegate = self; + self.tileCore.operationsDelegate = self; } - (void)saveThread @@ -66,20 +61,9 @@ - (void)saveThread NSLog(@"Save thread started"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - // Prepare GUI - [rowBar setIndeterminate:NO]; - [columnBar setIndeterminate:NO]; - [rowBar setMaxValue:(double)[image rowsWithTileHeight:[heightTextField floatValue]]]; - [rowBar setMinValue:0.]; - [rowBar setDoubleValue:0.]; - [columnBar setMinValue:0.]; - [columnBar setMaxValue:(double)[image columnsWithTileWidth:[widthTextField floatValue]]]; - [columnBar setDoubleValue:0.]; // Setup Tile Core - self.tileCore.inputFilename = tileCutterView.filename - self.tileCore.tileWidth = tileWidth; - self.tileCore.tileHeight = tileHeight; + self.tileCore.inputFilename = tileCutterView.filename; self.tileCore.outputFormat = (TileCutterOutputPrefs)[[NSUserDefaults standardUserDefaults] integerForKey:@"OutputFormat"]; self.tileCore.outputBaseFilename = baseFilename; if (![tileCutterView.skipCheckbox intValue]) @@ -111,8 +95,8 @@ -(void)didEndSaveSheet:(NSSavePanel *)savePanel if (returnCode == NSOKButton) { self.baseFilename = [[savePanel filename] stringByDeletingPathExtension]; - tileHeight = [heightTextField intValue]; - tileWidth = [widthTextField intValue]; + self.tileCore.tileHeight = [heightTextField intValue]; + self.tileCore.tileWidth = [widthTextField intValue]; [self performSelector:@selector(delayPresentSheet) withObject:nil afterDelay:0.1]; } @@ -167,29 +151,18 @@ - (void)dealloc #pragma mark - - (void)updateProgress { - if (progressRow >= tileRowCount) + if (self.tileCore.progressRow >= self.tileCore.tileRowCount) { - NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: - self.imageInfo, @"Source", - self.allTilesInfo, @"Tiles", nil]; - - [dict writeToFile:[NSString stringWithFormat:@"%@.plist", baseFilename] atomically:YES]; [NSApp endSheet:progressWindow]; } // [rowBar setDoubleValue:(double)progressRow]; // [columnBar setDoubleValue:(double)progressCol]; - [progressLabel setStringValue:[NSString stringWithFormat:@"Processing row %d, column %d", progressRow, progressCol]]; + [progressLabel setStringValue:[NSString stringWithFormat:@"Processing row %d, column %d", self.tileCore.progressRow, self.tileCore.progressCol]]; } - (void)operationDidFinishTile:(TileOperation *)op { - progressCol++; - if (progressCol >= tileColCount) - { - progressCol = 0; - progressRow++; - } - if (progressRow >= tileRowCount) + if (self.tileCore.progressRow >= self.tileCore.tileRowCount) [NSApp endSheet:progressWindow]; // [rowBar setDoubleValue:(double)progressRow]; From 6b207ff85ddd50540690799c21b496a08e1d45ce Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 21:25:56 +0400 Subject: [PATCH 15/40] Fixed compiler errors & warnings --- TileCutterCore.h | 2 +- TileCutterCore.m | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/TileCutterCore.h b/TileCutterCore.h index 554c8b8..e7df96b 100644 --- a/TileCutterCore.h +++ b/TileCutterCore.h @@ -31,7 +31,7 @@ @property(readwrite) int progressRow; // TileOperationDelegate messages will be forwarded after processing to this delegate -@property(readwrite, assign) id operationsDelegate; +@property(readwrite, assign) NSObject *operationsDelegate; #pragma mark Public Methods diff --git a/TileCutterCore.m b/TileCutterCore.m index 2092c71..6e68bad 100644 --- a/TileCutterCore.m +++ b/TileCutterCore.m @@ -7,6 +7,7 @@ // #import "TileCutterCore.h" +#import "NSImage-Tile.h" @implementation TileCutterCore @@ -25,6 +26,8 @@ - (id) init self.outputSuffix = @""; self.keepAllTiles = NO; } + + return self; } - (void) dealloc @@ -89,24 +92,25 @@ - (void)operationDidFinishTile:(TileOperation *)op self.imageInfo, @"Source", self.allTilesInfo, @"Tiles", nil]; - [dict writeToFile:[NSString stringWithFormat:@"%@.plist", baseFilename] atomically:YES]; + [dict writeToFile:[NSString stringWithFormat:@"%@.plist", self.outputBaseFilename] atomically:YES]; } - [self.delegate performSelector: _cmd withObject: op]; + [self.operationsDelegate performSelector: _cmd withObject: op]; } - (void)operationDidFinishSuccessfully:(TileOperation *)op { + [(NSMutableArray *)self.allTilesInfo addObjectsFromArray: op.tilesInfo]; op.tilesInfo = nil; - [self.delegate performSelector: _cmd withObject: op]; + [self.operationsDelegate performSelector: _cmd withObject: op]; } - (void)operation:(TileOperation *)op didFailWithMessage:(NSString *)message { - [self.delegate performSelector: _cmd withObject: op]; + [self.operationsDelegate performSelector: _cmd withObject: op]; } From 1b7e674e568714e6660278a3485f1d37291c43b9 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 21:35:34 +0400 Subject: [PATCH 16/40] Added outputSuffix to tileOperation --- TileCutterCore.m | 1 + TileOperation.h | 2 +- TileOperation.m | 8 +++++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/TileCutterCore.m b/TileCutterCore.m index 6e68bad..61d4d03 100644 --- a/TileCutterCore.m +++ b/TileCutterCore.m @@ -69,6 +69,7 @@ - (void) startSavingTiles op.baseFilename = outputBaseFilename; op.delegate = self; op.outputFormat = self.outputFormat; + op.outputSuffix = self.outputSuffix; op.skipTransparentTiles = (! self.keepAllTiles ); [queue addOperation:op]; [op release]; diff --git a/TileOperation.h b/TileOperation.h index 60d9521..96e1b33 100644 --- a/TileOperation.h +++ b/TileOperation.h @@ -7,7 +7,6 @@ // #import -//TODO: add suffix property @class TileOperation; @@ -27,6 +26,7 @@ @property (retain) NSBitmapImageRep *imageRep; @property NSUInteger row; @property (retain) NSString *baseFilename; +@property (readwrite, copy) NSString *outputSuffix; @property NSUInteger tileHeight; @property NSUInteger tileWidth; @property TileCutterOutputPrefs outputFormat; diff --git a/TileOperation.m b/TileOperation.m index 645aaca..63fa34d 100644 --- a/TileOperation.m +++ b/TileOperation.m @@ -44,6 +44,7 @@ @implementation TileOperation @synthesize delegate, imageRep, row, baseFilename, tileHeight, tileWidth, outputFormat; @synthesize tilesInfo; @synthesize skipTransparentTiles; +@synthesize outputSuffix; #pragma mark - - (void)informDelegateOfError:(NSString *)message { @@ -104,6 +105,10 @@ - (void)main // Create tilesInfo Array for holding this Operation Tiles Info self.tilesInfo = [NSMutableArray arrayWithCapacity: tileColCount]; + // Safe Empty Suffix + if (!self.outputSuffix) + self.outputSuffix = @""; + for (int column = 0; column < tileColCount; column++) { NSImage *subImage = [imageRep subImageWithTileWidth:(float)tileWidth tileHeight:(float)tileHeight column:column row:row]; @@ -144,7 +149,7 @@ - (void)main if ([self isCancelled]) goto finish; - NSString *outPath = [NSString stringWithFormat:@"%@_%d_%d.%@", baseFilename, row, column, extension]; + NSString *outPath = [NSString stringWithFormat:@"%@_%d_%d%@.%@", baseFilename, row, column, self.outputSuffix, extension]; [bitmapData writeToFile:outPath atomically:YES]; // Add created Tile Info to tilesInfo array @@ -181,6 +186,7 @@ - (void)main - (void)dealloc { + self.outputSuffix = nil; delegate = nil; [imageRep release], imageRep = nil; [baseFilename release], baseFilename = nil; From 3ff3b51758af598fe2e664b33bddc103e60a4f5b Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 21:36:05 +0400 Subject: [PATCH 17/40] Fixed possible memory leaks. --- TileCutterCore.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/TileCutterCore.m b/TileCutterCore.m index 61d4d03..10d9971 100644 --- a/TileCutterCore.m +++ b/TileCutterCore.m @@ -34,7 +34,10 @@ - (void) dealloc { self.queue = nil; self.allTilesInfo = nil; - self.imageInfo = nil; + self.imageInfo = nil; + self.inputFilename = nil; + self.outputBaseFilename = nil; + self.outputSuffix = nil; [super dealloc]; } From 1d3592206d9a70a549b77a8b48da0ef6b45cc96f Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 22:14:25 +0400 Subject: [PATCH 18/40] Added TileCutterCore use to cmdLineTool --- cmdToolMain.m | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/cmdToolMain.m b/cmdToolMain.m index 93b9df8..3182e3a 100644 --- a/cmdToolMain.m +++ b/cmdToolMain.m @@ -12,6 +12,8 @@ #import #import +#import "TileCutterCore.h" + void printUsageAndExit() { printf("\nUsage: tileCutter [keepTransparentTiles] --tileWidth WIDTH --tileHeight HEIGHT\ @@ -133,7 +135,18 @@ int main(int argc, char *argv[]) printUsageAndExit(); } - //TODO: process command line request + // Prepare Tile Cutter + TileCutterCore *tileCutterCore = [TileCutterCore new]; + tileCutterCore.inputFilename = inputFilename; + tileCutterCore.outputBaseFilename = outputBaseFilename; + tileCutterCore.outputSuffix = outputSuffix; + tileCutterCore.tileWidth = tileWidth; + tileCutterCore.tileHeight = tileWidth; + tileCutterCore.keepAllTiles = (keepAllTiles != 0); + + // Start Cutting and Wait for it. + [tileCutterCore startSavingTiles]; + [tileCutterCore.queue waitUntilAllOperationsAreFinished]; [pool release]; return 0; From 05dfdb7ec03272f44c50d98a064320f4e12b4aa5 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 22:18:04 +0400 Subject: [PATCH 19/40] Moved fileFormat enum to TileCutterSettings.h --- Tile Cutter.xcodeproj/project.pbxproj | 2 ++ TileCutterSettings.h | 19 +++++++++++++++++++ TileOperation.h | 1 + Tile_Cutter_Prefix.pch | 13 +------------ cmdToolMain.m | 1 + 5 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 TileCutterSettings.h diff --git a/Tile Cutter.xcodeproj/project.pbxproj b/Tile Cutter.xcodeproj/project.pbxproj index 703513b..8b00202 100644 --- a/Tile Cutter.xcodeproj/project.pbxproj +++ b/Tile Cutter.xcodeproj/project.pbxproj @@ -54,6 +54,7 @@ 6DA78C0C1369BEE1000EA884 /* cmdToolMain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = cmdToolMain.m; sourceTree = ""; }; 6DA78C411369C5FE000EA884 /* TileCutterCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TileCutterCore.h; sourceTree = ""; }; 6DA78C421369C5FE000EA884 /* TileCutterCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TileCutterCore.m; sourceTree = ""; }; + 6DA78CB51369E61A000EA884 /* TileCutterSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TileCutterSettings.h; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Tile_Cutter-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Tile_Cutter-Info.plist"; sourceTree = ""; }; 8D1107320486CEB800E47090 /* Tile Cutter.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Tile Cutter.app"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -80,6 +81,7 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( + 6DA78CB51369E61A000EA884 /* TileCutterSettings.h */, 1FFB9977127C874900BE5A73 /* NSInvocation-MCUtilities.h */, 1FFB9978127C874900BE5A73 /* NSInvocation-MCUtilities.m */, 256AC3D80F4B6AC300CF3369 /* Tile_CutterAppDelegate.h */, diff --git a/TileCutterSettings.h b/TileCutterSettings.h new file mode 100644 index 0000000..0dbbcf5 --- /dev/null +++ b/TileCutterSettings.h @@ -0,0 +1,19 @@ +// +// TileCutterSettings.h +// Tile Cutter +// +// Created by Stepan Generalov on 28.04.11. +// Copyright 2011 __MyCompanyName__. All rights reserved. +// + +#import + +typedef enum +{ + TileCutterOutputPrefsJPEG, + TileCutterOutputPrefsGIF, + TileCutterOutputPrefsTIFF, + TileCutterOutputPrefsBMP, + TileCutterOutputPrefsPNG, + TileCutterOutputPrefsJPEG2000 +} TileCutterOutputPrefs; \ No newline at end of file diff --git a/TileOperation.h b/TileOperation.h index 96e1b33..24a8dc1 100644 --- a/TileOperation.h +++ b/TileOperation.h @@ -7,6 +7,7 @@ // #import +#import "TileCutterSettings.h" @class TileOperation; diff --git a/Tile_Cutter_Prefix.pch b/Tile_Cutter_Prefix.pch index 21d7b6c..b4fbdc8 100644 --- a/Tile_Cutter_Prefix.pch +++ b/Tile_Cutter_Prefix.pch @@ -4,15 +4,4 @@ #ifdef __OBJC__ #import -#endif - - -typedef enum -{ - TileCutterOutputPrefsJPEG, - TileCutterOutputPrefsGIF, - TileCutterOutputPrefsTIFF, - TileCutterOutputPrefsBMP, - TileCutterOutputPrefsPNG, - TileCutterOutputPrefsJPEG2000 -} TileCutterOutputPrefs; \ No newline at end of file +#endif \ No newline at end of file diff --git a/cmdToolMain.m b/cmdToolMain.m index 3182e3a..2896043 100644 --- a/cmdToolMain.m +++ b/cmdToolMain.m @@ -13,6 +13,7 @@ #import #import "TileCutterCore.h" +#import "TileCutterSettings.h" void printUsageAndExit() { From 71f2b54ad56a452a2de9a770ece61931a7dc8e44 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 22:21:39 +0400 Subject: [PATCH 20/40] Assigned needed *.m files for cmd tool target. Builds OK --- Tile Cutter.xcodeproj/project.pbxproj | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Tile Cutter.xcodeproj/project.pbxproj b/Tile Cutter.xcodeproj/project.pbxproj index 8b00202..23e32c4 100644 --- a/Tile Cutter.xcodeproj/project.pbxproj +++ b/Tile Cutter.xcodeproj/project.pbxproj @@ -18,8 +18,12 @@ 1FFB9A18127CAD9F00BE5A73 /* NSBitmapImageRep-Tile.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FFB9A17127CAD9F00BE5A73 /* NSBitmapImageRep-Tile.m */; }; 256AC3DA0F4B6AC300CF3369 /* Tile_CutterAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 256AC3D90F4B6AC300CF3369 /* Tile_CutterAppDelegate.m */; }; 6DA78C0D1369BEE1000EA884 /* cmdToolMain.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DA78C0C1369BEE1000EA884 /* cmdToolMain.m */; }; - 6DA78C431369C5FE000EA884 /* TileCutterCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DA78C421369C5FE000EA884 /* TileCutterCore.m */; }; 6DA78C441369C5FE000EA884 /* TileCutterCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DA78C421369C5FE000EA884 /* TileCutterCore.m */; }; + 6DA78CD11369E71D000EA884 /* NSInvocation-MCUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FFB9978127C874900BE5A73 /* NSInvocation-MCUtilities.m */; }; + 6DA78CD21369E71D000EA884 /* NSImage-Tile.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F15EA19125E826600B32D97 /* NSImage-Tile.m */; }; + 6DA78CD41369E71D000EA884 /* NSBitmapImageRep-Tile.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FFB9A17127CAD9F00BE5A73 /* NSBitmapImageRep-Tile.m */; }; + 6DA78CD51369E71D000EA884 /* TileCutterCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DA78C421369C5FE000EA884 /* TileCutterCore.m */; }; + 6DA78CE11369E737000EA884 /* TileOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FFB9940127C847100BE5A73 /* TileOperation.m */; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; @@ -254,7 +258,11 @@ buildActionMask = 2147483647; files = ( 6DA78C0D1369BEE1000EA884 /* cmdToolMain.m in Sources */, - 6DA78C431369C5FE000EA884 /* TileCutterCore.m in Sources */, + 6DA78CD11369E71D000EA884 /* NSInvocation-MCUtilities.m in Sources */, + 6DA78CD21369E71D000EA884 /* NSImage-Tile.m in Sources */, + 6DA78CD41369E71D000EA884 /* NSBitmapImageRep-Tile.m in Sources */, + 6DA78CD51369E71D000EA884 /* TileCutterCore.m in Sources */, + 6DA78CE11369E737000EA884 /* TileOperation.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 5ad3b128bbbf84cb0b214e79a458e320d929f034 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 22:28:59 +0400 Subject: [PATCH 21/40] Little Usage Output fixes. --- cmdToolMain.m | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmdToolMain.m b/cmdToolMain.m index 2896043..dfe2e6d 100644 --- a/cmdToolMain.m +++ b/cmdToolMain.m @@ -17,14 +17,13 @@ void printUsageAndExit() { - printf("\nUsage: tileCutter [keepTransparentTiles] --tileWidth WIDTH --tileHeight HEIGHT\ + printf("\nUsage: tileCutter [--keepTransparentTiles] --tileWidth WIDTH --tileHeight HEIGHT \ --inputFile INPUT.PNG --outputFile OUTPUT [--outputSuffix SUFFIX]\n\ HEIGHT & WIDTH should be >= 1\n\ output tiles file names will be in this format:\n\ OUTPUT_X_Y-SUFFIX.png,\n\ where X & Y is tile number\n\ -Output plist file will be:\n\ -OUTPUT.plist"); +Output plist file will be: OUTPUT.plist\n"); exit(0); } From bfe4cf9fb3d823f393c9835d9971733604b97c1f Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 22:49:49 +0400 Subject: [PATCH 22/40] Moved threadSafety from TileOperation to TileCutterCore There was a problem in cmdLine tool - it didn't saved the plist file. Probably it was due to no performSelecterOnMainThread support in commandLine utility. Moving threadSafety checks from TileOperation to TileCutterCore delegate calls should make it possible for TileCutterCore work on single thread. --- TileCutterCore.m | 35 ++++++++++++++++++++++------------- TileOperation.m | 9 +++------ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/TileCutterCore.m b/TileCutterCore.m index 10d9971..5c27639 100644 --- a/TileCutterCore.m +++ b/TileCutterCore.m @@ -90,31 +90,40 @@ - (void)operationDidFinishTile:(TileOperation *)op progressRow++; } - if (progressRow >= tileRowCount) - { - NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: - self.imageInfo, @"Source", - self.allTilesInfo, @"Tiles", nil]; - - [dict writeToFile:[NSString stringWithFormat:@"%@.plist", self.outputBaseFilename] atomically:YES]; - } - - [self.operationsDelegate performSelector: _cmd withObject: op]; + if ([self.operationsDelegate respondsToSelector: _cmd]) + [self.operationsDelegate performSelectorOnMainThread: _cmd + withObject: op + waitUntilDone: NO]; } - (void)operationDidFinishSuccessfully:(TileOperation *)op { - [(NSMutableArray *)self.allTilesInfo addObjectsFromArray: op.tilesInfo]; op.tilesInfo = nil; - [self.operationsDelegate performSelector: _cmd withObject: op]; + // All Tiles Finished? + if (progressRow >= tileRowCount) + { + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: + self.imageInfo, @"Source", + self.allTilesInfo, @"Tiles", nil]; + + [dict writeToFile:[NSString stringWithFormat:@"%@.plist", self.outputBaseFilename] atomically:YES]; + } + + if ([self.operationsDelegate respondsToSelector: _cmd]) + [self.operationsDelegate performSelectorOnMainThread: _cmd + withObject: op + waitUntilDone: NO]; } - (void)operation:(TileOperation *)op didFailWithMessage:(NSString *)message { - [self.operationsDelegate performSelector: _cmd withObject: op]; + if ([self.operationsDelegate respondsToSelector: _cmd]) + [self.operationsDelegate performSelectorOnMainThread: _cmd + withObject: op + waitUntilDone: NO]; } diff --git a/TileOperation.m b/TileOperation.m index 63fa34d..17c47c3 100644 --- a/TileOperation.m +++ b/TileOperation.m @@ -165,16 +165,13 @@ - (void)main } if ([delegate respondsToSelector:@selector(operationDidFinishTile:)]) - [delegate performSelectorOnMainThread:@selector(operationDidFinishTile:) - withObject:self - waitUntilDone:NO]; + [delegate operationDidFinishTile: self]; } if ([delegate respondsToSelector:@selector(operationDidFinishSuccessfully:)]) - [delegate performSelectorOnMainThread:@selector(operationDidFinishSuccessfully:) - withObject:self - waitUntilDone:NO]; + [delegate operationDidFinishSuccessfully: self ]; + finish: [pool drain]; } From 2a5f3b2fd086ce8ba08661ec1e3e899cad6305cb Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 22:56:32 +0400 Subject: [PATCH 23/40] Added suffix to PLIST filename. --- TileCutterCore.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TileCutterCore.m b/TileCutterCore.m index 5c27639..0feb013 100644 --- a/TileCutterCore.m +++ b/TileCutterCore.m @@ -108,7 +108,7 @@ - (void)operationDidFinishSuccessfully:(TileOperation *)op self.imageInfo, @"Source", self.allTilesInfo, @"Tiles", nil]; - [dict writeToFile:[NSString stringWithFormat:@"%@.plist", self.outputBaseFilename] atomically:YES]; + [dict writeToFile:[NSString stringWithFormat:@"%@%@.plist", self.outputBaseFilename, self.outputSuffix] atomically:YES]; } if ([self.operationsDelegate respondsToSelector: _cmd]) From 1f18eed78d030dd6681d395d8b82e9b3f0ce5270 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 23:25:31 +0400 Subject: [PATCH 24/40] Updated README --- README | 1 - README.md | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) delete mode 100644 README create mode 100644 README.md diff --git a/README b/README deleted file mode 100644 index 4814bf5..0000000 --- a/README +++ /dev/null @@ -1 +0,0 @@ -Tile Cutter is an open source under the non-viral MIT license. Tile Cutter will take a large image and split it up into smaller tiles. I created this for use in a CATiledLayer-backed view for an iPad application, but it could be used for a number of other purposes. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..cde6f98 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +Tile-Cutter (by Jeff LaMarche) +================= + +Tile Cutter is an open source under the non-viral MIT license. +Tile Cutter will take a large image and split it up into smaller tiles. I created this for use in a CATiledLayer-backed view for an iPad application, but it could be used for a number of other purposes. + + +This Fork (by Stepan Generalov) +================ + +In this fork of Tile Cutter there was added some things: + +1. Plist file, that have info about tiles position and source image size. +2. Skipping of absolutely transparent tiles +3. Command Line Tool + +There's some minor issues in this fork, that i probably will not fix, cause everything is working fine for me now: + +1. You can't choose other than PNG file type in commandLine tool. +2. You can't set suffix in GUI. +3. There's no progressBar in commandLine tool. Here's a link, that maybe can help you with implementing non-duplicating progress bar: http://en.wikipedia.org/wiki/ANSI_escape_code + +If you're using Tile-Cutter and experiencing some issues - feel free to open new Issues or Pull Requests in this Repo. + + From c9bec8f10b70cf4e1ec63f6b713252b9e838a564 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Thu, 28 Apr 2011 23:31:50 +0400 Subject: [PATCH 25/40] Added AggregateTarget for both GUI app & cmdLine tool --- Tile Cutter.xcodeproj/project.pbxproj | 76 +++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/Tile Cutter.xcodeproj/project.pbxproj b/Tile Cutter.xcodeproj/project.pbxproj index 23e32c4..0ebd37d 100644 --- a/Tile Cutter.xcodeproj/project.pbxproj +++ b/Tile Cutter.xcodeproj/project.pbxproj @@ -6,6 +6,21 @@ objectVersion = 45; objects = { +/* Begin PBXAggregateTarget section */ + 6DA78D271369F7D9000EA884 /* Build All Targets */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 6DA78D3E1369F7FE000EA884 /* Build configuration list for PBXAggregateTarget "Build All Targets" */; + buildPhases = ( + ); + dependencies = ( + 6DA78D2B1369F7E0000EA884 /* PBXTargetDependency */, + 6DA78D2D1369F7E0000EA884 /* PBXTargetDependency */, + ); + name = "Build All Targets"; + productName = "Build All Targets"; + }; +/* End PBXAggregateTarget section */ + /* Begin PBXBuildFile section */ 1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58140DA1D0A300B32029 /* MainMenu.xib */; }; 1F15EAF9125E8ED200B32D97 /* NSImage-Tile.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F15EA19125E826600B32D97 /* NSImage-Tile.m */; }; @@ -29,6 +44,23 @@ 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 6DA78D2A1369F7E0000EA884 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D1107260486CEB800E47090 /* Tile Cutter */; + remoteInfo = "Tile Cutter"; + }; + 6DA78D2C1369F7E0000EA884 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6DA78C061369BEB0000EA884 /* tileCutter */; + remoteInfo = tileCutter; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; @@ -234,6 +266,7 @@ targets = ( 8D1107260486CEB800E47090 /* Tile Cutter */, 6DA78C061369BEB0000EA884 /* tileCutter */, + 6DA78D271369F7D9000EA884 /* Build All Targets */, ); }; /* End PBXProject section */ @@ -284,6 +317,19 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 6DA78D2B1369F7E0000EA884 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8D1107260486CEB800E47090 /* Tile Cutter */; + targetProxy = 6DA78D2A1369F7E0000EA884 /* PBXContainerItemProxy */; + }; + 6DA78D2D1369F7E0000EA884 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6DA78C061369BEB0000EA884 /* tileCutter */; + targetProxy = 6DA78D2C1369F7E0000EA884 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = { isa = PBXVariantGroup; @@ -350,6 +396,27 @@ }; name = Release; }; + 6DA78D281369F7DA000EA884 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + PRODUCT_NAME = "Build All Targets"; + }; + name = Debug; + }; + 6DA78D291369F7DA000EA884 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + PRODUCT_NAME = "Build All Targets"; + ZERO_LINK = NO; + }; + name = Release; + }; C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -436,6 +503,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 6DA78D3E1369F7FE000EA884 /* Build configuration list for PBXAggregateTarget "Build All Targets" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6DA78D281369F7DA000EA884 /* Debug */, + 6DA78D291369F7DA000EA884 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Tile Cutter" */ = { isa = XCConfigurationList; buildConfigurations = ( From 7b001396472304d9498fbab91bd6303318cf1bab Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Sun, 1 May 2011 00:48:54 +0400 Subject: [PATCH 26/40] Fix "(null)" suffix in plist filename, if suffix isn't set --- Tile Cutter.xcodeproj/project.pbxproj | 4 ++-- TileCutterCore.m | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Tile Cutter.xcodeproj/project.pbxproj b/Tile Cutter.xcodeproj/project.pbxproj index 0ebd37d..98fe7c9 100644 --- a/Tile Cutter.xcodeproj/project.pbxproj +++ b/Tile Cutter.xcodeproj/project.pbxproj @@ -49,14 +49,14 @@ isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; proxyType = 1; - remoteGlobalIDString = 8D1107260486CEB800E47090 /* Tile Cutter */; + remoteGlobalIDString = 8D1107260486CEB800E47090; remoteInfo = "Tile Cutter"; }; 6DA78D2C1369F7E0000EA884 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; proxyType = 1; - remoteGlobalIDString = 6DA78C061369BEB0000EA884 /* tileCutter */; + remoteGlobalIDString = 6DA78C061369BEB0000EA884; remoteInfo = tileCutter; }; /* End PBXContainerItemProxy section */ diff --git a/TileCutterCore.m b/TileCutterCore.m index 0feb013..edeed6d 100644 --- a/TileCutterCore.m +++ b/TileCutterCore.m @@ -108,6 +108,8 @@ - (void)operationDidFinishSuccessfully:(TileOperation *)op self.imageInfo, @"Source", self.allTilesInfo, @"Tiles", nil]; + if (!self.outputSuffix) + self.outputSuffix = @""; [dict writeToFile:[NSString stringWithFormat:@"%@%@.plist", self.outputBaseFilename, self.outputSuffix] atomically:YES]; } From 0d172691a623840173ae7e44bbf17605330b5165 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Sun, 1 May 2011 22:54:32 +0400 Subject: [PATCH 27/40] Performance & Mem Optimization: Serial queue with shared ImageRep --- TileCutterCore.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/TileCutterCore.m b/TileCutterCore.m index edeed6d..84c06dc 100644 --- a/TileCutterCore.m +++ b/TileCutterCore.m @@ -22,6 +22,8 @@ - (id) init if ( (self == [super init]) ) { self.queue = [[[NSOperationQueue alloc] init] autorelease]; + [self.queue setMaxConcurrentOperationCount:1]; + self.outputFormat = NSPNGFileType; self.outputSuffix = @""; self.keepAllTiles = NO; @@ -60,10 +62,12 @@ - (void) startSavingTiles self.allTilesInfo = [NSMutableArray arrayWithCapacity: tileRowCount * tileColCount]; + // One ImageRep for all TileOperation + NSBitmapImageRep *imageRep = + [[[NSBitmapImageRep alloc] initWithCGImage:[image CGImageForProposedRect:NULL context:NULL hints:nil]] autorelease]; + for (int row = 0; row < tileRowCount; row++) { - // Each row operation gets its own ImageRep to avoid contention - NSBitmapImageRep *imageRep = [[[NSBitmapImageRep alloc] initWithCGImage:[image CGImageForProposedRect:NULL context:NULL hints:nil]] autorelease]; TileOperation *op = [[TileOperation alloc] init]; op.row = row; op.tileWidth = self.tileWidth; From 9b5ffa68fdde82a2dfff31b7ff2d21dfb4a7b52d Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Wed, 4 May 2011 01:28:20 +0400 Subject: [PATCH 28/40] Added zero-out for non-image zone pixels --- NSBitmapImageRep-Tile.m | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/NSBitmapImageRep-Tile.m b/NSBitmapImageRep-Tile.m index 11fc530..7597388 100644 --- a/NSBitmapImageRep-Tile.m +++ b/NSBitmapImageRep-Tile.m @@ -74,8 +74,19 @@ -(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth tileHeight:(CGFloat)tileHei { p1 = srcData + bytesPerPixel * (y * width + x); p2 = destData + bytesPerPixel * ((y - theRow) * width + (x - theCol)); - for (i = 0; i < bytesPerPixel; i++) - p2[i] = p1[i]; + + if ( x >= width || y >= height) + { + // fill with zeroes pixels outside self.size + for (i = 0; i < bytesPerPixel; i++) + p2[i] = 0; + } + else + { + // copy pixels as usual + for (i = 0; i < bytesPerPixel; i++) + p2[i] = p1[i]; + } } } From fb9c1eff8b9c2b035a7c43a55dfa882d6511c800 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Wed, 4 May 2011 01:31:23 +0400 Subject: [PATCH 29/40] Added rigidSize attribute to subImage method. --- NSBitmapImageRep-Tile.h | 15 ++++++++++++++- NSBitmapImageRep-Tile.m | 18 +++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/NSBitmapImageRep-Tile.h b/NSBitmapImageRep-Tile.h index 46384bf..e02aee1 100644 --- a/NSBitmapImageRep-Tile.h +++ b/NSBitmapImageRep-Tile.h @@ -10,7 +10,20 @@ @interface NSBitmapImageRep(Tile) --(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth tileHeight:(CGFloat)tileHeight column:(NSUInteger)column row:(NSUInteger)row; + +-(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth + tileHeight:(CGFloat)tileHeight + column:(NSUInteger)column + row:(NSUInteger)row; + +// Same as previous, but if rigid = YES - adds black pixels to fill +// all tileWidthxtileHeight zone, if there's no enough pixels in image +-(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth + tileHeight:(CGFloat)tileHeight + column:(NSUInteger)column + row:(NSUInteger)row + rigidSize:(BOOL) rigid; + -(NSUInteger)columnsWithTileWidth:(CGFloat)tileWidth; -(NSUInteger)rowsWithTileHeight:(CGFloat)tileHeight; diff --git a/NSBitmapImageRep-Tile.m b/NSBitmapImageRep-Tile.m index 7597388..7307e28 100644 --- a/NSBitmapImageRep-Tile.m +++ b/NSBitmapImageRep-Tile.m @@ -10,7 +10,19 @@ @implementation NSBitmapImageRep(Tile) --(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth tileHeight:(CGFloat)tileHeight column:(NSUInteger)column row:(NSUInteger)row +-(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth + tileHeight:(CGFloat)tileHeight + column:(NSUInteger)column + row:(NSUInteger)row +{ + return [self subImageWithTileWidth:tileWidth tileHeight:tileHeight column: column row:row rigidSize: NO]; +} + +-(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth + tileHeight:(CGFloat)tileHeight + column:(NSUInteger)column + row:(NSUInteger)row + rigidSize:(BOOL) rigid { int width = [self pixelsWide]; int height = [self pixelsHigh]; @@ -25,7 +37,7 @@ -(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth tileHeight:(CGFloat)tileHei int lastCol; int outputWidth; - if (theCol + tileWidth > width) // last column, not full size + if ( !rigid && (theCol + tileWidth > width) ) // last column, not full size { lastCol = width; outputWidth = (width - theCol); @@ -37,7 +49,7 @@ -(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth tileHeight:(CGFloat)tileHei } int lastRow, outputHeight; - if (theRow + tileHeight > height) + if ( !rigid && (theRow + tileHeight > height) ) { lastRow = height; outputHeight = (height - theRow); From c5cd177d0c52ba800cb681636005391aaf4db570 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Wed, 4 May 2011 01:55:43 +0400 Subject: [PATCH 30/40] Added rigidTiles property to Operation and Core --- TileCutterCore.h | 1 + TileCutterCore.m | 3 +++ TileOperation.h | 1 + TileOperation.m | 7 ++++++- 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/TileCutterCore.h b/TileCutterCore.h index e7df96b..cdb57ac 100644 --- a/TileCutterCore.h +++ b/TileCutterCore.h @@ -16,6 +16,7 @@ #pragma mark Public Properties // Properties of Tiling Operation +@property(readwrite) BOOL rigidTiles; @property(readwrite) BOOL keepAllTiles; @property(readwrite) NSUInteger tileWidth; @property(readwrite) NSUInteger tileHeight; diff --git a/TileCutterCore.m b/TileCutterCore.m index 84c06dc..9885de7 100644 --- a/TileCutterCore.m +++ b/TileCutterCore.m @@ -14,6 +14,7 @@ @implementation TileCutterCore @synthesize keepAllTiles, tileWidth, tileHeight, inputFilename, outputBaseFilename, outputSuffix, operationsDelegate, queue, allTilesInfo, imageInfo, outputFormat; +@synthesize rigidTiles; #pragma mark Public Methods @@ -27,6 +28,7 @@ - (id) init self.outputFormat = NSPNGFileType; self.outputSuffix = @""; self.keepAllTiles = NO; + self.rigidTiles = NO; } return self; @@ -78,6 +80,7 @@ - (void) startSavingTiles op.outputFormat = self.outputFormat; op.outputSuffix = self.outputSuffix; op.skipTransparentTiles = (! self.keepAllTiles ); + op.rigidTiles = self.rigidTiles; [queue addOperation:op]; [op release]; } diff --git a/TileOperation.h b/TileOperation.h index 24a8dc1..bdd18c8 100644 --- a/TileOperation.h +++ b/TileOperation.h @@ -32,6 +32,7 @@ @property NSUInteger tileWidth; @property TileCutterOutputPrefs outputFormat; @property (readwrite) BOOL skipTransparentTiles; +@property (readwrite) BOOL rigidTiles; /* array of tiles info, * each item = NSDictionary { diff --git a/TileOperation.m b/TileOperation.m index 17c47c3..68b2b63 100644 --- a/TileOperation.m +++ b/TileOperation.m @@ -45,6 +45,7 @@ @implementation TileOperation @synthesize tilesInfo; @synthesize skipTransparentTiles; @synthesize outputSuffix; +@synthesize rigidTiles; #pragma mark - - (void)informDelegateOfError:(NSString *)message { @@ -111,7 +112,11 @@ - (void)main for (int column = 0; column < tileColCount; column++) { - NSImage *subImage = [imageRep subImageWithTileWidth:(float)tileWidth tileHeight:(float)tileHeight column:column row:row]; + NSImage *subImage = [imageRep subImageWithTileWidth:(float)tileWidth + tileHeight:(float)tileHeight + column:column + row:row + rigidSize:self.rigidTiles]; if (subImage == nil) { From fbcc4ab5c47b226a47c174b7921b70ed0de289b4 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Wed, 4 May 2011 02:02:25 +0400 Subject: [PATCH 31/40] Added --rigidTilesSize option to cmdLine tool --- cmdToolMain.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmdToolMain.m b/cmdToolMain.m index dfe2e6d..52b14c4 100644 --- a/cmdToolMain.m +++ b/cmdToolMain.m @@ -31,6 +31,7 @@ int main(int argc, char *argv[]) { // Options Storage int keepAllTiles = 0; + int rigidTilesSize = 0; NSUInteger tileWidth = 0; NSUInteger tileHeight = 0; NSString *inputFilename = nil; @@ -54,6 +55,7 @@ int main(int argc, char *argv[]) /* These options set a flag. */ {"skipTransparentTiles", no_argument, &keepAllTiles, 0}, {"keepTransparentTiles", no_argument, &keepAllTiles, 1}, + {"rigidTilesSize", no_argument, &rigidTilesSize, 1}, /* These options don't set a flag. We distinguish them by their indices. */ {"tileWidth", required_argument, 0, 'w'}, @@ -143,6 +145,7 @@ int main(int argc, char *argv[]) tileCutterCore.tileWidth = tileWidth; tileCutterCore.tileHeight = tileWidth; tileCutterCore.keepAllTiles = (keepAllTiles != 0); + tileCutterCore.rigidTiles = (rigidTilesSize != 0); // Start Cutting and Wait for it. [tileCutterCore startSavingTiles]; From 1414d8247e9ea2af875b328338d1ea3bc67e2b8d Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Wed, 4 May 2011 02:08:12 +0400 Subject: [PATCH 32/40] Updated README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index cde6f98..3512fb9 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,15 @@ In this fork of Tile Cutter there was added some things: 1. Plist file, that have info about tiles position and source image size. 2. Skipping of absolutely transparent tiles 3. Command Line Tool +4. Rigid Tile Size (can be useful if you need fixed tile size, even if image don't fit) + There's some minor issues in this fork, that i probably will not fix, cause everything is working fine for me now: 1. You can't choose other than PNG file type in commandLine tool. 2. You can't set suffix in GUI. 3. There's no progressBar in commandLine tool. Here's a link, that maybe can help you with implementing non-duplicating progress bar: http://en.wikipedia.org/wiki/ANSI_escape_code +4. rigidTilesSize option is available only in commandLine tool. (It allows you to have all tiles with equal size with black pixels that is out of image area) If you're using Tile-Cutter and experiencing some issues - feel free to open new Issues or Pull Requests in this Repo. From d69c7a7a5635347f6d7446fec0780afe1fd5995f Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Mon, 9 May 2011 03:18:07 +0400 Subject: [PATCH 33/40] Added info about flags to cmdLine tool usage output. --- cmdToolMain.m | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cmdToolMain.m b/cmdToolMain.m index 52b14c4..afbc69e 100644 --- a/cmdToolMain.m +++ b/cmdToolMain.m @@ -17,13 +17,16 @@ void printUsageAndExit() { - printf("\nUsage: tileCutter [--keepTransparentTiles] --tileWidth WIDTH --tileHeight HEIGHT \ + printf("\nUsage: tileCutter [--rigidTilesSize] [--keepTransparentTiles] --tileWidth WIDTH --tileHeight HEIGHT \ --inputFile INPUT.PNG --outputFile OUTPUT [--outputSuffix SUFFIX]\n\ HEIGHT & WIDTH should be >= 1\n\ output tiles file names will be in this format:\n\ OUTPUT_X_Y-SUFFIX.png,\n\ where X & Y is tile number\n\ -Output plist file will be: OUTPUT.plist\n"); +Output plist file will be: OUTPUT.plist\n\ +If --rigidTilesSize flag is set, then all tiles will have the same size.\n\ +If image isn't divisible by tileSize without a remainder - missing pixels will be added.\n\ +If --keepTransparentTiles flag is set, than absolute transparent tiles will be not skiped.\n"); exit(0); } From db067cf179814fd017e0d3e74dfa52d872ccbc73 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Mon, 9 May 2011 22:46:39 +0400 Subject: [PATCH 34/40] Added contentScale option to cmdLine Tool --- cmdToolMain.m | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cmdToolMain.m b/cmdToolMain.m index afbc69e..e54ef7a 100644 --- a/cmdToolMain.m +++ b/cmdToolMain.m @@ -40,6 +40,7 @@ int main(int argc, char *argv[]) NSString *inputFilename = nil; NSString *outputBaseFilename = nil; NSString *outputSuffix = nil; + CGFloat *contentScaleFactor = 1.0f; NSAutoreleasePool *pool = [NSAutoreleasePool new]; @@ -66,6 +67,7 @@ int main(int argc, char *argv[]) {"inputFile", required_argument, 0, 'i'}, {"outputFile", required_argument, 0, 'o'}, {"outputSuffix", required_argument, 0, 's'}, + {"contentScaleFactor", required_argument, 0, 'f'}, {0, 0, 0, 0} }; /* getopt_long stores the option index here. */ @@ -121,6 +123,12 @@ int main(int argc, char *argv[]) outputSuffix = [NSString stringWithCString:optarg encoding: NSUTF8StringEncoding]; break; + case 'f': + contentScaleFactor = [[NSString stringWithCString:optarg encoding: NSUTF8StringEncoding] floatValue]; + if (!contentScaleFactor) + contentScaleFactor = 1.0f; + break; + case '?': /* getopt_long already printed an error message. */ [pool release]; @@ -149,6 +157,7 @@ int main(int argc, char *argv[]) tileCutterCore.tileHeight = tileWidth; tileCutterCore.keepAllTiles = (keepAllTiles != 0); tileCutterCore.rigidTiles = (rigidTilesSize != 0); + tileCutterCore.contentScaleFactor = contentScaleFactor; // Start Cutting and Wait for it. [tileCutterCore startSavingTiles]; From 4ec1e2982b6af251c1b3354c96734518dc947935 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Mon, 9 May 2011 22:57:13 +0400 Subject: [PATCH 35/40] Added usage output for --contentScaleFactor --- cmdToolMain.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmdToolMain.m b/cmdToolMain.m index e54ef7a..0f1f817 100644 --- a/cmdToolMain.m +++ b/cmdToolMain.m @@ -26,7 +26,8 @@ void printUsageAndExit() Output plist file will be: OUTPUT.plist\n\ If --rigidTilesSize flag is set, then all tiles will have the same size.\n\ If image isn't divisible by tileSize without a remainder - missing pixels will be added.\n\ -If --keepTransparentTiles flag is set, than absolute transparent tiles will be not skiped.\n"); +If --keepTransparentTiles flag is set, than absolute transparent tiles will be not skiped.\n\ +--contentScaleFactor is used as denominator for tiles & image sizes & positions in plist file.\n"); exit(0); } From a61e7e9ef33b97e624e637abb6f34c1f3e77f81a Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Mon, 9 May 2011 23:25:11 +0400 Subject: [PATCH 36/40] Implemented scaleFactor in Core & grouped saving plist in one method --- TileCutterCore.h | 1 + TileCutterCore.m | 56 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/TileCutterCore.h b/TileCutterCore.h index cdb57ac..8ede4b8 100644 --- a/TileCutterCore.h +++ b/TileCutterCore.h @@ -20,6 +20,7 @@ @property(readwrite) BOOL keepAllTiles; @property(readwrite) NSUInteger tileWidth; @property(readwrite) NSUInteger tileHeight; +@property(readwrite) float_t contentScaleFactor; @property(readwrite) TileCutterOutputPrefs outputFormat; @property(readwrite, copy) NSString *inputFilename; @property(readwrite, copy) NSString *outputBaseFilename; diff --git a/TileCutterCore.m b/TileCutterCore.m index 9885de7..a2bb436 100644 --- a/TileCutterCore.m +++ b/TileCutterCore.m @@ -15,6 +15,7 @@ @implementation TileCutterCore outputBaseFilename, outputSuffix, operationsDelegate, queue, allTilesInfo, imageInfo, outputFormat; @synthesize rigidTiles; +@synthesize contentScaleFactor; #pragma mark Public Methods @@ -58,9 +59,12 @@ - (void) startSavingTiles tileRowCount = [image rowsWithTileHeight: self.tileHeight]; tileColCount = [image columnsWithTileWidth: self.tileWidth]; + NSSize outputImageSizeForPlist = [image size]; + outputImageSizeForPlist.width /= self.contentScaleFactor; + outputImageSizeForPlist.height /= self.contentScaleFactor; self.imageInfo = [NSDictionary dictionaryWithObjectsAndKeys: [self.inputFilename lastPathComponent], @"Filename", - NSStringFromSize([image size]), @"Size", nil]; + NSStringFromSize(outputImageSizeForPlist), @"Size", nil]; self.allTilesInfo = [NSMutableArray arrayWithCapacity: tileRowCount * tileColCount]; @@ -103,6 +107,48 @@ - (void)operationDidFinishTile:(TileOperation *)op waitUntilDone: NO]; } +- (void) saveImageInfoDictionary +{ + // Change coordinates & size of all tiles for contentScaleFactor + if (self.contentScaleFactor != 1.0f) + { + for (NSDictionary *tileDict in self.allTilesInfo) + { + // Get Tile Rect + NSRect rect = NSRectFromString([tileDict objectForKey: @"Rect"]); + + // Divide it by contentScaleFactor + rect.origin.x /= self.contentScaleFactor; + rect.origin.y /= self.contentScaleFactor; + rect.size.width /= self.contentScaleFactor; + rect.size.height /= self.contentScaleFactor; + + // Create new tile info Dict with changed rect + NSDictionary *newTileDict = [NSDictionary dictionaryWithObjectsAndKeys: + [tileDict objectForKey:@"Name"], @"Name", + NSStringFromRect(rect), @"Rect", + nil]; + + // Replace old Tile Info Dict with New One + [(NSMutableArray *)self.allTilesInfo replaceObjectAtIndex:[self.allTilesInfo indexOfObject: tileDict] withObject:newTileDict ]; + + } + } + + // Create Root Dictionary for a PLIST file + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: + self.imageInfo, @"Source", + self.allTilesInfo, @"Tiles", + [NSNumber numberWithFloat:self.contentScaleFactor], @"ContentScaleFactor", nil]; + + // Be safe with outputSuffix + if (!self.outputSuffix) + self.outputSuffix = @""; + + // Save Dict to File + [dict writeToFile:[NSString stringWithFormat:@"%@%@.plist", self.outputBaseFilename, self.outputSuffix] atomically:YES]; +} + - (void)operationDidFinishSuccessfully:(TileOperation *)op { [(NSMutableArray *)self.allTilesInfo addObjectsFromArray: op.tilesInfo]; @@ -111,13 +157,7 @@ - (void)operationDidFinishSuccessfully:(TileOperation *)op // All Tiles Finished? if (progressRow >= tileRowCount) { - NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: - self.imageInfo, @"Source", - self.allTilesInfo, @"Tiles", nil]; - - if (!self.outputSuffix) - self.outputSuffix = @""; - [dict writeToFile:[NSString stringWithFormat:@"%@%@.plist", self.outputBaseFilename, self.outputSuffix] atomically:YES]; + [self saveImageInfoDictionary]; } if ([self.operationsDelegate respondsToSelector: _cmd]) From 5710ebc0a9fad9fe77dd5ffd0790986acd71c484 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Mon, 9 May 2011 23:25:45 +0400 Subject: [PATCH 37/40] Fixed compiler errors --- cmdToolMain.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmdToolMain.m b/cmdToolMain.m index 0f1f817..ebe753e 100644 --- a/cmdToolMain.m +++ b/cmdToolMain.m @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) NSString *inputFilename = nil; NSString *outputBaseFilename = nil; NSString *outputSuffix = nil; - CGFloat *contentScaleFactor = 1.0f; + float_t contentScaleFactor = 1.0f; NSAutoreleasePool *pool = [NSAutoreleasePool new]; From 40ca402cc8a7743c015f6e03fd796106252839d7 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Mon, 9 May 2011 23:39:48 +0400 Subject: [PATCH 38/40] Fixed "mutated while being enumerated" crashes --- TileCutterCore.m | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/TileCutterCore.m b/TileCutterCore.m index a2bb436..61f355b 100644 --- a/TileCutterCore.m +++ b/TileCutterCore.m @@ -112,6 +112,9 @@ - (void) saveImageInfoDictionary // Change coordinates & size of all tiles for contentScaleFactor if (self.contentScaleFactor != 1.0f) { + // Create new array, that will replace old self.allTilesInfo + NSMutableArray *newTilesInfoArray = [NSMutableArray arrayWithCapacity: [self.allTilesInfo count]]; + for (NSDictionary *tileDict in self.allTilesInfo) { // Get Tile Rect @@ -129,10 +132,14 @@ - (void) saveImageInfoDictionary NSStringFromRect(rect), @"Rect", nil]; - // Replace old Tile Info Dict with New One - [(NSMutableArray *)self.allTilesInfo replaceObjectAtIndex:[self.allTilesInfo indexOfObject: tileDict] withObject:newTileDict ]; + // Add new tile info for new array + [newTilesInfoArray addObject:newTileDict ]; } + + // Replace Old Tiles with New + self.allTilesInfo = newTilesInfoArray; + } // Create Root Dictionary for a PLIST file From 86b5b4358b9f985a3320d9e9101331bebaaf97e5 Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Mon, 9 May 2011 23:52:37 +0400 Subject: [PATCH 39/40] Added file existence check in cmdLine Tool --- cmdToolMain.m | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/cmdToolMain.m b/cmdToolMain.m index ebe753e..daf5831 100644 --- a/cmdToolMain.m +++ b/cmdToolMain.m @@ -31,6 +31,27 @@ void printUsageAndExit() exit(0); } +BOOL fileExists(NSString* relPath) +{ + NSString *fullpath = nil; + + // only if it is not an absolute path + if( ! [relPath isAbsolutePath] ) + { + NSString *file = [relPath lastPathComponent]; + NSString *imageDirectory = [relPath stringByDeletingLastPathComponent]; + + fullpath = [[NSBundle mainBundle] pathForResource:file + ofType:nil + inDirectory:imageDirectory]; + } + + if (fullpath == nil) + fullpath = relPath; + + return [[NSFileManager defaultManager] fileExistsAtPath: fullpath]; +} + int main(int argc, char *argv[]) { // Options Storage @@ -149,6 +170,14 @@ int main(int argc, char *argv[]) printUsageAndExit(); } + // avoid crashing if file not exists + if ( !fileExists(inputFilename) ) + { + printf("\nFile not found: %s \n", [inputFilename cStringUsingEncoding:NSUTF8StringEncoding]); + [pool release]; + exit(0); + } + // Prepare Tile Cutter TileCutterCore *tileCutterCore = [TileCutterCore new]; tileCutterCore.inputFilename = inputFilename; From b5dbc5b7c64ef49d60667b4c881d3d4af59568ef Mon Sep 17 00:00:00 2001 From: Stepan Generalov Date: Mon, 25 Jul 2011 18:11:26 +0400 Subject: [PATCH 40/40] Added --roundTileSizeToPOT option flag. Closes #5 --- NSBitmapImageRep-Tile.h | 13 +++++++++++++ NSBitmapImageRep-Tile.m | 19 +++++++++++++++++-- TileCutterCore.h | 1 + TileCutterCore.m | 2 ++ TileOperation.h | 1 + TileOperation.m | 2 +- cmdToolMain.m | 10 +++++++++- 7 files changed, 44 insertions(+), 4 deletions(-) diff --git a/NSBitmapImageRep-Tile.h b/NSBitmapImageRep-Tile.h index e02aee1..47d9f05 100644 --- a/NSBitmapImageRep-Tile.h +++ b/NSBitmapImageRep-Tile.h @@ -24,6 +24,19 @@ row:(NSUInteger)row rigidSize:(BOOL) rigid; +/** Designated method. + * + * @param potSize If YES - tile width & height will be rounded to nearest POT value, larger then existing. + * potSize have no effect if rigidSize is YES. + * + */ +-(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth + tileHeight:(CGFloat)tileHeight + column:(NSUInteger)column + row:(NSUInteger)row + rigidSize:(BOOL) rigid + POTSize:(BOOL) potSize; + -(NSUInteger)columnsWithTileWidth:(CGFloat)tileWidth; -(NSUInteger)rowsWithTileHeight:(CGFloat)tileHeight; diff --git a/NSBitmapImageRep-Tile.m b/NSBitmapImageRep-Tile.m index 7307e28..3406d19 100644 --- a/NSBitmapImageRep-Tile.m +++ b/NSBitmapImageRep-Tile.m @@ -15,7 +15,7 @@ -(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth column:(NSUInteger)column row:(NSUInteger)row { - return [self subImageWithTileWidth:tileWidth tileHeight:tileHeight column: column row:row rigidSize: NO]; + return [self subImageWithTileWidth:tileWidth tileHeight:tileHeight column: column row:row rigidSize: NO POTSize: NO]; } -(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth @@ -23,6 +23,16 @@ -(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth column:(NSUInteger)column row:(NSUInteger)row rigidSize:(BOOL) rigid +{ + return [self subImageWithTileWidth:tileWidth tileHeight:tileHeight column: column row:row rigidSize: NO POTSize: NO]; +} + +-(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth + tileHeight:(CGFloat)tileHeight + column:(NSUInteger)column + row:(NSUInteger)row + rigidSize:(BOOL) rigid + POTSize:(BOOL) potSize { int width = [self pixelsWide]; int height = [self pixelsHigh]; @@ -41,6 +51,9 @@ -(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth { lastCol = width; outputWidth = (width - theCol); + + if (potSize) + outputWidth = (int)pow( 2, ceil(log2((double)outputWidth))); } else { @@ -53,7 +66,9 @@ -(NSImage *)subImageWithTileWidth:(CGFloat)tileWidth { lastRow = height; outputHeight = (height - theRow); - + + if (potSize) + outputHeight = (int)pow( 2, ceil(log2((double)outputHeight))); } else { diff --git a/TileCutterCore.h b/TileCutterCore.h index 8ede4b8..0072b86 100644 --- a/TileCutterCore.h +++ b/TileCutterCore.h @@ -16,6 +16,7 @@ #pragma mark Public Properties // Properties of Tiling Operation +@property(readwrite) BOOL POTTiles; @property(readwrite) BOOL rigidTiles; @property(readwrite) BOOL keepAllTiles; @property(readwrite) NSUInteger tileWidth; diff --git a/TileCutterCore.m b/TileCutterCore.m index 61f355b..748c8c0 100644 --- a/TileCutterCore.m +++ b/TileCutterCore.m @@ -16,6 +16,7 @@ @implementation TileCutterCore queue, allTilesInfo, imageInfo, outputFormat; @synthesize rigidTiles; @synthesize contentScaleFactor; +@synthesize POTTiles; #pragma mark Public Methods @@ -85,6 +86,7 @@ - (void) startSavingTiles op.outputSuffix = self.outputSuffix; op.skipTransparentTiles = (! self.keepAllTiles ); op.rigidTiles = self.rigidTiles; + op.POTTiles = self.POTTiles; [queue addOperation:op]; [op release]; } diff --git a/TileOperation.h b/TileOperation.h index bdd18c8..213886d 100644 --- a/TileOperation.h +++ b/TileOperation.h @@ -33,6 +33,7 @@ @property TileCutterOutputPrefs outputFormat; @property (readwrite) BOOL skipTransparentTiles; @property (readwrite) BOOL rigidTiles; +@property (readwrite) BOOL POTTiles; /* array of tiles info, * each item = NSDictionary { diff --git a/TileOperation.m b/TileOperation.m index 68b2b63..67c58f4 100644 --- a/TileOperation.m +++ b/TileOperation.m @@ -45,7 +45,7 @@ @implementation TileOperation @synthesize tilesInfo; @synthesize skipTransparentTiles; @synthesize outputSuffix; -@synthesize rigidTiles; +@synthesize rigidTiles, POTTiles; #pragma mark - - (void)informDelegateOfError:(NSString *)message { diff --git a/cmdToolMain.m b/cmdToolMain.m index daf5831..1725ef1 100644 --- a/cmdToolMain.m +++ b/cmdToolMain.m @@ -17,7 +17,7 @@ void printUsageAndExit() { - printf("\nUsage: tileCutter [--rigidTilesSize] [--keepTransparentTiles] --tileWidth WIDTH --tileHeight HEIGHT \ + printf("\nUsage: tileCutter [--rigidTilesSize | --roundTileSizeToPOT] [--keepTransparentTiles] --tileWidth WIDTH --tileHeight HEIGHT \ --inputFile INPUT.PNG --outputFile OUTPUT [--outputSuffix SUFFIX]\n\ HEIGHT & WIDTH should be >= 1\n\ output tiles file names will be in this format:\n\ @@ -25,6 +25,7 @@ void printUsageAndExit() where X & Y is tile number\n\ Output plist file will be: OUTPUT.plist\n\ If --rigidTilesSize flag is set, then all tiles will have the same size.\n\ +If --roundTileSizeToPOT flag is set, then all tiles will have POT size, and rigidTileSize will be disabled.\n\ If image isn't divisible by tileSize without a remainder - missing pixels will be added.\n\ If --keepTransparentTiles flag is set, than absolute transparent tiles will be not skiped.\n\ --contentScaleFactor is used as denominator for tiles & image sizes & positions in plist file.\n"); @@ -57,6 +58,7 @@ int main(int argc, char *argv[]) // Options Storage int keepAllTiles = 0; int rigidTilesSize = 0; + int roundTileSizeToPOT = 0; NSUInteger tileWidth = 0; NSUInteger tileHeight = 0; NSString *inputFilename = nil; @@ -82,6 +84,7 @@ int main(int argc, char *argv[]) {"skipTransparentTiles", no_argument, &keepAllTiles, 0}, {"keepTransparentTiles", no_argument, &keepAllTiles, 1}, {"rigidTilesSize", no_argument, &rigidTilesSize, 1}, + {"roundTileSizeToPOT", no_argument, &rigidTilesSize, 0}, /* These options don't set a flag. We distinguish them by their indices. */ {"tileWidth", required_argument, 0, 'w'}, @@ -178,6 +181,10 @@ int main(int argc, char *argv[]) exit(0); } + // Round To POT must disable rigidTileSize. + if (roundTileSizeToPOT) + rigidTilesSize = 0; + // Prepare Tile Cutter TileCutterCore *tileCutterCore = [TileCutterCore new]; tileCutterCore.inputFilename = inputFilename; @@ -187,6 +194,7 @@ int main(int argc, char *argv[]) tileCutterCore.tileHeight = tileWidth; tileCutterCore.keepAllTiles = (keepAllTiles != 0); tileCutterCore.rigidTiles = (rigidTilesSize != 0); + tileCutterCore.POTTiles = (roundTileSizeToPOT != 0); tileCutterCore.contentScaleFactor = contentScaleFactor; // Start Cutting and Wait for it.