2

I want to hard code the binary data for an image in a class file. When the class gets initialized, create an NSImage from that data. Storing the image in the resources folder is not an option.

Is this possible and how?

joels
  • 7,249
  • 11
  • 53
  • 94

2 Answers2

4

use NSData rather than NSString.

NSImage is NSCoding compliant - it knows how to archive itself, and how to create/read image representations of other file formats.

if you want to work with another image representation, you can use CGImage apis to create a CGImage, which can then be used to create a NSImage.

justin
  • 104,054
  • 14
  • 179
  • 226
  • I can get it into NSData no problem but what do I do with it after that? As for NSCoding, would that be saved to a plist or something that I could just copy and paste? – joels May 28 '11 at 22:56
  • the short path from NSData representation to data blob for a c source is to create a simple program which reformats the output of the data representation returned by `[data description]`, then print it out to the console and copy/paste that to your source file (or have it generate a source file). that, i presume, would work. – justin May 29 '11 at 00:28
  • "create a simple program which reformats the output of the data representation" That's the big question. How should it be formatted? Or, can I just copy the print out from [data description] and paste it into the source into var NSString *dataDescription = "printOutFromNSLog" then call NSData *fromDataDescription = [NSData dataFromString]? – joels May 29 '11 at 02:58
  • the result of `description` is implementation defined. from the way it is dumped as i see it, the basic needs are to convert it to unsigned 32bit hex value (prepend `0xU`) and add 32 bit Host->Big Endian swapping for each value in the resultant array. – justin May 30 '11 at 01:48
3
//get the image
NSImage *newImage = [[NSImage alloc] initWithContentsOfFile:@"~/Desktop/testImg.png"];
//convert to BitmapImageRep
NSBitmapImageRep *bitmap = [[newImage representations] objectAtIndex:0];
//convert to NSData
NSData *data = [bitmap representationUsingType: NSPNGFileType properties: nil];
//base64 encode and now I have the string. 
NSString *imageString = [data encodeBase64WithNewlines:NO];
NSLog(@"image %@", imageString);
//No that I have the string, I can hard code it into my source code (paste it in).

//When I want to create an image out of it I just get the imageString and convert it to an image
NSData *revData = [imageString decodeBase64WithNewlines:NO];
newImage = [[NSImage alloc] initWithData:revData];

I have 2 NSData Categories I use here (encodeBase64WithNewlines:NO and decodeBase64WithNewlines:NO) You will have to include libcrypto.dylib for them to work. I think I copied them from Cocoa Dev

- (NSString *) encodeBase64WithNewlines: (BOOL) encodeWithNewlines
{
// Create a memory buffer which will contain the Base64 encoded string
BIO * mem = BIO_new(BIO_s_mem());

// Push on a Base64 filter so that writing to the buffer encodes the data
BIO * b64 = BIO_new(BIO_f_base64());
if (!encodeWithNewlines)
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
mem = BIO_push(b64, mem);

// Encode all the data
BIO_write(mem, [self bytes], [self length]);
int flushResult = BIO_flush(mem);
if(flushResult != 0){
    //throw some warning?
}

// Create a new string from the data in the memory buffer
char * base64Pointer;
long base64Length = BIO_get_mem_data(mem, &base64Pointer);
NSData * base64data = [NSData dataWithBytesNoCopy:base64Pointer length:base64Length freeWhenDone:NO];
NSString * base64String = [[NSString alloc] initWithData:base64data encoding:NSUTF8StringEncoding];

// Clean up and go home
BIO_free_all(mem);
return [base64String autorelease];
}



- (NSData *)decodeBase64WithNewLines:(BOOL)encodedWithNewlines
{
// Create a memory buffer containing Base64 encoded string data
BIO * mem = BIO_new_mem_buf((void *) [self bytes], [self length]);

// Push a Base64 filter so that reading from the buffer decodes it
BIO * b64 = BIO_new(BIO_f_base64());
if (!encodedWithNewlines)
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
mem = BIO_push(b64, mem);

// Decode into an NSMutableData
NSMutableData * data = [NSMutableData data];
char inbuf[512];
int inlen;
while ((inlen = BIO_read(mem, inbuf, sizeof(inbuf))) > 0)
    [data appendBytes: inbuf length: inlen];

// Clean up and go home
BIO_free_all(mem);
return data;
}
joels
  • 7,249
  • 11
  • 53
  • 94