我正在使用一个音乐播放器,它从 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];
}
}
我也遇到了示例问题,实际上我不想删除 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);
}
试试这个...
//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);
试试这个代码....
+ (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;
}