Flutter 如何在Flatter Web中在Blob和Image之间来回转换? 上下文

Flutter 如何在Flatter Web中在Blob和Image之间来回转换? 上下文,flutter,dart,flutter-web,dart-html,Flutter,Dart,Flutter Web,Dart Html,我使用带有颤振web的图像选择器来允许用户选择图像。这将返回本地网络Blob对象的URI,我可以使用Image.network(pickedFile.path)显示该对象。我遇到的麻烦是当我想开始操纵图像时。首先,我需要把它从网络中拉出来,放到内存中。完成后,我需要将其推回到网络可访问的Blob 如何从图像创建水滴? 我不是指内置的图像小部件。我指的是ImageLib.Image,其中ImageLib是。我为什么要这样做?我有一个web应用程序,用户在其中选择一个图像,该图像作为Blob返回。我

我使用带有颤振web的图像选择器来允许用户选择图像。这将返回本地网络Blob对象的URI,我可以使用
Image.network(pickedFile.path)
显示该对象。我遇到的麻烦是当我想开始操纵图像时。首先,我需要把它从网络中拉出来,放到内存中。完成后,我需要将其推回到网络可访问的Blob

如何从图像创建水滴? 我不是指内置的图像小部件。我指的是ImageLib.Image,其中ImageLib是。我为什么要这样做?我有一个web应用程序,用户在其中选择一个图像,该图像作为Blob返回。我将其放入内存,使用ImageLib裁剪并调整其大小,然后将其推回到Blob URL。这是我的代码当前所在的位置:

# BROKEN:
var png = ImageLib.encodePng(croppedImage);
var blob = html.Blob([base64Encode(png)], 'image/png');
var url = html.Url.createObjectUrl(blob);
在我尝试使用
image(image:NetworkImage(url))
显示图像之前,代码不会抛出错误。错误开始于:

解析图像帧时引发了以下事件$object:

