How to load an image stored in a static library - iphone

in my iphone app, I am linking with a static library containing objective c files and images. Is it possible to load an image from a static library? I have tried
[UIImage imageNamed:[[NSBundle mainBundle] pathForResource:#"imageName" ofType:#"png"]];
but obviously the image is not in the main bundle, it's in the static library and the NSBundle class seems only to offer access to the main bundle and to bundles with known paths. Is there a way to load an image from a static library on the iPhone?

The simplest way is to store the image in an inline character array:
const char imageData[] = { 0x00, 0x01, 0xFF, ... };
And later when you need it:
UIImage *image = [UIImage imageWithData:[NSData dataWithBytesNoCopy:imageData length:sizeof(imageData) freeWhenDone:NO]];
You will have to convert your image's binary data (after saved as either PNG or JPEG) to the character array manually (or write a script to do so)

It's not clear what you mean by "the image is [...] in the static library". Static libraries are plain files (with the .a extension) and contain archived object files. Bundles on the other hand are directory hierarchies (containing executables and other resources).
If you link a static library, the code from the library is included directly into your executable. No files are copied to the application bundle, so there's no way to copy the image.
If you have the image file with your static library, you can simply copy it to your application bundle by adding a copy files build phase to your target in Xcode.

Do you use an Absolute Path in the static library copy files build phase and point it to the client application? I tried something like this and the images still cannot be accessed.

Related

iOS PDF with libHaru issue

I use libHary to create PDF.
I use this answer iOS SDK - Programmatically generate a PDF file to create pdf.
In this library method HPDF_LoadPngImageFromFile exist, but I need to load image from data (or UIImage). How can I do that?
Now the best solution for me is to right data to png file and then load it, but I thing better solution should exist.
LibHaru is platform independent so it does not know about about UIImage or NSData.
You have 2 options:
1. Save the UIImage/NSData to a file and then load the image from the file using HPDF_LoadPngImageFromFile method or
2. Save the UIImage to a NSData object, get a pointer to the NSData buffer ([nsdataobject bytes] method) and then use HPDF_LoadPngImageFromMem to load the image from memory.

jpg images are shown in iphone simulator but not in iPhone test device

i'm sorry for my english.
i'm new in iphone development and happens to me a strange things.
I have a set of jpg images to show in a table view. When i test the app in iphone simulator everything is ok and work properly but when built and run the same code in iphone test device the same images aren't displayed.
Another strange behavior is that with a set of png images instead of jpg are shown perfectly in simulator like as in iphone test device.
Anyone can suggest me a solution?
I detect the name of image to load from a json file. This is the code that i use to show the image:
UIImageView *immaginePiadina = [[UIImageView alloc] initWithFrame:immagineValueRect];
[immaginePiadina setImage:[UIImage imageNamed:[item objectForKey:#"immagine"]]];
where [item objectForKey:#"immagine"] is an element of my json file like this:
"nome": "66",
"immagine": "pianetapiadabufalavesuviani",
"prezzo": "€ 7,50",
"nomeingrediente": [
"bufala",
"vesuviani"
]
How you can see i refer to the image with only the name of the file and without the file extension. I did it in this way to show image retina, it's wrong?
I exclude that i wrote a different case sensitive name because the png set works properly.
thanks a lot!!
There are possibly two separate issues that need separation, here is how to solve your problem.
First write a method using the NSFileManager, that given a file path verifies a file exists and has a size greater than 0. Insert a call to this everywhere you fail to open an image. If you use "imageNamed" then get the path to the bundle and create the path. If this method fails to find an image, fix it.
Second, the image decoding is different for the simulator and the device - the simulator uses the full OSX libraries. So take one image that fails to open and move it somewhere. Open it in Preview and export it using the same name but with png+alpha format. Change your code to expect a png not a jpg, and retest. Make sure you still use the first method to insure the file is there.
Once you get one success you can try other options, like using Preview exported jpegs. The reason this should work is that all of these image formats permit a huge range of options all of which iOS does not support.
Given that the current format us the problem, you can script changes using the "sips" program, which is what Preview uses.
I solve my problem using the following code:
NSString* path = [[NSBundle mainBundle] pathForResource:[item objectForKey:#"immagine"] ofType:#"jpg"];
NSLog(#"%#",path);
UIImage* theImage = [[UIImage alloc] initWithContentsOfFile:path];
I don't know the reason but in this way i haven't any problem to display jpg in my iPhone test device. Maybe because NSBundle specify also the extension of the file.
Thanks #David-h that directed me in the right way to solve my problem.
Check the extensions of your images. If you write .PNG, in the simulator is Ok, but not in the device.

Assets naming for iPhone and iPad

Is it possible to have an image asset named architecture.png and rename it as architecture~ipad.png for the iPad version? And still use it in code as:
[UIImage imageWithName:#"architecture.png"];
will this then look for architecture~ipad for the iPad version?
If you have two image resources in your app:
"architecture.png" (iPhone version)
"architecture~ipad.png" (iPad version)
then
[UIImage imageWithName:#"architecture.png"]
will automatically load the correct one on iPhone/iPad devices.
(As DOOManiac correctly noticed, this works on iOS 4 and later.)
For more information, see "iOS Supports Device-Specific Resources" in the Resource Programming Guide.
Update:
From the link iOS Supports Device-Specific Resources, It looks like this is possible from iOS 4.0 onwards.
In iOS 4.0 and later, it is possible to mark individual resource files
as usable only on a specific type of device. This capability
simplifies the code you have to write for Universal applications.
Rather than creating separate code paths to load one version of a
resource file for iPhone and a different version of the file for iPad,
you can let the bundle-loading routines choose the correct file. All
you have to do is name your resource files appropriately.
To associate a resource file with a particular device, you add a
custom modifier string to its filename. The inclusion of this modifier
string yields filenames with the following format:
<basename><device>.<filename_extension>
The <basename> string represents the original name of the resource
file. It also represents the name you use when accessing the file from
your code. Similarly, the <filename_extension> string is the standard
filename extension used to identify the type of the file. The <device>
string is a case-sensitive string that can be one of the following
values:
~ipad - The resource should be loaded on iPad devices only.
~iphone - The resource should be loaded on iPhone or iPod touch
devices only.
You can apply device modifiers to any type of resource file. For
example, suppose you have an image named MyImage.png. To specify
different versions of the image for iPad and iPhone, you would create
resource files with the names MyImage~ipad.png and MyImage~iphone.png
and include them both in your bundle. To load the image, you would
continue to refer to the resource as MyImage.png in your code and let
the system choose the appropriate version, as shown here:
UIImage* anImage = [UIImage imageNamed:#"MyImage.png"]; On an iPhone
or iPod touch device, the system loads the MyImage~iphone.png resource
file, while on iPad, it loads the MyImage~ipad.png resource file. If a
device-specific version of a resource is not found, the system falls
back to looking for a resource with the original filename, which in
the preceding example would be an image named MyImage.png.
For devices which supports iOS < 4.0, you can follow the below approach. But I dont think it is needed any more. Still keeping it as it is.
One solution I can think of is, by defining a macro for iPad to append ~ipad.png for every image files. Then always call this macro while using this method as [UIImage imageWithName:imageName(#"architecture")]; which will convert it as [UIImage imageWithName:#"architecture.png"]; for iPhone and [UIImage imageWithName:#"architecture~ipad.png"]; for iPad.
For eg:-
#define IMAGENAME(Name) (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)?[(Name) stringByAppendingString:(#"~ipad.png")]:[(Name) stringByAppendingString:(#".png")]
and then use it as [UIImage imageWithName:IMAGENAME(#"architecture")];
it can also be defined as,
#define IMAGENAME(Name) (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)?[(Name) stringByReplacingOccurrencesOfString:#".png" withString:#"~ipad.png"]:(Name)
and then use it as [UIImage imageWithName:IMAGENAME(#"architecture.png")];
Another solution is to subclass UIImage class and override imageWithName method to have this logic implemented here. You need to search for .png in the name param and replace it with a ~ipad.png for iPad. After that you can directly use it as [UIImage imageWithName:#"architecture.png"] for both iPad and iPhone. This can also be achieved by creating a category on NSObject or UIImage. I dont think there are any other ways to achieve this.

Can the iPhone render vector graphics files directly? What formats are supported?

Is it possible to render a vector image file on the iPhone in the same way that one can render a bitmap (png, jpeg) file? I have tried eps and pdf files, neither of which seems to work – they are displayed correctly in Interface Builder but do not display when run.
The console outputs a message along the lines of 'Could not load the "image.pdf" image referenced from a nib in the bundle with identifier "com.yourcompany.project"'
All my searches on this come up with discussion of drawing a vector files using OpenGL, etc. Is this the only way? Since there is no mention of vector file support I am unsure if my files are not being loaded because of problems with the files (I have tried different versions), or because they are not supported.
One can render PDF images natively, and create them as well, with Core Graphics. Something like this:
void DrawPDF (CGContextRef context, NSString *name)
{
NSURL *url = [NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource: name ofType: #"pdf"]];
CGPDFDocumentRef doc = CGPDFDocumentCreateWithURL((CFURLRef)url);
CGPDFPageRef page = CGPDFDocumentGetPage(doc, 1);
CGRect box = CGPDFPageGetBoxRect(page, kCGPDFCropBox); //kCGPDFArtBox);
CGContextDrawPDFPage(context, page);
CGPDFDocumentRelease(doc);
}
UIWebView of course for SVG.
There is no direct support for vector graphics formats like there is for PNG and JPEG. Any vector graphics rendering would be done programmatically, i.e. stroking and filling path objects using Quartz drawing calls.
PDFs can be loaded by UIWebView. If you need more control you can use Quartz 2D to render PDFs: Quartz2D
Yes, it supports SVG.
You can convert your vector files to SVG and render them by conversion to javascript using a library like Raphael. My Raphael-based web sites have flash-like functionality and they render perfectly on the iPhone--the benefit of web standards!
You can use something like http://www.codeautomat.com/ to convert SVG files to Core Graphics Objective-C code.

iphone: relative paths to local file?

Using MontoTouch for .NET C# iPhone development. (though should not matter)
In the iPhoneSimulator, I use UIImage.FromFile (#"images/Bahai.png"); to get the Bahai.png from the images folder.
However, when I run it in debug mode on my iTouch, the function returns a null.
Only if I put the image file in the root does it work in the iTouch.
Is there a different relative path I need to use?
Ian
Not sure if this will help, but in objective-C, I would load an image from the app bundle like this:
UIImage *image = [UIImaged imageNamed:#"Bahai.png"];
For other types of files, I would get the absolute path like this:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Bahai" ofType:#"png"];