从UIImage PNG文件中删除透明度(不是ALPHA VALUE)

时间:2014-04-27 18:06:10

标签: ios uiimageview uiimage png

我正在使用一个音乐播放器,它从MP3中获取ID3资源中的图像。我遇到过某些ArtWorks具有透明度。 (图像具有透明部分)。这导致我的应用程序加载这些图像非常慢。我需要找到一种方法来在显示之前删除UIImage的透明度。或者还有其他建议吗?

"用白色"

等颜色替换图像的透明部分

如有必要,请提供我的代码:

NSURL *url = ad.audioPlayer.url;
AVAsset *asset = [AVAsset assetWithURL:url];
for (AVMetadataItem *metadataItem in asset.commonMetadata) {
    if ([metadataItem.commonKey isEqualToString:@"artwork"]){
        NSDictionary *imageDataDictionary = (NSDictionary *)metadataItem.value;
        NSData *imageData = [imageDataDictionary objectForKey:@"data"];
        UIImage *image = [UIImage imageWithData:imageData];

        // This is the image and the place in code where I want to convert it

       _artworkImageView.image = image;
       _bgImage.image = [image applyDarkEffect];

    }
}

3 个答案:

答案 0 :(得分:4)

我也有样本问题,实际上我不想删除alpha通道,只是用白色替换透明颜色。我试图删除Remove alpha channel from UIImage中的评论中建议的alpha颜色,但令人烦恼的是,在透明颜色变成黑色之后,我无法弄清楚如何使其变白。

最终,我最终只是在图像下面用透明部分绘制了一个白色背景而没有碰到alpha通道。

代码在这里:

// check if there is alpha channel
CGImageAlphaInfo alpha = CGImageGetAlphaInfo(wholeTemplate.CGImage);
if (alpha == kCGImageAlphaPremultipliedLast || alpha == kCGImageAlphaPremultipliedFirst ||
    alpha == kCGImageAlphaLast || alpha == kCGImageAlphaFirst || alpha == kCGImageAlphaOnly)
{
    // create the context with information from the original image
    CGContextRef bitmapContext = CGBitmapContextCreate(NULL,
                                                       wholeTemplate.size.width,
                                                       wholeTemplate.size.height,
                                                       CGImageGetBitsPerComponent(wholeTemplate.CGImage),
                                                       CGImageGetBytesPerRow(wholeTemplate.CGImage),
                                                       CGImageGetColorSpace(wholeTemplate.CGImage),
                                                       CGImageGetBitmapInfo(wholeTemplate.CGImage)
                                                       );

    // draw white rect as background
    CGContextSetFillColorWithColor(bitmapContext, [UIColor whiteColor].CGColor);
    CGContextFillRect(bitmapContext, CGRectMake(0, 0, wholeTemplate.size.width, wholeTemplate.size.height));

    // draw the image
    CGContextDrawImage(bitmapContext, CGRectMake(0, 0, wholeTemplate.size.width, wholeTemplate.size.height), wholeTemplate.CGImage);
    CGImageRef resultNoTransparency = CGBitmapContextCreateImage(bitmapContext);

    // get the image back
    wholeTemplate = [UIImage imageWithCGImage:resultNoTransparency];

    // do not forget to release..
    CGImageRelease(resultNoAlpha);
    CGContextRelease(bitmapContext);
}

答案 1 :(得分:1)

试试这个......

