Reading asset image dimensions without loading into memory - flutter

I'm trying to find out the dimensions (width and height) of an asset file but without loading it into memory, or with as little memory usage as possible.
I'm currently doing:
Image _mainMenuTable = Image.asset("images/main_menu_table.png");
but won't that make a widget into memory and also load the image onto it ? Even if I don't display it anywhere.
I've also tried creating an AssetImage, which I'm already doing to set as the background image of a Container, but I can't retrieve the dimensions of the image from it.
Any ideas if there's a better way that Image.asset? This way, I am indeed getting my width and height dynamically, but it loads it into memory twice, no? Once as an Image and once as an AssetImage
Disclaimer: it's my second week into Flutter, so please be gentle in case the answer is obvious.
Cheers!

You just need to use the File class from the dart:io package.
Example -
import 'dart:io';
void main(){
var file = File('file_path');
file.length().then((len) => print(len)); //prints bytes
}

Related

Change brightness of markers in Flutter

I made PNGs for custom markers on my GoogleMap view. By using e.g.:
BitmapDescriptor bikeBlack = await BitmapDescriptor.fromAsset(const ImageConfiguration(), "assets/images/bike_black.png")
I obtain an object that I can use as a marker directly. However, I need to be able to change the brighness as well for about 50 markers of 4 different types, during runtime. The only possible solution I have come up with so far is creating 1024 different PNGs. This will increase app size by about 2MB but it might be a lot of work to do..
I cannot really afford using await statements since they slow the app down considerably. But if I have to, I can force myself to live with that.
As far as I can tell, a marker icon has to be a BitmapDescriptor. But I cannot find a way to change the brightness of such a BitmapDescriptor.
I'm close to just giving up and just writing a python script that will generate the 1,024 PNGs for me. But there must be a nicer and more efficient solution. If you have one, please let me know.
[EDIT]:
I went with creating 1024 images. For anybody in the same situation, this is the script I used:
from PIL import Image, ImageEnhance
img = Image.open("../img.png")
enhancer = ImageEnhance.Brightness(img)
for i in range(256):
img_output = enhancer.enhance(i / 255)
img_output.save("img_{}.png".format(i), format="png")

How to compare two images and highlight the difference in new image in flutter?

I am a flutter developer. My need is to compare two images and highlight the difference (between two images) in a new image in flutter?
Two images First image and Second image.
My requirement is to compare those images and highlight the difference region in another image Difference image. I am trying to achieve screenshot based UI testing in flutter and need to fail the test cases if there is any differences between two images.
Please find the below screenshots for reference.
Is there any package in flutter/dart to achieve the same output?
Thanks and regards,
Ashwin
A few months ago I read your question, and today I've just uploaded a package that do what you want.
import 'package:diff_image/diff_image.dart';
final FIRST_IMAGE = 'https://raw.githubusercontent.com/nicolashahn/diffimg/master/images/mario-circle-cs.png';
final SECOND_IMAGE = 'https://raw.githubusercontent.com/nicolashahn/diffimg/master/images/mario-circle-node.png';
num getDiff() async{
try{
var diff = await DiffImage.compareFromUrl(
FIRST_IMAGE,
SECOND_IMAGE,
saveDiff:True
);
print('The difference between images is: $diff %');
return diff;
} catch(e){
print(e);
}
}
main() {
getDiff();
}
With two images as input, it returns the difference ratio between them, and exactly as you want, save the "diff image" as png.
I guess it can solve your problem but if you need something more specific, feel free to ask me the feature you need.
I believe what you are looking for is the Golden File Test:
flutter/Writing a golden file test for package:flutter
medium/Do you see the difference? — Flutter Snapshot test
medium/Flutter: Golden tests — compare Widgets with Snapshots
Basically, you create your golden widget and make an image snapshot of it.
Then during the test, you check to see if the app is displaying the exact same thing:
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('golden-file.png'),
);
So while it's not exactly your requirements, image==image?, it is at least image==live app display?
And for side-curiosities, Facebook also created something similar for native Android: http://facebook.github.io/screenshot-tests-for-android/
My team and I created the image_compare package to calculate differences between two images. There is a variety of algorithms to achieve this task such as percentage difference from overlaying images, euclid. color distance, RGB histogram comparison, and hashing comparison such as perceptual hash.
Here's quick example:
import 'package:image_compare/image_compare.dart';
// ...
Future<double> compare() async {
var a = File('../images/tiger.jpg');
var b = Uri.parse('https://fujifilm-x.com/wp-content/uploads/2019/08/x-t30_sample- images03.jpg');
return compareImages(src1: a, src2: b);
}
// ...

UI is Freezing when compressing an image

I'm trying to compress image from camera or gallery, but i tried answer in this question Flutter & Firebase: Compression before upload image
But the UI was freeze , so do you guys have any solution for that, and why the image plugin meet that problem ?
UPDATE:
compressImage(imageFile).then((File file) {
imageFile = file;
});
Future<File> compressImage(File imageFile) async {
return compute(decodeImage, imageFile);
}
File decodeImage(File imageFile) {
Im.Image image = Im.decodeImage(imageFile.readAsBytesSync());
Im.Image smallerImage = Im.copyResize(
image, 150); // choose the size here, it will maintain aspect ratio
return new File('123.jpg')
..writeAsBytesSync(Im.encodeJpg(smallerImage, quality: 85));
}
I meet "unhandled exception" in this code
This is because compression is done in the UI thread.
You can move computation to a new thread using compute() https://docs.flutter.io/flutter/foundation/compute.html
There are currently serious limitations what a non-UI thread can do.
If you pass the image data, it is copied from one thread to the other, which can be slow. If you have the image in a file like you get it from image_picker it is better to pass the file path and read the image in the new thread.
You can only pass values that can be encoded as JSON (it's not actually encoded as JSON, but it supports the same types)
You can not use plugins. This means you need to move the compressed data back to the UI thread by passing the data (which again is copied) or by writing in a file and passing back the path to the file, but in this case copying might be faster because writing a file in one thread and reading it in the other is even slower).
Then you can for example invoke image uploading to Firebase Cloud Storage in the UI thread, but because this is a plugin it will run in native code and not in the UI thread. It's just the UI thread that needs to pass the image along.

Load an Image from URL by many threads

I'm loading an image from URL into my app. The image size is large (around 1.5Mb). How can I use many threads (ex: 2 threads) to load this image to improve the speed? If using one thread to load this image, it takes me around 5s and I want to reduce this duration.
You are correct. 1.5Mb is a big image and the way to optimise is NOT to use many threads. Although you are on the right track. The technique is called "slicing" and is heavily used on web to load images faster. So take a image and slice it into 3 or 4 smaller pics (and not more) in your server. When rendering call these 4 images all at once. It will load faster than one big pic. Also this lessens the "perceived" latency for the end-user.
Also, when you slice up an image, it makes it easier to reduce the number of colors necessary to display that portion of the image, thus reducing your file size (sometimes fairly significantly).
As an example Google does used to do this for its main logo in its main search page. See 4 split us images of its logo?
The downside of slicing is that it increases maintenance costs. Some one has to maintain these image splits and make sure nothing goes amiss as the app keeps changing.
Please Try the following Code:
//in .h file declare the following objects:
IBOutlet UIImageView *imgTest;
-(IBAction)buttonTapped:(id)sender;
-(void)LoadImage:(NSString *) irlString;
-(void)setImage:(NSData *) imgData;
//in .m file write the following code:
-(IBAction)buttonTapped:(id)sender
{
[self performSelectorOnMainThread:#selector(LoadImage:) withObject:#"http://www.google.com/images/errors/logo_sm.gif" waitUntilDone:NO];
}
-(void)LoadImage:(NSString *) urlString
{
NSURL *imgURL=[NSURL URLWithString:urlString];
NSData *imgData=[NSData dataWithContentsOfURL:imgURL];
[self performSelectorInBackground:#selector(setImage:) withObject:imgData];
}
-(void)setImage:(NSData *) imgData;
{
imgTest.image=[UIImage imageWithData:imgData];
}
you can use activity indicator while loading the image as well. Start it in the buttonTapped method and stop it in the setImage method.
i hope this will help you.

TTImageView shows black image (OR: replacement for TTImageView)

I'm using Three20's TTImageView for it's async image loading + caching.
I've noticed this issue a bunch of times where an image will show up as completely black, and never finish loading. Here's an example of what I'm seeing:
http://screencast.com/t/7O7fnedX5Z2
So...basically I'm wondering if this is a bug in three20, and if so, how I might go about fixing it (is there a patch out there that might fix it)...OR:
Is there a good TTImageView replacement that performs async image loading + caching?
Turns out I was seeing the following in my log:
TTRequestLoader connection:didReceiveResponse:: TTDASSERT failed: 0 == _queue.maxContentLength || contentLength <=_queue\
.maxContentLength
(one for each failed image)
After that, a little bit of googling rendered:
http://groups.google.com/group/three20/browse_thread/thread/8bfac3654a6d9674/caf797f265445971?pli=1
Jeff Verkoeyen:
The comment immediately before that
assert should shed some light on the
situation.
// If you hit this assertion it's because a massive file is about to be downloaded.
// If you're sure you want to do this, add the following line to your app delegate startup
// method. Setting the max content length to zero allows anything to go through. If you just
// want to raise the limit, set it to any positive byte size.
// [[TTURLRequestQueue mainQueue] setMaxContentLength:0]