Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter - convert and resize asset image to dart ui image

I'm attempting to take an asset image, resize the image to an arbitrary width and height, and convert the image to a dart ui image so that I can draw the image on a canvas using the drawImage method. This so I can adjust the image for different screen sizes.

However I'm running into an issue resizing the image. I've attempted several different approaches but the best I've managed is to either draw the correct image data with the image cropped instead of resized, the data invalidated (incorrect decoding static) at the correct size, or the correct image data while failing to resize the image.

My named imports are

import 'dart:io' as io;
import 'dart:ui' as ui;
import 'package:flutter/widgets.dart' as widgets;
import 'package:image/image.dart' as image;

Some of my attempts are as follows:

Displays the correct image data while failing to adjust the size:

Future<ui.Image> loadUiImage(String imageAssetPath) async {
  widgets.Image widgetsImage = widgets.Image.asset(imageAssetPath, scale: 0.5);
  Completer<ui.Image> completer = Completer<ui.Image>();
  widgetsImage.image
    .resolve(widgets.ImageConfiguration(size: ui.Size(10, 10)))
    .addListener(widgets.ImageStreamListener((widgets.ImageInfo info, bool _){
      completer.complete(info.image);
    }));
  return completer.future;
}

Incorrectly crops the images without resizing, though the image data is correct:

Future<ui.Image> loadUiImage(String imageAssetPath) async {
  final ByteData data = await rootBundle.load(imageAssetPath);
  List<int> bytes = data.buffer.asUint8List();
  image.Image iconImage = image.Image.fromBytes(100, 100, bytes);
  final Completer<ui.Image> completer = Completer();
  ui.decodeImageFromList(image.decodePng(image.encodePng(iconImage)).getBytes(), (ui.Image img) {
    return completer.complete(img);
  });
  return completer.future;
}

Invalidated image data, correctly resized image:

Future<ui.Image> loadUiImage(String imageAssetPath) async {
  final ByteData data = await rootBundle.load(imageAssetPath);
  List<int> bytes = data.buffer.asUint8List();
  image.Image iconImage = image.Image.fromBytes(100, 100, bytes);
  final Completer<ui.Image> completer = Completer();
  ui.decodeImageFromList(image.encodePng(iconImage), (ui.Image img) {
    return completer.complete(img);
  });
  return completer.future;
}

I've also attempted to utilize the Bitmap method used here, but hit an error in the provided function

Failed assertion: line 274 pos 12: 'bitmap.length == size': is not true

in my attempted use after trying to resize the image.

I'd greatly appreciate any help in solving this, thanks in advance.

like image 822
JsonB Avatar asked Jan 26 '20 22:01

JsonB


2 Answers

Been a while since was able to work on this side project, but was able to accomplish the conversion and resize using the image package:

import 'dart:ui' as ui;
import 'package:image/image.dart' as image;
import 'package:flutter/services.dart';

Future<ui.Image> getUiImage(String imageAssetPath, int height, int width) async {
  final ByteData assetImageByteData = await rootBundle.load(imageAssetPath);
  image.Image baseSizeImage = image.decodeImage(assetImageByteData.buffer.asUint8List());
  image.Image resizeImage = image.copyResize(baseSizeImage, height: height, width: width);
  ui.Codec codec = await ui.instantiateImageCodec(image.encodePng(resizeImage));
  ui.FrameInfo frameInfo = await codec.getNextFrame();
  return frameInfo.image;
}
like image 101
JsonB Avatar answered Sep 18 '22 11:09

JsonB


You can achieve this without using the image package:

Future<ui.Image> getUiImage(String imageAssetPath, int height, int width) async {
  final ByteData assetImageByteData = await rootBundle.load(imageAssetPath);
  final codec = await ui.instantiateImageCodec(
    assetImageByteData.buffer.asUint8List(),
    targetHeight: height,
    targetWidth: width,
  );
  final image = (await codec.getNextFrame()).image;
}
like image 31
Andrey Gordeev Avatar answered Sep 20 '22 11:09

Andrey Gordeev