Skip to content

Instantly share code, notes, and snippets.

@plateaukao
Created April 13, 2019 05:18
Show Gist options
  • Save plateaukao/ebb5e7169dd89cc52bda338762d4997e to your computer and use it in GitHub Desktop.
Save plateaukao/ebb5e7169dd89cc52bda338762d4997e to your computer and use it in GitHub Desktop.
image remove background in flutter
Future<Uint8List> _downloadImage() async {
String dir = (await getApplicationDocumentsDirectory()).path;
File file = new File('$dir/$_filename');
if (file.existsSync()) {
var image = await file.readAsBytes();
return image;
} else {
var response = await http.get(_url,);
var bytes = response.bodyBytes;
Uint8List newPng = await removeWhiteBackground(bytes);
file.writeAsBytes(newPng);
return newPng;
}
}
Future<Uint8List> removeWhiteBackground(Uint8List bytes) async {
Img.Image image = Img.decodeImage(bytes);
Img.Image transparentImage = await colorTransparent(image, 255, 255, 255);
var newPng = Img.encodePng(transparentImage);
return newPng;
}
Future<Img.Image> colorTransparent(Img.Image src, int red, int green, int blue) async {
var pixels = src.getBytes();
for (int i = 0, len = pixels.length; i < len; i += 4) {
if(pixels[i] == red
&& pixels[i+1] == green
&& pixels[i+2] == blue
) {
pixels[i + 3] = 0;
}
}
return src;
}
@plateaukao
Copy link
Author

Hi, @meditat
you need to modify line 19 to input the color you want to remove (with correct red value, green value, and blue value).
Now it's 255, 255, 255, so it's moving white color now.

@tobinharris
Copy link

This is cool. Once the background is removed, how hard would it be to crop to the new boundaries? Basically, so you don't get a ton of empty space around the image?

@pauserra99
Copy link

Hey, Img.Image is not working.

@plateaukao
Copy link
Author

@pauserraa You need to install https://pub.dev/packages/image first.

@14397faiq
Copy link

hello Sir can you please share the link of any example project of removing image background in flutter dart. it would be a very
helpful for me thanks

@FabioFS
Copy link

FabioFS commented Feb 16, 2021

That was what I was looking for! Thanks man!

@Bellukchips
Copy link

