Skip to content

Commit 78dfd5b

Browse files
committed
added low memory footprint scaler
1 parent ca43cef commit 78dfd5b

File tree

11 files changed

+5225
-347
lines changed

11 files changed

+5225
-347
lines changed

.swiftpm/xcode/xcuserdata/radzivonbartoshyk.xcuserdatad/xcschemes/xcschememanagement.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<key>JxlCoder.xcscheme_^#shared#^_</key>
1818
<dict>
1919
<key>orderHint</key>
20-
<integer>0</integer>
20+
<integer>1</integer>
2121
</dict>
2222
<key>jxlcoder.xcscheme_^#shared#^_</key>
2323
<dict>

JxlCoder.podspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'JxlCoder'
3-
s.version = '1.1.6'
3+
s.version = '1.1.7'
44
s.summary = 'JXL coder for iOS and MacOS'
55
s.description = 'Provides support for JXL files in iOS and MacOS'
66
s.homepage = 'https://github.com/awxkee/jxl-coder-swift'
@@ -17,9 +17,9 @@ Pod::Spec.new do |s|
1717
s.public_header_files = 'Sources/jxlc/**.h', 'Sources/jxlc/**.hpp', 'Headers/**/*.h'
1818
s.project_header_files = 'Sources/jxlc/JxlWorker.hpp'
1919
s.pod_target_xcconfig = {
20-
'OTHER_CXXFLAGS' => '$(inherited) -std=c++20',
20+
'OTHER_CXXFLAGS' => '$(inherited) -std=c++20 -ffast-math',
2121
'HEADER_SEARCH_PATHS' => '$(inherited) "$(PODS_TARGET_SRCROOT)/Sources/Frameworks/libjxl.xcframework/ios-arm64/Headers"',
22-
'OTHER_CPLUSPLUSFLAGS' => '$(inherited) -fmodules -fcxx-modules -std=c++20'
22+
'OTHER_CPLUSPLUSFLAGS' => '$(inherited) -fmodules -fcxx-modules -std=c++20 -ffast-math'
2323
}
2424
s.preserve_paths = "Sources/Frameworks/*.xcframework", "Sources/Frameworks/*.xcframework/**/Headers", "Sources/Frameworks/libjxl.xcframework/ios-arm64/Headers/jxl", "Sources/Frameworks/libjxl.xcframework/ios-arm64/Headers/jpegli"
2525
s.libraries = 'c++'

Sources/JxlCoder/JXLCoder.swift

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,35 +32,41 @@ public class JXLCoder {
3232
}
3333

3434
/***
35+
- Parameter sampleSize: if image size larger than sampler then it will be resized to sample
3536
- Returns: Decoded JXL image if this is the valid one
3637
**/
3738
public static func decode(srcStream: InputStream,
3839
sampleSize: CGSize = .zero,
39-
pixelFormat: JXLPreferredPixelFormat = .optimal) throws -> JXLPlatformImage {
40-
return try shared.decode(srcStream, sampleSize: sampleSize, pixelFormat: pixelFormat)
40+
pixelFormat: JXLPreferredPixelFormat = .optimal,
41+
sampler: JxlSampler = .cubic) throws -> JXLPlatformImage {
42+
return try shared.decode(srcStream, sampleSize: sampleSize, pixelFormat: pixelFormat, sampler: sampler)
4143
}
4244

4345
/***
46+
- Parameter sampleSize: if image size larger than sampler then it will be resized to sample
4447
- Returns: Decoded JXL image if this is the valid one
4548
**/
4649
public static func decode(url: URL,
4750
sampleSize: CGSize = .zero,
48-
pixelFormat: JXLPreferredPixelFormat = .optimal) throws -> JXLPlatformImage {
51+
pixelFormat: JXLPreferredPixelFormat = .optimal,
52+
sampler: JxlSampler = .cubic) throws -> JXLPlatformImage {
4953
guard let srcStream = InputStream(url: url) else {
5054
throw NSError(domain: "JXLCoder", code: 500,
5155
userInfo: [NSLocalizedDescriptionKey: "JXLCoder cannot open provided URL"])
5256
}
53-
return try shared.decode(srcStream, sampleSize: sampleSize, pixelFormat: pixelFormat)
57+
return try shared.decode(srcStream, sampleSize: sampleSize, pixelFormat: pixelFormat, sampler: sampler)
5458
}
5559

