Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/)

Unretiner from [Mac App Store](http://itunes.apple.com/us/app/unretiner/id411277085?mt=12)

Please fork and improve :)
Expand All @@ -12,4 +14,4 @@ Requested Features
* Automatically watch a folder and convert instantly / Applescript Support
* Add better resizing algorithms
* Sharpness filter
* Option to save to same folder without prompt
* Option to save to same folder without prompt
25 changes: 16 additions & 9 deletions Unretiner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
17C3A37413E3FF1600294FBE /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17C3A37313E3FF1600294FBE /* Cocoa.framework */; };
17C3A39213E3FF1700294FBE /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17C3A39113E3FF1700294FBE /* SenTestingKit.framework */; };
17C3A39313E3FF1700294FBE /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17C3A37313E3FF1600294FBE /* Cocoa.framework */; };
726F622B150AAB1F00B2C276 /* Unretiner.m in Sources */ = {isa = PBXBuildFile; fileRef = 726F622A150AAB1F00B2C276 /* Unretiner.m */; };
72B86785155B46A1008BA544 /* SimpleScriptingVerbs.sdef in Resources */ = {isa = PBXBuildFile; fileRef = 72B86784155B46A1008BA544 /* SimpleScriptingVerbs.sdef */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -52,7 +54,7 @@
1713EFAE13E57A310019EA65 /* Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Icon.icns; sourceTree = "<group>"; };
1713EFB313E588740019EA65 /* NSDroppableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSDroppableView.h; sourceTree = "<group>"; };
1713EFB413E588740019EA65 /* NSDroppableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSDroppableView.m; sourceTree = "<group>"; };
1713EFB613E58E800019EA65 /* NSBitmapImageRep+Resizing.h */ = {isa = PBXFileReference; fileEncoding = 4; path = "NSBitmapImageRep+Resizing.h"; sourceTree = "<group>"; };
1713EFB613E58E800019EA65 /* NSBitmapImageRep+Resizing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSBitmapImageRep+Resizing.h"; sourceTree = "<group>"; };
1713EFB713E58E800019EA65 /* NSBitmapImageRep+Resizing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBitmapImageRep+Resizing.m"; sourceTree = "<group>"; };
17C3A36F13E3FF1600294FBE /* Unretiner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Unretiner.app; sourceTree = BUILT_PRODUCTS_DIR; };
17C3A37313E3FF1600294FBE /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
Expand All @@ -61,6 +63,11 @@
17C3A37813E3FF1600294FBE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
17C3A39013E3FF1700294FBE /* UnretinerTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnretinerTests.octest; sourceTree = BUILT_PRODUCTS_DIR; };
17C3A39113E3FF1700294FBE /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
726F6229150AAB1F00B2C276 /* Unretiner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Unretiner.h; sourceTree = "<group>"; };
726F622A150AAB1F00B2C276 /* Unretiner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Unretiner.m; sourceTree = "<group>"; };
726F622C150AAB3D00B2C276 /* SynthesizeSingleton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SynthesizeSingleton.h; sourceTree = "<group>"; };
726F622D150AB5AF00B2C276 /* Constants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = "<group>"; };
72B86784155B46A1008BA544 /* SimpleScriptingVerbs.sdef */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = SimpleScriptingVerbs.sdef; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -87,6 +94,7 @@
1713EF8513E524A60019EA65 /* Resources */ = {
isa = PBXGroup;
children = (
72B86784155B46A1008BA544 /* SimpleScriptingVerbs.sdef */,
1713EFA813E526AF0019EA65 /* Config */,
1713EF8613E524A60019EA65 /* Images */,
);
Expand All @@ -106,7 +114,6 @@
isa = PBXGroup;
children = (
1713EF8F13E526A10019EA65 /* Controller */,
1713EF9413E526A10019EA65 /* Model */,
1713EF9513E526A10019EA65 /* Utilities */,
1713EF9813E526A10019EA65 /* View */,
);
Expand All @@ -121,26 +128,23 @@
1713EF9313E526A10019EA65 /* UnretinerAppDelegate.m */,
1713EF9013E526A10019EA65 /* UnretinaViewController.h */,
1713EF9113E526A10019EA65 /* UnretinaViewController.m */,
726F622D150AB5AF00B2C276 /* Constants.h */,
);
path = Controller;
sourceTree = "<group>";
};
1713EF9413E526A10019EA65 /* Model */ = {
isa = PBXGroup;
children = (
);
path = Model;
sourceTree = "<group>";
};
1713EF9513E526A10019EA65 /* Utilities */ = {
isa = PBXGroup;
children = (
1713EF9613E526A10019EA65 /* main.m */,
1713EF9713E526A10019EA65 /* Unretiner-Prefix.pch */,
726F6229150AAB1F00B2C276 /* Unretiner.h */,
726F622A150AAB1F00B2C276 /* Unretiner.m */,
1713EFAB13E579760019EA65 /* NSURL+Unretina.h */,
1713EFAC13E579760019EA65 /* NSURL+Unretina.m */,
1713EFB613E58E800019EA65 /* NSBitmapImageRep+Resizing.h */,
1713EFB713E58E800019EA65 /* NSBitmapImageRep+Resizing.m */,
726F622C150AAB3D00B2C276 /* SynthesizeSingleton.h */,
);
path = Utilities;
sourceTree = "<group>";
Expand Down Expand Up @@ -258,6 +262,7 @@
17C3A36613E3FF1600294FBE /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0420;
ORGANIZATIONNAME = Bonobo;
};
buildConfigurationList = 17C3A36913E3FF1600294FBE /* Build configuration list for PBXProject "Unretiner" */;
Expand Down Expand Up @@ -289,6 +294,7 @@
1713EFA613E526A10019EA65 /* MainMenu.xib in Resources */,
1713EFA713E526A10019EA65 /* UnretinaViewController.xib in Resources */,
1713EFAF13E57A310019EA65 /* Icon.icns in Resources */,
72B86785155B46A1008BA544 /* SimpleScriptingVerbs.sdef in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -328,6 +334,7 @@
1713EFAD13E579760019EA65 /* NSURL+Unretina.m in Sources */,
1713EFB513E588740019EA65 /* NSDroppableView.m in Sources */,
1713EFB813E58E800019EA65 /* NSBitmapImageRep+Resizing.m in Sources */,
726F622B150AAB1F00B2C276 /* Unretiner.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
19 changes: 19 additions & 0 deletions Unretiner/Classes/Controller/Constants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Constants.h
// Unretiner
//
// Created by Josh Hudnall on 3/9/12.
// Copyright (c) 2012 Bonobo. All rights reserved.
//

#ifndef Unretiner_Constants_h
#define Unretiner_Constants_h

// Defaults Keys
#define kDefaultsKeyForOverwrite @"kDefaultsKeyForOverwrite"
#define kDefaultsKeyForSaveToOrigin @"kDefaultsKeyForSaveToOrigin"

// Notification Names
#define UnretinerDidFinishProcessing @"UnretinerDidFinishProcessing"

#endif
11 changes: 6 additions & 5 deletions Unretiner/Classes/Controller/UnretinaViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
#import <Cocoa/Cocoa.h>
#import "NSDroppableView.h"

@interface UnretinaViewController : NSViewController<NSOpenSavePanelDelegate, NSDroppableViewDelegate>
@interface UnretinaViewController : NSViewController<NSOpenSavePanelDelegate, NSDroppableViewDelegate,NSTableViewDataSource>

@property (assign) IBOutlet NSButton* checkBox;
@property (assign) IBOutlet NSButton* saveToOriginCheckBox;
@property (assign) IBOutlet NSButton* overwriteCheckBox;
@property (assign) IBOutlet NSTableView* tableView;

// Plus button handler
// Button handlers
- (IBAction)onSelectFolder:(id)sender;
- (IBAction)onCheckOverwriteChange:(id)sender;

// Converts an array of URLs to non retina files
- (void)unretinaUrls:(NSArray*)urls;

@end
175 changes: 75 additions & 100 deletions Unretiner/Classes/Controller/UnretinaViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,26 @@

#import "UnretinaViewController.h"
#import "NSURL+Unretina.h"
#import "Unretiner.h"


@interface UnretinaViewController ()

@end


@implementation UnretinaViewController

static NSString* const kRetinaString = @"@2x";
static NSString* const kHdString = @"-hd";

@synthesize checkBox;
@synthesize saveToOriginCheckBox;
@synthesize overwriteCheckBox;
@synthesize tableView;

#pragma mark - Initialisation

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil {
id s = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (s == self) {
// Register for drag and drop
Expand All @@ -27,139 +36,77 @@ - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
return s;
}

#pragma mark - Memory Management

- (void)dealloc {
self.checkBox = nil;
[super dealloc];
- (void)awakeFromNib {
[super awakeFromNib];

overwriteCheckBox.state = [[NSUserDefaults standardUserDefaults] boolForKey:kDefaultsKeyForOverwrite];
saveToOriginCheckBox.state = [[NSUserDefaults standardUserDefaults] boolForKey:kDefaultsKeyForSaveToOrigin];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(unretinerDidFinishProcessing)
name:UnretinerDidFinishProcessing
object:nil];
}

#pragma mark - Private Methods

// Retrieves a folder to save to
- (NSURL*)getSaveFolder:(NSURL*)url {
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseDirectories:YES];
[panel setCanChooseFiles:NO];
[panel setAllowsMultipleSelection:NO];
[panel setDirectoryURL:url];
panel.prompt = @"Export Here";
panel.title = @"Select folder to save converted files.";
if ([panel runModal] == NSOKButton) {
// Got it, return the URL
return [panel URL];
}

return nil;
}

- (BOOL)isDirectory:(NSURL*)url {
// Determine if it is a directory
return CFURLHasDirectoryPath((CFURLRef)url);
- (void)unretinerDidFinishProcessing {
// All we really need to do right now is refresh the table view
[self.tableView reloadData];
}

- (void)unretinaUrls:(NSArray*)urls savePath:(NSURL*)savePath errors:(NSMutableArray*)errors warnings:(NSMutableArray*)warnings recursive:(BOOL)recursive {
// Parse each file passed in
for (NSURL* url in urls) {
if (url) {
BOOL directory = [self isDirectory:url];
if (recursive && directory) {
// Folder and we want to jump into it, grab the urls
NSFileManager* fileManager = [NSFileManager defaultManager];
NSArray* contents = [fileManager contentsOfDirectoryAtURL:url includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsHiddenFiles | NSDirectoryEnumerationSkipsSubdirectoryDescendants error:nil];

// Parse them, but don't go into any further sub folders
[self unretinaUrls:contents savePath:savePath errors:errors warnings:warnings recursive:NO];
}
else if (!directory) {
// Parse the file
[url unretina:savePath errors:errors warnings:warnings overwrite:[checkBox state]];
}
}
}
}
#pragma mark - Memory Management

#pragma mark - public methods

// Converts an array of URLs to non retina files
- (void)unretinaUrls:(NSArray*)urls {
// Extract the default export folder
if ([urls count] > 0) {
NSURL* firstUrl = [urls objectAtIndex:0];
if (![self isDirectory:firstUrl]) {
firstUrl = [firstUrl URLByDeletingLastPathComponent];
}
NSURL* savePath = [self getSaveFolder:firstUrl];

if (savePath) {
// Arrays to store warnings and errors
NSMutableArray* errors = [NSMutableArray array];
NSMutableArray* warnings = [NSMutableArray array];

// Do it!
[self unretinaUrls:urls savePath:savePath errors:errors warnings:warnings recursive:YES];

// Show the results
if ([errors count] > 0 || [warnings count] > 0) {
NSMutableString* message = [NSMutableString string];
if ([warnings count] > 0) {
[message appendString:@"Please check the following warnings:\r\n\r\n"];
for (NSString* s in warnings) {
[message appendFormat:@"%@\r\n", s];
}
[message appendString:@"\r\n\r\n"];
}

if ([errors count] > 0) {
[message appendString:@"The following errors occured:\r\n\r\n"];
for (NSString* s in errors) {
[message appendFormat:@"%@\r\n", s];
}
}

NSRunAlertPanel(@"Conversion Complete.",
message,
@"OK", nil, nil);
}
}
}
- (void)dealloc {
[super dealloc];
}

#pragma mark - View Events
#pragma mark - Private Methods

- (IBAction)onSelectFolder:(id)sender {
// Select the files to convert
NSOpenPanel *panel = [NSOpenPanel openPanel];
NSOpenPanel*panel = [NSOpenPanel openPanel];
[panel setCanChooseDirectories:YES];
[panel setCanChooseFiles:YES];
[panel setAllowsMultipleSelection:YES];
[panel setDelegate:self];
[panel setCanCreateDirectories:YES];
panel.title = @"Select @2x or -hd retina files";

if ([panel runModal] == NSOKButton) {
// Success, process all the files
[self unretinaUrls:panel.URLs];
[[Unretiner sharedInstance] unretinaUrls:panel.URLs];
}
}

- (IBAction)onCheckOverwriteChange:(id)sender {
BOOL overwrite = overwriteCheckBox.state;
[[NSUserDefaults standardUserDefaults] setBool:overwrite forKey:kDefaultsKeyForOverwrite];
[[NSUserDefaults standardUserDefaults] synchronize];
}

- (IBAction)onCheckOriginChange:(id)sender {
BOOL origin = saveToOriginCheckBox.state;
[[NSUserDefaults standardUserDefaults] setBool:origin forKey:kDefaultsKeyForSaveToOrigin];
[[NSUserDefaults standardUserDefaults] synchronize];
}

#pragma mark - NSOpenSavePanelDelegate

- (BOOL)allowFile:(NSString*)filename {
// Allow directories
NSURL* url = [NSURL fileURLWithPath:filename];
if (url && [self isDirectory:url])
if (url && [Unretiner isDirectory:url])
return YES;

// See if the file is a retina image
return url && [url isRetinaImage];
}

- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url {
- (BOOL)panel:(id)sender shouldEnableURL:(NSURL*)url {
// Only enable valid files
return [self allowFile:[url path]];
}

- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename {
- (BOOL)panel:(id)sender shouldShowFilename:(NSString*)filename {
// Only show valid files
return [self allowFile:filename];
}
Expand All @@ -168,7 +115,35 @@ - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename {

- (void)filesDropped:(NSArray*)urls {
// Process them
[self unretinaUrls:urls];
[[Unretiner sharedInstance] unretinaUrls:urls];
}

#pragma mark - Table View Data Source

- (NSInteger)numberOfRowsInTableView:(NSTableView*)aTableView {
return [[[Unretiner sharedInstance] errors] count] + [[[Unretiner sharedInstance] warnings] count];
}

- (id)tableView:(NSTableView*)tableView objectValueForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row {
NSArray* errors = [[Unretiner sharedInstance] errors];
NSArray* warnings = [[Unretiner sharedInstance] warnings];

if ([tableColumn.identifier isEqualToString:@"Type"]) {
if (row < [errors count]) {
return @"Error";
} else {
return @"Warning";
}
} else {
if (row < [errors count]) {
return [errors objectAtIndex:row];
} else {
return [warnings objectAtIndex:row - [errors count]];
}
}

return nil;
}


@end
Loading