Flutter responsive image compressing/downsizing - flutter

Hello i am using image_picker plugin on flutter and with it i can change the quality of an image from 100 percent to 1. with image quality property.
Some of my uploaded images are 500 kb to 10 mb so some needs compressing and some dont.
So is it possible to check the 100% quality version and if it is less size than 2 mb it stays 100% and we upload the image.
if it is bigger than 2mb drop the quality to 75%.
check the size < 2 mb upload it or >2mb drop to 50 quality.
try it on 25% and 10% and 1% if its still not less than 2mb on 1 percent quality just dont upload it.
there must be a way to do this like even on instagram they try to save the photos on full size but i dont think so that they will still save it on full size if it is bigger than 100mb or something like that right?
and this plugin opens a weird last 40 images page? on the pick file screen why doesnt it open the default gallery app although i use the source: ImageSource.gallery property ?

First you can get the image size by following code:
final bytes = image.readAsBytesSync().lengthInBytes;
final kb = bytes / 1024;
final mb = kb / 1024;
Then you can implement switch cases of if-else statements to implement image compressing functionality.
Also there's a package called flutter_image_compress which can compress your image after you have selected it.
Also they have provided various examples for multiple file formats

ImagePicker()
.pickImage(
source: useCamera ? ImageSource.camera : ImageSource.gallery,
imageQuality: 60)
Hope it will help.

Related

flutter compressing images resolves in bad quality

I am using flutter_image_compress to compress images. I wrote a method that takes a fileSize and tries to reduce the image down to that fileSize with best quality. Here is the method:
Future<File?> compressImage(File image, {int kb = 50}) async {
var inPath = image.absolute.path;
int q = 95;
File? result = image;
while (q >= 1 && result != null && (await result.length() > kb * 1024)) {
result = await FlutterImageCompress.compressAndGetFile(
inPath,
outPath,
quality: q,
minHeight: 1500,
minWidth: 1500,
);
q = q ~/ 2;
}
return result;
}
So basically this method checks whether the image is already smaller than the given size, and if not, compresses the image down. For every run, the quality gets reduces by 50%, until it is 1.
This method works, but I get very different image qualities for the same sizes on my iPhone and Android Phone.
on my iPhone (iPhone 11, iOS 15.5), I can compress the image down to 50kb and the quality is perfect, I don't see any difference. On my Android Phone (Samsung Galaxy A13, Android 12), if I compress the image down to 50kb, the quality is pretty bad.
Android Example:
initial length: 1213154
compress quality: 47
compressed length: 89085
iOS Example:
initial length: 1409313
compress quality: 2
compressed length: 76801
So, in the iOS example, I set had to use a quality of 2 to get it down to about 76kb and the result is perfect. On Android, I used a quality of 47 to get it down to 89kb, and the quality is pretty bad.
Is there a method how I can reduce the size as much as possible without really loosing quality of the image? Are there any other factors I missed? This does not really make sense to me, because the image on iOS is way better even though it is compressed to a way lower file size.
The package seems to provide native code written in Kotlin (for Android) and Swift (for iOS). So there may be differences between those two implementations, or even a bug in the Android code leading to worse quality.
You could file an issue on their github page.

How to shrink or manage an image's size in bytes

Python 3.6.6, Pillow 5.2.0
The Google Vision API has a size limit of 10485760 bytes.
When I'm working with a PIL Image, and save it to Bytes, it is hard to predict what the size will be. Sometimes when I try to resize it to have smaller height and width, the image size as bytes gets bigger.
I've tried experimenting with modes and formats, to understand their impact on size, but I'm not having much luck getting consistent results.
So I start out with a rawImage that is Bytes obtained from some user uploading an image (meaning I don't know much about what I'm working with yet).
rawImageSize = sys.getsizeof(rawImage)
if rawImageSize >= 10485760:
imageToShrink = Image.open(io.BytesIO(rawImage))
## do something to the image here to shrink it
# ... mystery code ...
## ideally, the minimum amount of shrinkage necessary to get it under 10485760
rawBuffer = io.BytesIO()
# possibly convert to RGB first
shrunkImage.save(rawBuffer, format='JPEG') # PNG files end up bigger after this resizing (!?)
rawImage = rawBuffer.getvalue()
print(sys.getsizeof(rawImage))
To shrink it I've tried getting a shrink ratio and then simply resizing it:
shrinkRatio = 10485760.0 / float(rawImageSize)
imageWidth, imageHeight = pilImage.size
shrunkImage = imageToShrink.resize((int(imageWidth * shrinkRatio),
int(imageHeight * shrinkRatio)), Image.LANCZOS)
Of course I could use a sufficiently small and somewhat arbitrary thumbnail size instead. I've thought about iterating thumbnail sizes until a combination takes me below the maximum bytes size threshold. I'm guessing the bytes size varies based on the color depth and mode and (?) I got from the end user that uploaded the original image. And that brings me to my questions:
Can I predict the size in bytes a PIL Image will be before I convert it for consumption by Google Vision? What is the best way to manage that size in bytes before I convert it?
First all, you probably don't need to maximize to the 10M limit posed by Google Vision API. In most case, a much smaller file will be just fine, and faster.
In addition to that, you may want to keep in mind that the aspect ratio might lead to different result. See this, https://www.mlreader.com/prepare-image-for-google-vision-api

