chooyan-eng / crop_your_image

A flutter plugin which provides Crop Widget for cropping images.
https://pub.dev/packages/crop_your_image
Apache License 2.0
155 stars 136 forks source link

Image has tripled in size after being cropped #48

Open raulmabe opened 3 years ago

raulmabe commented 3 years ago

I have tested these on several images and when cropping it multiplies its size up to x3. Why is that? Am I doing something wrong?

flutter: Bytes before cropping 1930990 (1.9 MB)
flutter: Bytes after cropping 4916747 (4.9 MB)
Dart file ```dart class PictureCroppingPage extends StatefulWidget { const PictureCroppingPage({ Key? key, required this.picture, required this.onCropped, this.isCircular = false, this.aspectRatio, }) : super(key: key); final Uint8List picture; final Function(Uint8List) onCropped; final bool isCircular; final double? aspectRatio; @override _PictureCroppingPageState createState() => _PictureCroppingPageState(); } class _PictureCroppingPageState extends State { final _controller = CropController(); bool isCropping = false; @override Widget build(BuildContext context) { print('Bytes before cropping ${widget.picture.lengthInBytes}'); return Scaffold( appBar: AppBar( leading: const CloseButton(), title: Text(context.l10n.cropPicturePageTitle), elevation: 1.0, ), body: Crop( controller: _controller, image: widget.picture, onCropped: (picture) { widget.onCropped(picture); print('Bytes after cropping ${picture.lengthInBytes}'); context.navigator.pop(); }, aspectRatio: widget.aspectRatio, withCircleUi: widget.isCircular, baseColor: context.theme.backgroundColor, ), bottomNavigationBar: BottomBarAction( builder: (context) { return DivenElevatedButton( isLoading: isCropping, isDisabled: isCropping, onPressed: () { _controller.crop(); setState(() { isCropping = true; }); }, label: Text( context.l10n.cropPicturePageCroppingButton, ), ); }, ), ); } } ```
Images attached ![IMG_0003](https://user-images.githubusercontent.com/20211760/129740679-09346a67-07f4-43ba-b24a-dce838f3839b.JPG) ![IMG_0002](https://user-images.githubusercontent.com/20211760/129740663-fc4ce12e-74cb-46a5-a5f9-89f009fc22e0.JPG)
raulmabe commented 2 years ago

Any news?

aseem2625 commented 2 years ago

Any fixes for this? It's a pretty good lib but it's increasing size by 4-5x

raulmabe commented 2 years ago

I think this may be a problem of the image package https://github.com/brendan-duncan/image/issues/312

luca-nardelli commented 2 years ago

I suppose it's also because the image is encoded as PNG by default? https://github.com/chooyan-eng/crop_your_image/blob/main/lib/src/crop.dart#L687

chooyan-eng commented 2 years ago

Sorry for replying this late.

@luca-nardelli Thank you for your suggestion! Now it's clear what point should be checked. I'll try to fix this problem by determining the image format first and returning cropped data with the same format.

luca-nardelli commented 2 years ago

No problem, you can do that or also (even better) allow passing in a format + quality options, so that it's fully customizable

sandrocsimas commented 1 year ago

Any news?

Hannnes1 commented 1 year ago

I have opened a pull request (https://github.com/chooyan-eng/crop_your_image/pull/102) that would fix this issue, by exposing an encodeFunction parameter.

As an example i tried setting it to encodeJpg(croppedImage, quality: 75) (where encodeJpg comes from package:image) which reduced an image of 1700 KB to about 570 KB

komakur commented 1 week ago

@chooyan-eng Currently there is no formatDetectorImplemented by default. But you can try using something like this:

formatDetector: (data) {
                            final format = img.findFormatForData(data);

                            return switch (format) {
                              img.ImageFormat.png => ImageFormat.png,
                              img.ImageFormat.jpg => ImageFormat.jpeg,
                              img.ImageFormat.webp => ImageFormat.webp,
                              img.ImageFormat.bmp => ImageFormat.bmp,
                              img.ImageFormat.ico => ImageFormat.ico,
                              _ => ImageFormat.png,
                            };
                          },

With that proper ImageFormat will pass to _cropFunc(args)=>cropper.call in crop.dart.

Then in ImageCropper there should be something similiar to this:

final encoder = switch (outputFormat) {
      ImageFormat.bmp => encodeBmp,
      ImageFormat.ico => encodeIco,
      ImageFormat.jpeg => encodeJpg,
      ImageFormat.png => encodePng,
      _ => encodeJpg,
    };
...  
return function(
      original,
      encoder: encoder,
      topLeft: topLeft,
      size: Size(
        bottomRight.dx - topLeft.dx,
        bottomRight.dy - topLeft.dy,
      ),
    );

And in _doCrop pass the encoder function.

 return Uint8List.fromList(
    encoder(
      copyCrop(
        original,
        x: topLeft.dx.toInt(),
        y: topLeft.dy.toInt(),
        width: size.width.toInt(),
        height: size.height.toInt(),
      ),
    ),
  );

With that you have proper ImageFormat detection, which comes with normal cropped image size.