我已经搜索了一段时间如何创建一个可以从字节数组(或简单的十六进制颜色值列表)创建的有状态图像。我在ui库中遇到了这个看似有用的函数用于飞镖。
有人能给出一个如何使用它的例子吗?你能决定每个像素有多少位?
提前致谢。
decodeImageFromList
只是instantiateImageCodec
的一个便利包装器,它解码了少数支持的图像格式之一(JPEG,PNG,GIF,动画GIF,WebP,动画WebP,BMP和WBMP)。有点令人惊讶的是,还没有办法传递原始位图。但是,BMP文件格式基本上是位图前面的简单标题(可以是RGB,RGBA或使用索引颜色映射)。标题字段告诉解码器诸如宽度,高度,每像素位数,像素格式等
在内存中构造BMP头很容易,附加位图并将其传递给上述任一函数。
这是一个完整的例子。请注意,从RGB332到ARGB的映射有点偏。真的,你应该使用256成员查找表。该循环为RGB322字节的256个可能值产生256个近似ARGB值。
如果您更喜欢在Canvas上绘画,请使用instantiateImageCodec
而不是Image.memory
Widget。
import 'dart:math';
import 'dart:typed_data';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'BMP Demo',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Uint8List bmp;
BMP332Header header;
Random r = Random();
@override
void initState() {
super.initState();
header = BMP332Header(100, 100);
bmp = header.appendBitmap(
Uint8List.fromList(List<int>.generate(10000, (i) => r.nextInt(255))));
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Bitmap'),
),
body: Center(
child: Image.memory(bmp),
),
);
}
}
class BMP332Header {
int _width; // NOTE: width must be multiple of 4 as no account is made for bitmap padding
int _height;
Uint8List _bmp;
int _totalHeaderSize;
BMP332Header(this._width, this._height) : assert(_width & 3 == 0) {
int baseHeaderSize = 54;
_totalHeaderSize = baseHeaderSize + 1024; // base + color map
int fileLength = _totalHeaderSize + _width * _height; // header + bitmap
_bmp = new Uint8List(fileLength);
ByteData bd = _bmp.buffer.asByteData();
bd.setUint8(0, 0x42);
bd.setUint8(1, 0x4d);
bd.setUint32(2, fileLength, Endian.little); // file length
bd.setUint32(10, _totalHeaderSize, Endian.little); // start of the bitmap
bd.setUint32(14, 40, Endian.little); // info header size
bd.setUint32(18, _width, Endian.little);
bd.setUint32(22, _height, Endian.little);
bd.setUint16(26, 1, Endian.little); // planes
bd.setUint32(28, 8, Endian.little); // bpp
bd.setUint32(30, 0, Endian.little); // compression
bd.setUint32(34, _width * _height, Endian.little); // bitmap size
// leave everything else as zero
// there are 256 possible variations of pixel
// build the indexed color map that maps from packed byte to RGBA32
// better still, create a lookup table see: http://unwind.se/bgr233/
for (int rgb = 0; rgb < 256; rgb++) {
int offset = baseHeaderSize + rgb * 4;
int red = rgb & 0xe0;
int green = rgb << 3 & 0xe0;
int blue = rgb & 6 & 0xc0;
bd.setUint8(offset + 3, 255); // A
bd.setUint8(offset + 2, red); // R
bd.setUint8(offset + 1, green); // G
bd.setUint8(offset, blue); // B
}
}
/// Insert the provided bitmap after the header and return the whole BMP
Uint8List appendBitmap(Uint8List bitmap) {
int size = _width * _height;
assert(bitmap.length == size);
_bmp.setRange(_totalHeaderSize, _totalHeaderSize + size, bitmap);
return _bmp;
}
}