IOS Objective C将具有透明背景的PNG文件加载到UIImageView

时间:2016-11-22 15:05:41

标签: objective-c uiimageview png uiimagepickercontroller transparency

我正在尝试将具有透明背景的PNG文件加载到UIImageView中(如果重要的话,使用Objective C,XCode 8.0进行开发,用于IOS 10.0目标)。 当在UIImageView中显示时,图像的背景颜色显示为BLACK(见下文)。

如何将任意PNG文件加载到UIImageView,以保留其透明背景?

奇怪的是,我的应用资产中有透明背景的PNG图像,它们显示在UIImageView中,没有任何额外的混乱。

请注意,在下面的代码中,我尝试过的一件事是重建从imagePicker传递的UIImage(请参阅imageWithImage),为新图像设置新的图形上下文。我曾经看到过这种方法在一些帖子中用于模糊相似的问题,但它没有用(更不用说看起来很愚蠢的IOS会要求它支持加载图像中定义的透明度)。

我正在测试的PNG图像是一个标准的PNG32(从互联网上收集用于测试目的 - 请注意我已尝试过许多其他图像):

enter image description here

左下方显示加载上图之前的应用程序屏幕,右侧显示加载的图像: enter image description here

通过点击屏幕底部的“选择图像”打开的imagePicker选择PNG图像文件。

我的ViewController代码:

//
//  ViewController.m
//  ImageTest
//

#import "ViewController.h"
#import "MobileCoreServices/MobileCoreServices.h"


#define FONT_SIZE_BUTTON    32

@interface ViewController ()

@end

@implementation ViewController

UIImageView *myImageView;
UIImage *myImage;
UIButton *btnSelect;

