fix: nullable
This commit is contained in:
parent
b8c9ca9d9b
commit
22bcc87895
|
|
@ -47,11 +47,11 @@ final jpegData = await ImageConverter.convert(
|
|||
quality: 90,
|
||||
);
|
||||
|
||||
// Convert and resize an image to fit within 200x200
|
||||
// Convert and resize an image to fit within a width of 200, scaling height proportionally
|
||||
final resizedData = await ImageConverter.convert(
|
||||
inputData: imageData,
|
||||
format: OutputFormat.png,
|
||||
resizeMode: const FitResizeMode(width: 200, height: 200),
|
||||
resizeMode: const FitResizeMode(width: 200),
|
||||
);
|
||||
|
||||
// Convert any format to PNG
|
||||
|
|
@ -117,7 +117,7 @@ A sealed class representing different ways to resize an image.
|
|||
|
||||
- **`OriginalResizeMode()`**: Keeps the original dimensions of the image.
|
||||
- **`ExactResizeMode({required int width, required int height})`**: Resizes the image to exact dimensions, possibly changing the aspect ratio.
|
||||
- **`FitResizeMode({required int width, required int height})`**: Fits the image within the specified dimensions while maintaining the aspect ratio. If the image is smaller than the specified dimensions, it will not be scaled up.
|
||||
- **`FitResizeMode({int? width, int? height})`**: Fits the image within the specified dimensions while maintaining the aspect ratio. At least one of `width` or `height` must be provided. If only one dimension is provided, the other is scaled proportionally. If the image is smaller than the specified dimensions, it will not be scaled up.
|
||||
|
||||
|
||||
## Implementation Details
|
||||
|
|
|
|||
|
|
@ -90,6 +90,42 @@ void main() {
|
|||
expect(resizedImage.width, equals(originalWidth));
|
||||
expect(resizedImage.height, equals(originalHeight));
|
||||
});
|
||||
|
||||
test('FitResizeMode with only width maintains aspect ratio', () async {
|
||||
// Original jpeg.jpg is 1502x2000
|
||||
final targetWidth = 150;
|
||||
final expectedWidth = 150;
|
||||
final expectedHeight = 200;
|
||||
|
||||
final converted = await ImageConverter.convert(
|
||||
inputData: jpegData,
|
||||
format: OutputFormat.jpeg,
|
||||
resizeMode: FitResizeMode(width: targetWidth),
|
||||
);
|
||||
|
||||
final resizedImage = img.decodeImage(converted)!;
|
||||
// Allow for small rounding differences
|
||||
expect(resizedImage.width, closeTo(expectedWidth, 1));
|
||||
expect(resizedImage.height, closeTo(expectedHeight, 1));
|
||||
});
|
||||
|
||||
test('FitResizeMode with only height maintains aspect ratio', () async {
|
||||
// Original jpeg.jpg is 1502x2000
|
||||
final targetHeight = 200;
|
||||
final expectedWidth = 150;
|
||||
final expectedHeight = 200;
|
||||
|
||||
final converted = await ImageConverter.convert(
|
||||
inputData: jpegData,
|
||||
format: OutputFormat.jpeg,
|
||||
resizeMode: FitResizeMode(height: targetHeight),
|
||||
);
|
||||
|
||||
final resizedImage = img.decodeImage(converted)!;
|
||||
// Allow for small rounding differences
|
||||
expect(resizedImage.width, closeTo(expectedWidth, 1));
|
||||
expect(resizedImage.height, closeTo(expectedHeight, 1));
|
||||
});
|
||||
});
|
||||
|
||||
group('File size consistency tests', () {
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ class _MainPageState extends State<MainPage> {
|
|||
final resizeMode = switch ((width, height)) {
|
||||
(null, null) => const OriginalResizeMode(),
|
||||
(final w?, final h?) => ExactResizeMode(width: w, height: h),
|
||||
(final w?, null) => FitResizeMode(width: w, height: 1 << 30),
|
||||
(null, final h?) => FitResizeMode(width: 1 << 30, height: h),
|
||||
(final w?, null) => FitResizeMode(width: w),
|
||||
(null, final h?) => FitResizeMode(height: h),
|
||||
};
|
||||
|
||||
final converted = await ImageConverter.convert(
|
||||
|
|
|
|||
|
|
@ -72,26 +72,51 @@ final class ImageConverterAndroid implements ImageConverterPlatform {
|
|||
final originalWidth = originalBitmap.getWidth();
|
||||
final originalHeight = originalBitmap.getHeight();
|
||||
|
||||
if (originalWidth <= width && originalHeight <= height) {
|
||||
bitmapToCompress = originalBitmap;
|
||||
} else {
|
||||
final aspectRatio = originalWidth / originalHeight;
|
||||
var newWidth = width.toDouble();
|
||||
var newHeight = newWidth / aspectRatio;
|
||||
double newWidth;
|
||||
double newHeight;
|
||||
|
||||
if (width != null && height != null) {
|
||||
if (originalWidth <= width && originalHeight <= height) {
|
||||
bitmapToCompress = originalBitmap;
|
||||
break;
|
||||
}
|
||||
final aspectRatio = originalWidth / originalHeight;
|
||||
newWidth = width.toDouble();
|
||||
newHeight = newWidth / aspectRatio;
|
||||
if (newHeight > height) {
|
||||
newHeight = height.toDouble();
|
||||
newWidth = newHeight * aspectRatio;
|
||||
}
|
||||
|
||||
scaledBitmap = Bitmap.createScaledBitmap(
|
||||
originalBitmap,
|
||||
newWidth.round(),
|
||||
newHeight.round(),
|
||||
true, // filter
|
||||
);
|
||||
bitmapToCompress = scaledBitmap;
|
||||
} else if (width != null) {
|
||||
if (originalWidth <= width) {
|
||||
bitmapToCompress = originalBitmap;
|
||||
break;
|
||||
}
|
||||
newWidth = width.toDouble();
|
||||
final aspectRatio = originalWidth / originalHeight;
|
||||
newHeight = newWidth / aspectRatio;
|
||||
} else if (height != null) {
|
||||
if (originalHeight <= height) {
|
||||
bitmapToCompress = originalBitmap;
|
||||
break;
|
||||
}
|
||||
newHeight = height.toDouble();
|
||||
final aspectRatio = originalWidth / originalHeight;
|
||||
newWidth = newHeight * aspectRatio;
|
||||
} else {
|
||||
// This case should not be reachable due to the assertion
|
||||
// in the FitResizeMode constructor.
|
||||
bitmapToCompress = originalBitmap;
|
||||
break;
|
||||
}
|
||||
|
||||
scaledBitmap = Bitmap.createScaledBitmap(
|
||||
originalBitmap,
|
||||
newWidth.round(),
|
||||
newHeight.round(),
|
||||
true, // filter
|
||||
);
|
||||
bitmapToCompress = scaledBitmap;
|
||||
}
|
||||
|
||||
if (bitmapToCompress == null) {
|
||||
|
|
|
|||
|
|
@ -82,23 +82,48 @@ final class ImageConverterDarwin implements ImageConverterPlatform {
|
|||
final originalWidth = CGImageGetWidth(originalImage);
|
||||
final originalHeight = CGImageGetHeight(originalImage);
|
||||
|
||||
if (originalWidth <= width && originalHeight <= height) {
|
||||
imageToEncode = originalImage;
|
||||
} else {
|
||||
final aspectRatio = originalWidth / originalHeight;
|
||||
var newWidth = width.toDouble();
|
||||
var newHeight = newWidth / aspectRatio;
|
||||
double newWidth;
|
||||
double newHeight;
|
||||
|
||||
if (width != null && height != null) {
|
||||
if (originalWidth <= width && originalHeight <= height) {
|
||||
imageToEncode = originalImage;
|
||||
break;
|
||||
}
|
||||
final aspectRatio = originalWidth / originalHeight;
|
||||
newWidth = width.toDouble();
|
||||
newHeight = newWidth / aspectRatio;
|
||||
if (newHeight > height) {
|
||||
newHeight = height.toDouble();
|
||||
newWidth = newHeight * aspectRatio;
|
||||
}
|
||||
imageToEncode = _resizeImage(
|
||||
originalImage,
|
||||
newWidth.round(),
|
||||
newHeight.round(),
|
||||
);
|
||||
} else if (width != null) {
|
||||
if (originalWidth <= width) {
|
||||
imageToEncode = originalImage;
|
||||
break;
|
||||
}
|
||||
newWidth = width.toDouble();
|
||||
final aspectRatio = originalWidth / originalHeight;
|
||||
newHeight = newWidth / aspectRatio;
|
||||
} else if (height != null) {
|
||||
if (originalHeight <= height) {
|
||||
imageToEncode = originalImage;
|
||||
break;
|
||||
}
|
||||
newHeight = height.toDouble();
|
||||
final aspectRatio = originalWidth / originalHeight;
|
||||
newWidth = newHeight * aspectRatio;
|
||||
} else {
|
||||
// This case should not be reachable due to the assertion
|
||||
// in the FitResizeMode constructor.
|
||||
imageToEncode = originalImage;
|
||||
break;
|
||||
}
|
||||
imageToEncode = _resizeImage(
|
||||
originalImage,
|
||||
newWidth.round(),
|
||||
newHeight.round(),
|
||||
);
|
||||
}
|
||||
if (imageToEncode == nullptr) {
|
||||
throw Exception('Failed to prepare image for encoding.');
|
||||
|
|
|
|||
|
|
@ -26,11 +26,12 @@ class ExactResizeMode extends ResizeMode {
|
|||
/// If the image is smaller than the specified dimensions, it will not be
|
||||
/// scaled up.
|
||||
class FitResizeMode extends ResizeMode {
|
||||
const FitResizeMode({required this.width, required this.height});
|
||||
const FitResizeMode({this.width, this.height})
|
||||
: assert(width != null || height != null);
|
||||
|
||||
/// The maximum width for the resized image.
|
||||
final int width;
|
||||
final int? width;
|
||||
|
||||
/// The maximum height for the resized image.
|
||||
final int height;
|
||||
final int? height;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,21 +70,53 @@ final class ImageConverterWeb implements ImageConverterPlatform {
|
|||
destWidth = w;
|
||||
destHeight = h;
|
||||
case FitResizeMode(:final width, :final height):
|
||||
if (img.width <= width && img.height <= height) {
|
||||
destWidth = img.width;
|
||||
destHeight = img.height;
|
||||
} else {
|
||||
final aspectRatio = img.width / img.height;
|
||||
var newWidth = width.toDouble();
|
||||
var newHeight = newWidth / aspectRatio;
|
||||
final originalWidth = img.width;
|
||||
final originalHeight = img.height;
|
||||
|
||||
double newWidth;
|
||||
double newHeight;
|
||||
|
||||
if (width != null && height != null) {
|
||||
if (originalWidth <= width && originalHeight <= height) {
|
||||
destWidth = originalWidth;
|
||||
destHeight = originalHeight;
|
||||
break;
|
||||
}
|
||||
final aspectRatio = originalWidth / originalHeight;
|
||||
newWidth = width.toDouble();
|
||||
newHeight = newWidth / aspectRatio;
|
||||
if (newHeight > height) {
|
||||
newHeight = height.toDouble();
|
||||
newWidth = newHeight * aspectRatio;
|
||||
}
|
||||
destWidth = newWidth.round();
|
||||
destHeight = newHeight.round();
|
||||
} else if (width != null) {
|
||||
if (originalWidth <= width) {
|
||||
destWidth = originalWidth;
|
||||
destHeight = originalHeight;
|
||||
break;
|
||||
}
|
||||
newWidth = width.toDouble();
|
||||
final aspectRatio = originalWidth / originalHeight;
|
||||
newHeight = newWidth / aspectRatio;
|
||||
} else if (height != null) {
|
||||
if (originalHeight <= height) {
|
||||
destWidth = originalWidth;
|
||||
destHeight = originalHeight;
|
||||
break;
|
||||
}
|
||||
newHeight = height.toDouble();
|
||||
final aspectRatio = originalWidth / originalHeight;
|
||||
newWidth = newHeight * aspectRatio;
|
||||
} else {
|
||||
// This case should not be reachable due to the assertion
|
||||
// in the FitResizeMode constructor.
|
||||
destWidth = originalWidth;
|
||||
destHeight = originalHeight;
|
||||
break;
|
||||
}
|
||||
|
||||
destWidth = newWidth.round();
|
||||
destHeight = newHeight.round();
|
||||
}
|
||||
|
||||
canvas.width = destWidth;
|
||||
|
|
|
|||
Loading…
Reference in New Issue