Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Build your own WebP codec in Swift

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on. →

Build your own WebP codec in Swift

Avatar for Kishikawa Katsumi

Kishikawa Katsumi

September 20, 2025

More Decks by Kishikawa Katsumi

Other Decks in Programming

Transcript

  1. r 8FC1ͬͯͳʹʁ r ̎छྨͷѹॖϞʔυ r J04Ͱ͸Ͳ͜·Ͱ࢖͑Δʁ r σʔλߏ଄ʹ͍ͭͯ r ϔομΛಡΉ

    r খ͞ͳ࣮૷Ͱʮ8FC1ը૾ʯΛ࡞Δ r ·ͱΊͱ࣍ͷεςοϓ 0VUMJOF ໨࣍
  2. r 8FCαΠτͰར༻͢Δը૾ͷͨΊʹ࡞ΒΕͨը૾ѹॖܗࣜ r ಉ͡ݟͨ໨ͰϑΝΠϧ͕খ͘͞ͳΓ΍͍͢ͷͰωοτϫʔΫΛ௨ͨ͡഑৴ʹద͍ͯ͠Δ r എܠͷಁաΛαϙʔτ ‣ ΞΠίϯ΍ϩΰʹར༻͠΍͍͢ r ΞχϝʔγϣϯΛαϙʔτ

    r छྨͷѹॖϞʔυ ‣ -PTTZʢඇՄٯѹॖʣʜࡉ෦ͷ඼࣭͸Θ͔ͣʹࣦΘΕΔ͕ඇৗʹαΠζ͕খ͘͞ͳΔ ‣ -PTTMFTTʢՄٯѹॖʣʜݩͷըૉΛ׬શʹ෮ݩͰ͖Δ 8FC1ͬͯͳʹʁ
  3. 8FC1ͬͯͳʹʁ r 8FCαΠτͰར༻͢Δը૾ͷͨΊʹ࡞ΒΕͨը૾ѹॖܗࣜ r ಉ͡ݟͨ໨ͰϑΝΠϧ͕খ͘͞ͳΓ΍͍͢ͷͰωοτϫʔΫΛ௨ͨ͡഑৴ʹద͍ͯ͠Δ r എܠͷಁաΛαϙʔτ ‣ ΞΠίϯ΍ϩΰʹར༻͠΍͍͢ r

    ΞχϝʔγϣϯΛαϙʔτ r छྨͷѹॖϞʔυ ‣ -PTTZʢඇՄٯѹॖʣʜࡉ෦ͷ඼࣭͸Θ͔ͣʹࣦΘΕΔ͕ඇৗʹαΠζ͕খ͘͞ͳΔ ‣ -PTTMFTTʢՄٯѹॖʣʜݩͷըૉΛ׬શʹ෮ݩͰ͖Δ
  4. 'R' 'I' 'F' 'F' CZUFT 3*''$POUBJOFS 'R' 'I' 'F' 'F'

    'W' 'E' 'B' 'P' σʔλߏ଄ʹ͍ͭͯ 3*'' 3FTPVSDF*OUFSDIBOHF'JMF'PSNBU
  5. 'R' 'I' 'F' 'F' CZUFT 3*''$POUBJOFS 'R' 'I' 'F' 'F'

    'W' 'E' 'B' 'P' $IVOL'PVS$$ $IVOL4J[F $IVOL1BZMPBE σʔλߏ଄ʹ͍ͭͯ 3*'' 3FTPVSDF*OUFSDIBOHF'JMF'PSNBU 8FC1)FBEFS
  6. 'R' 'I' 'F' 'F' CZUFT 3*''$POUBJOFS 'R' 'I' 'F' 'F'

    'W' 'E' 'B' 'P' 'V' 'P' '8' ' ' $IVOL4J[F $IVOL1BZMPBE 4JNQMF'JMF'PSNBU 71 -PTTZ
  7. 'R' 'I' 'F' 'F' CZUFT 3*''$POUBJOFS 'R' 'I' 'F' 'F'

    'W' 'E' 'B' 'P' 'V' 'P' '8' 'L' $IVOL1BZMPBE 4JNQMF'JMF'PSNBU 71- -PTTMFTT $IVOL4J[F
  8. 'R' 'I' 'F' 'F' CZUFT 3*''$POUBJOFS 'R' 'I' 'F' 'F'

    'W' 'E' 'B' 'P' 'V' 'P' '8' 'L' CZUFT $IVOL1BZMPBE 4JNQMF'JMF'PSNBU 71 -PTTZ CZUFT CZUFT CZUFT
  9. 'R' 'I' 'F' 'F' CZUFT 3*''$POUBJOFS 'R' 'I' 'F' 'F'

    'W' 'E' 'B' 'P' 'V' 'P' '8' 'L' CZUFT $IVOL1BZMPBE 4JNQMF'JMF'PSNBU 71- -PTTMFTT CZUFT CZUFT CZUFT
  10. 'R' 'I' 'F' 'F' CZUFT 3*''$POUBJOFS 'R' 'I' 'F' 'F'

    'W' 'E' 'B' 'P' 'V' 'P' '8' 'X' CZUF $IVOL1BZMPBE &YUFOEFE'JMF'PSNBU *$$1SP fi MF "MQIBDIBOOFM "OJNBUJPO &9*'9.1NFUBEBUB 'E' 'X' 'I' 'F' $IVOL 4J[F $IVOL 1BZMPBE
  11. 'A' 'N' 'I' 'M' 3*''$POUBJOFS 'A' 'N' 'M' 'F' &YUFOEFE'JMF'PSNBU

    *$$1SP fi MF "MQIBDIBOOFM "OJNBUJPO &9*'9.1NFUBEBUB 'A' 'N' 'M' 'F' $IVOL1BZMPBE $IVOL1BZMPBE
  12. 3*'')FBEFS3FBEFS 4BNQMF$PEF struct RIFFHeaderReader { static func read(_ data: Data)

    throws -> (header: RIFFHeader, chunks: [RIFFChunk]) { var reader = ByteReader(data) let sig = try reader.readFourCC() let riffSize = try reader.readUInt32LE() let formType = try reader.readFourCC() let logicalEnd = 8 + Int(riffSizeLE) guard logicalEnd <= data.count else { throw WebPListError.truncatedRIFF } var chunks: [RIFFChunk] = [] while reader.offset + 8 <= logicalEnd { let fourCC = try r.readFourCC() let size = try r.readUInt32LE() let payloadStart = r.offset let payloadEnd = payloadStart + Int(size) try reader.skip(Int(sizeLE)) if (size & 1) == 1 { try reader.skip(1) } } let header = RIFFHeader(signature: sig, fileSizeLE: riffSize, formType: formType) return (header, chunks) } }
  13. খ͞ͳ࣮૷Ͱʮ8FC1ը૾ʯΛ࡞Δ – 'VP8 ' ʜ-PTTZʢඇՄٯѹॖʣ – 'VP8L' ʜ-PTTMFTTʢՄٯѹॖʣ – 'ALPH'ʜ-PTTZʢඇՄٯѹॖʣϑΥʔϚοτͷΞϧϑΝ৘ใ

    r ANIM''ANMF' ʜΞχϝʔγϣϯʗΞχϝʔγϣϯϑϨʔϜ – 'ICCP' ʜ*$$ΧϥʔϓϩϑΝΠϧ r 'EXIF''XMP 'ʜϝλσʔλ
  14. – 'VP8 ' ʜ-PTTZʢඇՄٯѹॖʣ – 'VP8L' ʜ-PTTMFTTʢՄٯѹॖʣ – 'ALPH'ʜ-PTTZʢඇՄٯѹॖʣϑΥʔϚοτͷΞϧϑΝ৘ใ r

    ANIM''ANMF' ʜΞχϝʔγϣϯʗΞχϝʔγϣϯϑϨʔϜ – 'ICCP' ʜ*$$ΧϥʔϓϩϑΝΠϧ r 'EXIF''XMP 'ʜϝλσʔλ খ͞ͳ࣮૷Ͱʮ8FC1ը૾ʯΛ࡞Δ
  15. – 'VP8 ' ʜ-PTTZʢඇՄٯѹॖʣ – 'VP8L' ʜ-PTTMFTTʢՄٯѹॖʣ – 'ALPH'ʜ-PTTZʢඇՄٯѹॖʣϑΥʔϚοτͷΞϧϑΝ৘ใ r

    ANIM''ANMF' ʜΞχϝʔγϣϯʗΞχϝʔγϣϯϑϨʔϜ – 'ICCP' ʜ*$$ΧϥʔϓϩϑΝΠϧ r 'EXIF''XMP 'ʜϝλσʔλ খ͞ͳ࣮૷Ͱʮ8FC1ը૾ʯΛ࡞Δ
  16. – 'VP8 ' ʜ-PTTZʢඇՄٯѹॖʣ – 'VP8L' ʜ-PTTMFTTʢՄٯѹॖʣ – 'ALPH'ʜ-PTTZʢඇՄٯѹॖʣϑΥʔϚοτͷΞϧϑΝ৘ใ r

    ANIM''ANMF' ʜΞχϝʔγϣϯʗΞχϝʔγϣϯϑϨʔϜ – 'ICCP' ʜ*$$ΧϥʔϓϩϑΝΠϧ r 'EXIF''XMP 'ʜϝλσʔλ খ͞ͳ࣮૷Ͱʮ8FC1ը૾ʯΛ࡞Δ എܠ͕෼͔ΕͯͨΓΩϟϯόεશମͰ͸ͳ͘ ಈ͘෦෼͚ͩ֨ೲ͢ΔͳͲएׯͷ௥Ճ࣮૷͕ඞཁ
  17. – 'VP8 ' ʜ-PTTZʢඇՄٯѹॖʣ – 'VP8L' ʜ-PTTMFTTʢՄٯѹॖʣ – 'ALPH'ʜ-PTTZʢඇՄٯѹॖʣϑΥʔϚοτͷΞϧϑΝ৘ใ r

    ANIM''ANMF' ʜΞχϝʔγϣϯʗΞχϝʔγϣϯϑϨʔϜ – 'ICCP' ʜ*$$ΧϥʔϓϩϑΝΠϧ r 'EXIF''XMP 'ʜϝλσʔλ খ͞ͳ࣮૷Ͱʮ8FC1ը૾ʯΛ࡞Δ
  18. – 'VP8 ' ʜ-PTTZʢඇՄٯѹॖʣ – 'VP8L' ʜ-PTTMFTTʢՄٯѹॖʣ – 'ALPH'ʜ-PTTZʢඇՄٯѹॖʣϑΥʔϚοτͷΞϧϑΝ৘ใ r

    ANIM''ANMF' ʜΞχϝʔγϣϯʗΞχϝʔγϣϯϑϨʔϜ – 'ICCP' ʜ*$$ΧϥʔϓϩϑΝΠϧ r 'EXIF''XMP 'ʜϝλσʔλ খ͞ͳ࣮૷Ͱʮ8FC1ը૾ʯΛ࡞Δ
  19. #JU3FBEFS 4BNQMF$PEF struct BitReader { var bits: UInt32 = 0

    // Buffered bits (LSB-first). var nBits: UInt32 = 0 // Number of valid bits currently in `bits`. var reader: ByteReader init(data: Data) { self.reader = ByteReader(data) } mutating func read(_ n: UInt32) throws -> UInt32 { precondition((1...32).contains(n), "n must be in 1…32") // Refill until we have enough bits. while nBits < n { guard let byte = try reader.read() else { throw BitStreamError.unexpectedEOF } // Append the byte at the current high position. bits |= UInt32(byte) << nBits nBits += 8 } // Mask out the requested bits. let result = bits & ((1 << n) &- 1) // (&- avoids overflow trap when n == 32) // Shift away the bits we've consumed. bits >>= n nBits -= n return result } }
  20. ৭ม׵ Color Indexing Subtract Green Cross Color Color Cache Predictor

    LZ77 τʔΫϯԽ খ͞ͳ࣮૷ͰʮѹॖσʔλʯΛ࡞ͬͯΈΔ )VGGNBO$PEJOH )VGGNBO$PEJOH
  21. 4BNQMF$PEF ➡IUUQTHJUIVCDPNLJTIJLBXBLBUTVNJXFCQFYFSDJTFT 📦 1SF fi Y$PEJOH 4VCUSBDU (SFFO -; 1SFEJDUPS

    Cross Color $PMPS *OEFYJOH $PMPS$BDIF 1SF fi Y$PEJOH 🗜📤 4VCUSBDU(SFFO 🗜📤 🗜📤 -; 🗜📤 🗜📤 1SFEJDUPS 🗜📤 🗜📤 $SPTT$PMPS 🗜📤 🗜📤 $PMPS*OEFYJOH 🗜📤 🗜📤 $PMPS$BDIF 🗜📤 🗜📤 $PNQMFUF 🗜📤 🗜📤 🗜📤 🗜📤 🗜📤 🗜📤 🗜📤
  22. ϋϑϚϯූ߸Խ ྫ#00,,&&1&3 BOOKKEEPER γϯϘϧ & 0 , # 1 3

    ग़ݱස౓       ௿ස౓ ߴස౓
  23. ϋϑϚϯූ߸Խ ྫ#00,,&&1&3 B P γϯϘϧ & 0 , 3 #

    1 ग़ݱස౓         O K R E    
  24. ϋϑϚϯූ߸Խ ྫ#00,,&&1&3 B P γϯϘϧ & 0 , 3 #

    1 ग़ݱස౓         O K R E    
  25. ϋϑϚϯූ߸Խ ྫ#00,,&&1&3 B P γϯϘϧ & 0 , 3 #

    1 ग़ݱස౓         O K R E     
  26. ϋϑϚϯූ߸Խ ྫ#00,,&&1&3 B P γϯϘϧ & 0 , 3 #

    1 ग़ݱස౓         O K R E      
  27. ϋϑϚϯූ߸Խ ྫ#00,,&&1&3 B P γϯϘϧ & 0 , 3 #

    1 ग़ݱස౓         O K R E     2 
  28. B P O K R E γϯϘϧ & 0 ,

    3 # 1 ग़ݱස౓       ූ߸ 0 0 1 0 1 1 1 0 1 0
  29. B P O K R E γϯϘϧ & 0 ,

    3 # 1 ग़ݱස౓       ූ߸ 00 0 0 1 0 1 1 1 0 1 0
  30. γϯϘϧ & 0 , 3 # 1 ग़ݱස౓  

        ූ߸ 00 10 B P O K R E 2 0 0 1 0 1 1 1 0 1 0
  31. B P O K R E γϯϘϧ & 0 ,

    3 # 1 ग़ݱස౓       ූ߸ 00 10 010 0 0 1 0 1 1 1 0 1 0
  32. γϯϘϧ & 0 , 3 # 1 ग़ݱස౓  

        ූ߸ 00 10 010 011 110 111 B P O K R E 0 0 1 0 1 1 1 0 1 0
  33. ϋϑϚϯූ߸Խ ྫ#00,,&&1&3 γϯϘϧ & 0 , 3 # 1 ग़ݱස౓

          ූ߸ 00 10 010 011 110 111 B O O K K E E P E R 100 101 101 01 01 00 00 110 00 111
  34. B P   O K R E  

           γϯϘϧ & 0 , 3 # 1 ग़ݱස౓       ූ߸ 00 10 010 011 110 111
  35. ූ߸௕ CJU CJU B P O K R E $BOPOJDBM)VGGNBO$PEJOH

    ਖ਼४ʢਖ਼نԽʣϋϑϚϯූ߸Խ CJU
  36. ූ߸௕ CJU CJU P R O B K E $BOPOJDBM)VGGNBO$PEJOH

    ਖ਼४ʢਖ਼نԽʣϋϑϚϯූ߸Խ CJU
  37. ූ߸௕ CJU CJU P R O B K E $BOPOJDBM)VGGNBO$PEJOH

    ਖ਼४ʢਖ਼نԽʣϋϑϚϯූ߸Խ CJU 00 01
  38. ූ߸௕ CJU CJU P R O B K E $BOPOJDBM)VGGNBO$PEJOH

    ਖ਼४ʢਖ਼نԽʣϋϑϚϯූ߸Խ CJU 00 01 100 101 110 111
  39. B O O K K E E P E R

    100 01 01 101 101 00 00 110 00 111 $BOPOJDBM)VGGNBO$PEJOH ਖ਼४ʢਖ਼نԽʣϋϑϚϯූ߸Խ [A:0, B:3, C:0, D:0, E:2, F:0, G:0, H:0, I:0, J:0, K:3, L:0, M:0, N:0, O:2, P:3, Q:0, R:3, S:0, T:0, U:0, V:0, W:0, X:0, Y:0, Z:0]
  40. B O O K K E E P E R

    100 01 01 101 101 00 00 110 00 111 $BOPOJDBM)VGGNBO$PEJOH ਖ਼४ʢਖ਼نԽʣϋϑϚϯූ߸Խ [0,3,0,0,2,0,0,0,0,0,3,0,0,0,2,3,0,3,0,0,0,0,0,0,0,0]
  41. γϯϘϧ         ग़ݱස౓

            ූ߸ 0 101 110 100 11111 11100 11101 11110
  42. ৭ม׵ Color Indexing Subtract Green Cross Color Color Cache Predictor

    LZ77 τʔΫϯԽ )VGGNBO$PEJOH )VGGNBO$PEJOH 3FRVJSFE 0QUJPOBM
  43. 4VCUSBDU(SFFO Τϯίʔυ func applySubtractGreenTransform(pixels: inout [NRGBA]) { for i in

    pixels.indices { pixels[i].r = pixels[i].r &- pixels[i].g pixels[i].b = pixels[i].b &- pixels[i].g } }
  44. 4VCUSBDU(SFFO σίʔυʢٯม׵ʣ func inverseSubtractGreen(_ pixel: [UInt8]) -> [UInt8] { var

    out = pixel var i = 0 while p < out.count { let g = out[i + 1] // green out[i + 0] &+= g // red += green out[i + 2] &+= g // blue += green I += 4 } return out }
  45. 4VCUSBDU(SFFO ޮՌ [52, 50, 47] [106, 110, 97] [147, 150,

    156] [202, 200, 197] [2, 50, -3] [-4, 100, -3] [-3, 150, 6] [2, 200, -3]
  46. 3FGFSFODFT r 4BNQMF$PEF IUUQTHJUIVCDPNLJTIJLBXBLBUTVNJXFCQFYFSDJTFT r "OJNBHFGPSNBUGPSUIF8FC c 8FC1 c (PPHMFGPS%FWFMPQFST

    IUUQTEFWFMPQFSTHPPHMFDPNTQFFEXFCQ r MJCXFCQ IUUQTDISPNJVNHPPHMFTPVSDFDPNXFCNMJCXFCQ r MJCXFCQUFTUEBUB IUUQTDISPNJVNHPPHMFTPVSDFDPNXFCNMJCXFCQUFTUEBUB