//First create a white image that has an equal size with your image.

        CGImageRef sourceImage = yourImage.CGImage;

        CFDataRef theData;
        theData = CGDataProviderCopyData(CGImageGetDataProvider(sourceImage));

        UInt8 *pixelData = (UInt8 *) CFDataGetBytePtr(theData);

        int dataLength = CFDataGetLength(theData);

        int red = 0;
        int green = 1;
        int blue = 2;
        int alpha = 3;

        for (int i = 0; i < (dataLength); i += 4) {

        //create white pixels    

            int r = 255;
            int b = 255;
            int g = 255;
            int al = 255;


            pixelData[i + red] = r;
            pixelData[i + blue] = b;
            pixelData[i + green] = g;
            pixelData[i + alpha] = al;


        }

        CGContextRef context;
        context = CGBitmapContextCreate(pixelData,
                                        CGImageGetWidth(sourceImage),
                                        CGImageGetHeight(sourceImage),
                                        8,
                                        CGImageGetBytesPerRow(sourceImage),
                                        CGImageGetColorSpace(sourceImage),
                                        kCGImageAlphaPremultipliedLast);

        CGImageRef newCGImage = CGBitmapContextCreateImage(context);

        CGContextRelease(context);
        CFRelease(theData);

        //Now that you have your image use CIFilter "CISourceOverCompositing".
        //this adds your white image as the background.

        UIImageOrientation originalOrientation = origim.imageOrientation;
        data3 = UIImagePNGRepresentation(origim);
        CIImage *result = [CIImage imageWithData:data3];
        CIImage *result2 = [CIImage imageWithCGImage:newCGImage];

        CIContext *contextt = [CIContext contextWithOptions:nil];

        CIFilter *addBackground = [CIFilter filterWithName:@"CISourceOverCompositing"];
        [addBackground setDefaults];
        [addBackground setValue:result forKey:@"inputImage"];
        [addBackground setValue:result2 forKey:@"inputBackgroundImage"];
        result = [addBackground valueForKey:@"outputImage"];

        CGImageRef imgRef = [contextt createCGImage:result fromRect:result.extent];
        image = [[UIImage alloc] initWithCGImage:imgRef scale:1.0 orientation:originalOrientation];
        CGImageRelease(imgRef);

答案 2 :(得分:0)

尝试此代码....

+ (UIImage *)removeTransparentArea:(UIImage *)image {
  CGRect newRect = [self cropRectForImage:image];
  CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, newRect);
  UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
  CGImageRelease(imageRef);

  return finalImage;
}

+ (CGRect)cropRectForImage:(UIImage *)image {

  CGImageRef cgImage = image.CGImage;
  CGContextRef context = [self createARGBBitmapContextFromImage:cgImage];
  if (context == NULL) return CGRectZero;

  int width = image.size.width;
  int height = image.size.height;
  CGRect rect = CGRectMake(0, 0, width, height);

  CGContextDrawImage(context, rect, cgImage);

  unsigned char *data = CGBitmapContextGetData(context);
  CGContextRelease(context);

  //Filter through data and look for non-transparent pixels.
  int lowX = width;
  int lowY = height;

  int highX = 0;
  int highY = 0;
  if (data != NULL) {
    for (int y=0; y<height; y++) {
      for (int x=0; x<width; x++) {
        int pixelIndex = ((width * y) + x) * 4 /* 4 for A, R, G, B */;
        if (data[pixelIndex] != 0) { //Alpha value is not zero; pixel is not transparent.
          if (x < lowX) lowX = x;
          if (x > highX) highX = x;
          if (y < lowY) lowY = y;
          if (y > highY) highY = y;
        }
      }
    }
    free(data);
  } else {
    return CGRectZero;
  }

  return CGRectMake(lowX, lowY, highX-lowX, highY-lowY);
}


+ (CGContextRef)createARGBBitmapContextFromImage:(CGImageRef)inImage {

  CGContextRef context = NULL;
  CGColorSpaceRef colorSpace;
  void *bitmapData;
  int bitmapByteCount;
  int bitmapBytesPerRow;

  // Get image width, height. We'll use the entire image.
  size_t width = CGImageGetWidth(inImage);
  size_t height = CGImageGetHeight(inImage);

  // Declare the number of bytes per row. Each pixel in the bitmap in this
  // example is represented by 4 bytes; 8 bits each of red, green, blue, and
  // alpha.
  bitmapBytesPerRow = ((int)width * 4);
  bitmapByteCount = (bitmapBytesPerRow * (int)height);

  // Use the generic RGB color space.
  colorSpace = CGColorSpaceCreateDeviceRGB();
  if (colorSpace == NULL) return NULL;

  // Allocate memory for image data. This is the destination in memory
  // where any drawing to the bitmap context will be rendered.
  bitmapData = malloc( bitmapByteCount );
  if (bitmapData == NULL)
  {
    CGColorSpaceRelease(colorSpace);
    return NULL;
  }

  // Create the bitmap context. We want pre-multiplied ARGB, 8-bits
  // per component. Regardless of what the source image format is
  // (CMYK, Grayscale, and so on) it will be converted over to the format
  // specified here by CGBitmapContextCreate.
  context = CGBitmapContextCreate (bitmapData,
                                   width,
                                   height,
                                   8,      // bits per component
                                   bitmapBytesPerRow,
                                   colorSpace,
                                   kCGImageAlphaPremultipliedFirst);
  if (context == NULL) free (bitmapData);

  // Make sure and release colorspace before returning
  CGColorSpaceRelease(colorSpace);

  return context;
}