iOS: Feather with glow/shadow effect on uiimage

后端 未结 2 718
野性不改
野性不改 2021-01-06 05:03

I am trying to find a way to apply feather effect with shadow around the UIImage, not UIImageView I have in iOS, I couldn\'t find any perfect solut

相关标签:
2条回答
  • 2021-01-06 05:29

    OK so: I was looking for same thing, but unfortunately with no luck. I decided to create my own feather(ing) code.

    add this code to the UIImage extension, and then call [image featherImageWithDepth:4], 4 is just example. Try to keep depth as low as possible.

    //==============================================================================
    
    
    - (UIImage*)featherImageWithDepth:(int)featherDepth {
    
        // First get the image into your data buffer
        CGImageRef imageRef = [self CGImage];
        NSUInteger width = CGImageGetWidth(imageRef);
        NSUInteger height = CGImageGetHeight(imageRef);
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));
        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);
    
    
        // Now your rawData contains the image data in the RGBA8888 pixel format.
        NSUInteger byteIndex = 0;
    
    
    
        NSUInteger rawDataCount = width*height;
        for (int i = 0 ; i < rawDataCount ; ++i, byteIndex += bytesPerPixel) {
    
            NSInteger alphaIndex = byteIndex + 3;
    
            if (rawData[alphaIndex] > 100) {
    
                for (int row = 1; row <= featherDepth; row++) {
                    if (testBorderLayer((long)alphaIndex,
                                        rawData,
                                        (long)rawDataCount,
                                        (long)width,
                                        (long)height,
                                        row)) {
    
                        int destinationAlpha = 255 / (featherDepth+1) * (row + 1);
                        double alphaDiv =  (double)destinationAlpha / (double)rawData[alphaIndex];
    
                        rawData[alphaIndex] = destinationAlpha;
                        rawData[alphaIndex-1] = (double)rawData[alphaIndex-1] * alphaDiv;
                        rawData[alphaIndex-2] = (double)rawData[alphaIndex-2] * alphaDiv;
                        rawData[alphaIndex-3] = (double)rawData[alphaIndex-3] * alphaDiv;
    
    //                    switch (row) {
    //                        case 1:
    //                            rawData[alphaIndex-1] = 255;
    //                            rawData[alphaIndex-2] = 0;
    //                            rawData[alphaIndex-3] = 0;
    //                            break;
    //                        case 2:
    //                            rawData[alphaIndex-1] = 0;
    //                            rawData[alphaIndex-2] = 255;
    //                            rawData[alphaIndex-3] = 0;
    //                            break;
    //                        case 3:
    //                            rawData[alphaIndex-1] = 0;
    //                            rawData[alphaIndex-2] = 0;
    //                            rawData[alphaIndex-3] = 255;
    //                            break;
    //                        case 4:
    //                            rawData[alphaIndex-1] = 127;
    //                            rawData[alphaIndex-2] = 127;
    //                            rawData[alphaIndex-3] = 0;
    //                            break;
    //                        case 5:
    //                            rawData[alphaIndex-1] = 127;
    //                            rawData[alphaIndex-2] = 0;
    //                            rawData[alphaIndex-3] = 127;
    //                        case 6:
    //                            rawData[alphaIndex-1] = 0;
    //                            rawData[alphaIndex-2] = 127;
    //                            rawData[alphaIndex-3] = 127;
    //                            break;
    //                        default:
    //                            break;
    //                    }
    
                        break;
    
                    }
                }
            }
        }
    
    
        CGImageRef newCGImage = CGBitmapContextCreateImage(context);
    
        UIImage *result = [UIImage imageWithCGImage:newCGImage scale:[self scale] orientation:UIImageOrientationUp];
    
        CGImageRelease(newCGImage);
    
        CGContextRelease(context);
        free(rawData);
    
        return result;
    }
    
    
    //==============================================================================
    
    
    bool testBorderLayer(long byteIndex,
                         unsigned char *imageData,
                         long dataSize,
                         long pWidth,
                         long pHeight,
                         int border) {
    
    
        int width = border * 2 + 1;
        int height = width - 2;
    
        // run thru border pixels
        // |-|
        // | |
        // |-|
    
        //top,bot - hor
        for (int i = 1; i < width - 1; i++) {
    
    
            long topIndex = byteIndex + 4 * ( - border * pWidth - border + i);
            long botIndex = byteIndex + 4 * ( border * pWidth - border + i);
    
            long destColl = byteIndex/4 % pWidth - border + i;
    
            if (destColl > 1 && destColl < pWidth) {
                if (testPoint(topIndex, imageData, dataSize) ||
                    testPoint(botIndex, imageData, dataSize)) {
                    return true;
                }
    
            }
    
        }
    
    
        //left,right - ver
        if (byteIndex / 4 % pWidth < pWidth - border - 1) {
            for (int k = 0; k < height; k++) {
                long rightIndex = byteIndex + 4 * ( border - (border) * pWidth + pWidth * k);
    
                if (testPoint(rightIndex, imageData, dataSize)) {
                    return true;
                }
            }
        }
    
        if (byteIndex / 4 % pWidth > border) {
    
            for (int k = 0; k < height; k++) {
                long leftIndex = byteIndex + 4 * ( - border - (border) * pWidth + pWidth * k);
    
                if (testPoint(leftIndex, imageData, dataSize)) {
                    return true;
                }
            }
        }
    
        return false;
    }
    
    
    //==============================================================================
    
    
    bool testPoint(long pointIndex, unsigned char *imageData, long dataSize) {
        if (pointIndex >= 0 && pointIndex < dataSize * 4 - 1 &&
            imageData[pointIndex] < 30) {
            return true;
        }
        return false;
    }
    
    //==============================================================================
    

    Sorry for rare commenting ;)

    0 讨论(0)
  • 2021-01-06 05:38

    I suggest looking at this CIFilter list put out by apple, they got some pretty decent filters.

    • /reference/CoreImageFilterReference

    And also check out GPUImage.

    • https://github.com/BradLarson/GPUImage
    0 讨论(0)
提交回复
热议问题