Flutter合成星轨图报错:'PixelUint8'无法转换为'int'类型
问题描述
使用Dart和Flutter开发星轨图合成功能,相册选图展示功能正常,但执行图片合成时触发类型转换错误:
I/flutter (17585): Error creating image: type 'PixelUint8' is not a subtype of type 'int' in type cast
错误原因
问题出在使用的image库(代码中以img为前缀):
getPixel方法返回的不是int类型像素值,而是PixelUint8对象(根据图像格式不同可能是其他Pixel子类),直接强制转换为int会失败- 原代码最后将
int类型的像素值强制转换为img.Color属于多余操作,setPixel可直接接受该int值
修复方案
- 改用
image库内置的颜色提取方法(getAlpha/getRed/getGreen/getBlue),避免手动处理Pixel对象和类型转换 - 修正星轨合成逻辑:星轨效果需要保留多张图片对应像素的最亮值,原代码仅做像素覆盖,无法生成正确星轨
- 移除所有不必要的强制类型转换
修复后的完整代码
late int alphaValue; late int redValue; late int greenValue; late int blueValue; // 直接使用image库的内置方法提取颜色分量,规避类型转换问题 int getAlpha(img.Image image, int x, int y) { return image.getAlpha(x, y); } int getRed(img.Image image, int x, int y) { return image.getRed(x, y); } int getGreen(img.Image image, int x, int y) { return image.getGreen(x, y); } int getBlue(img.Image image, int x, int y) { return image.getBlue(x, y); } Future<File> _createStartrail(List<File> images) async { if (images.isEmpty) { throw Exception('No images selected'); } img.Image? startrailImage; for (final imageFile in images) { final bytes = await imageFile.readAsBytes(); final image = img.decodeImage(Uint8List.fromList(bytes)); if (image == null) continue; startrailImage ??= img.Image(width: image.width, height: image.height); for (int y = 0; y < image.height; y++) { for (int x = 0; x < image.width; x++) { // 提取当前图片的颜色分量 final currentAlpha = getAlpha(image, x, y); final currentRed = getRed(image, x, y); final currentGreen = getGreen(image, x, y); final currentBlue = getBlue(image, x, y); // 提取星轨画布中已有像素的颜色分量 final existingRed = getRed(startrailImage, x, y); final existingGreen = getGreen(startrailImage, x, y); final existingBlue = getBlue(startrailImage, x, y); // 星轨核心逻辑:保留更亮的颜色值 redValue = currentRed > existingRed ? currentRed : existingRed; greenValue = currentGreen > existingGreen ? currentGreen : existingGreen; blueValue = currentBlue > existingBlue ? currentBlue : existingBlue; alphaValue = currentAlpha; // 可按需改为取最大值 // 组合成像素值,直接传入setPixel,无需类型转换 final newPixel = (alphaValue << 24) | (redValue << 16) | (greenValue << 8) | blueValue; startrailImage.setPixel(x, y, newPixel); } } } final output = await getTemporaryDirectory(); final outputPath = '${output.path}/startrail.png'; final outputFile = File(outputPath); await outputFile.writeAsBytes(img.encodePng(startrailImage!)); return outputFile; } // 以下代码无需修改 File? _combinedImage; void _combineImages() { if (_images.isNotEmpty) { _createStartrail(_images).then((combinedImage) { setState(() { _combinedImage = combinedImage; }); }).catchError((error) { print('Errore durante la creazione dell\'immagine startrail: $error'); }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Camera Preview')), body: Column( children: [ Expanded( child: FutureBuilder<void>( future: _initializeControllerFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { return AspectRatio( aspectRatio: 16 / 9, child: CameraPreview(_controller), ); } else { return const Center(child: CircularProgressIndicator()); } }, ), ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: _pickImages, child: const Text('Select Images'), ), const SizedBox(width: 10), ElevatedButton( onPressed: _combineImages, child: const Text('Create Startrail'), ), ], ), if (_imagePreviews.isNotEmpty) Container( padding: EdgeInsets.symmetric(vertical: 10), height: 100, child: ListView( scrollDirection: Axis.horizontal, children: _imagePreviews, ), ), if (_combinedImage != null) Container( padding: EdgeInsets.all(10), child: Image.file(_combinedImage!), ), ], ), ); }
内容的提问来源于stack exchange,提问作者Gabriele Iocco
相关产品推荐
相关产品推荐

