Я пытаюсь автоматически показывать полезную часть прозрачного png в приложении для iPhone. Изображение может быть указано 500x500, но оно в основном прозрачно. Где-то внутри этого изображения есть непрозрачная часть, которую я хочу показать пользователю настолько, насколько я могу, поэтому я хочу обрезать как можно больше с каждой стороны (или заставить ее выглядеть таким образом, растягиваясь и перемещаясь внутри UIImageView. Любые идеи?
IOS: как обрезать изображение на полезные части (удалить прозрачную рамку)
Ответ 1
Используя кварц, преобразуйте изображение в растровое изображение, просмотрите биты альфа-канала, чтобы найти границы непрозрачной части изображения.
Вот Apple Tech Примечание: Получение данных пикселя из объекта CGImage. Вы можете получить CIImage из UIImage с помощью:
CGImageRef imageRef = [uiImage CGImage];
Ответ 2
Я сделал метод для этого, который сканирует все пиксели в изображении в поисках прозрачных столбцов или строк (с допуском 0,01) по сравнению с непрозрачными пикселями, а затем обрезает изображение соответствующим образом.
///crops image by trimming transparent edges
-(UIImage *)trimImage:(UIImage *)originalImage {
// components of replacement color – in a 255 UInt8 format (fairly standard bitmap format)
const CGFloat* colorComponents = CGColorGetComponents([UIColor colorWithRed:1 green:0 blue:0 alpha:1].CGColor);
UInt8* color255Components = calloc(sizeof(UInt8), 4);
for (int i = 0; i < 4; i++) color255Components[i] = (UInt8)round(colorComponents[i]*255.0);
// raw image reference
CGImageRef rawImage = originalImage.CGImage;
// image attributes
size_t width = CGImageGetWidth(rawImage);
size_t height = CGImageGetHeight(rawImage);
CGRect rect = {CGPointZero, {width, height}};
// image format
size_t bitsPerComponent = 8;
size_t bytesPerRow = width*4;
// the bitmap info
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
// data pointer – stores an array of the pixel components. For example (r0, b0, g0, a0, r1, g1, b1, a1 .... rn, gn, bn, an)
UInt8* data = calloc(bytesPerRow, height);
// get new RGB color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// create bitmap context
CGContextRef ctx = CGBitmapContextCreate(data, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo);
// draw image into context (populating the data array while doing so)
CGContextDrawImage(ctx, rect, rawImage);
//float iln2 = 1.0f/log(2.0f);
float topTrim = 0;
float bottomTrim = 0;
float leftTrim = 0;
float rightTrim = 0;
@autoreleasepool {
int pixelPosition = 0;
//
float row = 1;
float column = 1;
BOOL found = NO;
while (row < height) {
while (column < width) {
pixelPosition = row*width+column;
NSInteger pixelIndex = 4*pixelPosition;
float alphaValue = data[pixelIndex+3]/255.0f;
if (alphaValue > 0.01f) {
found = YES;
break;
}
column++;
}
if (found) {
break;
}
column = 1;
row++;
}
topTrim = row;
//
row = height-1;
column = 1;
found = NO;
while (row > 0) {
while (column < width) {
pixelPosition = row*width+column;
NSInteger pixelIndex = 4*pixelPosition;
float alphaValue = data[pixelIndex+3]/255.0f;
if (alphaValue > 0.01f) {
found = YES;
break;
}
column++;
}
if (found) {
break;
}
column = 1;
row--;
}
bottomTrim = row;
//
row = 1;
column = 1;
found = NO;
while (column < width) {
while (row < height) {
pixelPosition = row*width+column;
NSInteger pixelIndex = 4*pixelPosition;
float alphaValue = data[pixelIndex+3]/255.0f;
if (alphaValue > 0.01f) {
found = YES;
break;
}
row++;
}
if (found) {
break;
}
row = 1;
column++;
}
leftTrim = column;
//
row = 1;
column = width-1;
found = NO;
while (column > 0) {
while (row < height) {
pixelPosition = row*width+column;
NSInteger pixelIndex = 4*pixelPosition;
float alphaValue = data[pixelIndex+3]/255.0f;
if (alphaValue > 0.01f) {
found = YES;
break;
}
row++;
}
if (found) {
break;
}
row = 1;
column--;
}
rightTrim = column;
}
// clean up
free(color255Components);
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
free(data);
//
float trimWidth = rightTrim-leftTrim;
float trimHeight = bottomTrim-topTrim;
UIView *trimCanvas = [[UIView alloc] initWithFrame:CGRectMake(0, 0, trimWidth, trimHeight)];
trimCanvas.backgroundColor = [UIColor clearColor];
UIImageView *trimImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
trimImageView.image = originalImage;
trimImageView.contentMode = UIViewContentModeScaleToFill;
trimImageView.backgroundColor = [UIColor clearColor];
[trimCanvas addSubview:trimImageView];
//
trimImageView.center = CGPointMake(trimImageView.center.x-leftTrim, trimImageView.center.y-topTrim);
//
CGRect __rect = [trimCanvas bounds];
UIGraphicsBeginImageContextWithOptions(__rect.size, (NO), (originalImage.scale));
CGContextRef __context = UIGraphicsGetCurrentContext();
[trimCanvas.layer renderInContext:__context];
UIImage *__image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//
return __image;
}