How to split/divide image in parts in Flutter
Asked Answered
B

2

12

How to split an image into equal-sized parts? Just taking an image from asset and splitting it into equal parts in a grid-like manner, so that each image part can be used as a separate image.

Something similar to picture here

Broadfaced answered 13/10, 2019 at 11:35 Comment(0)
C
14

You can use this package (https://pub.dev/packages/image) to crop the image from asset with the function copyCrop. Save them to List then display like your example.

Edit:

I think you know how to split your image and display them like your example if you know how to crop your image so I just show you how to change from image from asset to image of image package for cropping.

List<Image> splitImage(List<int> input) {
  // convert image to image from image package
  imglib.Image image = imglib.decodeImage(input);

  int x = 0, y = 0;
  int width = (image.width / 3).floor();
  int height = (image.height / 3).floor();

  // split image to parts
  List<imglib.Image> parts = List<imglib.Image>();
  for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
      parts.add(imglib.copyCrop(image, x, y, width, height));
      x += width;
    }
    x = 0;
    y += height;
  }

  // convert image from image package to Image Widget to display
  List<Image> output = List<Image>();
  for (var img in parts) {
    output.add(Image.memory(imglib.encodeJpg(img)));
  }

  return output;
}

Remember to add this import 'package:image/image.dart' as imglib;

Cohe answered 14/10, 2019 at 2:6 Comment(11)
could you give an example code or link an example post for the grid-like split?Broadfaced
the output return in function is Image Widget, so you can add it into Container child to display these imageCohe
just figured that out; thanks for the code; could you edit the code to correct the minor issue and then I can mark it as accepted.Broadfaced
Is there a way to check if 2 images are equal or similar to each other? need help with stackoverflow.com/questions/58372045Broadfaced
Can I split the image into arbitrary shapes rather than just a rectangle? Like using a Path to define the shape of the cut.Broadfaced
I didn't try it yet but let try copyRectify() function in image packageCohe
pub.dev/documentation/image/latest/image/copyRectify.html let me cut a 4-sided polygon rather than a general shape like this one images.vexels.com/media/users/3/167408/isolated/lists/…Broadfaced
If you just want to display it to screen and do nothing with it, you can use ClipPath widgetCohe
no, I want it as a Draggable. And then it can be dropped to a DragTarget. My current implementation of the ClipPath widget draws the required shape but also draws the extra part without painting it.Broadfaced
I have simplified my question here stackoverflow.com/questions/58554601Broadfaced
It's probably better to use floor() for rounding integers instead of using round() when calculating cell width & height. Otherwise it could lead to RangeError (index): Index out of range because all the extra fractions could add up and when trying to slice the last one with the width/height that goes beyond image boundary and cause this. floor is just the safest option in that case.Buskined
S
0

Modified hoangquyy's answer a bit, so you can just pass the asset path to the function and get a list of images:

import 'package:image/image.dart' as imglib;

Future<List<Image>> splitImage(String path) async {
    imglib.Image? image = await decodeAsset(path);

    List<Image> pieces = [];
    int x = 0, y = 0;
    int width = (image!.width / 3).floor();
    int height = (image.height / 3).floor();
    for (int i = 0; i < 3; i++) {
      for (int j = 0; j < 3; j++) {
        imglib.Image croppedImage = imglib.copyCrop(image, x: x, y: y, width: width, height: height);
        pieces.add(Image.memory(imglib.encodeJpg(croppedImage)));
        x += width;
      }
      x = 0;
      y += height;
    }

    return pieces;
  }

  /* From documentation: 
   * https://github.com/brendan-duncan/image/blob/main/doc/flutter.md#convert-a-flutter-asset-to-the-dart-image-library
   */
  Future<imglib.Image?> decodeAsset(String path) async {
    final data = await rootBundle.load(path);

    // Utilize flutter's built-in decoder to decode asset images as it will be
    // faster than the dart decoder.
    final buffer = await ui.ImmutableBuffer.fromUint8List(
        data.buffer.asUint8List());

    final id = await ui.ImageDescriptor.encoded(buffer);
    final codec = await id.instantiateCodec(
        targetHeight: id.height,
        targetWidth: id.width);

    final fi = await codec.getNextFrame();

    final uiImage = fi.image;
    final uiBytes = await uiImage.toByteData();

    final image = imglib.Image.fromBytes(width: id.width, height: id.height,
        bytes: uiBytes!.buffer, numChannels: 4);

    return image;
  }
Sambo answered 12/11, 2023 at 13:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.