Сделать эффект размытия на UIImage iphone Проблема?

Привет, в этом коде я делаю изображение размытым. но проблема в том, что это очень медленно на iPhone.

вот мой код.

- (UIImage*) gaussianBlur:(NSUInteger)radius
{

    // Pre-calculated kernel
    double dKernel[5][5]={ 
        {1.0f/273.0f, 4.0f/273.0f, 7.0f/273.0f, 4.0f/273.0f, 1.0f/273.0f},
        {4.0f/273.0f, 16.0f/273.0f, 26.0f/273.0f, 16.0f/273.0f, 4.0f/273.0f},
        {7.0f/273.0f, 26.0f/273.0f, 41.0f/273.0f, 26.0f/273.0f, 7.0f/273.0f},
        {4.0f/273.0f, 16.0f/273.0f, 26.0f/273.0f, 16.0f/273.0f, 4.0f/273.0f},             
        {1.0f/273.0f, 4.0f/273.0f, 7.0f/273.0f, 4.0f/273.0f, 1.0f/273.0f}};

    NSMutableArray *kernel = [[[NSMutableArray alloc] initWithCapacity:5] autorelease];
    for (int i = 0; i < 5; i++) {
        NSMutableArray *row = [[[NSMutableArray alloc] initWithCapacity:5] autorelease];
        for (int j = 0; j < 5; j++) {
            [row addObject:[NSNumber numberWithDouble:dKernel[i][j]]];
        }
        [kernel addObject:row];
    }



    return [self applyConvolve:kernel];
}


- (UIImage*) applyConvolve:(NSArray*)kernel
{
    CGImageRef inImage = self.CGImage;
    CFDataRef m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage));  
    CFDataRef m_OutDataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage));  
    UInt8 * m_PixelBuf = (UInt8 *) CFDataGetBytePtr(m_DataRef);  
    UInt8 * m_OutPixelBuf = (UInt8 *) CFDataGetBytePtr(m_OutDataRef);  

    int h = CGImageGetHeight(inImage);
    int w = CGImageGetWidth(inImage);

    int kh = [kernel count] / 2;
    int kw = [[kernel objectAtIndex:0] count] / 2;
    int i = 0, j = 0, n = 0, m = 0;

    for (i = 0; i < h; i++) {
        for (j = 0; j < w; j++) {
            int outIndex = (i*w*4) + (j*4);
            double r = 0, g = 0, b = 0;
            for (n = -kh; n <= kh; n++) {
                for (m = -kw; m <= kw; m++) {
                    if (i + n >= 0 && i + n < h) {
                        if (j + m >= 0 && j + m < w) {
                            double f = [[[kernel objectAtIndex:(n + kh)] objectAtIndex:(m + kw)] doubleValue];
                            if (f == 0) {continue;}
                            int inIndex = ((i+n)*w*4) + ((j+m)*4);
                            r += m_PixelBuf[inIndex] * f;
                            g += m_PixelBuf[inIndex + 1] * f;
                            b += m_PixelBuf[inIndex + 2] * f;
                        }
                    }
                }
            }
            m_OutPixelBuf[outIndex]     = SAFECOLOR((int)r);
            m_OutPixelBuf[outIndex + 1] = SAFECOLOR((int)g);
            m_OutPixelBuf[outIndex + 2] = SAFECOLOR((int)b);
            m_OutPixelBuf[outIndex + 3] = 255;
        }
    }

    CGContextRef ctx = CGBitmapContextCreate(m_OutPixelBuf,  
                                             CGImageGetWidth(inImage),  
                                             CGImageGetHeight(inImage),  
                                             CGImageGetBitsPerComponent(inImage),
                                             CGImageGetBytesPerRow(inImage),  
                                             CGImageGetColorSpace(inImage),  
                                             CGImageGetBitmapInfo(inImage) 
                                             ); 

    CGImageRef imageRef = CGBitmapContextCreateImage(ctx);  
    CGContextRelease(ctx);
    UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    CFRelease(m_DataRef);
    CFRelease(m_OutDataRef);
    return finalImage;

}

person sivakumar.j    schedule 16.09.2011    source источник
comment
Вам действительно нужны четыре вложенных цикла? Попробуйте оптимизировать их.   -  person beryllium    schedule 16.09.2011
comment
Если я уменьшу значения количества циклов. изображение отображается как черное. я не знаю, что здесь происходит. но если я использую этот код непосредственно в симуляторе, он отлично работает.   -  person sivakumar.j    schedule 16.09.2011
comment
Если я что-то не упустил, с вашим кодом, кажется, есть некоторые очевидные проблемы; У меня нет времени, чтобы составить правильный ответ, поэтому я просто напишу это в комментариях: это большая вычислительная трата - делить каждое из чисел в матрице ядра на одно и то же число (273.0f); вы можете просто разделить результат свертки один раз в конце ... и, хотя я не знаю архитектуры процессоров iPhone навскидку, вы должны значительно сэкономить, просто рассматривая свою свертка как между целыми значениями.   -  person Aky    schedule 16.09.2011
comment
Прости Аки. Я не мог тебя достать. Я только что однажды вызвал метод gaussianBlur. проблема в методе applyConvolve. Как оптимизировать выполнение цикла, не влияя на результат.   -  person sivakumar.j    schedule 16.09.2011
comment
Чтобы оптимизировать метод applyConvolve, найдите свойство отделимости ядра Гаусса; это позволит вам разделить 2D-свертку на 1D-горизонтальную и вертикальную свертки.   -  person Aky    schedule 16.09.2011
comment
ваша свертка также неэффективна из-за первой причины, которую я вам привел; вы выполняете операции с плавающей запятой, где будет достаточно интегральных.   -  person Aky    schedule 16.09.2011


Ответы (1)


Двумерная гауссова свертка отделима, что означает, что ее можно выполнить как 2 одномерные свертки, одну горизонтальную и одну вертикальную. Это должно сэкономить вам немного времени.

http://en.wikipedia.org/wiki/Gaussian_blur#Implementation

person Martin Thompson    schedule 16.09.2011