-
Notifications
You must be signed in to change notification settings - Fork 648
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wuffs: update, add jpeg decoding, add simple tests
- Loading branch information
Showing
8 changed files
with
287 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
# This file is auto-generated! check build-support/check-zig-cache-hash.sh for | ||
# more details. | ||
"sha256-ot5onG1yq7EWQkNUgTNBuqvsnLuaoFs2UDS96IqgJmU=" | ||
"sha256-njCce+r1DPTKLNrmrD2ObEoBS9nR7q03hqegQWe1UuY=" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,13 @@ | ||
const std = @import("std"); | ||
|
||
const c = @import("c.zig").c; | ||
|
||
pub const Error = std.mem.Allocator.Error || error{WuffsError}; | ||
|
||
pub fn check(log: anytype, status: *const c.struct_wuffs_base__status__struct) error{WuffsError}!void { | ||
if (!c.wuffs_base__status__is_ok(status)) { | ||
const e = c.wuffs_base__status__message(status); | ||
log.warn("decode err={s}", .{e}); | ||
return error.WuffsError; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
const std = @import("std"); | ||
const Allocator = std.mem.Allocator; | ||
const c = @import("c.zig").c; | ||
const Error = @import("error.zig").Error; | ||
const check = @import("error.zig").check; | ||
|
||
const log = std.log.scoped(.wuffs_jpeg); | ||
|
||
/// Decode a JPEG image. | ||
pub fn decode(alloc: Allocator, data: []const u8) Error!struct { | ||
width: u32, | ||
height: u32, | ||
data: []const u8, | ||
} { | ||
// Work around some weirdness in WUFFS/Zig, there are some structs that | ||
// are defined as "extern" by the Zig compiler which means that Zig won't | ||
// allocate them on the stack at compile time. WUFFS has functions for | ||
// dynamically allocating these structs but they use the C malloc/free. This | ||
// gets around that by using the Zig allocator to allocate enough memory for | ||
// the struct and then casts it to the appropriate pointer. | ||
|
||
const decoder_buf = try alloc.alloc(u8, c.sizeof__wuffs_jpeg__decoder()); | ||
defer alloc.free(decoder_buf); | ||
|
||
const decoder: ?*c.wuffs_jpeg__decoder = @ptrCast(decoder_buf); | ||
{ | ||
const status = c.wuffs_jpeg__decoder__initialize( | ||
decoder, | ||
c.sizeof__wuffs_jpeg__decoder(), | ||
c.WUFFS_VERSION, | ||
0, | ||
); | ||
try check(log, &status); | ||
} | ||
|
||
var source_buffer: c.wuffs_base__io_buffer = .{ | ||
.data = .{ .ptr = @constCast(@ptrCast(data.ptr)), .len = data.len }, | ||
.meta = .{ | ||
.wi = data.len, | ||
.ri = 0, | ||
.pos = 0, | ||
.closed = true, | ||
}, | ||
}; | ||
|
||
var image_config: c.wuffs_base__image_config = undefined; | ||
{ | ||
const status = c.wuffs_jpeg__decoder__decode_image_config( | ||
decoder, | ||
&image_config, | ||
&source_buffer, | ||
); | ||
try check(log, &status); | ||
} | ||
|
||
const width = c.wuffs_base__pixel_config__width(&image_config.pixcfg); | ||
const height = c.wuffs_base__pixel_config__height(&image_config.pixcfg); | ||
|
||
c.wuffs_base__pixel_config__set( | ||
&image_config.pixcfg, | ||
c.WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL, | ||
c.WUFFS_BASE__PIXEL_SUBSAMPLING__NONE, | ||
width, | ||
height, | ||
); | ||
|
||
const destination = try alloc.alloc( | ||
u8, | ||
width * height * @sizeOf(c.wuffs_base__color_u32_argb_premul), | ||
); | ||
errdefer alloc.free(destination); | ||
|
||
// temporary buffer for intermediate processing of image | ||
const work_buffer = try alloc.alloc( | ||
u8, | ||
|
||
// The type of this is a u64 on all systems but our allocator | ||
// uses a usize which is a u32 on 32-bit systems. | ||
std.math.cast( | ||
usize, | ||
c.wuffs_jpeg__decoder__workbuf_len(decoder).max_incl, | ||
) orelse return error.OutOfMemory, | ||
); | ||
defer alloc.free(work_buffer); | ||
|
||
const work_slice = c.wuffs_base__make_slice_u8( | ||
work_buffer.ptr, | ||
work_buffer.len, | ||
); | ||
|
||
var pixel_buffer: c.wuffs_base__pixel_buffer = undefined; | ||
{ | ||
const status = c.wuffs_base__pixel_buffer__set_from_slice( | ||
&pixel_buffer, | ||
&image_config.pixcfg, | ||
c.wuffs_base__make_slice_u8(destination.ptr, destination.len), | ||
); | ||
try check(log, &status); | ||
} | ||
|
||
var frame_config: c.wuffs_base__frame_config = undefined; | ||
{ | ||
const status = c.wuffs_jpeg__decoder__decode_frame_config( | ||
decoder, | ||
&frame_config, | ||
&source_buffer, | ||
); | ||
try check(log, &status); | ||
} | ||
|
||
{ | ||
const status = c.wuffs_jpeg__decoder__decode_frame( | ||
decoder, | ||
&pixel_buffer, | ||
&source_buffer, | ||
c.WUFFS_BASE__PIXEL_BLEND__SRC, | ||
work_slice, | ||
null, | ||
); | ||
try check(log, &status); | ||
} | ||
|
||
return .{ | ||
.width = width, | ||
.height = height, | ||
.data = destination, | ||
}; | ||
} | ||
|
||
test "jpeg_decode_000000" { | ||
const data = try decode(std.testing.allocator, @embedFile("1x1#000000.jpg")); | ||
defer std.testing.allocator.free(data.data); | ||
|
||
try std.testing.expectEqual(1, data.width); | ||
try std.testing.expectEqual(1, data.height); | ||
try std.testing.expectEqualSlices(u8, &.{ 0, 0, 0, 255 }, data.data); | ||
} | ||
|
||
test "jpeg_decode_FFFFFF" { | ||
const data = try decode(std.testing.allocator, @embedFile("1x1#FFFFFF.jpg")); | ||
defer std.testing.allocator.free(data.data); | ||
|
||
try std.testing.expectEqual(1, data.width); | ||
try std.testing.expectEqual(1, data.height); | ||
try std.testing.expectEqualSlices(u8, &.{ 255, 255, 255, 255 }, data.data); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,9 @@ | ||
const std = @import("std"); | ||
|
||
pub const png = @import("png.zig"); | ||
pub const jpeg = @import("jpeg.zig"); | ||
pub const swizzle = @import("swizzle.zig"); | ||
|
||
test { | ||
std.testing.refAllDeclsRecursive(@This()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters