以下是我想修剪的图片示例。我想摆脱图像周围的边框(在这种情况下是顶部和底部黑条)。
我在Github上找到了一个库:CKImageAdditions,但它似乎不起作用。当我传入UIColor(RGB颜色)时,它只返回相同的图像。
我可以找到许多示例和类别类来修剪UIImage,任何透明像素作为边框,但在这种情况下我需要修剪黑色。我在我的图像中对颜色进行了采样,颜色值确实为255,但它似乎与上面的库所需的颜色不匹配。
是否有人拥有他们使用的图书馆或任何见解?我进行了搜索和搜索,CKImageAdditions是我唯一可以找到广告用颜色修剪的东西(虽然不幸的是在我的情况下不起作用)。
答案 0 :(得分:7)
我最终定义了function in CKImageAdditions中具有此功能的方法,但我无法使其工作。它只是不会修剪颜色,所以我改为检查像素的RGB值为\0
(黑色)。不幸的是,CKImageAdditions
无法找到黑色像素。
由于我想修剪的图像有时没有超级黑条(有时它们会有一个较暗的颜色的杂散像素或其他东西)我在方法中添加了GPUImage功能,基本上只是创建一个黑白版本的图像,上面有一个强大的滤镜,所以任何深色都会变成黑色,任何浅色变成白色,使得黑条边框更加突出,并且当我在方法中查找它们时确保更好的效果。当然,我会根据黑/白图像的结果在最后裁剪原始图像。
这是我的代码:
typedef struct Pixel { uint8_t r, g, b, a; } Pixel;
+(UIImage*)trimBlack:(UIImage*)originalImage {
GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:originalImage];
GPUImageLuminanceThresholdFilter *stillImageFilter = [[GPUImageLuminanceThresholdFilter alloc] init];
stillImageFilter.threshold = 0.1;
[stillImageSource addTarget:stillImageFilter];
[stillImageSource processImage];
UIImage *imageToProcess = [stillImageFilter imageFromCurrentlyProcessedOutput];
RMImageTrimmingSides sides = RMImageTrimmingSidesAll;
CGImageRef image = imageToProcess.CGImage;
void * bitmapData = NULL;
CGContextRef context = CKBitmapContextAndDataCreateWithImage(image, &bitmapData);
Pixel *data = bitmapData;
size_t width = CGBitmapContextGetWidth(context);
size_t height = CGBitmapContextGetHeight(context);
size_t top = 0;
size_t bottom = height;
size_t left = 0;
size_t right = width;
// Scan the left
if (sides & RMImageTrimmingSidesLeft) {
for (size_t x = 0; x < width; x++) {
for (size_t y = 0; y < height; y++) {
Pixel pixel = data[y * width + x];
if (pixel.r != '\0' && pixel.g != '\0' && pixel.b != '\0') {
left = x;
goto SCAN_TOP;
}
}
}
}
// Scan the top
SCAN_TOP:
if (sides & RMImageTrimmingSidesTop) {
for (size_t y = 0; y < height; y++) {
for (size_t x = 0; x < width; x++) {
Pixel pixel = data[y * width + x];
if (pixel.r != '\0' && pixel.g != '\0' && pixel.b != '\0') {
top = y;
goto SCAN_RIGHT;
}
}
}
}
// Scan the right
SCAN_RIGHT:
if (sides & RMImageTrimmingSidesRight) {
for (size_t x = width-1; x >= left; x--) {
for (size_t y = 0; y < height; y++) {
Pixel pixel = data[y * width + x];
if (pixel.r != '\0' && pixel.g != '\0' && pixel.b != '\0') {
right = x;
goto SCAN_BOTTOM;
}
}
}
}
// Scan the bottom
SCAN_BOTTOM:
if (sides & RMImageTrimmingSidesBottom) {
for (size_t y = height-1; y >= top; y--) {
for (size_t x = 0; x < width; x++) {
Pixel pixel = data[y * width + x];
if (pixel.r != '\0' && pixel.g != '\0' && pixel.b != '\0') {
bottom = y;
goto FINISH;
}
}
}
}
FINISH:
CGContextRelease(context);
free(bitmapData);
CGRect rect = CGRectMake(left, top, right - left, bottom - top);
return [originalImage imageCroppedToRect:rect];
}
感谢上面代码中使用的库的开发人员所做的所有努力,当然所有的功劳都归功于他们!
答案 1 :(得分:1)
我已经调整了你的解决方案,因为GPUI的imageFromCurrentlyProcessedOutput方法已被删除,并被另一个根本不起作用的方法所取代。
还调整了图像的裁剪方式,并删除了一些刚被破坏的东西。似乎工作。
typedef struct Pixel { uint8_t r, g, b, a; } Pixel;
-(UIImage*)trimBlack:(UIImage*)originalImage {
GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:originalImage];
GPUImageLuminanceThresholdFilter *stillImageFilter = [[GPUImageLuminanceThresholdFilter alloc] init];
stillImageFilter.threshold = 0.1;
[stillImageSource addTarget:stillImageFilter];
[stillImageSource processImage];
[stillImageSource useNextFrameForImageCapture];
//UIImage *imageToProcess = [stillImageFilter imageFromCurrentFramebufferWithOrientation:UIImageOrientationUp];
//UIImage *imageToProcess = [UIImage imageWithCGImage:[stillImageFilter newCGImageFromCurrentlyProcessedOutput]];
UIImage *imageToProcess = originalImage;
//RMImageTrimmingSides sides = RMImageTrimmingSidesAll;
CGImageRef image = imageToProcess.CGImage;
void * bitmapData = NULL;
CGContextRef context = CKBitmapContextAndDataCreateWithImage(image, &bitmapData);
Pixel *data = bitmapData;
size_t width = CGBitmapContextGetWidth(context);
size_t height = CGBitmapContextGetHeight(context);
size_t top = 0;
size_t bottom = height;
size_t left = 0;
size_t right = width;
// Scan the left
//if (sides & RMImageTrimmingSidesLeft) {
for (size_t x = 0; x < width; x++) {
for (size_t y = 0; y < height; y++) {
Pixel pixel = data[y * width + x];
if (pixel.r != '\0' && pixel.g != '\0' && pixel.b != '\0') {
left = x;
goto SCAN_TOP;
}
}
}
//}
// Scan the top
SCAN_TOP:
//if (sides & RMImageTrimmingSidesTop) {
for (size_t y = 0; y < height; y++) {
for (size_t x = 0; x < width; x++) {
Pixel pixel = data[y * width + x];
if (pixel.r != '\0' && pixel.g != '\0' && pixel.b != '\0') {
top = y;
goto SCAN_RIGHT;
}
}
}
//}
// Scan the right
SCAN_RIGHT:
//if (sides & RMImageTrimmingSidesRight) {
for (size_t x = width-1; x >= left; x--) {
for (size_t y = 0; y < height; y++) {
Pixel pixel = data[y * width + x];
if (pixel.r != '\0' && pixel.g != '\0' && pixel.b != '\0') {
right = x;
goto SCAN_BOTTOM;
}
}
}
//}
// Scan the bottom
SCAN_BOTTOM:
//if (sides & RMImageTrimmingSidesBottom) {
for (size_t y = height-1; y >= top; y--) {
for (size_t x = 0; x < width; x++) {
Pixel pixel = data[y * width + x];
if (pixel.r != '\0' && pixel.g != '\0' && pixel.b != '\0') {
bottom = y;
goto FINISH;
}
}
}
//}
FINISH:
CGContextRelease(context);
free(bitmapData);
CGRect rect = CGRectMake(left, top, right - left, bottom - top);
CGImageRef imageRef = CGImageCreateWithImageInRect([originalImage CGImage], rect);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return croppedImage;
}