CoreGraphicsͰυοτֆΛඳ͜͏Track C ϨΪϡϥʔτʔΫʢ20ʣ1
View Slide
noppe• Twi%er: noppefoxwolf• גࣜձࣾσΟʔɾΤψɾΤʔ• ݸਓΞϓϦ։ൃऀ• iOSDC18~21 ొஃ• ͖ͭͶ͕͖2
3
4
Editormode5
6
Agenda1. υοτֆΤσΟλͱ2. γϯϓϧͳυοτֆΤσΟλΛ࡞Δ3. CoreGraphicsͷ֦ு4. ύϑΥʔϚϯεͷվળ7
υοτֆΤσΟλͱ8
9
28x28 2bit10
48x48 8bit11
300x300 10bit12
υοτֆΛදࣔ͢ΔimageView.contentMode = .centerimageView.image = UIImage(named: "watch")13
υοτֆΛදࣔ͢ΔimageView.contentMode = .scaleAspectFitimageView.image = UIImage(named: "watch")14
υοτֆΛදࣔ͢Δ// Use nearest magnificationFilterimageView.contentMode = .scaleAspectFitimageView.layer.magnificationFilter = .nearestimageView.image = UIImage(named: "watch")// SwiftUIImage(...).interpolation(.none)-ɹը૾ࣗମͷϦαΠζॏ͘ϝϞϦΛ࿘අ͢ΔͷͰNG15
γϯϓϧͳυοτֆΤσΟλΛ࡞Δ16
17
18
υοτֆΤσΟλͷϫʔΫϑϩʔlet imageView = UIImageView()let context = CGContext()func setup() {imageView.onTap = { point in // 1context.fill(point) // 2let image = context.makeImage() // 3imageView.image = image // 4}}19
άϨʔεέʔϧͷCGContextͷॳظԽ// άϨʔεέʔϧઐ༻ͷCGContextΛੜlet context = CGContext(data: nil,width: 16,height: 16,bitsPerComponent: 8,bytesPerRow: 1 * 16,space: CGColorSpaceCreateDeviceGray(),bitmapInfo: CGImageAlphaInfo.none.rawValue)20
bitsPerComponent• 1,2,4,8 bit͔Β1৭ͷ֊ௐΛࢦఆ͢Δ• 4bit = 16֊ௐ• 8bit = 256֊ௐ• RGBͳͲɺෳͷίϯϙʔωϯτͰ৭Λද͢͜ͱ͋Γ·͢21
bytesPerRow• ը૾ͷԣҰྻ͕ԿόΠτʹͳΔ͔• 8bit(1byte)ͳΒ ίϯϙʔωϯτ x ԣͷϐΫηϧ৭ۭؒ ԣ෯ͷόΠτάϨʔ 1 * width = 16ϑϧΧϥʔRGB 4 * width = 25622
space• Χϥʔεϖʔε৭ۭؒ ΫϥεάϨʔ CGColorSpaceCreateDeviceGray()ϑϧΧϥʔRGB CGColorSpaceCreateDeviceRGB()23
bitmapInfo• ΞϧϑΝνϟϯωϧͷॴ | όΠτΦʔμʔ | ϑΥʔϚοτɹͷϏοτϚεΫྫ• CGImageAlphaInfo.noneSkipLast.rawValue |CGImageByteOrderInfo.order32LiCle.rawValue |CGImagePixelFormatInfo.packed.rawValue• CGImageAlphaInfo.none.rawValue24
25
contextͷը૾Λඳը͢Δlet cgImage: CGImage = context.makeImage()!let uiImage: UIImage = UIImage(cgImage: cgImage,scale: 1,orientation: .downMirrored // UIImageͷ࠲ඪܥʹม)// UIKitimageView.image = uiImage// SwiftUIImage(uiImage: uiImage)26
৭ͷృΓͭͿ͠let color = CGColor(gray: 0, alpha: 1)context.setFillColor(color)let path = CGPath(rect: CGRect(origin: point, size: CGSize(width: 1, height: 1)))context.addPath(path) // PathͷՃcontext.fillPath()27
CoreGraphicsͷ֦ு28
29
30
31
CGContextʹࣗ࡞ؔΛੜ͢extension CGContext {func fillEllipseLine(in rect: CGRect) {// ృΓͭͿ͢ύεΛ࡞Δlet path = makeEllipsePath(in: rect)// ύεΛՃaddPath(path)// Ճͨ͠ύεΛృΓͭͿ͢fillPath()}}32
Bresenham's line algorithm2• 1962ɺIBMͷδϟοΫɾϒϨθϯϋϜ͕։ൃ• ઢ͔Β࠷ڑʹ͋ΔըૉΛฒΔ• ԁΛඳը͢ΔൃలܥͷΞϧΰϦζϜ͕͋Δ• noppefoxwolf/swi,-line-algorithms2 h$ps://ja.wikipedia.org/wiki/ϒϨθϯϋϜͷΞϧΰϦζϜ33
CoreGraphicsͷ֦ு234
όέππʔϧ• ด͡ΒΕͨൣғΛృΓͭͿ͢ػೳ• Flood Fillͱ͍͏ΞϧΰϦζϜ• બͨ͠৭Λಉ͡৭͔Ͳ͏͔Λ୳͠ͳ͕Β৭Λஔ͖͍͑ͯ͘→ CGContext͔Β৭Λऔಘ͢Δඞཁ͕͋Δ35
CGContext͔Β৭ΛऔΓग़͢• ಛఆͷ࠲ඪͷ৭Λऔಘ͢ΔAPIͳ͍• cgContext.data͔Βը૾͕֨ೲ͞Ε͍ͯΔϙΠϯλΛΕΔ• ϝϞϦϨΠΞτΛ֬ೝ͠ɺҙͷ࠲ඪͷ৭ΛऔΓग़͢APIΛ࡞Δ36
ϝϞϦϨΠΞτΛ֬ೝ͢Δ2x2ͷCGContextΛ৭ ɹ৭ʢHexʣɹ Ґஔ17.0 / 255.0 0x11 ɹࠨԼ34.0 / 255.0 0x22 ɹӈԼ51.0 / 255.0 0x33 ɹࠨ্68.0 / 255.0 0x44 ɹӈ্ͷάϨʔ̐৭Ͱண৭37
ϝϞϦϨΠΞτΛ֬ೝ͢ΔlldbͰcgContext.dataͷΞυϨεΛ֬ೝ͢Δ(lldb) frame var -L ctxData0x000000016d5379e8: (UnsafeMutableRawPointer) ctxData = 0x600000c51670→ 0x600000c51670͕CGContextͷdata͕֨ೲ͞Ε͍ͯΔΞυϨε38
ϝϞϦϨΠΞτΛ֬ೝ͢Δ• Debug > Debug Workflow > ViewMemory• ϝϞϦΞυϨεΛೖྗ͢Δ39
άϨʔεέʔϧͷϝϞϦϨΠΞτ• ࠨԼ͔Βӈ্ʹ͔͚ͯॱ൪ʹஔ͞Ε͍ͯΔ• 1υοτ1byteͰ4υοτฒΜͰ͍Δ40
CGContextͷdata͔Β৭ΛऔΓग़͢struct GrayColor {let gray: UInt8}// ϙΠϯλ͔Βઌ಄8bitΛGrayColorͱͯ͠औΓग़͢let color = data.load(as: GrayColor.self)// 100ϐΫηϧͷ৭ΛऔΓग़͢let color = data.load(fromByteOffset: MemoryLayout.size * 100,as: GrayColor.self)41
ృΓ௵͠• ΩϟϯόεαΠζృΓͭͿ͠ൣғͷෳࡶ͞ʹΑ͕͔͔ͬͯ࣌ؒΔ• ࠷దͳΞϧΰϦζϜͷબఆ• ϝϞϦΛɾॻ͖ࠐΈͯ͠ߴԽ→ Swi'ͳΒܕ҆શʹͰ͖Δ• noppefoxwolf/PixelArtKit42
ύϑΥʔϚϯεͷվળ43
ύϑΥʔϚϯεͷվળ• ϝϞϦͷফඅΛ͑ΔΛͯ͠Έ·͢• ৗʹτϨʔυΦϑ͕͋Δ• Կ͕τϨʔυΦϑʹͳΔͷ͔Λߟ͑ͯΈ·͠ΐ͏44
ΠϯσοΫεΧϥʔ1. ը૾Λ256৭ͷάϨʔεέʔϧͰฤू͢Δ2. 256৭ͷάϨʔͷ৭ͦΕͧΕʹϑϧΧϥʔͷ৭ΛରԠͤͨ͞ΠϯσοΫεΛ༻ҙ͢Δ3. ΠϯσοΫεΛݩʹඳը• ΩϟϯόεͷϝϞϦ֬อ͕1/4ఔͰࡁΉ• ϨτϩήʔϜͷ2PΧϥʔͷΈ45
ΠϯσοΫεΧϥʔͷ࣮• CGContextʹػೳͱͯ͠ଘࡏ͠ͳ͍ͷͰࣗ࡞• ࣗલͷCIFilter (CoreImage)ΛͬͯඳըͷલͰண৭͢Δ• CIFilterͷγΣʔμMetalͰ࣮46
ΠϯσοΫεΧϥʔϑΟϧλͷ࣮float4 lookupTable(sampler src, sampler lut) {float2 pos = src.coord();float4 pixelColor = src.sample(pos);int index = pixelColor.r * 255;int x = index % int(lut.size().x);int y = index / int(lut.size().y);float2 lutPos = float2(x, y);float4 lutColor = lut.sample(lutPos);return lutColor;}• noppefoxwolf/PixelArtKit47
ΠϯσοΫεΧϥʔͷτϨʔυΦϑ• ৭੍͕ݶ͞ΕΔ• ը૾ͷϖʔετ͕͍͠• άϥσʔγϣϯʹऑ͘ͳΔ• ൣғબͷᮢΛѻ͍ʹ͍͘48
Recap1. υοτֆΤσΟλCoreGraphicsͱUIKit(Swi5UI)Ͱ࣮Ͱ͖Δ2. CGContextCGPathΛ͑ࣗ༝ͳඳըؔΛ࣮Ͱ͖Δ3. CGContextϝϞϦΛࢀরͰ͖Δ4. ϒϨθϯϋϜΠϯσοΫεΧϥʔͳͲͷݟࠓ׆͔ͤΔ49