- (void)viewDidLoad {

    NSLog(@"viewDidLoad" );

    [super viewDidLoad];

    CGRect screenRect = [[UIScreen mainScreen] bounds];

    CGFloat btnHeight = 40;
    CGFloat btnMargin = 10;
    CGFloat btnWidth = screenRect.size.width - 2*btnMargin;
    CGFloat btnULY = screenRect.size.height - btnHeight - 2*btnMargin;

    btnSelect  = [[UIButton alloc] initWithFrame:CGRectMake(btnMargin, btnULY, btnWidth, btnHeight)];
    [btnSelect.titleLabel setFont:[UIFont boldSystemFontOfSize:FONT_SIZE_BUTTON]];
    [btnSelect setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
    [btnSelect setTitle :@"Select Image" forState:UIControlStateNormal];
    [btnSelect.layer setBorderWidth:4.0f];
    [btnSelect.layer setBorderColor:[UIColor blueColor].CGColor];
    [btnSelect setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [btnSelect setTitleColor:[UIColor grayColor] forState:UIControlStateSelected];
    [btnSelect setTitleColor:[UIColor grayColor] forState:UIControlStateDisabled];
    btnSelect.backgroundColor = [UIColor whiteColor];
    btnSelect.tag = 4200;
    [btnSelect addTarget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside];
    btnSelect.userInteractionEnabled = true;

    CGFloat ulx = 10;
    CGFloat uly = 20;
    CGFloat width = screenRect.size.width - 2*ulx;
    CGFloat height = width * 9.0 / 16.0;

    CGRect imageFrame = CGRectMake(ulx, uly, width, height);

    myImageView = [[UIImageView alloc] initWithFrame:imageFrame];
    myImageView.alpha = 1.0f;
    myImageView.backgroundColor = [UIColor lightGrayColor];
    myImageView.contentMode = UIViewContentModeScaleAspectFit;

    myImageView.opaque = false;
    [[myImageView layer] setOpaque:false];

    [[myImageView layer] setBorderWidth:4.0f];
    [[myImageView layer] setBorderColor:[UIColor redColor].CGColor];

    // Add elements to this view controller
    [self.view addSubview:myImageView];
    [self.view addSubview:btnSelect];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


// Ensure image is opened honoring transparency of PNGs
- (UIImage *)imageWithImage:(UIImage *)image {
    CGSize newSize = image.size;
    CGRect newRect = CGRectMake(0,0,newSize.width, newSize.height);

    UIGraphicsBeginImageContextWithOptions(newSize, NO, 1.0);

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [[UIColor clearColor] set];
    CGContextFillRect(ctx, newRect);

    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.Height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#pragma mark - Select Actions
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- (IBAction)onClick: (UIButton *)btn
{
    NSLog(@"onClick" );
    //    DDLogInfo(@"%@:%@", THIS_FILE, THIS_METHOD );

    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.delegate = self;
    picker.allowsEditing = YES;
    picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    NSMutableArray *mediaTypes = [[NSMutableArray alloc] init];
    [mediaTypes addObject:(__bridge NSString *)kUTTypeImage];
    picker.mediaTypes = mediaTypes;

    [self presentViewController:picker animated:YES completion:NULL];
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#pragma mark - UIImagePicker's Delegate
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

    NSLog(@"imagePickerController" );

    UIImage *chosenImage = [self imageWithImage:info[UIImagePickerControllerEditedImage]];
//    UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
//    UIImage *chosenImage = [info[UIImagePickerControllerEditedImage] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
    if (myImageView != nil)
        myImageView.image = chosenImage;

    myImage = chosenImage;

    [picker dismissViewControllerAnimated:YES completion:NULL];
}



- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {

    [picker dismissViewControllerAnimated:YES completion:NULL];
}


@end

**

使用FINAL FIX编辑

**

更新的应用屏幕的屏幕截图,以显示问题:

enter image description here

和最终(固定)代码,显示使用字典键(UIImagePickerControllerOriginalImage)和字典键(UIImagePickerControllerEditedImage)之间的区别:

//
//  ViewController.m
//  ImageTest
//
//  Created by Robb Main on 2016-11-21.
//  Copyright © 2016 Robb Main. All rights reserved.
//

#import "ViewController.h"
#import "MobileCoreServices/MobileCoreServices.h"


#define FONT_SIZE_BUTTON    32

@interface ViewController ()

@end

@implementation ViewController

UIImageView *myImageView1;
UIImageView *myImageView2;
UIImageView *myImageView3;
UIImage *myImage;
UIButton *btnSelect;

- (void)viewDidLoad {

    NSLog(@"viewDidLoad" );

    [super viewDidLoad];

    CGRect screenRect = [[UIScreen mainScreen] bounds];

    CGFloat btnHeight = 40;
    CGFloat btnMargin = 10;
    CGFloat btnWidth = screenRect.size.width - 2*btnMargin;
    CGFloat btnULY = screenRect.size.height - btnHeight - 2*btnMargin;

    btnSelect  = [[UIButton alloc] initWithFrame:CGRectMake(btnMargin, btnULY, btnWidth, btnHeight)];
    [btnSelect.titleLabel setFont:[UIFont boldSystemFontOfSize:FONT_SIZE_BUTTON]];
    [btnSelect setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
    [btnSelect setTitle :@"Select Image" forState:UIControlStateNormal];
    [btnSelect.layer setBorderWidth:4.0f];
    [btnSelect.layer setBorderColor:[UIColor blueColor].CGColor];
    [btnSelect setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [btnSelect setTitleColor:[UIColor grayColor] forState:UIControlStateSelected];
    [btnSelect setTitleColor:[UIColor grayColor] forState:UIControlStateDisabled];
    btnSelect.backgroundColor = [UIColor whiteColor];
    btnSelect.tag = 4200;
    [btnSelect addTarget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside];
    btnSelect.userInteractionEnabled = true;

    CGFloat imgMargin = 60;
    CGFloat ulx = imgMargin;
    CGFloat uly = 20;
    CGFloat imgWidth = screenRect.size.width - 2*imgMargin;
    CGFloat imgHeight = imgWidth * 9.0 / 16.0;

    CGRect imageFrame = CGRectMake(ulx, uly, imgWidth, imgHeight);

    myImageView1 = [[UIImageView alloc] initWithFrame:imageFrame];
    myImageView1.alpha = 1.0f;
    myImageView1.backgroundColor = [UIColor lightGrayColor];
    myImageView1.contentMode = UIViewContentModeScaleAspectFit;
    myImageView1.opaque = NO;
    [myImageView1.layer setOpaque:NO];
//    myImageView.clearsContextBeforeDrawing = YES;
    [myImageView1.layer setBorderWidth:4.0f];
    [myImageView1.layer setBorderColor:[UIColor redColor].CGColor];

    myImageView1.image = [UIImage imageNamed:@"imageTest.png"];

    uly += imgHeight+8;
    CGFloat lblHeight = 10;
    CGRect lblFrame = CGRectMake( ulx, uly, imgWidth, lblHeight);
    UILabel *myLabel1 = [[UILabel alloc] initWithFrame:lblFrame];
    [myLabel1 setFont:[UIFont systemFontOfSize:12]];
    myLabel1.text = @"PNG Image from assets";

    uly += lblHeight+20;
    imageFrame.origin.y = uly;

    myImageView2 = [[UIImageView alloc] initWithFrame:imageFrame];
    myImageView2.alpha = 1.0f;
    myImageView2.backgroundColor = [UIColor lightGrayColor];
    myImageView2.contentMode = UIViewContentModeScaleAspectFit;
    myImageView2.opaque = NO;
    [myImageView2.layer setOpaque:NO];
//    myImageView2.clearsContextBeforeDrawing = YES;
    [myImageView2.layer setBorderWidth:4.0f];
    [myImageView2.layer setBorderColor:[UIColor redColor].CGColor];

    uly += imgHeight+8;
    lblFrame.origin.y = uly;

    UILabel *myLabel2 = [[UILabel alloc] initWithFrame:lblFrame];
    [myLabel2 setFont:[UIFont systemFontOfSize:12]];
    myLabel2.text = @"UIImagePickerControllerOriginalImage";

    uly += lblHeight+20;
    imageFrame.origin.y = uly;

    myImageView3 = [[UIImageView alloc] initWithFrame:imageFrame];
    myImageView3.alpha = 1.0f;
    myImageView3.backgroundColor = [UIColor lightGrayColor];
    myImageView3.contentMode = UIViewContentModeScaleAspectFit;
    myImageView3.opaque = NO;
    [myImageView3.layer setOpaque:NO];
//    myImageView3.clearsContextBeforeDrawing = YES;
    [myImageView3.layer setBorderWidth:4.0f];
    [myImageView3.layer setBorderColor:[UIColor redColor].CGColor];

    uly += imgHeight+8;
    lblFrame.origin.y = uly;

    UILabel *myLabel3 = [[UILabel alloc] initWithFrame:lblFrame];
    [myLabel3 setFont:[UIFont systemFontOfSize:12]];
    myLabel3.text = @"UIImagePickerControllerEditedImage";

    // Add elements to this view controller
    [self.view addSubview:myImageView1];
    [self.view addSubview:myLabel1];
    [self.view addSubview:myImageView2];
    [self.view addSubview:myLabel2];
    [self.view addSubview:myImageView3];
    [self.view addSubview:myLabel3];
    [self.view addSubview:btnSelect];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#pragma mark - Select Actions
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- (IBAction)onClick: (UIButton *)btn
{
    NSLog(@"onClick" );
    //    DDLogInfo(@"%@:%@", THIS_FILE, THIS_METHOD );

    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.delegate = self;
    picker.allowsEditing = NO;
    picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    NSMutableArray *mediaTypes = [[NSMutableArray alloc] init];
    [mediaTypes addObject:(__bridge NSString *)kUTTypeImage];
    picker.mediaTypes = mediaTypes;

    [self presentViewController:picker animated:YES completion:NULL];
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#pragma mark - UIImagePicker's Delegate
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

    NSLog(@"imagePickerController" );

    myImage = info[UIImagePickerControllerOriginalImage];
    if (myImageView2 != nil)
        myImageView2.image = myImage;

    if (myImageView3 != nil)
        myImageView3.image = info[UIImagePickerControllerEditedImage];

    [picker dismissViewControllerAnimated:YES completion:NULL];
}



- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {

    [picker dismissViewControllerAnimated:YES completion:NULL];
}


@end

这项工作,虽然我的原因并不清楚:

  1. 对于无效的字典键,imagePicker不会返回nil(我已指定编辑是不允许的)。

  2. “已编辑”图片会删除透明度信息。

1 个答案:

答案 0 :(得分:0)

您的主要问题是在获取所选图片时使用UIImagePickerControllerEditedImage而不是UIImagePickerControllerOriginalImage。编辑后的图像会丢失Alpha通道,导致黑色而不是透明度。

您也不需要imageWithImage:方法。