如何:旋转选取/设定的影像(Flutter)

sqougxex  于 2022-12-05  发布在  Flutter
关注(0)|答案(3)|浏览(132)

我已经设法旋转图像后,选择他们从图像选择器(画廊/相机)的风景/肖像。
这工作正常,并将继续设置新的图像到我想要的方向。
然而,我试图使用相同的方法来旋转一个已经选择/设置的图像,它不工作。
下面是我使用的逻辑:

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

  void _rotateImage(File file) async {
    print('>>> rotating image');
    try {
      List<int> imageBytes = await file.readAsBytes();
      final originalImage = img.decodeImage(imageBytes);
      print('>>> original width: ${originalImage.width}');
      img.Image fixedImage;
      fixedImage = img.copyRotate(originalImage, 90);
      print('>>> fixed width: ${fixedImage.width}');
      final fixedFile = await file.writeAsBytes(img.encodeJpg(fixedImage));
      setState(() {
        print('>>> setting state');
        _image = fixedFile;
      });
    } catch (e) {
      print(e);
    }
  }

我甚至可以看到图像在设置状态之前被旋转,但它仍然没有在屏幕上更新(这是显示两次尝试,而不是一次多次)

I/flutter (18314): >>> rotating image
I/flutter (18314): >>> original width: 450
I/flutter (18314): >>> fixed width: 360
I/flutter (18314): >>> setting state
I/flutter (18314): >>> rotating image
I/flutter (18314): >>> original width: 360
I/flutter (18314): >>> fixed width: 450
I/flutter (18314): >>> setting state

有没有人知道为什么这个方法在从相机/图库中挑选新图像时有效,而在使用已经处于状态的文件时无效?
[EDIT]我想这可能是因为使用了相同的文件路径。所以我在下面添加了这段代码,虽然它使图像刷新,但在几分之一秒内,它仍然不显示旋转后的图像[/EDIT]

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

  void _rotateImage(File file) async {
    try {
      Random random = new Random();
      int randomNumber = random.nextInt(1000000);

      final newFile = await file.copy(
          '/data/user/0/!PRIVATE!/cache/rotatedImage$randomNumber.jpg');

      List<int> imageBytes = await newFile.readAsBytes();

      final originalImage = img.decodeImage(imageBytes);

      img.Image fixedImage;
      fixedImage = img.copyRotate(originalImage, 90);

      final fixedFile = await newFile.writeAsBytes(img.encodeJpg(fixedImage),
          mode: FileMode.append, flush: true);

      setState(() {
        _image = fixedFile;
      });
    } catch (e) {
      print(e);
    }
  }

下面的代码显示了选择图像并选择旋转时发生的情况

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

  void _pickImage() async {
    Navigator.pop(context);
    try {
      final pickedFile =
          await _imagePicker.getImage(source: ImageSource.gallery);
      File file = File(pickedFile.path);
      if (pickedFile != null && _rotateToLandscape) {
        await _setImageToLandscape(file);
      } else if (pickedFile != null) {
        await _setImageToPortrait(file);
      }
    } catch (e) {
      print(e);
    }
  }

  Future<void> _setImageToLandscape(File file) async {
    print('>>> setting image to landscape');
    try {
      setState(() {
        _loading = true;
      });
      var decodedImage = await decodeImageFromList(file.readAsBytesSync());
      int width = decodedImage.width;
      int height = decodedImage.height;
      if (width > height) {
        print('>>> returing original image');
        _setSelectedImage(file);
      } else if (width < height) {
        print('>>> rotating image');
        List<int> imageBytes = await file.readAsBytes();
        final originalImage = img.decodeImage(imageBytes);
        img.Image fixedImage;
        fixedImage = img.copyRotate(originalImage, -90);
        final fixedFile = await file.writeAsBytes(img.encodeJpg(fixedImage));
        _setSelectedImage(fixedFile);
      }
    } catch (e) {
      print(e);
    } finally {
      setState(() {
        _loading = false;
      });
    }
  }


 void _setSelectedImage(File file) {
    switch (_selectedImage) {
      case 1:
        setState(() {
          _image = file;
          widget.setImage(image: file);
        });
        break;
      case 2:
        setState(() {
          _image2 = file;
          widget.setImage(image2: file);
        });
        break;
      case 3:
        setState(() {
          _image3 = file;
          widget.setImage(image3: file);
        });
        break;
    }
  }
insrf1ej

insrf1ej1#

您已在写入FileMode.append时设置了FileMode,因此它将在同一文件中的旧图像之后添加新图像(因为您复制了旧文件),这意味着在解码新图像时,仅解码第一部分(原始图像)
因此,要修复此问题,您只需从写操作中删除mode即可

i7uq4tfw

i7uq4tfw2#

Future<File?> _rotateImage(
      String url, String fileExt, AttachmentModel item) async {
    try {
      File file;
      if (item.file == null) {
        file = await urlToFile(url, fileExt, true);
      } else {
        file = await urlToFile(url, fileExt, false);
        List<int> temp = await item.file!.readAsBytes();
        await file.writeAsBytes(temp);
      }

      List<int> imageBytes = await file.readAsBytes();
      final originalImage = img.decodeImage(imageBytes);
      print('previous width: ${originalImage?.width}');
      img.Image newImage;
      newImage = img.copyRotate(originalImage!, 90);
      print('width: ${newImage.width}');
      final fixedFile = await file.writeAsBytes(img.encodeJpg(newImage));
      int index = attachments!.indexOf(item);
      attachments![index] = AttachmentModel(
        attachmentUrl: fixedFile.path,
        fileExt: fileExt,
        file: fixedFile,
      );
      setState(() {});
      return fixedFile;
    } catch (e) {
      print(e);
      return null;
    }
  }

  Future<File> urlToFile(String imageUrl, String fileExt, bool isNet) async {
    Directory tempDir = await getTemporaryDirectory();
    String tempPath = tempDir.path;
    File file = File(tempPath + DateTime.now().toString() + '.$fileExt');
    if (!isNet) return file;
    Uri uri = Uri.parse(imageUrl);
    http.Response response = await http.get(uri);
    await file.writeAsBytes(response.bodyBytes);
    return file;
  }

不要使用原始文件,在原始文件上创建一个新的,我把这个代码作为一个例子。我知道这是晚了,但也许它可以帮助别人

hgb9j2n6

hgb9j2n63#

我有同样的问题,我的照片捕捉应用程序,其中使用两个相机(正面和背面)。
问题是前置摄像头拍摄的照片被水平翻转了。
我所做的是检测前置摄像头是否在使用中,如果没有,就水平翻转图像;按原样返回图像。

Future<File?> takePicture() async {
 final CameraController? cameraController = controller;
 if (cameraController == null || !cameraController.value.isInitialized) {
   print('Error >>>>: select a camera first.');
   return null;
 }

 if (cameraController.value.isTakingPicture) {
   // A capture is already pending, do nothing.
   return null;
 }

 try {
   final XFile file = await cameraController.takePicture();
   print(file);

   List<int> imageBytes = await file.readAsBytes();
   File file2 = File(file.path);

   if(_selectedCamera == 1){ // When using the front camera; flip the image
     img.Image? originalImage = img.decodeImage(imageBytes);
     img.Image fixedImage = img.flipHorizontal(originalImage!);
     File fixedFile = await file2.writeAsBytes(
       img.encodeJpg(fixedImage),
       flush: true,
     );
     // When using the back camara, don't flip the image
     return fixedFile;
   }
   return file2;

 } on CameraException catch (e) {
   print(e);
   return null;
 }
}

相关问题