|
| 1 | +// |
| 2 | +// NSImage+extensions.swift |
| 3 | +// SwitchKey |
| 4 | +// |
| 5 | +// Created by Jinyu Li on 2019/05/10. |
| 6 | +// Copyright © 2019 Jinyu Li. All rights reserved. |
| 7 | +// |
| 8 | + |
| 9 | +import Cocoa |
| 10 | + |
| 11 | +extension NSImage { |
| 12 | + // A dumb method: |
| 13 | + // go over the pixels, and check the color range. |
| 14 | + // an image can be safely templated if its color range is limited. |
| 15 | + // luckily, our image is small, and the check is done once for each new icon. |
| 16 | + func canTemplate() -> Bool { |
| 17 | + guard let cgContext = CGContext( |
| 18 | + data: nil, |
| 19 | + width: Int(size.width), |
| 20 | + height: Int(size.height), |
| 21 | + bitsPerComponent: 8, |
| 22 | + bytesPerRow: 0, |
| 23 | + space: CGColorSpaceCreateDeviceRGB(), |
| 24 | + bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue |
| 25 | + ) else { |
| 26 | + return false |
| 27 | + } |
| 28 | + |
| 29 | + let nsContext = NSGraphicsContext(cgContext: cgContext, flipped: false) |
| 30 | + NSGraphicsContext.current = nsContext |
| 31 | + draw(in: NSMakeRect(0, 0, size.width, size.height)) |
| 32 | + |
| 33 | + guard let pixel = cgContext.data else { |
| 34 | + return false; |
| 35 | + } |
| 36 | + |
| 37 | + let width = cgContext.width; |
| 38 | + var rmin:UInt32 = 255, rmax:UInt32 = 0 |
| 39 | + var gmin:UInt32 = 255, gmax:UInt32 = 0 |
| 40 | + var bmin:UInt32 = 255, bmax:UInt32 = 0 |
| 41 | + for y in 0 ... cgContext.height { |
| 42 | + for x in 0 ... width { |
| 43 | + let px = pixel.load(fromByteOffset: (y * width + x) * 4, as: UInt32.self) |
| 44 | + let r = (px & 0x000000ff) >> 0 |
| 45 | + let g = (px & 0x0000ff00) >> 8 |
| 46 | + let b = (px & 0x00ff0000) >> 16 |
| 47 | + rmin = min(r, rmin) |
| 48 | + rmax = max(r, rmax) |
| 49 | + gmin = min(g, rmin) |
| 50 | + gmax = max(g, rmax) |
| 51 | + bmin = min(b, rmin) |
| 52 | + bmax = max(b, rmax) |
| 53 | + } |
| 54 | + } |
| 55 | + |
| 56 | + NSGraphicsContext.current = nil |
| 57 | + |
| 58 | + let isTemplate = (abs(Int(rmax)-Int(rmin)) + abs(Int(gmax)-Int(gmin)) + abs(Int(bmax)-Int(bmin))) <= 9 |
| 59 | + |
| 60 | + return isTemplate |
| 61 | + } |
| 62 | +} |
0 commit comments