如何将 BitmapData 从 Flash 转换为画布 HTML?

Posted

技术标签:

【中文标题】如何将 BitmapData 从 Flash 转换为画布 HTML?【英文标题】:How to convert BitmapData from Flash to canvas HTML? 【发布时间】:2021-01-13 07:51:15 【问题描述】:

我遇到了一个相当严重的问题。我正在将 Flash 重写为 JS,并遇到了 SOAP 返回数据处理的问题。它是关于我以字符串形式获取的图像,然后将其转换为 Flash 中使用的 BitmapData。 我尝试了许多不同的方法,但充其量它会在画布上得到一个带有噪点的绿色图像。以下是您可能会发现有用的所有代码 sn-ps

来自 Flash 的代码:

        private function encode(bitmap:Bitmap):ByteArray
            var encoder:JPGEncoder = new JPGEncoder(QUALITY);
            return encoder.encode(bitmap.bitmapData);
        

        public function decodeBytes(bm:Bitmap):void
            _bitmap = bm;
            _bytesData = encode(_bitmap);
            var imgConventer:ArrayDataConventer = new ArrayDataConventer();
            imgConventer.addEventListener(ImageConvertCompleteEvent.IMAGE_CONVERT_COMPLETE, convertCompleteHandler);
            imgConventer.decByteArrToHexStr(bytesData);
           

decByteArrToHexStr 返回字符串,其中两个十六进制字符表示字节。这个字符串被推送到 SOAP 并在我想要获取它时返回。所以这是 Flash 部分。

现在我想将此字符串转换为可以放入画布的图像数据。

我有将字符串转换为 Uint8Array 的方法。

  public hexStrToDecByteArr(str: string): Uint8Array 
    const byteArr: Uint8Array = new Uint8Array(str.length / 2);

    for (let i: number = 0; i < str.length; i = i + 2) 
      const n: number = parseInt('0x' + str.substr(i, 2), 0);

      if (!isNaN(n)) 
        byteArr[i] = n;
      
    

    return data;
  

然后在响应处理程序中我有这样的东西:

const decodes: ArrayDataConverter = new ArrayDataConverter();
        const data = decodes.hexStrToDecByteArr(downloadedImage.sData);
        const encoder: any = new JPGEncoder(100);
        const encoded = encoder.encode(width: 400, height: 300, data);

        const context = this.canvas.nativeElement.getContext('2d');
        context.clearRect(0, 0, 400, 300);

        const image = new Image();
        image.onload = () => 
          context.drawImage(image, 0, 0);
        ;
        image.src = encoded;

