Marcel Dz
Marcel Dz

Reputation: 2714

Flutter get pixel color from image in var

Lets say we have several background images:

enter image description here

How can we pick top left, top right, bottom left, bottom right and center center pixel color of image with a function and save them in vars?

I didn't find anything good to go..

EDIT, this is the code I got so far.

import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:image/image.dart' as img;
import 'package:flutter/services.dart' show rootBundle;
import 'package:flutter/rendering.dart';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:muego_dev2/models/songs.dart';
import 'package:provider/provider.dart';



class ColorDetect extends StatefulWidget {
  //static const routeName = '/';

  @override
  _ColorDetectState createState() => _ColorDetectState();
}

class _ColorDetectState extends State<ColorDetect> {


 @override
  Widget build(BuildContext context) {

final coverData = 'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg';
img.Image photo;



void setImageBytes(imageBytes) {

    List<int> values = imageBytes.buffer.asUint8List();
    photo = null;
    photo = img.decodeImage(values);
  }

  // image lib uses uses KML color format, convert #AABBGGRR to regular #AARRGGBB
int abgrToArgb(int argbColor) {
  int r = (argbColor >> 16) & 0xFF;
  int b = argbColor & 0xFF;
  return (argbColor & 0xFF00FF00) | (b << 16) | r;
}


  // FUNCTION

 Future<void> _getColor() async {

Uint8List data = (await NetworkAssetBundle(Uri.parse(coverData))
      .load(coverData)
  )
      .buffer
      .asUint8List();

setImageBytes(data);

//FractionalOffset(1.0, 0.0); //represents the top right of the [Size].
double px = 1.0;
double py = 0.0;

int pixel32 = photo.getPixelSafe(px.toInt(), py.toInt());
int hex = abgrToArgb(pixel32);
print("Value of int: $hex ");

 }



    return Scaffold(
      appBar: AppBar(
      ),
      body: Column(
        children: <Widget>[
          Flexible(
            flex: 2,
            child: Container(
              decoration: BoxDecoration(
                image: DecorationImage(
                  image: NetworkImage(coverData),
                  fit: BoxFit.cover,
                ),
              ),
            ),
          ),
          Flexible(
            flex: 1,
            child: Container(
              color: HOW TO APPLY MY HEX COLOR HERE?????,
            ),
          ),
          Spacer(),
          Padding(
            padding: const EdgeInsets.only(bottom: 8.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                MaterialButton(
                  elevation: 5.0,
                  padding: EdgeInsets.all(15.0),
                  color: Colors.grey,
                  child: Text("Get Sizes"),
                  onPressed: null,
                ),
                MaterialButton(
                  elevation: 5.0,
                  color: Colors.grey,
                  padding: EdgeInsets.all(15.0),
                  child: Text("Get Positions"),
                  onPressed: _getColor,
                )
              ],
            ),
          )
        ],
      ),
    );
  }}

And this is what I get printed with value $hex

Restarted application in 1.419ms.
I/flutter ( 2103): Value of int: 4287593304

I'm not sure if I already have the hex value now. So how can I apply it to my Container color? It seems that there is something still missing..

Upvotes: 2

Views: 14466

Answers (3)

user2233706
user2233706

Reputation: 7207

getPixel from the image package as of version 4.0 no longer returns an integer, but a Pixel object, from which you can get the colors. This retrieves the color of a pixel as an integer:

import 'dart:ui' as ui;
...
final pixel = image.getPixel(x, y);

final intColor = ui.Color.fromRGBO(pixel.r.toInt(), pixel.g.toInt(), pixel.b.toInt(), pixel.a.toDouble()).value;

Upvotes: 3

Marcelo Glasberg
Marcelo Glasberg

Reputation: 30889

Since September 2020, if you need to read image pixels of an image you have in your widget tree, you can use the ImagePixels widget from the https://pub.dev/packages/image_pixels package:

// Given some position x and y...

@override
Widget build(BuildContext context) {
    return ImagePixels(
              imageProvider: image,
              builder: (context, img) =>
                  Text(
                     "Img size is: ${img.width} × ${img.height}.\n"
                     "Pixel color is: ${img.pixelColorAt(x, y)}.");
              );
} 

Note: You can also use pixelColorAt to read the pixel color from a specific position, or pixelColorAtAlignment to read from a fractional offset.

Also note: I've created this package.

Upvotes: 6

camillo777
camillo777

Reputation: 2367

Hello did you try with this function?

https://api.flutter.dev/flutter/image/Image/getPixel.html

int getPixel (
int x,
int y
)

Get the pixel from the given x, y coordinate. Color is encoded in a Uint32 as #AABBGGRR. No range checking is done.

Working example:

import 'dart:typed_data';

import 'package:image/image.dart' as img;
import 'package:flutter/rendering.dart';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
//import 'package:muego_dev2/models/songs.dart';
//import 'package:provider/provider.dart';


main() {
  runApp(MaterialApp(home: ColorDetect()));
}

class ColorDetect extends StatefulWidget {
  //static const routeName = '/';

  @override
  _ColorDetectState createState() => _ColorDetectState();
}

class _ColorDetectState extends State<ColorDetect> {
  final coverData =
      'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg';

  img.Image photo;

  void setImageBytes(imageBytes) {
    print("setImageBytes");
    List<int> values = imageBytes.buffer.asUint8List();
    photo = null;
    photo = img.decodeImage(values);
  }

  // image lib uses uses KML color format, convert #AABBGGRR to regular #AARRGGBB
  int abgrToArgb(int argbColor) {
    print("abgrToArgb");
    int r = (argbColor >> 16) & 0xFF;
    int b = argbColor & 0xFF;
    return (argbColor & 0xFF00FF00) | (b << 16) | r;
  }

  // FUNCTION

  Future<Color> _getColor() async {
    print("_getColor");
    Uint8List data;

    try{
    data =
        (await NetworkAssetBundle(
          Uri.parse(coverData)).load(coverData))
            .buffer
            .asUint8List();
    }
    catch(ex){
      print(ex.toString());
    }

    print("setImageBytes....");
    setImageBytes(data);

//FractionalOffset(1.0, 0.0); //represents the top right of the [Size].
    double px = 1.0;
    double py = 0.0;

    int pixel32 = photo.getPixelSafe(px.toInt(), py.toInt());
    int hex = abgrToArgb(pixel32);
    print("Value of int: $hex ");

    return Color(hex);
  }

  @override
  Widget build(BuildContext context) {
    print("build");

    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: <Widget>[
          Flexible(
            flex: 2,
            child: Container(
              decoration: BoxDecoration(
                image: DecorationImage(
                  image: NetworkImage(coverData),
                  fit: BoxFit.cover,
                ),
              ),
            ),
          ),
          Flexible(
            flex: 1,
            child: 

            FutureBuilder(
              future: _getColor(),
              builder: (_, AsyncSnapshot<Color> data){
                if (data.connectionState==ConnectionState.done){
                  return Container(
              color: data.data,
            );                
            }
            return CircularProgressIndicator();
              }
            ),
          ),
          Spacer(),
          Padding(
            padding: const EdgeInsets.only(bottom: 8.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                MaterialButton(
                  elevation: 5.0,
                  padding: EdgeInsets.all(15.0),
                  color: Colors.grey,
                  child: Text("Get Sizes"),
                  onPressed: null,
                ),
                MaterialButton(
                  elevation: 5.0,
                  color: Colors.grey,
                  padding: EdgeInsets.all(15.0),
                  child: Text("Get Positions"),
                  onPressed: _getColor,
                )
              ],
            ),
          )
        ],
      ),
    );
  }
}

enter image description here

Upvotes: 12

Related Questions