Skip to content

Commit

Permalink
Merge pull request #24 from tayloraswift/refactor-modules
Browse files Browse the repository at this point in the history
factor the OS-dependent APIs into a separate JPEGSystem module
  • Loading branch information
tayloraswift authored Nov 16, 2024
2 parents 7617808 + 199d451 commit c5243c1
Show file tree
Hide file tree
Showing 24 changed files with 80 additions and 230 deletions.
191 changes: 10 additions & 181 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,218 +6,47 @@ let package = Package(
products:
[
.library(name: "JPEG", targets: ["JPEG"]),
.executable(name: "fuzzer", targets: ["JPEGFuzzer"]),
.executable(name: "comparator", targets: ["JPEGComparator"]),
.executable(name: "unit-test", targets: ["JPEGUnitTests"]),
.executable(name: "regression-test", targets: ["JPEGRegressionTests"]),
.executable(name: "integration-test", targets: ["JPEGIntegrationTests"]),

.executable(name: "decode-basic", targets: ["JPEGDecodeBasic"]),
.executable(name: "encode-basic", targets: ["JPEGEncodeBasic"]),
.executable(name: "decode-advanced", targets: ["JPEGDecodeAdvanced"]),
.executable(name: "encode-advanced", targets: ["JPEGEncodeAdvanced"]),
.executable(name: "in-memory", targets: ["JPEGInMemory"]),
.executable(name: "decode-online", targets: ["JPEGDecodeOnline"]),
.executable(name: "recompress", targets: ["JPEGRecompress"]),
.executable(name: "rotate", targets: ["JPEGRotate"]),
.executable(name: "custom-color", targets: ["JPEGCustomColor"]),
.library(name: "JPEGSystem", targets: ["JPEGSystem"]),
],
targets:
[
.target(name: "JPEG"),

.target(name: "JPEGSystem",
dependencies: ["JPEG"]),

.target(name: "JPEGInspection"),

.executableTarget(name: "JPEGFuzzer",
dependencies: ["JPEG", "JPEGInspection"],
dependencies: ["JPEG", "JPEGInspection", "JPEGSystem"],
path: "tests/fuzz",
exclude: [
"data/",
]
),

.executableTarget(name: "JPEGComparator",
dependencies: ["JPEG", "JPEGInspection"],
dependencies: ["JPEG", "JPEGInspection", "JPEGSystem"],
path: "tests/compare"),

.executableTarget(name: "JPEGUnitTests",
dependencies: ["JPEG", "JPEGInspection"],
dependencies: ["JPEG", "JPEGInspection", "JPEGSystem"],
path: "tests/unit"),

.executableTarget(name: "JPEGRegressionTests",
dependencies: ["JPEG", "JPEGInspection"],
dependencies: ["JPEG", "JPEGInspection", "JPEGSystem"],
path: "tests/regression",
exclude: [
"gold/",
]),

.executableTarget(name: "JPEGIntegrationTests",
dependencies: ["JPEG", "JPEGInspection"],
dependencies: ["JPEG", "JPEGInspection", "JPEGSystem"],
path: "tests/integration",
exclude: [
"decode/",
"encode/",
]),

.executableTarget(name: "JPEGDecodeBasic",
dependencies: ["JPEG", "JPEGInspection"],
path: "examples/decode-basic",
exclude: [
"karlie-kwk-2019.jpg.rgb",
"karlie-kwk-2019.jpg",
"karlie-kwk-2019.jpg.rgb.png",
]),

.executableTarget(name: "JPEGEncodeBasic",
dependencies: ["JPEG", "JPEGInspection"],
path: "examples/encode-basic",
exclude: [
"karlie-milan-sp12-2011-4-4-0-4.0.jpg",
"karlie-milan-sp12-2011-4-2-2-1.0.jpg",
"karlie-milan-sp12-2011-4-4-0-2.0.jpg",
"karlie-milan-sp12-2011-4-4-4-0.5.jpg",
"karlie-milan-sp12-2011-4-2-2-8.0.jpg",
"karlie-milan-sp12-2011-4-4-0-0.0.jpg",
"karlie-milan-sp12-2011-4-4-0-0.5.jpg",
"karlie-milan-sp12-2011-4-4-0-1.0.jpg",
"karlie-milan-sp12-2011-4-2-0-4.0.jpg",
"karlie-milan-sp12-2011-4-2-0-0.25.jpg",
"karlie-milan-sp12-2011-4-2-0-0.5.jpg",
"karlie-milan-sp12-2011-4-4-4-1.0.jpg",
"karlie-milan-sp12-2011-4-2-0-1.0.jpg",
"karlie-milan-sp12-2011-4-2-2-0.25.jpg",
"karlie-milan-sp12-2011-4-2-2-4.0.jpg",
"karlie-milan-sp12-2011-4-2-2-2.0.jpg",
"karlie-milan-sp12-2011-4-4-0-0.125.jpg",
"karlie-milan-sp12-2011-4-4-4-4.0.jpg",
"karlie-milan-sp12-2011-4-2-0-2.0.jpg",
"karlie-milan-sp12-2011-4-4-4-0.0.jpg",
"karlie-milan-sp12-2011-4-2-2-0.0.jpg",
"karlie-milan-sp12-2011-4-2-2-0.5.jpg",
"karlie-milan-sp12-2011-4-2-2-0.125.jpg",
"karlie-milan-sp12-2011-4-2-0-0.125.jpg",
"karlie-milan-sp12-2011-4-2-0-8.0.jpg",
"karlie-milan-sp12-2011.rgb",
"karlie-milan-sp12-2011.rgb.png",
"karlie-milan-sp12-2011-4-4-0-8.0.jpg",
"karlie-milan-sp12-2011-4-4-4-2.0.jpg",
"karlie-milan-sp12-2011-4-4-4-8.0.jpg",
"karlie-milan-sp12-2011-4-4-4-0.25.jpg",
"karlie-milan-sp12-2011-4-4-0-0.25.jpg",
"karlie-milan-sp12-2011-4-2-0-0.0.jpg",
"karlie-milan-sp12-2011-4-4-4-0.125.jpg",
]),

.executableTarget(name: "JPEGDecodeAdvanced",
dependencies: ["JPEG", "JPEGInspection"],
path: "examples/decode-advanced",
exclude:
[
"karlie-2019.jpg-0.640x432.gray",
"karlie-2019.jpg-2.320x216.gray.png",
"karlie-2019.jpg",
"karlie-2019.jpg.rgb.png",
"karlie-2019.jpg-1.320x216.gray",
"karlie-2019.jpg-1.320x216.gray.png",
"karlie-2019.jpg-2.320x216.gray",
"karlie-2019.jpg.rgb",
"karlie-2019.jpg-0.640x432.gray.png",
]),
.executableTarget(name: "JPEGEncodeAdvanced",
dependencies: ["JPEG", "JPEGInspection"],
path: "examples/encode-advanced",
exclude:
[
"karlie-cfdas-2011.png.rgb",
"karlie-cfdas-2011.png",
"karlie-cfdas-2011.png.rgb.jpg",
]),
.executableTarget(name: "JPEGInMemory",
dependencies: ["JPEG", "JPEGInspection"],
path: "examples/in-memory",
exclude:
[
"karlie-2011.jpg.rgb.png",
"karlie-2011.jpg",
"karlie-2011.jpg.rgb",
"karlie-2011.jpg.jpg",
]),
.executableTarget(name: "JPEGDecodeOnline",
dependencies: ["JPEG", "JPEGInspection"],
path: "examples/decode-online",
exclude:
[
"karlie-oscars-2017.jpg-9.rgb.png",
"karlie-oscars-2017.jpg-difference-8.rgb.png",
"karlie-oscars-2017.jpg-difference-6.rgb",
"karlie-oscars-2017.jpg-2.rgb",
"karlie-oscars-2017.jpg-5.rgb.png",
"karlie-oscars-2017.jpg-8.rgb",
"karlie-oscars-2017.jpg-7.rgb",
"karlie-oscars-2017.jpg-3.rgb",
"karlie-oscars-2017.jpg-difference-0.rgb.png",
"karlie-oscars-2017.jpg-difference-1.rgb.png",
"karlie-oscars-2017.jpg-5.rgb",
"karlie-oscars-2017.jpg-difference-7.rgb.png",
"karlie-oscars-2017.jpg-8.rgb.png",
"karlie-oscars-2017.jpg-6.rgb",
"karlie-oscars-2017.jpg-9.rgb",
"karlie-oscars-2017.jpg-difference-3.rgb.png",
"karlie-oscars-2017.jpg-6.rgb.png",
"karlie-oscars-2017.jpg-difference-9.rgb.png",
"karlie-oscars-2017.jpg-difference-5.rgb.png",
"karlie-oscars-2017.jpg-2.rgb.png",
"karlie-oscars-2017.jpg-difference-0.rgb",
"karlie-oscars-2017.jpg-difference-4.rgb.png",
"karlie-oscars-2017.jpg-difference-4.rgb",
"karlie-oscars-2017.jpg-1.rgb",
"karlie-oscars-2017.jpg-difference-6.rgb.png",
"karlie-oscars-2017.jpg-0.rgb",
"karlie-oscars-2017.jpg-4.rgb",
"karlie-oscars-2017.jpg",
"karlie-oscars-2017.jpg-difference-2.rgb",
"karlie-oscars-2017.jpg-4.rgb.png",
"karlie-oscars-2017.jpg-1.rgb.png",
"karlie-oscars-2017.jpg-difference-7.rgb",
"karlie-oscars-2017.jpg-difference-8.rgb",
"karlie-oscars-2017.jpg-difference-5.rgb",
"karlie-oscars-2017.jpg-difference-2.rgb.png",
"karlie-oscars-2017.jpg-3.rgb.png",
"karlie-oscars-2017.jpg-7.rgb.png",
"karlie-oscars-2017.jpg-0.rgb.png",
"karlie-oscars-2017.jpg-difference-9.rgb",
"karlie-oscars-2017.jpg-difference-3.rgb",
"karlie-oscars-2017.jpg-difference-1.rgb",
]),
.executableTarget(name: "JPEGRecompress",
dependencies: ["JPEG", "JPEGInspection"],
path: "examples/recompress",
exclude:
[
"recompressed-requantized.jpg",
"original.jpg",
"recompressed-full-cycle.jpg",
]),
.executableTarget(name: "JPEGRotate",
dependencies: ["JPEG", "JPEGInspection"],
path: "examples/rotate",
exclude:
[
"karlie-kwk-wwdc-2017.jpg",
"karlie-kwk-wwdc-2017-iii.jpg",
"karlie-kwk-wwdc-2017-ii.jpg",
"karlie-kwk-wwdc-2017-iv.jpg",
]),
.executableTarget(name: "JPEGCustomColor",
dependencies: ["JPEG", "JPEGInspection"],
path: "examples/custom-color",
exclude:
[
"output.jpg",
"output.jpg.rgb-16.png",
"output.jpg.rgb-difference.png",
"output.jpg.rgb-8.png",
"output.jpg.rgb",
]),
],
swiftLanguageVersions: [.v4_2, .v5]
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import JPEG
import JPEGSystem

extension JPEG
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import JPEG
import JPEGSystem

extension String
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import JPEG
import JPEGSystem

let path:String = "examples/decode-basic/karlie-kwk-2019.jpg"

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import JPEG
import JPEGSystem

struct Stream
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import JPEG
import JPEGSystem

let path:String = "examples/encode-advanced/karlie-cfdas-2011.png.rgb",
size:(x:Int, y:Int) = (600, 900)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import JPEG
import JPEGSystem

let path:String = "examples/encode-basic/karlie-milan-sp12-2011",
size:(x:Int, y:Int) = (400, 665)
Expand Down
1 change: 1 addition & 0 deletions examples/in-memory/main.swift → Snippets/InMemory.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import JPEG
import JPEGSystem

extension System
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import JPEG
import JPEGSystem

let path:String = "examples/recompress/original.jpg"
guard let original:JPEG.Data.Spectral<JPEG.Common> = try .decompress(path: path)
Expand Down
1 change: 1 addition & 0 deletions examples/rotate/main.swift → Snippets/Rotate.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import JPEG
import JPEGSystem

enum Parameter:String
{
Expand Down
15 changes: 11 additions & 4 deletions Sources/JPEG/decode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ extension JPEG.Table.Huffman
self.size = size
}

@_spi(_Testable) public
init?<RAC>(counts:[Int], values:RAC, target:Selector)
where RAC:RandomAccessCollection, RAC.Element == UInt8, RAC.Index == Int
{
Expand Down Expand Up @@ -1007,12 +1008,16 @@ extension JPEG.Header.Scan
// huffman decoder
extension JPEG.Table.Huffman
{
@_spi(_Testable) public
struct Decoder
{
@_spi(_Testable) public
struct Entry
{
@_spi(_Testable) public
let symbol:Symbol
@General.Storage<UInt8>
@_spi(_Testable) public
var length:Int
}

Expand All @@ -1034,6 +1039,7 @@ extension JPEG.Table.Huffman
// this is a (relatively) expensive function. however most jpegs define a
// fresh set of huffman tables for each scan, so it is very unlikely that
// this function will get called redundantly.
@_spi(_Testable) public
func decoder() -> Decoder
{
/*
Expand Down Expand Up @@ -1243,6 +1249,7 @@ extension JPEG.Table.Huffman
extension JPEG.Table.Huffman.Decoder
{
// codeword is big-endian
@_spi(_Testable) public
subscript(codeword:UInt16) -> Entry
{
// [ level 0 index | offset ]
Expand Down Expand Up @@ -2738,8 +2745,8 @@ extension JPEG.Bitstream
}
}

static
func extend<I>(binade:Int, _ tail:UInt16, as _:I.Type) -> I
@_spi(_Testable) public
static func extend<I>(binade:Int, _ tail:UInt16, as _:I.Type) -> I
where I:FixedWidthInteger & SignedInteger
{
assert(binade > 0)
Expand All @@ -2753,8 +2760,8 @@ extension JPEG.Bitstream
return .init(combined)
}

static
func compact<I>(_ x:I) -> (binade:Int, tail:UInt16)
@_spi(_Testable) public
static func compact<I>(_ x:I) -> (binade:Int, tail:UInt16)
where I:FixedWidthInteger & SignedInteger
{
let x:Int16 = .init(x)
Expand Down
11 changes: 9 additions & 2 deletions Sources/JPEG/encode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -775,13 +775,18 @@ extension JPEG.Table.Huffman
// inverse huffman tables
extension JPEG.Table.Huffman
{
@_spi(_Testable) public
struct Encoder
{
@_spi(_Testable) public
struct Codeword
{
// the inhabited bits are in the most significant end of the `UInt16`
@_spi(_Testable) public
let bits:UInt16

@General.Storage<UInt16>
@_spi(_Testable) public
var length:Int
}

Expand All @@ -796,6 +801,7 @@ extension JPEG.Table.Huffman
}
extension JPEG.Table.Huffman
{
@_spi(_Testable) public
func encoder() -> Encoder
{
var storage:[Encoder.Codeword] =
Expand All @@ -822,6 +828,7 @@ extension JPEG.Table.Huffman
// table accessors
extension JPEG.Table.Huffman.Encoder
{
@_spi(_Testable) public
subscript(symbol:Symbol) -> Codeword
{
self.storage[.init(symbol.value)]
Expand Down Expand Up @@ -902,8 +909,8 @@ extension JPEG.Bitstream
}
extension JPEG.Bitstream.AnySymbol
{
static
func frequencies<S>(of path:KeyPath<S.Element, Self>, in sequence:S) -> [Int]
@_spi(_Testable) public
static func frequencies<S>(of path:KeyPath<S.Element, Self>, in sequence:S) -> [Int]
where S:Sequence
{
var frequencies:[Int] = .init(repeating: 0, count: 256)
Expand Down
Loading

0 comments on commit c5243c1

Please sign in to comment.