yackle / CLImageEditor

MIT License
2.21k stars 573 forks source link

Fix for the whitespace after applying the pixellate effect. #7

Closed rosswaycaster closed 10 years ago

rosswaycaster commented 10 years ago

The code below will crop the transparent space around the image after the pixellate effect is applied to it. Without this code the user sees a white border around the image when they close the editor. I hope this helps someone out. It could probably be cleaned up a bit, but it's working just fine for me.

This change needs to be applied to the file CLImageEditor/ImageTools/CLEffectTool/CLEffect/CLPixellateEffect.m Find -(UIImage)applyEffect:(UIImage)image { ..... } and replace it with..

- (UIImage*)applyEffect:(UIImage*)image
{
    CIImage *ciImage = [[CIImage alloc] initWithImage:image];
    CIFilter *filter = [CIFilter filterWithName:@"CIPixellate" keysAndValues:kCIInputImageKey, ciImage, nil];

    //NSLog(@"%@", [filter attributes]);

    [filter setDefaults];

    CGFloat R = (0.1 * _radiusSlider.value) * MIN(image.size.width, image.size.height);
    CIVector *vct = [[CIVector alloc] initWithX:image.size.width/2 Y:image.size.height/2];
    [filter setValue:vct forKey:@"inputCenter"];
    [filter setValue:[NSNumber numberWithFloat:R] forKey:@"inputScale"];

    CIContext *context = [CIContext contextWithOptions:nil];
    CIImage *outputImage = [filter outputImage];

    CGImageRef cgImage = [context createCGImage:outputImage fromRect:[outputImage extent]];

    UIImage *result = [UIImage imageWithCGImage:cgImage];

    CGImageRelease(cgImage);

    CGImageRef inImage = result.CGImage;
    CFDataRef m_DataRef;
    m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage));
    UInt8 * m_PixelBuf = (UInt8 *) CFDataGetBytePtr(m_DataRef);

    int width = result.size.width;
    int height = result.size.height;

    CGPoint top,left,right,bottom;

    BOOL breakOut = NO;
    for (int x = 0;breakOut==NO && x < width; x++) {
        for (int y = 0; y < height; y++) {
            int loc = x + (y * width);
            loc *= 4;
            if (m_PixelBuf[loc + 3] != 0) {
                left = CGPointMake(x, y);
                breakOut = YES;
                break;
            }
        }
    }

    breakOut = NO;
    for (int y = 0;breakOut==NO && y < height; y++) {

        for (int x = 0; x < width; x++) {

            int loc = x + (y * width);
            loc *= 4;
            if (m_PixelBuf[loc + 3] != 0) {
                top = CGPointMake(x, y);
                breakOut = YES;
                break;
            }

        }
    }

    breakOut = NO;
    for (int y = height-1;breakOut==NO && y >= 0; y--) {

        for (int x = width-1; x >= 0; x--) {

            int loc = x + (y * width);
            loc *= 4;
            if (m_PixelBuf[loc + 3] != 0) {
                bottom = CGPointMake(x, y);
                breakOut = YES;
                break;
            }

        }
    }

    breakOut = NO;
    for (int x = width-1;breakOut==NO && x >= 0; x--) {

        for (int y = height-1; y >= 0; y--) {

            int loc = x + (y * width);
            loc *= 4;
            if (m_PixelBuf[loc + 3] != 0) {
                right = CGPointMake(x, y);
                breakOut = YES;
                break;
            }

        }
    }

    CGRect cropRect = CGRectMake(left.x, top.y, right.x - left.x, bottom.y - top.y);

    UIGraphicsBeginImageContextWithOptions( cropRect.size,
                                           NO,
                                           0.);
    [result drawAtPoint:CGPointMake(-cropRect.origin.x, -cropRect.origin.y)
           blendMode:kCGBlendModeCopy
               alpha:1.];
    UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    CFRelease(m_DataRef);
    return croppedImage;
}
yackle commented 10 years ago

Fixed. If you have some codes for us, please send pull request :)

Thank you!