请求开发UIImage自定义滤镜:仅保留指定颜色其余转为黑色
Alright, I’ve got you covered on creating that custom UIImage filter that keeps only a specific color and turns everything else black. Let’s break down how to implement this step by step, with code that’s easy to drop into your iOS project.
Core Concept
The core idea is straightforward:
- Iterate over every pixel in the image
- Compare each pixel’s color to your target reference color (with a tolerance range, since real-world images rarely have perfectly identical colors)
- Replace any pixel that doesn’t match the target color with black
- Keep matching pixels in their original state
Swift Implementation (UIImage Extension)
We’ll wrap this logic in an extension for UIImage so it’s reusable across your app:
import UIKit extension UIImage { func keepOnlyColor(_ targetColor: UIColor, tolerance: CGFloat = 0.1) -> UIImage? { // Get the underlying CGImage and set up a pixel manipulation context guard let cgImage = self.cgImage, let context = CGContext(data: nil, width: cgImage.width, height: cgImage.height, bitsPerComponent: 8, bytesPerRow: cgImage.width * 4, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else { return nil } // Draw the original image into the context to access pixel data context.draw(cgImage, in: CGRect(x: 0, y: 0, width: cgImage.width, height: cgImage.height)) // Get a pointer to the raw pixel data guard let pixelData = context.data?.assumingMemoryBound(to: UInt8.self) else { return nil } // Convert the target color to RGB integer components (0-255 range) var targetRed: CGFloat = 0, targetGreen: CGFloat = 0, targetBlue: CGFloat = 0, _: CGFloat = 0 targetColor.getRed(&targetRed, green: &targetGreen, blue: &targetBlue, alpha: nil) let targetRedInt = UInt8(targetRed * 255) let targetGreenInt = UInt8(targetGreen * 255) let targetBlueInt = UInt8(targetBlue * 255) // Calculate the tolerance range (adjust based on your use case) let toleranceRange = Int(tolerance * 255) // Loop through every pixel in the image let totalPixels = cgImage.width * cgImage.height for i in 0..<totalPixels { let pixelOffset = i * 4 // Each pixel has 4 components: R, G, B, A let currentRed = pixelData[pixelOffset] let currentGreen = pixelData[pixelOffset + 1] let currentBlue = pixelData[pixelOffset + 2] let currentAlpha = pixelData[pixelOffset + 3] // Skip fully transparent pixels (optional: remove this to turn transparent pixels black) if currentAlpha == 0 { continue } // Check if the current pixel's color falls within the target color's tolerance range let isColorMatch = abs(Int(currentRed) - Int(targetRedInt)) <= toleranceRange && abs(Int(currentGreen) - Int(targetGreenInt)) <= toleranceRange && abs(Int(currentBlue) - Int(targetBlueInt)) <= toleranceRange if !isColorMatch { // Turn non-matching pixels to black (keep alpha unchanged) pixelData[pixelOffset] = 0 pixelData[pixelOffset + 1] = 0 pixelData[pixelOffset + 2] = 0 } // Matching pixels stay in their original state } // Create a new UIImage from the modified pixel data guard let modifiedCGImage = context.makeImage() else { return nil } return UIImage(cgImage: modifiedCGImage) } }
How to Use the Filter
Integrate this into your code with a simple call:
// Example: Filter an image to keep only a specific blue color if let originalImage = UIImage(named: "myPhoto"), let targetBlue = UIColor(red: 0.2, green: 0.4, blue: 0.8, alpha: 1.0), let filteredImage = originalImage.keepOnlyColor(targetBlue, tolerance: 0.15) { // Assign the filtered image to your UIImageView myImageView.image = filteredImage }
Key Tips for Best Results
- Tolerance Adjustment: The
toleranceparameter (0.0 to 1.0) controls how strict the color match is. Use 0.1-0.2 for most cases—higher values will include more similar shades of your target color. - Performance: For very large images, pixel-by-pixel iteration can be slow. If you need better performance, consider using Metal or a custom Core Image filter, but this implementation works great for most standard use cases.
- Transparency: The code skips fully transparent pixels. If you want to turn transparent areas black, remove the
if currentAlpha == 0 { continue }check.
内容的提问来源于stack exchange,提问作者user9507127
相关产品推荐
相关产品推荐

