Box Blur CGImageRef - PullRequest
       22

Box Blur CGImageRef

1 голос
/ 08 февраля 2011

Я пытаюсь реализовать простое Box Blur, но у меня проблемы.А именно, вместо размытия изображений кажется, что каждый пиксель конвертируется в: красный, зеленый, синий или черный.Не уверен, что именно происходит.Буду признателен за любую помощь.

Обратите внимание, этот код - просто первый проход, чтобы заставить его работать, я не беспокоюсь о скорости ... пока.

- (CGImageRef)blur:(CGImageRef)base radius:(int)radius {
CGContextRef ctx;
CGImageRef imageRef = base;
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char *rawData = malloc(height * width *4);
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                                             bitsPerComponent, bytesPerRow, colorSpace,
                                             kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);

CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);

char red = 0;
char green = 0;
char blue = 0;
for (int widthIndex = radius; widthIndex < width - radius; widthIndex++) {
    for (int heightIndex = radius; heightIndex < height - radius; heightIndex++) {
        red = 0;
        green = 0;
        blue = 0;
        for (int radiusY = -radius; radiusY <= radius; ++radiusY) {
            for (int radiusX = -radius; radiusX <= radius; ++radiusX) {

                int xIndex = widthIndex + radiusX;
                int yIndex = heightIndex + radiusY;

                int index = ((yIndex * width) + xIndex) * 4;
                red += rawData[index];
                green += rawData[index + 1];
                blue += rawData[index + 2];
            }
        }

        int currentIndex = ((heightIndex * width) + widthIndex) * 4;

        int divisor = (radius * 2) + 1;
        divisor *= divisor;

        int finalRed = red / divisor;
        int finalGreen = green / divisor;
        int finalBlue = blue / divisor;

        rawData[currentIndex] = (char)finalRed;
        rawData[currentIndex + 1] = (char)finalGreen;
        rawData[currentIndex + 2] = (char)finalBlue;
    }
}


ctx = CGBitmapContextCreate(rawData,
                            CGImageGetWidth( imageRef ),
                            CGImageGetHeight( imageRef ),
                            8,
                            CGImageGetBytesPerRow( imageRef ),
                            CGImageGetColorSpace( imageRef ),
                            kCGImageAlphaPremultipliedLast ); 

imageRef = CGBitmapContextCreateImage (ctx);

CGContextRelease(ctx);  

free(rawData);
[(id)imageRef autorelease];
return imageRef;
}

Ответы [ 2 ]

1 голос
/ 27 марта 2012

У меня просто есть комментарий. Я использовал этот скрипт, и он действительно работает хорошо и быстро. Единственное, что оставляет рамку с шириной радиуса, которая не размыта. Поэтому я немного изменил его, чтобы он размывал всю область, используя технику зеркального отражения около краев.

Для этого нужно поставить следующие строки:

// Mirroring the part between edge and blur raduis
if (xIndex<0) xIndex=-xIndex-1; else if (xIndex>width-1) xIndex=2*width-xIndex-1;
if (yIndex<0) yIndex=-yIndex-1; else if (yIndex>height-1) yIndex=2*height-yIndex-1;

после этих строк:

int xIndex = widthIndex + radiusX;
int yIndex = heightIndex + radiusY;

А затем замените заголовки для циклов:

for (int widthIndex = radius; widthIndex < width - radius; widthIndex++) {
    for (int heightIndex = radius; heightIndex < height - radius; heightIndex++) {

с этими заголовками:

for (int widthIndex = 0; widthIndex < width; widthIndex++) {
    for (int heightIndex = 0; heightIndex < height; heightIndex++) {
1 голос
/ 08 февраля 2011

Цвета символов должны быть объявлены как int.

int red = 0;
int green = 0;
int blue = 0;
...