url
复制并粘贴到浏览器中会显示一个黑屏,我认为这是一个0x0图像。因此,我提出了我的问题:

  • 如何正确编码图像并创建Blob
  • 除了使用BLOB,还有更好的方法来处理颤振web中的图像吗?我基本上只使用它,因为这是image\u picker\u for\u web返回的内容,因此,除了可能使用虚拟文件系统之外,它是我知道的唯一方法,我没有对虚拟文件系统进行过太多的探讨
  • 如何将图像提取到内存中? 当我这么做的时候,我不妨问一下,将图像带入记忆的最佳实践是什么。对于mobile,我使用
    image\u picker
    获取文件名,并使用
    包:image/image.dart as ImageLib
    对其进行操作:

    // pickedfile.path is the name of a file
    ImageLib.Image img = ImageLib.decodeImage(File(pickedfile.path).readAsBytesSync());
    
    对于web,我没有文件系统访问权限,因此我一直在这样做:

    // pickedfile.path is the URL of an HTML Blob
    var response = await http.get(pickedfile.path);
    ImageLib.Image img = ImageLib.decodeImage(response.bodyBytes);
    
    这比旧方法慢得多,可能是因为GET。这真的是将图像存储到内存中的最佳(或唯一)方法吗?

    正如Brendan Duncan所说,秘密在于使用浏览器的本机解码功能:

      // user browser to decode
      html.ImageElement myImageElement = html.ImageElement(src: imagePath);
      await myImageElement.onLoad.first; // allow time for browser to render
      html.CanvasElement myCanvas = html.CanvasElement(width: myImageElement.width, height: myImageElement.height);
      html.CanvasRenderingContext2D ctx = myCanvas.context2D;
    
      //ctx.drawImage(myImageElement, 0, 0);
      //html.ImageData rgbaData = ctx.getImageData(0, 0, myImageElement.width, myImageElement.height);
    
      // resize to save time on encoding
      int _MAXDIM = 500;
      int width, height;
      if (myImageElement.width > myImageElement.height) {
        width = _MAXDIM;
        height = (_MAXDIM*myImageElement.height/ myImageElement.width).round();
      } else {
        height = _MAXDIM;
        width = (_MAXDIM*myImageElement.width/ myImageElement.height).round();
      }
      ctx.drawImageScaled(myImageElement, 0, 0, width, height);
      html.ImageData rgbaData = ctx.getImageData(0, 0, width, height);
    
      var myImage = ImageLib.Image.fromBytes(rgbaData.width, rgbaData.height, rgbaData.data);
    
    他提出了一个类似的编码技巧,但对于我的用例来说,使用Dart就足够了:

      int width, height;
      if (myImageElement.width > myImageElement.height) {
        width = 800;
        height = (800*myImageElement.height/ myImageElement.width).round();
      } else {
        height = 800;
        width = (800*myImageElement.width/ myImageElement.height).round();
      }
      ctx.drawImageScaled(myImageElement, 0, 0, width, height);
      html.ImageData rgbaData = ctx.getImageData(0, 0, width, height);
      var myImage = ImageLib.Image.fromBytes(rgbaData.width, rgbaData.height, rgbaData.data);
    
    请注意,在这两种情况下,我都会首先调整图像的大小以减小大小。

    正如Brendan Duncan所说,秘密在于使用浏览器的本机解码功能:

      // user browser to decode
      html.ImageElement myImageElement = html.ImageElement(src: imagePath);
      await myImageElement.onLoad.first; // allow time for browser to render
      html.CanvasElement myCanvas = html.CanvasElement(width: myImageElement.width, height: myImageElement.height);
      html.CanvasRenderingContext2D ctx = myCanvas.context2D;
    
      //ctx.drawImage(myImageElement, 0, 0);
      //html.ImageData rgbaData = ctx.getImageData(0, 0, myImageElement.width, myImageElement.height);
    
      // resize to save time on encoding
      int _MAXDIM = 500;
      int width, height;
      if (myImageElement.width > myImageElement.height) {
        width = _MAXDIM;
        height = (_MAXDIM*myImageElement.height/ myImageElement.width).round();
      } else {
        height = _MAXDIM;
        width = (_MAXDIM*myImageElement.width/ myImageElement.height).round();
      }
      ctx.drawImageScaled(myImageElement, 0, 0, width, height);
      html.ImageData rgbaData = ctx.getImageData(0, 0, width, height);
    
      var myImage = ImageLib.Image.fromBytes(rgbaData.width, rgbaData.height, rgbaData.data);
    
    他提出了一个类似的编码技巧,但对于我的用例来说,使用Dart就足够了:

      int width, height;
      if (myImageElement.width > myImageElement.height) {
        width = 800;
        height = (800*myImageElement.height/ myImageElement.width).round();
      } else {
        height = 800;
        width = (800*myImageElement.width/ myImageElement.height).round();
      }
      ctx.drawImageScaled(myImageElement, 0, 0, width, height);
      html.ImageData rgbaData = ctx.getImageData(0, 0, width, height);
      var myImage = ImageLib.Image.fromBytes(rgbaData.width, rgbaData.height, rgbaData.data);
    

    请注意,在这两种情况下,我都会先调整图像大小以减小大小。

    有相同的问题,您解决了吗?请参阅下面的答案。有相同的问题,您解决了吗?请参阅下面的答案。如何使用dio将其发送到服务器多部分?我正在上载到Firebase。我首先按照上面的方式对图像进行编码,然后:``//encodeasjpgstringcontenttype='image/jpeg';var jpg=ImageLib.encodeJpg(img,质量:90);//上传至firebase存储字符串url;请尝试{fb.StorageReference}fb.storage().ref(imageKey);fb.UploadTaskSnapshot UploadTaskSnapshot=await{u storage.put(jpg,fb.UploadMetadata(contentType:contentType)).future;var-imageUri=await UploadTaskSnapshot.ref.getDownloadURL();url=imageUri.toString()}catch(e){print(e);}``我如何使用dio将其发送到服务器Multipart?我正在上传到Firebase。我首先按照上面的方式对图像进行编码,然后:``//encodeasjpgstringcontenttype='image/jpeg';var jpg=ImageLib.encodeJpg(img,质量:90);//上传至firebase存储字符串url;请尝试{fb.StorageReference}fb.storage().ref(imageKey);fb.UploadTaskSnapshot UploadTaskSnapshot=await{u storage.put(jpg,fb.UploadMetadata(contentType:contentType)).future;var-imageUri=await UploadTaskSnapshot.ref.getDownloadURL();url=imageUri.toString()}catch(e){print(e);}```