Skip to content

Commit

Permalink
Support lossless WebP (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
poppingmoon authored Apr 3, 2024
1 parent cbacd48 commit 545d611
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 0 deletions.
Binary file added example/asset/demo_lossless.webp
Binary file not shown.
24 changes: 24 additions & 0 deletions library/lib/src/decoder/impl/webp_decoder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ class WebpDecoder extends BaseDecoder {
final widthList = input.getRange(0x18, 0x1b);
final heightList = input.getRange(0x1b, 0x1d);
return _createExtendedFormatSize(widthList, heightList);
} else if (_isLosslessFormat(chunkHeader)) {
final sizeList = input.getRange(0x15, 0x19);
return _createLosslessFormatSize(sizeList);
} else {
final widthList = input.getRange(0x1a, 0x1c);
final heightList = input.getRange(0x1c, 0x1e);
Expand All @@ -39,17 +42,38 @@ class WebpDecoder extends BaseDecoder {
return Size(width, height);
}

Size _createLosslessFormatSize(List<int> sizeList) {
final bits = sizeList
.map(
(i) => i.toRadixString(2).split('').reversed.join().padRight(8, '0'),
)
.join()
.split('');
final width =
(int.tryParse(bits.sublist(0, 14).reversed.join(), radix: 2) ?? 0) + 1;
final height =
(int.tryParse(bits.sublist(14, 28).reversed.join(), radix: 2) ?? 0) + 1;
return Size(width, height);
}

bool _isExtendedFormat(List<int> chunkHeader) {
return ListEquality().equals(chunkHeader, "VP8X".codeUnits);
}

bool _isLosslessFormat(List<int> chunkHeader) {
return ListEquality().equals(chunkHeader, "VP8L".codeUnits);
}

@override
Future<Size> getSizeAsync(AsyncImageInput input) async {
final chunkHeader = await input.getRange(12, 16);
if (_isExtendedFormat(chunkHeader)) {
final widthList = await input.getRange(0x18, 0x1b);
final heightList = await input.getRange(0x1b, 0x1d);
return _createExtendedFormatSize(widthList, heightList);
} else if (_isLosslessFormat(chunkHeader)) {
final sizeList = await input.getRange(0x15, 0x19);
return _createLosslessFormatSize(sizeList);
} else {
final widthList = await input.getRange(0x1a, 0x1c);
final heightList = await input.getRange(0x1c, 0x1e);
Expand Down
7 changes: 7 additions & 0 deletions library/test/image_size_getter_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ void main() {
await expectLater(size, Size(988, 466));
});

test('Test webp lossless format size', () async {
final file = File('../example/asset/demo_lossless.webp');
final size = ImageSizeGetter.getSize(FileInput(file));
print('size = $size');
await expectLater(size, Size(988, 466));
});

test('Test jpeg size', () async {
final file = File('../example/asset/IMG_20180908_080245.jpg');
final size = ImageSizeGetter.getSize(FileInput(file));
Expand Down

0 comments on commit 545d611

Please sign in to comment.