how to compress apk size in unity3d

I am making a simple test game in unity3d using c#, the size of the apk of my game is 70 MB.I have reduced the resolution of each and ever sprites, but its still 58 MB, how do i compress the game so that the apk file is of the least possible size.
Apart from following this short guide by Unity themselves, there are a couple things to keep in mind:
Files which are not used or dependent on are removed by Unity when building.
Textures, music and videos take up most of the size. Sound files should ideally be .mp3 format (otherwise .wav for very short clips).
I would recommend you go through the link above and properly analyse Editor.log as it provides valuable information to trim the build size.
You can also choose to set the Device filter to Arm7. This will exclude certain devices, but I believe the number is quite small and it does minimize the apk size a bit. (This is located in Player Setting -> Other Settings -> Device Filter). You could try a build and see how much it would reduce it by and decide whether it was worth it.
Some Info on device filter: http://answers.unity3d.com/questions/971648/device-filter-to-arm-7-only.html
Additionally, if you look in your editor build file you can find information on what is taking up the majority of space in your build (it is a long log so you'll have to search for the right parts). There should be a part in it after you do a build that will list how much space things are taking up. It will be followed by a list of the assets from largest to smallest so you can identify particular assets that may be too large.
E.g.
Build Report
Uncompressed usage by category:
Textures 81.1 mb 92.0%
Meshes 0.0 kb 0.0%
Animations 17.1 kb 0.0%
Sounds 0.0 kb 0.0%
Shaders 90.0 kb 0.1%
Other Assets 549.9 kb 0.6%
Levels 338.3 kb 0.4%
Scripts 993.0 kb 1.1%
Included DLLs 5.1 mb 5.8%
File headers 33.1 kb 0.0%
Complete size 88.2 mb 100.0%
How to find editor file: https://docs.unity3d.com/Manual/LogFiles.html
One most effective and important change for reduce image size is
Set your image size square and
Set unity suggested pixels.(32, 64, 128, 256, 512, 1024, 2048, 4096, 8192)
If your image size is 567x890 pixels then set this image in a 1024x1024 pixels background transparent blank image and save it as a png file.
Then in unity inspector set this image as a sprite and slice it by sprite editor.
This process will make your image size reduce minimum 20%.
Example image and changes given below.
Before: resolution 567x890 pixel, size 1.9MB
After: resolution 1024x1024 pixel, size 1.3MB
Result: size 0.6MB reduced, almost 32%.
Image file Link: https://drive.google.com/file/d/0B9zkzr6JdNYlaHhqcDVUSk9KNjA/view
It is also good to set texture / sprite compression format.
Check this website:
https://docs.unity3d.com/Manual/class-TextureImporterOverride.html
Most texture compression format needs image in power of 2 resolution (128, 256, 512, 1024, 2048). Resolutions 4096 and 8192 may not work on some android devices.
For example texture with no alpha in 1024x1024 resolution using RGB ETC2 compressions takes about 0,5MB in memory. Image 1280x800 with compression format RGB 16bit takes 2MB.

How to reduce image size captured from cam

The Picture taken from the iphone cam is nearly 2.5 Mb, How to reduce this size ,I have tried
UIJPEGRepresentation(image,0.1f),but it does not effect the size ?
You really can't reduce the size the images takes up in memory.
When an image is loaded, basically a UIImage object the size wil be width x height x 4 bytes. That is the size the an uncompressed image will take up in memory.
Since you can use compressed images all image, once loaded in a UIImage will be uncompressed.
If you really need so save some memory, save the image to disk and create a thumbnail which you use in your app. Then when need you can load the larger image and use it,
Try using the Resize method in UIImage+Resize.h
https://github.com/AliSoftware/UIImage-Resize
[aImgView setImage:[ImageObjectFromPicker resizedImageWithContentMode:UIViewContentModeScaleAspectFit bounds:YourSize interpolationQuality:kCGInterpolationHigh]];

memory issues with UIImage when we load 2000 images

I'm trying to run an animation by changing the images of my UIImageView . I need about 200 images of 24K to create a 5 sec animation. I am able to load all the images into the memory (into an NSArray), but when I start the animation (switching the UIImage of the UIImageView) - after about 60 images I get a memory warning and if I continue displaying images the app crashes.
Just because your image files are 24Kb on disk, doesn't mean that is the amount of memory they will take up.
If you have an image that is 480x960 with 1 byte per pixel, that may only be a small file size due to compression (jpeg, for example), but when it is in memory in your app, it will be 450KB. Multiply that by 60 (the point at which you get the memory warning) and you will see that is approx 27MB.
If your images are larger, or have a greater colour depth, then obviously they will consume more memory. I think I read once that iOS gives you a memory warning when you hit 22Mb, but that includes other memory allocated to your app for other things as well.
And just because your app "loads" the images into the array, doesn't mean it actually loads it into memory, or expands it until it really needs it.
So, to calculate how much memory your image is going to use, don't look at the file size, but instead work it out from the image dimensions.