Skip to content

Commit

Permalink
Merge pull request #60 from tayloraswift/modernize-docs
Browse files Browse the repository at this point in the history
Modernize docs
  • Loading branch information
tayloraswift authored Feb 21, 2024
2 parents e4c16d0 + a63f4ce commit d3aa6f9
Show file tree
Hide file tree
Showing 142 changed files with 3,760 additions and 4,669 deletions.
4 changes: 2 additions & 2 deletions Benchmarks/Compression/Swift/Main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ enum Benchmark
}
}
}
extension Benchmark.Encode.Blob:PNG.Bytestream.Destination
extension Benchmark.Encode.Blob:PNG.BytestreamDestination
{
mutating
func write(_ data:[UInt8]) -> Void?
Expand All @@ -55,7 +55,7 @@ extension Benchmark.Encode
static
func rgba8(level:Int, path:String, trials:Int) -> ([(time:Int, hash:Int)], Int)
{
guard let image:PNG.Data.Rectangular = try? .decompress(path: path)
guard let image:PNG.Image = try? .decompress(path: path)
else
{
fatalError("failed to decode test image '\(path)'")
Expand Down
4 changes: 2 additions & 2 deletions Benchmarks/Decompression/Swift/Main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ enum Benchmark
}
}
}
extension Benchmark.Decode.Blob:PNG.Bytestream.Source
extension Benchmark.Decode.Blob:PNG.BytestreamSource
{
static
func load(path:String) -> Self?
Expand Down Expand Up @@ -102,7 +102,7 @@ extension Benchmark.Decode
{
let start:Int = clock()

let image:PNG.Data.Rectangular = try .decompress(stream: &blob)
let image:PNG.Image = try .decompress(stream: &blob)
let pixels:[PNG.RGBA<UInt8>] = image.unpack(as: PNG.RGBA<UInt8>.self)

let stop:Int = clock()
Expand Down
2 changes: 1 addition & 1 deletion Notes/improving-deflate-compression-speed.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ clang -lpng ${prefix}/main.c -o ${binary}

The same script also builds an equivalent Swift program in [`Benchmarks/compression/swift/`](../Benchmarks/compression/swift) using the Swift Package Manager. The Swift program, of course, invokes Swift *PNG* instead of *libpng*.

Disk latency contributes a noticeable (but not overwhelming) proportion of the time needed to encode a PNG file, especially at low compression levels. To avoid this problem, the C and Swift benchmarks both have their respective backends configured to write output images to memory instead of the file system. For *libpng*, you can do this by creating a custom buffer context and passing a callback function to `png_set_write_fn(_:_:_:_:)`. For Swift *PNG*, you can do this statically by conforming a buffer type of your choice to the `PNG.Bytestream.Destination` protocol.
Disk latency contributes a noticeable (but not overwhelming) proportion of the time needed to encode a PNG file, especially at low compression levels. To avoid this problem, the C and Swift benchmarks both have their respective backends configured to write output images to memory instead of the file system. For *libpng*, you can do this by creating a custom buffer context and passing a callback function to `png_set_write_fn(_:_:_:_:)`. For Swift *PNG*, you can do this statically by conforming a buffer type of your choice to the `PNG.BytestreamDestination` protocol.

The memory target for the baseline C program is a `malloc`-based vector which uses the following reallocation rule:

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import PNG
func decode(png path:String) throws
{
guard
let image:PNG.Data.Rectangular = try .decompress(path: path)
let image:PNG.Image = try .decompress(path: path)
else
{
// failed to access file from file system
Expand All @@ -66,7 +66,7 @@ Encode an image:
```swift
func encode(png path:String, size:(x:Int, y:Int), pixels:[PNG.RGBA<UInt8>]) throws
{
let image:PNG.Data.Rectangular = .init(packing: pixels, size: size,
let image:PNG.Image = .init(packing: pixels, size: size,
layout: .init(format: .rgba8(palette: [], fill: nil)))
try image.compress(path: path, level: 9)
}
Expand All @@ -84,7 +84,7 @@ func encode(png path:String, size:(x:Int, y:Int), pixels:[PNG.RGBA<UInt8>]) thro

- ***Batteries included.*** *Swift PNG* comes with [built-in color targets](https://tayloraswift.github.io/swift-png/PNG/Color/) with support for [premultiplied alpha](https://tayloraswift.github.io/swift-png/PNG/RGBA/premultiplied/). [Convolution](https://tayloraswift.github.io/swift-png/PNG/convolve(_:dereference:kernel:)/) and [deconvolution](https://tayloraswift.github.io/swift-png/PNG/deconvolve(_:reference:kernel:)/) helper functions make [implementing custom color targets](examples/#custom-color-targets) a breeze.

On MacOS and Linux, *Swift PNG* has built-in file system support, allowing you to [compress](https://tayloraswift.github.io/swift-png/PNG/Data/Rectangular/compress(path:level:hint:)/) or [decompress](https://tayloraswift.github.io/swift-png/PNG/Data/Rectangular/decompress(path:)/) an image, given a filepath, in a single function call. Other platforms can take advantage of *Swift PNG*’s [protocol-oriented IO](https://tayloraswift.github.io/swift-png/PNG/Bytestream/) to implement their own data loading.
On MacOS and Linux, *Swift PNG* has built-in file system support, allowing you to [compress](https://tayloraswift.github.io/swift-png/PNG/Image/compress(path:level:hint:)/) or [decompress](https://tayloraswift.github.io/swift-png/PNG/Image/decompress(path:)/) an image, given a filepath, in a single function call. Other platforms can take advantage of *Swift PNG*’s [protocol-oriented IO](https://tayloraswift.github.io/swift-png/PNG/Bytestream/) to implement their own data loading.

- ***First-class iPhone optimization support.*** *Swift PNG* requires no custom setup or third-party plugins to handle [iPhone-optimized](examples/#using-iphone-optimized-images) PNG images. iPhone-optimized images just work, on all platforms. Reproduce [`pngcrush`](https://developer.apple.com/library/archive/qa/qa1681/_index.html)’s output with [bit width-aware alpha premultiplication](https://tayloraswift.github.io/swift-png/PNG/RGBA/premultiplied(as:)/), for seamless integration anywhere in your application stack.

Expand Down
Binary file removed Snippets/BasicDecoding/example.png.rgba.png
Binary file not shown.
Binary file removed Snippets/BasicDecoding/example.png.v.png
Binary file not shown.
Binary file removed Snippets/BasicDecoding/example.png.va.png
Binary file not shown.
Binary file removed Snippets/ImagesInMemory/example.png.rgba.png
Binary file not shown.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import LZ77
import PNG

let path:String = "Snippets/GzipCompression/example"
let path:String = "Sources/LZ77/docs.docc/GzipCompression/GzipCompression"

guard
let original:[UInt8] = (System.File.Source.open(path: "\(path).gz")
Expand Down
21 changes: 19 additions & 2 deletions Snippets/BasicDecoding.swift → Snippets/PNG/BasicDecoding.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
// On platforms with built-in file system support (MacOS and Linux), decoding a PNG file to a
// pixel array takes just two function calls.

// snippet.RGBA
import PNG

let path:String = "Snippets/BasicDecoding/example"
let path:String = "Sources/PNG/docs.docc/BasicDecoding/BasicDecoding"

guard
let image:PNG.Data.Rectangular = try .decompress(path: "\(path).png")
let image:PNG.Image = try .decompress(path: "\(path).png")
else
{
fatalError("failed to open file '\(path).png'")
}

let rgba:[PNG.RGBA<UInt8>] = image.unpack(as: PNG.RGBA<UInt8>.self)

// snippet.end

guard
let _:Void = (System.File.Destination.open(path: "\(path).png.rgba")
{
Expand All @@ -25,7 +32,12 @@ else
fatalError("failed to open file '\(path).png.rgba'")
}

// snippet.VA

let va:[PNG.VA<UInt8>] = image.unpack(as: PNG.VA<UInt8>.self)

// snippet.end

guard
let _:Void = (System.File.Destination.open(path: "\(path).png.va")
{
Expand All @@ -41,7 +53,12 @@ else
fatalError("failed to open file '\(path).png.va'")
}

// snippet.V

let v:[UInt8] = image.unpack(as: UInt8.self)

// snippet.end

guard
let _:Void = (System.File.Destination.open(path: "\(path).png.v")
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import PNG

/// https://commons.wikimedia.org/wiki/File:Photo_of_a_venetian_mask_in_a_studio_photo_session.jpg
let path:String = "Snippets/BasicEncoding/example"
let path:String = "Sources/PNG/docs.docc/BasicEncoding/BasicEncoding"
let size:(x:Int, y:Int) = (638, 425)

guard
Expand Down Expand Up @@ -33,7 +33,7 @@ let layout:(rgb:PNG.Layout, v:PNG.Layout) =

do
{
let image:PNG.Data.Rectangular = .init(packing: rgba, size: size, layout: layout.rgb)
let image:PNG.Image = .init(packing: rgba, size: size, layout: layout.rgb)
try image.compress(path: "\(path)-color-rgb.png", level: 9)

for level:Int in [0, 4, 8, 13]
Expand All @@ -43,7 +43,7 @@ do
}
do
{
let image:PNG.Data.Rectangular = .init(packing: rgba, size: size, layout: layout.v)
let image:PNG.Image = .init(packing: rgba, size: size, layout: layout.v)
try image.compress(path: "\(path)-color-v.png", level: 9)
}

Expand All @@ -57,11 +57,11 @@ let luminance:[UInt8] = rgba.map
}
do
{
let image:PNG.Data.Rectangular = .init(packing: luminance, size: size, layout: layout.v)
let image:PNG.Image = .init(packing: luminance, size: size, layout: layout.v)
try image.compress(path: "\(path)-luminance-v.png", level: 9)
}
do
{
let image:PNG.Data.Rectangular = .init(packing: luminance, size: size, layout: layout.rgb)
let image:PNG.Image = .init(packing: luminance, size: size, layout: layout.rgb)
try image.compress(path: "\(path)-luminance-rgb.png", level: 9)
}
12 changes: 6 additions & 6 deletions Snippets/CustomColor.swift → Snippets/PNG/CustomColor.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import PNG

/// https://commons.wikimedia.org/wiki/File:Alice-in-Wonderland_by-David-Revoy_2010-07-21.jpg
let path:String = "Snippets/CustomColor/example"
let path:String = "Sources/PNG/docs.docc/CustomColor/CustomColor"

struct HSVA
{
Expand Down Expand Up @@ -296,36 +296,36 @@ extension HSVA:PNG.Color
}

guard
let image:PNG.Data.Rectangular = try .decompress(path: "\(path).png")
let image:PNG.Image = try .decompress(path: "\(path).png")
else
{
fatalError("failed to open file '\(path).png'")
}

let hsva:[HSVA] = image.unpack(as: HSVA.self)

let hue:PNG.Data.Rectangular = .init(
let hue:PNG.Image = .init(
packing: hsva.map{ HSVA.init(h: $0.h, s: .max / 2, v: .max, a: $0.a) },
size: image.size,
layout: image.layout,
metadata: image.metadata)
try hue.compress(path: "\(path)-hue.png")

let saturation:PNG.Data.Rectangular = .init(
let saturation:PNG.Image = .init(
packing: hsva.map{ HSVA.init(h: 370000, s: $0.s, v: .max, a: $0.a) },
size: image.size,
layout: image.layout,
metadata: image.metadata)
try saturation.compress(path: "\(path)-saturation.png")

let value:PNG.Data.Rectangular = .init(
let value:PNG.Image = .init(
packing: hsva.map{ HSVA.init(h: 0, s: 0, v: $0.v, a: $0.a) },
size: image.size,
layout: image.layout,
metadata: image.metadata)
try value.compress(path: "\(path)-value.png")

let new:PNG.Data.Rectangular = .init(packing: hsva,
let new:PNG.Image = .init(packing: hsva,
size: image.size,
layout: image.layout,
metadata: image.metadata)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import PNG

/// https://commons.wikimedia.org/wiki/File:Coat_of_arms_of_Siam.svg
let path:String = "Snippets/ImageMetadata/example"
let path:String = "Sources/PNG/docs.docc/ImageMetadata/ImageMetadata"

guard
var image:PNG.Data.Rectangular = try .decompress(path: "\(path).png")
var image:PNG.Image = try .decompress(path: "\(path).png")
else
{
fatalError("failed to open file '\(path).png'")
Expand All @@ -30,7 +30,7 @@ image.metadata.time = .init(year: 1992, month: 8, day: 3, hour: 0, minute: 0, se
try image.compress(path: "\(path)-newtime.png")


if let image:PNG.Data.Rectangular = try .decompress(path: "\(path)-newtime.png"),
if let image:PNG.Image = try .decompress(path: "\(path)-newtime.png"),
let time:PNG.TimeModified = image.metadata.time ?? nil
{
print(time)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import PNG

let path:String = "Snippets/ImagesInMemory/example"
let path:String = "Sources/PNG/docs.docc/ImagesInMemory/ImagesInMemory"

extension System
{
Expand All @@ -12,7 +12,7 @@ extension System
}
}

extension System.Blob:PNG.Bytestream.Source, PNG.Bytestream.Destination
extension System.Blob:PNG.BytestreamSource, PNG.BytestreamDestination
{
init(_ data:[UInt8])
{
Expand Down Expand Up @@ -64,7 +64,7 @@ else

var blob:System.Blob = .init(data)
// read from blob
let image:PNG.Data.Rectangular = try .decompress(stream: &blob)
let image:PNG.Image = try .decompress(stream: &blob)
let rgba:[PNG.RGBA<UInt8>] = image.unpack(as: PNG.RGBA<UInt8>.self)
guard
let _:Void = (System.File.Destination.open(path: "\(path).png.rgba")
Expand Down
10 changes: 5 additions & 5 deletions Snippets/Indexing.swift → Snippets/PNG/Indexing.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import PNG

let path:String = "Snippets/Indexing/example"
let path:String = "Sources/PNG/docs.docc/Indexing/Indexing"

guard
let image:PNG.Data.Rectangular = try .decompress(path: "\(path).png")
let image:PNG.Image = try .decompress(path: "\(path).png")
else
{
fatalError("failed to open file '\(path).png'")
Expand Down Expand Up @@ -77,12 +77,12 @@ let swatch:[PNG.RGBA<UInt8>] = (0 ..< 16).flatMap
return .init(r, g, b, a)
}
}
let visualization:PNG.Data.Rectangular = .init(packing: swatch, size: (256, 16),
let visualization:PNG.Image = .init(packing: swatch, size: (256, 16),
layout: .init(format: .rgb8(palette: [], fill: nil, key: nil)))
try visualization.compress(path: "Snippets/Indexing/gradient-visualization.png")
try visualization.compress(path: "\(path)-gradient.png")

// encode colorized image
let indexed:PNG.Data.Rectangular = .init(packing: v, size: image.size,
let indexed:PNG.Image = .init(packing: v, size: image.size,
layout: .init(format: .indexed8(palette: gradient, fill: nil)),
metadata: image.metadata)
{
Expand Down
20 changes: 10 additions & 10 deletions Snippets/OnlineDecoding.swift → Snippets/PNG/OnlineDecoding.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import PNG

let path:String = "Snippets/OnlineDecoding/example"
let path:String = "Sources/PNG/docs.docc/OnlineDecoding/OnlineDecoding"

struct Stream
{
Expand All @@ -10,7 +10,7 @@ struct Stream
available:Int
}

extension Stream:PNG.Bytestream.Source
extension Stream:PNG.BytestreamSource
{
init(_ data:[UInt8])
{
Expand Down Expand Up @@ -108,7 +108,7 @@ func waitChunk(stream:inout Stream) throws -> (type:PNG.Chunk, data:[UInt8])

func decodeOnline(stream:inout Stream,
overdraw:Bool,
capture:(PNG.Data.Rectangular) throws -> ()) throws -> PNG.Data.Rectangular
capture:(PNG.Image) throws -> ()) throws -> PNG.Image
{
// lex PNG signature bytes
try waitSignature(stream: &stream)
Expand Down Expand Up @@ -212,9 +212,9 @@ func decodeOnline(stream:inout Stream,
var stream:Stream = .init(path: "\(path).png")

var counter:Int = 0
let image:PNG.Data.Rectangular = try decodeOnline(stream: &stream, overdraw: false)
let image:PNG.Image = try decodeOnline(stream: &stream, overdraw: false)
{
(snapshot:PNG.Data.Rectangular) in
(snapshot:PNG.Image) in

let _:[PNG.RGBA<UInt8>] = snapshot.unpack(as: PNG.RGBA<UInt8>.self)

Expand All @@ -223,15 +223,15 @@ let image:PNG.Data.Rectangular = try decodeOnline(stream: &stream, overdraw: fal
}

let layout:PNG.Layout = .init(format: image.layout.format, interlaced: true)
let progressive:PNG.Data.Rectangular = image.bindStorage(to: layout)
let progressive:PNG.Image = image.bindStorage(to: layout)

try progressive.compress(path: "\(path)-progressive.png", hint: 1 << 12)

stream = .init(path: "\(path)-progressive.png")
counter = 0
let _:PNG.Data.Rectangular = try decodeOnline(stream: &stream, overdraw: false)
let _:PNG.Image = try decodeOnline(stream: &stream, overdraw: false)
{
(snapshot:PNG.Data.Rectangular) in
(snapshot:PNG.Image) in

try snapshot.compress(path: "\(path)-progressive-\(counter).png")
counter += 1
Expand All @@ -240,9 +240,9 @@ let _:PNG.Data.Rectangular = try decodeOnline(stream: &stream, overdraw: false)
stream.reset(position: 0)

counter = 0
let _:PNG.Data.Rectangular = try decodeOnline(stream: &stream, overdraw: true)
let _:PNG.Image = try decodeOnline(stream: &stream, overdraw: true)
{
(snapshot:PNG.Data.Rectangular) in
(snapshot:PNG.Image) in

try snapshot.compress(path: "\(path)-progressive-overdrawn-\(counter).png")
counter += 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import PNG

let path:String = "Snippets/iPhoneOptimized/example"
let path:String = "Sources/PNG/docs.docc/iPhoneOptimized/iPhoneOptimized"

guard
var image:PNG.Data.Rectangular = try .decompress(path: "\(path).png")
var image:PNG.Image = try .decompress(path: "\(path).png")
else
{
fatalError("failed to open file '\(path).png'")
Expand All @@ -15,14 +15,14 @@ let rgba:[PNG.RGBA<UInt8>] = image.unpack(as: PNG.RGBA<UInt8>.self).map(\.straig

print(image.storage[..<16])

let standard:PNG.Data.Rectangular = .init(
let standard:PNG.Image = .init(
packing: rgba,
size: image.size,
layout: .init(format: .rgb8(palette: [], fill: nil, key: nil)))

try standard.compress(path: "\(path)-rgb8.png")

let apple:PNG.Data.Rectangular = .init(
let apple:PNG.Image = .init(
packing: standard.unpack(as: PNG.RGBA<UInt8>.self).map(\.premultiplied),
size: standard.size,
layout: .init(format: .bgr8(palette: [], fill: nil, key: nil)))
Expand Down
Loading

0 comments on commit d3aa6f9

Please sign in to comment.