Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

readable symbol links #83

Merged
merged 1 commit into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
.vscode
/.build
/.build.*
/.entrapta
/documentation
/.ssgc
/*.xcodeproj
.swiftpm
/Benchmarks/*.png.png
/Benchmarks/compression/out/*.png
/Benchmarks/compression/baseline/main
Expand Down
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/tayloraswift/swift-grammar",
"state" : {
"revision" : "642d5957896f06b03e35c48fc439488367d3fd21",
"version" : "0.4.0"
"revision" : "4b47a153732e0b094ef7dd95d891b37b7ae37a69",
"version" : "0.4.1"
}
},
{
Expand Down
7 changes: 4 additions & 3 deletions Sources/PNG/PNG.Image.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1000,8 +1000,9 @@ extension PNG.Image
/// Unpacks this image to a pixel array.
///
/// - Parameter _:
/// A color target type. This type provides the ``PNG.Color/unpack(_:of:) [9CTKA]``
/// implementation used to unpack the image data.
/// A color target type. This type provides the
/// ``PNG.Color/unpack(_:of:) [requirement]`` implementation used to unpack the image
/// data.
/// - Returns:
/// A pixel array. Its elements are arranged in row-major order. The
/// first pixel in this array corresponds to the top-left corner of
Expand All @@ -1017,7 +1018,7 @@ extension PNG.Image
/// - Parameter pixels:
/// A pixel array. Its elements are arranged in row-major order. The
/// first pixel in this array corresponds to the top-left corner of
/// the image. The `Color` type provides the ``PNG.Color/pack(_:as:) [2Y9R9]``
/// the image. The `Color` type provides the ``PNG.Color/pack(_:as:) [requirement]``
/// implementation used to pack the image data.
///
/// The length of this array must match `size.x * size.y`. Passing an
Expand Down
4 changes: 2 additions & 2 deletions Sources/PNG/docs.docc/BasicDecoding/BasicDecoding.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ We could also have unpacked the image pixels to the [`PNG.VA<UInt8>`](PNG/VA) bu
The example image, decoded to an grayscale-alpha data file, and re-encoded as a png.
}

The ``PNG/Image/unpack(as:) [3T47M]`` method is non-mutating, so you can unpack the same image to multiple color targets without having to re-decode the file each time.
The ``PNG/Image/unpack(as:) -> [Color]`` method is non-mutating, so you can unpack the same image to multiple color targets without having to re-decode the file each time.

The ``PNG/Image/unpack(as:) [69N73]`` method also has an overload which allows you to unpack an image into scalar grayscale samples.
The ``PNG/Image/unpack(as:) -> [T]`` method also has an overload which allows you to unpack an image into scalar grayscale samples.

```swift
let v:[UInt8] = image.unpack(as: UInt8.self)
Expand Down
4 changes: 2 additions & 2 deletions Sources/PNG/docs.docc/BasicEncoding/BasicEncoding.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Most PNG viewers ignore the `fill` field, and a few ignore the `key` field as we

The non-grayscale color formats include a `palette` field. Setting it to the empty array is analogous to setting `fill` or `key` to nil. For the indexed color formats, a non-empty `palette` is mandatory. For the other formats, it is optional (meaning it can be set to `[]`), and furthermore, ignored by almost all PNG clients, since it only specifies a suggested [posterization](https://en.wikipedia.org/wiki/Posterization) for the image.

To create a rectangular image data instance, use the ``PNG/Image/init(packing:size:layout:metadata:) [95YD5]`` initializer. This initializer is the inverse of the ``PNG/Image/unpack(as:) [3T47M]`` method we used in the <doc:BasicDecoding> tutorial. Needless to say, the length of the pixel array must equal `size.x * size.y`. The `metadata` argument has a default value, which is an empty metadata record.
To create a rectangular image data instance, use the ``PNG/Image/init(packing:size:layout:metadata:) ([Color], _, _, _)`` initializer. This initializer is the inverse of the ``PNG/Image/unpack(as:) -> [Color]`` method we used in the <doc:BasicDecoding> tutorial. Needless to say, the length of the pixel array must equal `size.x * size.y`. The `metadata` argument has a default value, which is an empty metadata record.

@Snippet(id: "BasicEncoding", slice: "PACK_RGB")

Expand Down Expand Up @@ -121,7 +121,7 @@ The built-in [`PNG.RGBA<T>`](PNG/RGBA) color target will discard the green, blue
The example image, encoded by *swift png* in the 8-bit grayscale color format.
}

Like the ``PNG/Image/unpack(as:) [3T47M]`` method, the ``PNG/Image/init(packing:size:layout:metadata:) [95YD5]`` initializer is generic and can take an array of any color target. It also has an overload (``PNG/Image/init(packing:size:layout:metadata:) [8AEMD]``) which takes an array of scalars. To demonstrate this use case, we will compute the luminance of our example image (using a standard formula), and store it as a `[UInt8]` array.
Like the ``PNG/Image/unpack(as:) -> [Color]`` method, the ``PNG/Image/init(packing:size:layout:metadata:) ([Color], _, _, _)`` initializer is generic and can take an array of any color target. It also has an overload (``PNG/Image/init(packing:size:layout:metadata:) ([T], _, _, _)``) which takes an array of scalars. To demonstrate this use case, we will compute the luminance of our example image (using a standard formula), and store it as a `[UInt8]` array.

@Snippet(id: "BasicEncoding", slice: "COMPUTE_LUMINANCE")

Expand Down
4 changes: 2 additions & 2 deletions Sources/PNG/docs.docc/CustomColor/CustomColor.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,14 @@ protocol PNG.Color
}
```

For certain associated ``PNG.Color/Aggregate`` types, the library provides default implementations for ``PNG.Color/unpack(_:of:) [9CTKA]`` and ``PNG.Color/pack(_:as:) [2Y9R9]``, which have behaviors detailed in the <doc:Indexing> tutorial. In such cases, we only need to implement ``PNG.Color/unpack(_:of:deindexer:)`` and ``PNG.Color/pack(_:as:indexer:)``. The specific `Aggregate` types are
For certain associated ``PNG.Color/Aggregate`` types, the library provides default implementations for ``PNG.Color/unpack(_:of:) [requirement]`` and ``PNG.Color/pack(_:as:) [requirement]``, which have behaviors detailed in the <doc:Indexing> tutorial. In such cases, we only need to implement ``PNG.Color/unpack(_:of:deindexer:)`` and ``PNG.Color/pack(_:as:indexer:)``. The specific `Aggregate` types are

- `(UInt8, UInt8)`, and
- `(UInt8, UInt8, UInt8, UInt8)`.

In the [indexed color tutorial](doc:Indexing), we saw how they were used by the [`PNG.VA<T>`](PNG/VA) and [`PNG.RGBA<T>`](PNG/RGBA) color targets. (The scalar color targets also use their own `Aggregate` type, ``UInt8``, though this does not go through the ``PNG.Color`` protocol.)

The core idea of a color target is the **pixel kernel**. Pixel kernels convert groups of image data samples into instances of a color target, and vice-versa. In *Swift PNG*, the application of a pixel kernel to an image data buffer is called a **convolution**, and the inverse operation is called a **deconvolution**. The simplest deconvolution is to flatten an array of RGBA pixels to an array of [*r*, *g*, *b*, *a*, *r*, *g*, *b*, *a*, …] samples, and the simplest convolution is to group the elements of such an array into an array of RGBA pixels. Conceptually, this is a Swift ``Sequence/flatMap(_:) [JO2Y]``, and whatever you would call the opposite of a flatmap, respectively. We are allowed to do arbitrary computations in the pixel kernels, which is why we call it a (de)convolution, and not just a flatmap.
The core idea of a color target is the **pixel kernel**. Pixel kernels convert groups of image data samples into instances of a color target, and vice-versa. In *Swift PNG*, the application of a pixel kernel to an image data buffer is called a **convolution**, and the inverse operation is called a **deconvolution**. The simplest deconvolution is to flatten an array of RGBA pixels to an array of [*r*, *g*, *b*, *a*, *r*, *g*, *b*, *a*, …] samples, and the simplest convolution is to group the elements of such an array into an array of RGBA pixels. Conceptually, this is a Swift ``Sequence/flatMap(_:) ((Self.Element) -> SegmentOfResult)``, and whatever you would call the opposite of a flatmap, respectively. We are allowed to do arbitrary computations in the pixel kernels, which is why we call it a (de)convolution, and not just a flatmap.

Let’s tackle the unpacking operation first. *Swift PNG* provides a set of helper functions to reduce the amount of boilerplate you have to write.

Expand Down
8 changes: 4 additions & 4 deletions Sources/PNG/docs.docc/Indexing/Indexing.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ We can visualize the gradient using the same APIs we used in the <doc:BasicEncod
A visualization of the generated gradient.
}

We can create an indexed image by defining an indexed layout, and passing the grayscale samples we obtained earlier to one of the pixel-packing APIs. The ``PNG/Image/init(packing:size:layout:metadata:) [8AEMD]`` initializer will treat the grayscale samples as pixel colors, not indices, and will try to match the pixel colors to entries in the given palette. This is not what we want, so we need to use a variant of that function, ``PNG/Image/init(packing:size:layout:metadata:indexer:) [7UEEA]``, and pass it a custom [*indexing function*](#st:indexing-function).
We can create an indexed image by defining an indexed layout, and passing the grayscale samples we obtained earlier to one of the pixel-packing APIs. The ``PNG/Image/init(packing:size:layout:metadata:) ([T], _, _, _)`` initializer will treat the grayscale samples as pixel colors, not indices, and will try to match the pixel colors to entries in the given palette. This is not what we want, so we need to use a variant of that function, ``PNG/Image/init(packing:size:layout:metadata:indexer:) (_, _, _, _, ([(UInt8, UInt8, UInt8, UInt8)]) -> (UInt8) -> Int)``, and pass it a custom [*indexing function*](#st:indexing-function).

@Snippet(id: "Indexing", slice: "PACK_EXAMPLE")

The best way to understand the indexing function is to compare it with the behavior of the ``PNG/Image/init(packing:size:layout:metadata:) [8AEMD]`` initializer. Calling that initializer is equivalent to calling ``PNG/Image/init(packing:size:layout:metadata:indexer:) [7UEEA]`` with the following indexing function.
The best way to understand the indexing function is to compare it with the behavior of the ``PNG/Image/init(packing:size:layout:metadata:) ([T], _, _, _)`` initializer. Calling that initializer is equivalent to calling ``PNG/Image/init(packing:size:layout:metadata:indexer:) (_, _, _, _, ([(UInt8, UInt8, UInt8, UInt8)]) -> (UInt8) -> Int)`` with the following indexing function.

```swift
{
Expand Down Expand Up @@ -87,7 +87,7 @@ Let’s go back to the custom indexing function:
}
```

Since we just want to cast the grayscale samples directly to index values, we don’t need the palette parameter, so we discard it with the `_` binding. We then return the ``Int.init(_:) [4EKVL]`` initializer, which casts the grayscale samples to ``Int``s.
Since we just want to cast the grayscale samples directly to index values, we don’t need the palette parameter, so we discard it with the `_` binding. We then return ``Int``’s ``SignedInteger/init(_:)`` initializer, which casts the grayscale samples to ``Int``s.

On appropriate platforms, we can encode the image to a file with the ``PNG/Image/compress(path:level:hint:)`` method.

Expand All @@ -97,7 +97,7 @@ On appropriate platforms, we can encode the image to a file with the ``PNG/Image
The example image, colorized as an indexed png.
}

To read back the index values from the indexed image, we can use a custom **deindexing function**, which we pass to ``PNG/Image/unpack(as:deindexer:) [JEO1]``.
To read back the index values from the indexed image, we can use a custom **deindexing function**, which we pass to ``PNG/Image/unpack(as:deindexer:) (_, ([(UInt8, UInt8, UInt8, UInt8)]) -> (Int) -> UInt8)``.

@Snippet(id: "Indexing", slice: "UNPACK_EXAMPLE")

Expand Down