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

Support lossless WebP #38

Merged
merged 1 commit into from Apr 3, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
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
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