5660
/***
61+
- Parameter sampleSize: if image size larger than sampler then it will be resized to sample
5762
- Returns: Decoded JXL image if this is the valid one
5863
**/
5964
public static func decode(data: Data,
6065
sampleSize: CGSize = .zero,
61-
pixelFormat: JXLPreferredPixelFormat = .optimal) throws -> JXLPlatformImage {
66+
pixelFormat: JXLPreferredPixelFormat = .optimal,
67+
sampler: JxlSampler = .cubic) throws -> JXLPlatformImage {
6268
let srcStream = InputStream(data: data)
63-
return try shared.decode(srcStream, sampleSize: sampleSize, pixelFormat: pixelFormat)
69+
return try shared.decode(srcStream, sampleSize: sampleSize, pixelFormat: pixelFormat, sampler: sampler)
6470
}
6571

6672
/***

Sources/jxlc/JxlInternalCoder.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,22 @@ typedef NS_ENUM(NSInteger, JXLCompressionOption) {
4141

4242
typedef NS_ENUM(NSInteger, JXLPreferredPixelFormat) {
4343
kOptimal NS_SWIFT_NAME(optimal),
44-
kUniform8 NS_SWIFT_NAME(r8),
44+
kR8 NS_SWIFT_NAME(r8),
4545
kFloat16 NS_SWIFT_NAME(float16),
4646
};
4747

48+
typedef NS_ENUM(NSInteger, JxlSampler) {
49+
kNearestNeighbor NS_SWIFT_NAME(nearestNeighbor),
50+
kBilinear NS_SWIFT_NAME(bilinear),
51+
kCubic NS_SWIFT_NAME(cubic),
52+
kMitchell NS_SWIFT_NAME(mitchell)
53+
};
54+
4855
@interface JxlInternalCoder: NSObject
4956
- (nullable JXLSystemImage *)decode:(nonnull NSInputStream *)inputStream
5057
sampleSize:(CGSize)sampleSize
51-
pixelFormat:(JXLPreferredPixelFormat)pixelFormat
58+
pixelFormat:(JXLPreferredPixelFormat)preferredPixelFormat
59+
sampler:(JxlSampler)sampler
5260
error:(NSError *_Nullable * _Nullable)error;
5361
- (CGSize)getSize:(nonnull NSInputStream *)inputStream error:(NSError *_Nullable * _Nullable)error;
5462
- (nullable NSData *)encode:(nonnull JXLSystemImage *)platformImage

Sources/jxlc/JxlInternalCoder.mm

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ - (CGSize)getSize:(nonnull NSInputStream *)inputStream error:(NSError *_Nullable
189189

190190
- (nullable JXLSystemImage *)decode:(nonnull NSInputStream *)inputStream
191191
sampleSize:(CGSize)sampleSize
192-
pixelFormat:(JXLPreferredPixelFormat)pixelFormat
192+
pixelFormat:(JXLPreferredPixelFormat)preferredPixelFormat
193+
sampler:(JxlSampler)sampler
193194
error:(NSError *_Nullable * _Nullable)error {
194195
try {
195196
int buffer_length = 30196;
@@ -236,14 +237,14 @@ - (nullable JXLSystemImage *)decode:(nonnull NSInputStream *)inputStream
236237
int components;
237238
JxlExposedOrientation jxlExposedOrientation = Identity;
238239
JxlDecodingPixelFormat pixelFormat;
239-
switch (pixelFormat) {
240-
case optimal:
240+
switch (preferredPixelFormat) {
241+
case kOptimal:
241242
pixelFormat = optimal;
242243
break;
243-
case r8:
244+
case kR8:
244245
pixelFormat = r8;
245246
break;
246-
case float16:
247+
case kFloat16:
247248
pixelFormat = float16;
248249
break;
249250
}
@@ -257,6 +258,8 @@ - (nullable JXLSystemImage *)decode:(nonnull NSInputStream *)inputStream
257258
return nil;
258259
}
259260

261+
imageData.clear();
262+
260263
if (jxlExposedOrientation == Rotate90CW || jxlExposedOrientation == Rotate90CCW
261264
|| jxlExposedOrientation == AntiTranspose
262265
|| jxlExposedOrientation == OrientTranspose) {
@@ -266,9 +269,26 @@ - (nullable JXLSystemImage *)decode:(nonnull NSInputStream *)inputStream
266269
}
267270

268271
if (sampleSize.width > 0 && sampleSize.height > 0) {
272+
XSampler xSampler = bilinear;
273+
274+
switch (sampler) {
275+
case kNearestNeighbor:
276+
xSampler = nearest;
277+
break;
278+
case kBilinear:
279+
xSampler = bilinear;
280+
break;
281+
case kCubic:
282+
xSampler = cubic;
283+
break;
284+
case kMitchell:
285+
xSampler = mitchell;
286+
break;
287+
}
288+
269289
auto scaleResult = [RgbaScaler scaleData:outputData width:(int)xSize height:(int)ySize
270290
newWidth:(int)sampleSize.width newHeight:(int)sampleSize.height
271-
components:components pixelFormat:useFloats ? kF16 : kU8];
291+
components:components pixelFormat:useFloats ? kF16 : kU8 sampler:xSampler];
272292
if (!scaleResult) {
273293
*error = [[NSError alloc] initWithDomain:@"JXLCoder" code:500 userInfo:@{ NSLocalizedDescriptionKey: @"Rescale image has failed" }];
274294
return nil;

Sources/jxlc/JxlWorker.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ bool DecodeJpegXlOneShot(const uint8_t *jxl, size_t size,
108108
*useFloats = true;
109109
hdrImage = true;
110110
format = { static_cast<uint32_t>(baseComponents), JXL_TYPE_FLOAT16, JXL_NATIVE_ENDIAN, 0 };
111+
} else if (pixelFormat == float16) {
112+
*useFloats = true;
113+
hdrImage = true;
114+
format = { static_cast<uint32_t>(baseComponents), JXL_TYPE_FLOAT16, JXL_NATIVE_ENDIAN, 0 };
111115
} else {
112116
if (pixelFormat == r8) {
113117
*depth = 8;

Sources/jxlc/RgbaScaler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#ifdef __cplusplus
3030

3131
#import <vector>
32+
#import "XScaler.hpp"
3233

3334
typedef NS_ENUM(NSInteger, JxlIPixelFormat) {
3435
kU8 NS_SWIFT_NAME(Uniform8),
@@ -46,7 +47,7 @@ typedef NS_ENUM(NSInteger, JxlIPixelFormat) {
4647
* @param pixelFormat Pixel Format of the image
4748
* @return destination
4849
*/
49-
+(bool) scaleData:(std::vector<uint8_t>&)src width:(int)width height:(int)height newWidth:(int)newWidth newHeight:(int)newHeight components:(int)components pixelFormat:(JxlIPixelFormat)pixelFormat;
50+
+(bool) scaleData:(std::vector<uint8_t>&)src width:(int)width height:(int)height newWidth:(int)newWidth newHeight:(int)newHeight components:(int)components pixelFormat:(JxlIPixelFormat)pixelFormat sampler:(XSampler)sampler;
5051
@end
5152

5253
#endif

0 commit comments

Comments
 (0)