简体   繁体   中英

How to Save UIImage to a Transparent PNG?

I'm not sure where I'm doing the mistake, that's why I'd like to paste here some block of codes in order to find out what went wrong.

I have some PNG images that have transparent background and with using the block of codes below I'm trying save the selected image to application folder and NSUserDefault. And then I'm trying to call that saved image from application folder and display on UIBarButtonItem.

The purpose of saving to NSUserDefault as well is for testing.

So,

This is how I'm selecting the image.

- (IBAction)btnPressed:(UIButton *)sender
{
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum])
    {
        UIImagePickerController *imgPicker = [[UIImagePickerController alloc] init];
        imgPicker.delegate = self;
        imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        imgPicker.mediaTypes = [NSArray arrayWithObject:(NSString *)kUTTypeImage];
        imgPicker.allowsEditing = NO;

        [self presentViewController:imgPicker animated:YES completion:nil];
    }

}

And with this I'm saving it to application using didFinishPickingMediaWithInfo;

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
    [self dismissViewControllerAnimated:YES completion:nil];

    if ([mediaType isEqualToString:(NSString *) kUTTypeImage])
    {
        UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

        //I believe this has the problem.
        NSData *pngData = UIImagePNGRepresentation(image);

        NSString *stringPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:@"AppImages"];;

        NSError *error = nil;

        if (![[NSFileManager defaultManager] fileExistsAtPath:stringPath])
        [[NSFileManager defaultManager] createDirectoryAtPath:stringPath withIntermediateDirectories:NO attributes:nil error:&error];

        NSString *fileName = [stringPath stringByAppendingPathComponent:@"logoImage.png"];
        [pngData writeToFile:fileName atomically:YES];
        NSUserDefaults *logoUserDef = [NSUserDefaults standardUserDefaults];
        [logoUserDef setValue:pngData forKey:@"logoImageData"];
    }
}

Note: I don't have problem for the images that doesn't have transparent background.

And lastly this is how I'm calling it from both Application and NSUserDefault.

Using both NSUserDefaults and AppDirectory to see if they're showing different result.

if ([[NSUserDefaults standardUserDefaults] objectForKey:@"logoImageData"])
{
    NSUserDefaults *user = [NSUserDefaults standardUserDefaults]; 
    UIImage *testing = [UIImage imageWithData:[user valueForKey:@"logoImageData"]];

    NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    UIImage * image = [self loadImageWithFileName:@"logoImage" ofType:@"png" inDirectory:documentsDirectory];

    UIBarButtonItem *logoBarButton = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(logoTapped)];
    logoBarButton.imageInsets = UIEdgeInsetsMake(9, 0, 9, 90);
    logoBarButton.image = [logoBarButton.image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    [self.navigationItem setLeftBarButtonItems:@[logoBarButton]];
}

And method that returns UIImage from App Document.

-(UIImage *)loadImageWithFileName:(NSString *)fileName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
    UIImage * result = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@/%@.%@",   directoryPath, @"AppImages", fileName, [extension lowercaseString]]];

    return result;
}

I don't know from where I'm doing wrong but as always, when I select image that has transparent background. It always convert its background to White. I need to save it as it is as transparent. I've searched a lot but couldn't find anything to solve this.

Any help is appreciated.

Solved the problem!

The block of codes that I posted with my question have nothing wrong. The problem was occurring from iTunes, when I synchronize images from my Mac to my iPhone iTunes convert them to JPEG and because of this images loses their transparency etc... and when I select images using my app, I was selecting them as JPEG without being aware and that's why I had these problems.

So I came up with a solution to have images via email. I just send them from my mac to iPhone with e-mail, and by this images didn't lose anything as a feature. After that when I used them in app as a right image, the program worked as it supposed to be.

You wrote

     [logoUserDef setValue:pngData forKey:@"logoImageData"];

but I don't see where you synchronize. So add:

      [logoUserDef synchronize];

I was able to preserve the transparency when saving an image to the Documents directory after using

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{

    [self dismissViewControllerAnimated:YES completion:nil];
    UIImage *img = [info valueForKey:UIImagePickerControllerOriginalImage];
    [yourButton setImage:img forState:UIControlStateNormal];

    NSData *pngData = UIImagePNGRepresentation(img);
    //do something with pngData
}

The key is the UIImagePickerControllerOriginalImage instead of other options like UIImagePickerControllerEditedImage.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM