Dart 使用';ui.decodeImageFromList';显示从字节列表创建的图像的步骤
我已经搜索了一段时间,了解如何创建一个有状态图像,该图像可以从字节数组(或简单的十六进制颜色值列表)创建。我在dart的ui库中遇到了这个看似有用的函数 有人能举例说明如何使用它吗?你能决定每像素多少位吗Dart 使用';ui.decodeImageFromList';显示从字节列表创建的图像的步骤,dart,flutter,Dart,Flutter,我已经搜索了一段时间,了解如何创建一个有状态图像,该图像可以从字节数组(或简单的十六进制颜色值列表)创建。我在dart的ui库中遇到了这个看似有用的函数 有人能举例说明如何使用它吗?你能决定每像素多少位吗 提前感谢。decodeImageFromList只是实例化图像编解码器的一个方便包装,它可以解码少数受支持的图像格式之一(JPEG、PNG、GIF、动画GIF、WebP、动画WebP、BMP和WBMP)。令人惊讶的是,目前还没有一种方法可以传递原始位图。但是,BMP文件格式基本上是固定在位图前
提前感谢。
decodeImageFromList
只是实例化图像编解码器
的一个方便包装,它可以解码少数受支持的图像格式之一(JPEG、PNG、GIF、动画GIF、WebP、动画WebP、BMP和WBMP)。令人惊讶的是,目前还没有一种方法可以传递原始位图。但是,BMP文件格式基本上是固定在位图前面的简单标题(可以是RGB、RGBA或使用索引颜色贴图)。标题字段告诉解码器宽度、高度、每像素位数、像素格式等
在内存中构造BMP头、附加位图并将其传递给上述任一函数都非常容易
这里有一个完整的例子。请注意,从RGB332到ARGB的映射有点不正确。实际上,您应该使用256个成员的查找表。循环为RGB322字节的256个可能值生成256个近似ARGB值
如果您希望在画布上绘制,请使用instantialeimagecodec
而不是Image.memory
小部件
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;
}
}
import'dart:math';
导入“dart:键入的_数据”;
进口“包装:颤振/材料.省道”;
void main()=>runApp(新的MyApp());
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回新材料PP(
标题:“BMP演示”,
主页:新建MyHomePage(),
);
}
}
类MyHomePage扩展StatefulWidget{
@凌驾
_MyHomePageState createState()=>new_MyHomePageState();
}
类_MyHomePageState扩展状态{
Uint8List-bmp;
BMP332割台;
随机r=随机();
@凌驾
void initState(){
super.initState();
收割台=BMP332收割台(100100);
bmp=header.append位图(
Uint8List.fromList(List.generate(10000,(i)=>r.nextInt(255));
}
@凌驾
小部件构建(构建上下文){
归还新脚手架(
appBar:新的appBar(
标题:新文本(“位图”),
),
正文:中(
子:Image.memory(bmp),
),
);
}
}
类bmp332头{
int _width;//注意:宽度必须是4的倍数,因为没有考虑位图填充
内部高度;
Uint8List\u bmp;
int_totalHeaderSize;
BMP332Header(this.\u width,this.\u height):断言(\u width&3==0){
int baseHeaderSize=54;
_totalHeaderSize=baseHeaderSize+1024;//基本+颜色贴图
int fileLength=\u totalHeaderSize+\u width*\u height;//头+位图
_bmp=新的UINT8列表(文件长度);
ByteData bd=_bmp.buffer.asByteData();
bd.setUint8(0,0x42);
bd.setUint8(1,0x4d);
bd.setUint32(2,fileLength,Endian.little);//文件长度
bd.setUint32(10,_totalHeaderSize,Endian.little);//位图的开始
bd.setUint32(14,40,Endian.little);//信息头大小
bd.setUint32(18,宽度,尾端小);
bd.setUint32(22,高度,尾端小);
bd.setUint16(26,1,Endian.little);//平面
bd.setUint32(28,8,Endian.little);//bpp
bd.setUint32(30,0,Endian.little);//压缩
bd.setUint32(34,_-width*_-height,Endian.little);//位图大小
//其他一切都保持为零
//像素有256种可能的变化
//构建从压缩字节映射到RGBA32的索引颜色映射
//更好的方法是创建查找表,请参见:http://unwind.se/bgr233/
用于(int rgb=0;rgb<256;rgb++){
int offset=baseHeaderSize+rgb*4;
int red=rgb&0xe0;
int green=rgb可能对颤振插件有帮助
我通过以下方式从指纹设备转换java位图:
ByteArrayOutputStream stream = new ByteArrayOutputStream();
fingerBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
fingerBitmap.recycle();
然后在飞镖我只是用
Uint8List fingerImages;
void mapFingerImage(dynamic imageBytes) {
setState(() {
fingerImages = imageBytes;
});
}
Image.memory(fingerImages,
width: 100,
height: 100,
fit: BoxFit.contain,)
当您在ByteData对象中设置字节时,是否有任何原因需要这种特定的信息顺序?如果有,我可以在哪里找到文档来显示所有的内容?另外,如果我理解正确,这不会接受来自外部源的数据,而是数据是rgb循环,对吗?搜索bmp头格式
例如,对于格式。是的,它需要来自外部源的数据!上面的代码只生成标题(对于给定的宽度/高度值,您只需要生成一次标题)。然后,您需要附加包含位图的字节数组(必须是宽*高字节长)到标头字节数组。我更新了标头类,因此您只需调用appendBitmap
,它就会返回一个完整有效的BMP,为图像做好准备。memory
或InstanceImageCodec
。还显示了它在示例应用程序中的用法。我正试图在自己的项目中使用该类来转换一个ByteData对象,即ui.ImageByteFormat.rawRgba格式。我的字节数据的长度是宽度*高度的四倍。因此,每个像素有四个字节。有没有办法将此数据写入BMP图像类型以显示图像?旁注:dart:ui
函数decodeImageFromPixels
现在使创建dart:ui::image
更容易了。No需要在BMP标题前添加更多内容。您仍然需要显示图像(例如使用CustomPainter
)。