所以下载的Image.sData 包含十六进制字符串。 JPGEncoder 是我找到的包,它是 JPGEncoder Flash 版本重写为 JS (https://www.npmjs.com/package/@koba04/jpeg-encoder)。

正如我之前提到的,我在画布上得到了带有一些噪点的绿色图像。

提前致谢。

【问题讨论】:

【参考方案1】:

您似乎正在使用 JPEG 压缩来压缩实际像素颜色(原始位图数据),然后尝试将相同的 JPEG 数据加载到 html5 画布中?

这种方式行不通,因为 Canvas 需要像素颜色值而不是 JPEG 压缩算法。

可能的修复 #1:在 Canvas 中使用 AS3 像素值...

在您的 AS3 代码中,不要编码为 JPEG,而只需将像素值写入为十六进制字符串(来自数组)。

public function decodeBytes(bm:Bitmap):void

    //# get pixel values into an array named: _bytesData
    bm.bitmapData.copyPixelsToByteArray( bm.bitmapData.rect, _bytesData );
    
    var imgConventer:ArrayDataConventer = new ArrayDataConventer();
    imgConventer.addEventListener(ImageConvertCompleteEvent.IMAGE_CONVERT_COMPLETE, convertCompleteHandler);
    imgConventer.decByteArrToHexStr( _bytesData );

然后在 TypeScript(或 javascript)端,只需将接收到的数据读入数组/缓冲区。

要在 (HTML5) Canvas 中显示图像,您必须使用 for 循环来读取数组

var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var imgData = ctx.createImageData( canvas.width, canvas.height );

//# notice the order is:
//# JS imagedata = R-G-B-A
//# AS3 bitmap   = A-R-G-B

for (var i=0; i < imgData.data.length; i += 4)

    imgData.data[i + 0] = downloadedImage.sData[i + 1]; //put RED
    imgData.data[i + 1] = downloadedImage.sData[i + 2]; //put GREEN
    imgData.data[i + 2] = downloadedImage.sData[i + 3]; //put BLUE
    imgData.data[i + 3] = downloadedImage.sData[i + 0]; //put ALPHA


//# Update canvas with the image data
ctx.putImageData(imgData,0,0);

这应该会在您网页的画布中显示您的图像(其中有 idmyCanvas)。

可能的修复 #2:在数组中使用 JPEG 数据...

由于上述发送原始位图数据的方法可能意味着您正在发送一个大文件,因此您可以尝试使用 JPEG 压缩,这种方式意味着您可以将 JPEG 数组直接加载到 &lt;Image&gt; 标记中,就像加载文件。

无需对 JPEG 进行两次编码(首先在 AS3 中,然后再次在 TypeScript 中,这只会破坏您的图像数据)

(1) 首先像在原始 AS3 代码中一样创建 JPEG,然后 (2) 在 TypeScript 或 HTML 端,检查前 3 个值给你(使用alertconsole.log 选项)...

downloadedImage.sData[0] //should be: 0xFF (or 255)
downloadedImage.sData[1] //should be: 0xD8 (or 216)
downloadedImage.sData[2] //should be: 0xFF (or 255)

这 3 个值是 JPEG 标头的正确和预期的开始字节(它表明您的数据确实是一个有效的 JPEG 图像)。

在您的 HTML 的 &lt;body&gt; 部分中,确保您有一个 &lt;image&gt; 标记,等待将字节图像添加为 .src...

<body>

<img id="myPic" src="none.jpg"  >

</body>

然后在 JavaScript 中(我不知道 TypeScript,所以你将自己转换这部分)

<script>

//# downloadedImage.sData String must look like "0xFF,0xD8,0xFF" etc (using 0xFF or 0xff is same result)
var myArr = new Uint8Array( [ downloadedImage.sData ] );

var blob = new Blob( [downloadedImage.sData],  type: "image/jpeg"  );
var urlCreator = window.URL || window.webkitURL;
var imageUrl = urlCreator.createObjectURL( blob );
var img = document.getElementById( "myPic" );
img.src = imageUrl;

</script>

希望这对获得工作结果有用。

PS:一些完整的可测试示例代码(仅限 HTML/JS,无 TypeScript)...

<!DOCTYPE html>
<html>
<body>

<img id="myPic" src="none.jpg"  >

</body>

<script>

//# fill the array properly & fully, below is just small example of expected values
var myArr = new Uint8Array( [0xFF,0xD8,0xFF,0xE0,0x00 ... 0xFF,0xD9]);

var blob = new Blob( [myArr],  type: "image/jpeg"  );
var urlCreator = window.URL || window.webkitURL;
var imageUrl = urlCreator.createObjectURL( blob );
var img = document.getElementById( "myPic" );
img.src = imageUrl;

</script>

</html>

【讨论】:

以上是关于如何将 BitmapData 从 Flash 转换为画布 HTML?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 MovieClip 转换为 bitmapData

flash里面,位图动态缩小,如何消除锯齿?

将 RGB 转换为 YUV,+ ffmpeg

如何指定跨域策略文件以允许 Flash 从 RTMP (Wowza) 视频流中获取位图?

粒子频谱BitmapData版

FLASH AS3图片内存清除方法