Cocoa - Draw image from binary string - cocoa

Iam trying to draw a TIFF image from a string in XCode to display it in the dock.
The TIFF-image is obtained through an AppleScript that interacts with Spotify:
tell application "Spotify"
set aTrackArtwork to artwork of current track
end tell
The string that I receive is something like this:
TIFF4D4D002A00041EB821585D22595E215..
How can I draw an image from this binary code? My current code (which is a proof-of-concept) looks like this:
NSImage *myImage = [[NSImage alloc] init];
myImage = [NSImage imageNamed:#"ikoner"];
[NSApp setApplicationIconImage:myImage];
Is there any way to draw the image within the myImage object?
And, is there any easier way to obtain this information directly in my Xcode project without having to rely on the applescript?
My goal is to create a simple application that gets the current playing song and display it's album art in the dock.
I appreciate all answers that may or may not lead me closer to the answer!

This is fairly simply with the Scripting Bridge.
First, generate Spotify.h in the Terminal:
sdef /Applications/Spotify.app | sdp -fh --basename Spotify
Then, import the header file into your project, then link to ScriptingBridge.framework.
Finally, grab the image and put it in the Dock. Here's a basic example:
#import "Spotify.h"
// Get the image from Spotify
SpotifyApplication *spotify = [SBApplication applicationWithBundleIdentifier:#"com.spotify.client"];
NSImage *coverArt = spotify.currentTrack.artwork;
// Create an image view and put it in the Dock
NSImageView *imageView = [[NSImageView alloc] initWithFrame:NSZeroRect];
imageView.image = coverArt;
NSDockTile *dock = [[NSApplication sharedApplication] dockTile];
dock.contentView = imageView;
[dock display];

I'm not to familiar with the Spotify api, however something like this seems like it would work (convert your string into an NSData object:
[[NSImage alloc] initWithData:]

Related

Try to set an icon to a file in Cocoa

I try to get a file icon and to set it back to the same file (goal is to have overlay, but I first want to have this one work):
NSImage *img=[[NSWorkspace sharedWorkspace] iconForFile:#"MyFilePath"];
NSLog(#"x=%.f",img.size.width); // Result=32
[[NSWorkspace sharedWorkspace] setIcon:img forFile:#"MyFilePath" options:0];
-> Result is that my file gets a standard Finder icon instead of keeping its own icon. Anything I am doing wrong ?
Try using it like this:
[[NSWorkspace sharedWorkspace]
setIcon: [[NSImage alloc] initWithContentsOfFile:#"MyFilePath"]
forFile: #"MyFilePath"
options: 0];
You need to to load the icon/image into memory first.
EDIT: Answer updated to provide additional information in regards to
the comment below.
"how can I keep the image in memory to "play" with it before reassigning it?"
The NSImage that gets allocated into memory from your specified path can be manipulated in just about any possible way once it's been loaded. You'll want to thoroughly read the NSImage Class Reference to gain a real understanding of what it does and how use it's methods. For this particular scenario you'll want to be able have a named variable assigned from the icon you load.
Only one change needs to happen with the code above to make it work:
NSImage *iconImage = [[NSImage alloc] initWithContentsOfFile:#"MyFilePath"];
[[NSWorkspace sharedWorkspace]
setIcon: iconImage
forFile: #"MyFilePath"
options: 0];
NSLog(#"iconImage: %#",iconImage);
The slight change essentially assigns the variable iconImage from the NSImage icon; everything else stays the same. The NSLog will give you a very quick glimpse at properties associated with iconImage — where you take it from there is really up to your coding ability and creativity.

NSImage → NSURL → Custom Object

My application is trying to create custom objects from NSImage objects (coming from the pasteboard) but my current process only takes in image URLs.
I'd like to avoid major changes at this point so I was wondering if there was any way to get the URL of an NSImage (it seems like a reasonable expectation since one can initialize an NSImage from a URL)
Thanks.
EDIT (answer)
I went a slightly different route. Instead of getting the content of the pasteboard as an array of NSImage, I simply got it as an array of NSURL. I can then feed those into my process.
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSArray *classArray = [NSArray arrayWithObject:[NSURL class]];
NSDictionary *options = [NSDictionary dictionary];
BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options];
if (ok) {
NSArray *URLs = [pasteboard readObjectsForClasses:classArray options:options];
}
Quote by BlazingFrog:
(it seems like a reasonable expectation since one can initialize an NSImage from a URL)
Lets say I initialize a NSString by using:
NSString * theString = [NSString initWithContentsOfURL: encoding: error: ];
I'm sure it's not possible to retrieve the original NSURL from the NSString.
And I'm quite sure the same applies to NSImage. (Actually, completely sure.)
Indeed NSImage can be initialized by initWithContentsOfURL:.
But it can also be initialized by initWithData: or initWithPasteboard:.
The NSURL is no strict requirement for initializing a NSImage.
In other words, the NSImage might be initialized without using a URL.
The NSImage is simply a container for image representations.
Quote by Apple:
An NSImage object manages a group of image representations.
Solutions
Change you 'process' to accept NSImage.
Write the NSImage to a temporary file and use that file path.
If the image is being delivered via the standard pasteboard (i.e. the copy/paste mechanism) then there is no way to refer to it by URL because it might not have one. For instance, if you open a document in Word or Pages, select an image and copy it there is no possible way to create a URL reference to that image. It's on the pasteboard but not in the file system in a form you can access.
I think that you're going to have to modify your code to handle NSImage objects directly.

How can I load an NSImage representation of the icon for my application?

I have a custom icon file (MyApp.icns) set up for my Cocoa App. How can I access an NSImage representation of the icon from within my application?
Something like the following would be perfect:
NSImage * iconImage = [MyApplication defaultIconAsImage];
But I'm sure it isn't that easy :)
I can, of course, get a path to the icon file as follows:
NSString * iconPath = [[NSBundle mainBundle]
pathForResource:#"MyApp" ofType:#"icns"];
But it seems to me that there should be some kind of standard way to access the icon file for the application, other than calling it by name, since the name could change.
What is the proper way to do this?
[NSApp applicationIconImage]
Just for completeness - This is how you get the icon for any application or file on your system.
NSImage *iconImage = [[NSWorkspace sharedWorkspace] iconForFile:#"path"];
Pass in the path to the application bundle for an application icon or the path to a file for the icon associated with the file.
Note that -[NSApplication applicationIconImage] doesn't return the correct icon when a custom icon is pasted onto the app. Then you need to do:
NSString* appPath = [[NSBundle mainBundle] bundlePath];
NSImage* appIcon = [[NSWorkspace sharedWorkspace] iconForFile:appPath];
(Reference the dock icon code I wrote for Chromium: http://src.chromium.org/svn/trunk/src/chrome/browser/ui/cocoa/dock_icon.mm)

Printing a file to NSImage not working right (cocoa)

This is probably a n00b question so I apologize in advance. I'm working with NSImage for the first time and basically I need to simply take a picture that is in my Resources folder, and have it display in an NSView/NSImageWell when a button is clicked.
NSImage *image = [[NSImage alloc] initWithContentsOfFile:#"tiles.PNG"];
if ( [image isValid] ) {
NSImageView *view = [[NSImageView alloc] init];
[selection setImage:image];
[selection setImageScaling:NSScaleProportionally];
}
else {
--- This line of code always activates meaning my image isn't valid
}
My only guess is that I am getting the path wrong to the image file and I have looked all over for the right way to access it. Another guess is that I have my code wrong. Anybody familiar with this? Thanks!
I work a lot more with the iPhone, but initWithContentsOfFile seems to require a full/relative path, which I assume tiles.PNG wouldn't fulfill.
I'd use the class method imageNamed:(NSString *)name, which will search your bundle for you.
You should use NSBundleManger to locate the image like so:
NSBundle *mb=[NSBundle mainBundle];
NSString *fp=[mb pathForResource:#"titles" ofType:#"PNG"];
UIImage *img=[UIImage imageWithContentsOfFile:fp];
That way you don't have to mess with internal paths yourself. Otherwise, you have to have the path relative to the final built product which is hard to create and maintain.

Why is bitmapImageRepForCachingDisplayInRect: creating an empty image?

I have a very simple bit of code that is supposed to capture the bitmap of a view. This used to work in Leopard, but seems horribly broken in Snow Leopard.
Here is the code, responding to a button press on the window:
- (IBAction)snapshot:(id)sender
{
NSView* view = [[sender window] contentView];
NSBitmapImageRep* bitmap
= [view bitmapImageRepForCachingDisplayInRect:[view bounds]];
NSData *tiff = [bitmap TIFFRepresentation];
[tiff writeToFile:[#"~/Desktop/snapshot.tiff" stringByExpandingTildeInPath]
atomically:YES];
}
Clicking on the button to take a snapshot just results in a fully transparent image.
Am I just completely clueless here, or is this bitmap caching method broken?
A simple project — basically a starter NSDocument project, with a button that calls this code -- can be found here.
-bitmapImageRepForCachingDisplayInRect: doesn't actually capture anything; it just generates a blank bitmap ready for caching. You need to call -cacheDisplayInRect:toBitmapImageRep: to do that.

Resources