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

问题描述 投票:0回答:3

我正在使用一个音乐播放器,它从 MP3 的 ID3 资源中获取图像。我遇到过某些透明的艺术作品(图像有透明部分)。这导致我的应用程序加载这些图像非常缓慢。我需要找到一种方法在显示 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];

    }
}
ios uiimageview uiimage png
3个回答
5
投票

我也遇到了示例问题,实际上我不想删除 alpha 通道,只是想用白色替换透明颜色。我尝试按照从 UIImage 中删除 alpha 通道中的评论中的建议删除 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);
}

2
投票

试试这个...

//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);

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.