flutter_image_compress icon indicating copy to clipboard operation
flutter_image_compress copied to clipboard

Provide an option to set max width and height

Open Aljulanda9 opened this issue 6 years ago • 9 comments

Hi,

Thanks for providing this assume package. I would like to ask if it's possible to add a feature to specify max width and height when compressing the image. This way we can set a limit on the size of the resulting file regardless of the size of the original image. The exact issue that I'm facing is that I don't know if the user will upload a 4MB image or a 100KB image that was already compressed somewhere else. Do you suggest making the quality parameter a function of the original size of the image as a temporary solution at least?

Best,

Aljulanda9 avatar Aug 20 '19 19:08 Aljulanda9

Both max and min have problems that involve priority. So temporarily will not increase the max related attributes.

CaiJingLong avatar Aug 27 '19 00:08 CaiJingLong

Closing #84 and adding the details to this issue.

Diving in some implementation details, given a maximum dimension of 1280 x 1280, this package would identify which side is larger (height or width), resize this side to 1280 and resize the other side keeping the original aspect ratio. It is important to know which side is larger because if you resize the smaller side to 1280 and resize the larger one to keep the aspect ratio, the latter size would be larger than 1280.
For example, considering a maximum dimension of 1280 x 1280, a 4000 x 3000 image would become 1280 x 960.

ghost avatar Aug 28 '19 14:08 ghost

I think the max size is most needed, not min size. I try to found someway to resize image by myself, but surprisingly, I can't find anyway to get image raw pixel size in flutter or dart... WTF..

xpader avatar Sep 27 '19 10:09 xpader

@xpader give this a shot, given an Image originalImage:

import 'dart:ui';

final thumbnailImage = await instantiateImageCodec(event.rawImageData,
        targetHeight:
            originalImage.height <= originalImage.width ? 300 : null,
        targetWidth:
            originalImage.width <= originalImage.height ? 300 : null)
    .then((c) => c.getNextFrame())
    .then((f) => f.image);

If you're starting with a Uint8List, try:

import 'package:flutter/widgets.dart';

final originalImage = await decodeImageFromList(event.rawImageData);

thetanz-geoff avatar Oct 08 '19 00:10 thetanz-geoff

@xpader give this a shot, given an Image originalImage:

import 'dart:ui';

final thumbnailImage = await instantiateImageCodec(event.rawImageData,
        targetHeight:
            originalImage.height <= originalImage.width ? 300 : null,
        targetWidth:
            originalImage.width <= originalImage.height ? 300 : null)
    .then((c) => c.getNextFrame())
    .then((f) => f.image);

If you're starting with a Uint8List, try:

import 'package:flutter/widgets.dart';

final originalImage = await decodeImageFromList(event.rawImageData);

Yes, I found this way too, and another way use image package, has a method copyResize to resize image, but this two way resize image used too much time. and after resize, the image file size is bigger than before..

xpader avatar Oct 08 '19 04:10 xpader

This is still an issue. On Android I used

val bitmap = GlideApp.with(context!!)
    .asBitmap()
    .override(
        AppConstants.MAX_PICTURE_RESOLUTION_WIDTH,
        AppConstants.MAX_PICTURE_RESOLUTION_HEIGHT
    )
    .fitCenter()
    .load(uri)
    .submit().get()

I can't find an equivalent on Flutter. With those params

  var scale = calcScale(
    srcWidth: 4000,
    srcHeight: 2000,
    minWidth: 1920,
    minHeight: 1080,
  );

The current result is width = 2160.0, height = 1080.0. I need the result to be width = 1920.0, height = 960.0. Is there any way to achieve that?

jonasN5 avatar Oct 29 '20 10:10 jonasN5

Here is my work around to get the proper minWidth and minHeight:

Size getCompressionSize(sourceWidth, sourceHeight, minWidth, minHeight){
  if (minWidth >= sourceWidth && minHeight >= sourceHeight) return Size(minWidth, minHeight);
  double _width = minWidth;
  double _height = minHeight;
  final double inputAspectRatio = sourceWidth/sourceHeight;
  final double targetAspectRatio = minWidth/minHeight;
  if (inputAspectRatio <= 1){
    _width = minHeight*inputAspectRatio;
  }else{
    //inputAspectRatio > 1
    if (inputAspectRatio > targetAspectRatio){
      _height = minWidth/inputAspectRatio;
    }else{
      _width = minHeight/targetAspectRatio;
    }
  }
  return Size(_width, _height);
}

The method will adjust the value to simulate the 'maxWidth' and 'maxHeight' params, e.g. the output image width will never be higher than 'minWidth' and the output image height never higher than 'minHeight'. The source resolution is also preserved. The Size values are the values you pass to FlutterImageCompress.

jonasN5 avatar Oct 29 '20 18:10 jonasN5

any progress on this?

vytautas-pranskunas- avatar Jul 07 '21 13:07 vytautas-pranskunas-

I solved it by using flutter_native_image

Future<File?> getMaxResizedImage(String imagePath) async {
  ImageProperties prop = await FlutterNativeImage.getImageProperties(imagePath);
  if (prop.width == null || prop.height == null) return null;
  var maxSize = 1024;
  var targetWidth = 1;
  var targetHeight = 1;
  if (prop.width! > prop.height!) {
    targetWidth = min(maxSize, prop.width!);
    targetHeight = (prop.height! * targetWidth / prop.width!).round();
  } else {
    targetHeight = min(maxSize, prop.height!);
    targetWidth = (prop.width! * targetHeight / prop.height!).round();
  }

  return await FlutterNativeImage.compressImage(
    imagePath, quality: 100,
    targetWidth: targetWidth,
    targetHeight: targetHeight,
  );
}

kalloszsolty avatar Jan 16 '22 23:01 kalloszsolty