[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method 'getBytes' was called on null.

how to fix this?

@plateaukao
Copy link
Author

[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method 'getBytes' was called on null.

how to fix this?

@Belllukchips it seems your Img.Image is null?

@Bellukchips
Copy link

Bellukchips commented Mar 4, 2021

Img.Image(error) is not work, i use Image but import image/image.dart as documented

@jaykukadiya99
Copy link

This is cool. Once the background is removed, how hard would it be to crop to the new boundaries? Basically, so you don't get a ton of empty space around the image?

How to crop background?

@Alvarocda
Copy link

Alvarocda commented Aug 17, 2021

In case you are not getting the background to be turned transparent, just add this line before line 25
src.channels = Img.Channels.rgba;

@DemianGo
Copy link

DemianGo commented Dec 16, 2021

this code doesn't work, what am I doing wrong guys, please, help.

// the function returns  List<int> , but should return Future<Uint8List>, makes no sence !!?? What am I missing ?

var newPng = Img.encodePng(transparentImage) ;       
return newPng ;           // List

Spent a lot of time here, giving up =[


import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:image/image.dart' as Img;
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
import 'package:flutter/material.dart';
import 'package:path/path.dart';
//import 'package:file/file.dart';
import 'dart:async';
import 'dart:io';

class CriaSticker extends StatefulWidget {
  const CriaSticker({Key? key}) : super(key: key);

  @override
  State<CriaSticker> createState() => _CriaStickerState();
}

class _CriaStickerState extends State<CriaSticker> {
  @override
  Widget build(BuildContext context) {

    dynamic img = Imagem()._downloadImage();
    dynamic teste = Imagem().removeWhiteBackground(img as dynamic);
    //Future<Image> resu = Imagem().colorTransparent(teste, 110, 110, 110);

    if (kDebugMode) {
      print(img);
    }

    return const Center(child: Text('aabc',),);
  }
}


 class Imagem {

  Future<Uint8List> _downloadImage() async {
    String dir = (await getApplicationDocumentsDirectory()).path;
    //File file = File("http://photo.tuchong.com/4870004/f/298584322.jpg");

    final ByteData imageData = await NetworkAssetBundle(Uri.parse("http://photo.tuchong.com/4870004/f/298584322.jpg")).load("");
    final Uint8List finalImg = imageData.buffer.asUint8List();

    // display it with the Image.memory widget
    //var image = await file.readAsBytes();
    return finalImg;

  }

  Future<Uint8List>   removeWhiteBackground(Uint8List bytes) async {
    Img.Image? image = Img.decodeImage(bytes);
    Img.Image transparentImage = await colorTransparent(image!, 255, 255, 255);
    var newPng = Img.encodePng(transparentImage) as Future<Uint8List> ;
    return newPng ;
  }


  Future<Img.Image> colorTransparent(Img.Image src, int red, int green, int blue) async {
    var pixels = src.getBytes();
    for (int i = 0, len = pixels.length; i < len; i += 4) {
      if(pixels[i] == red
          && pixels[i+1] == green
          && pixels[i+2] == blue
      ) {
        pixels[i + 3] = 0;
      }
    }

    return src;
  }
}

@LukaMajcenic
Copy link

LukaMajcenic commented Dec 19, 2021

@DemianGo return newPng as Uint8List;

@silvanasilvana
Copy link

@DemianGo could you do it? I've been trying for weeks and I can't !!!

@ibrahimEltayfe
Copy link

greeting for the author for sharing this code.
i modified little things in the code and it works for me, hope this works for you.

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:io';

Future<Uint8List?> removeWhiteBackground(Uint8List bytes) async {
  img.Image? image = img.decodeImage(bytes);
  img.Image? transparentImage = await colorTransparent(image!, 255, 255, 255);
  var newPng = img.encodePng(transparentImage!);
  Uint8List unit8list = Uint8List.fromList(newPng);
  return unit8list;
}


Future<Uint8List> _downloadImage() async {
  File file =File('your image path here');

  var image = await file.readAsBytes();

  return image;

}

Future<img.Image?> colorTransparent(img.Image src, int red, int green, int blue) async {
  var bytes = src.getBytes() ;
  for (int i = 0, len = bytes.length; i < len; i += 4) {
    if((bytes[i] == red&&bytes[i+1] == green&&bytes[i+2] == blue)
    ){
      bytes[i+3] = 0;
    }
  }

  return img.Image.fromBytes(src.width, src.height, bytes);
}

class RemoveBG extends StatelessWidget {
  RemoveBG({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blue,
      body: FutureBuilder(
        future: _downloadImage(),
        builder:(context, snapshot) => snapshot.data==null?SizedBox.shrink(): FutureBuilder(
          future: removeWhiteBackground(snapshot.data!),
          builder:(context, snapshot1) =>  snapshot1.data==null?SizedBox.shrink():Container(
            child: Center(
                child: Image.memory(snapshot1.data!,)
            ),
          ),
        ),
      ),
    );
  }
}

@nit900
Copy link

nit900 commented Oct 22, 2022

I don't get it I cant get Img.Image to work at all and cant find the library online anywhere. Did they change it to something else?

@zynxyzouo
Copy link

I don't get it I cant get Img.Image to work at all and cant find the library online anywhere. Did they change it to something else?

import 'package:image/image.dart' as img;←
the img.Image will work

@Alvarocda
Copy link

It's working on version 3.2.0
Not working on latest version 4.0.15

@KoOVERLINE
Copy link

KoOVERLINE commented May 26, 2023

Adding it to the 25th line does not make it transparent.

Future<Img.Image> colorTransparent(Img.Image src, int red, int green, int blue) async{
    src.channels = Img.Channels.rgba;
    var pixels = src.getBytes();
    for (int i = 0, len = pixels.length; i < len; i += 4) {
      if(pixels[i] == red
          && pixels[i+1] == green
          && pixels[i+2] == blue
      ) {
        pixels[i + 3] = 0;
      }
    }

    return src;
  }

@KoOVERLINE
Copy link

This is All code.

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:remove_background/remove_background.dart';
import 'dart:ui' as ui;

import 'package:syncfusion_flutter_signaturepad/signaturepad.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';

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


class SignPage2 extends StatefulWidget {
  const SignPage2({super.key});

  @override
  State<SignPage2> createState() => _SignPage2State();
}

class _SignPage2State extends State<SignPage2> {

  final GlobalKey<SfSignaturePadState> signatureGlobalKey = GlobalKey();


  ui.Image? signImage;

  void _handleClearButtonPressed() {
    signatureGlobalKey.currentState!.clear();
  }


  //백그라운드 제거
  Future<Uint8List> removeWhiteBackground(Uint8List bytes) async {
    Img.Image? image = Img.decodeImage(bytes);
    Img.Image transparentImage = await colorTransparent(image!, 255, 255, 255);
    var newPng = Img.encodePng(transparentImage);
    return Uint8List.fromList(newPng);
  }

  Future<Img.Image> colorTransparent(Img.Image src, int red, int green, int blue) async{
    src.channels = Img.Channels.rgba;
    var pixels = src.getBytes();
    for (int i = 0, len = pixels.length; i < len; i += 4) {
      if(pixels[i] == red
          && pixels[i+1] == green
          && pixels[i+2] == blue
      ) {
        pixels[i + 3] = 0;
      }
    }

    return src;
  }

  void _handleSaveButtonPressed() async {
    final data =
        await signatureGlobalKey.currentState!.toImage(pixelRatio: 3.0);
    final bytes = await data.toByteData(format: ui.ImageByteFormat.png);

    Uint8List signImage;

    print('>>>데이터의 타입 : ${data.runtimeType}');
    if( bytes != null ){
      signImage = await removeWhiteBackground(Uint8List.fromList(bytes.buffer.asUint8List()));

      final result = await ImageGallerySaver.saveImage(Uint8List.view(signImage.buffer));

      ByteData item = await cutImage(context: context, image: data);
      
    }

    print('>>>바이트 형식 : ${bytes.runtimeType}');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("SYNCFUSION FLUTTER SIGNATUREPAD"),
      ),
      body: Center(
        child: Column(
          children: [
            Container(
              width: double.infinity,
              height: 400,
              decoration: BoxDecoration(
                border: Border.all(
                  width: 1.0, color: Colors.black, style: BorderStyle.solid
                ),
                color: Colors.blue,
              ),
              child: SfSignaturePad(
                key: signatureGlobalKey,
                backgroundColor: Colors.white,
              ),
            ),
            ElevatedButton(onPressed: _handleSaveButtonPressed, child: Text('사진 저장')),
            ElevatedButton(onPressed: _handleClearButtonPressed, child: Text('사진 초기화')),

          ],
        ),
      ),
    );
  }
}

@hydev777
Copy link

hydev777 commented Oct 2, 2023

This coded worked for me, thanks!

@Aishh2211
Copy link

Its not removing background , making the shade of white greyish

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment