当像素阵列为小型可编辑文本 AS3 时,不会生成 8 位 BMP 图像

8 bit BMP image not generated when pixel array is to small richeditable text AS3

不知道我的标题能不能表达出我现在面临的问题。 我会详细解释:

我正在从 RichEditableTexts 生成 bmp 图像,我正在使用位图 class 来获取允许我将其作为像素进行管理的 DisplayObject 属性。

那么我有这个功能:

    /*
     * Create a 8 bit BMP image as bytearray, with 256 color ( grayscale ).
     * 
    */
    private static function encode( bitmapData:BitmapData ):ByteArray {
        // bit depth configuration
        var bytesPerPixel:int = 1;
        var bitDepth:int = 8;

        // image/file properties
        var bmpWidth:int         = bitmapData.width;
        var bmpHeight:int        = bitmapData.height;
        var imageBytes:ByteArray = bitmapData.getPixels( bitmapData.rect );

        /* Image from Preview size */
        var imageSize:int = bmpWidth * bmpHeight * bytesPerPixel;

        /* Image offset */
        var imageDataOffset:int = 0x436;

        /* File size */
        var fileSize:int = imageSize + imageDataOffset;

        // binary BMP data
        var bmpBytes:ByteArray = new ByteArray();
        bmpBytes.endian = Endian.LITTLE_ENDIAN; // byte order

        // header information
        bmpBytes.length = fileSize;
        bmpBytes.writeByte(0x42);             // B                   //0
        bmpBytes.writeByte(0x4D);             // M (BMP identifier)  //1
        bmpBytes.writeInt(fileSize);          // file size           //2
        bmpBytes.position = 0x0A;             // offset to image data
        bmpBytes.writeInt( imageDataOffset );                        //10 4 Bytes
        bmpBytes.writeInt(0x28);              // header size         //14 4 Bytes
        bmpBytes.position = 0x12;             // width, height        
        bmpBytes.writeInt( bmpWidth );                             //18 4 Bytes
        bmpBytes.writeInt( bmpHeight );                            //22 4 Bytes
        bmpBytes.writeShort( 1 );             // planes (1)        //26 2 Bytes
        bmpBytes.writeShort( bitDepth );      // color depth       //28 2 Bytes
        bmpBytes.writeInt( 0 );               // compression type  //30 4 Bytes 
        bmpBytes.writeInt( imageSize );       // image data size   //34 4 Bytes 

        bmpBytes.writeInt( 0x2E23 );          // Horizontal resolution //38 4 Bytes
        bmpBytes.writeInt( 0x2E23 );          // Vertical resolution   //42 4 Bytes

        bmpBytes.writeInt( 0x100 );           // Color in the palette

        bmpBytes.position = 0x36;             // start of color table

        /* COLOR TABLE */
        var table:uint = 256 * 4;
        for (var i:uint = 0; i < table; i++) {
            bmpBytes.writeByte( i ); //B
            bmpBytes.writeByte( i ); //G
            bmpBytes.writeByte( i ); //R
            bmpBytes.writeByte( 0 ); //A
            /*
             * Grays are made of equal bytes, for example: #AAAAAA is gray. 
            */
        }

        bmpBytes.position = imageDataOffset; // start of image data... byte 310 // 1078

        // write pixel bytes in upside-down order
        // ( as per BMP format )
        var col:int = bmpWidth;
        var row:int = bmpHeight;
        var rowLength:int = col * bytesPerPixel; // Bytes per column based on Bit depth

        // Writing bytes to new image vars
        var writingOffset:int = 4 - ( bitDepth / 8 );

        try {               
            // make sure we're starting at the
            // beginning of the image data
            imageBytes.position = 0;

            // Tmp ByteArray to extract 32 bits per pixel 
            var tmpBytes:ByteArray;

            // bottom row up
            while (row--) {
                /* hey += "LINE\n"; */

                // from end of file up to imageDataOffset
                tmpBytes = new ByteArray();
                bmpBytes.position = imageDataOffset + ( row * rowLength );

                // read through each column writing
                // those bits to the image in normal
                // left to rightorder
                col = bmpWidth;
                while (col--) {
                    // Extracting the 32 bits corresponding 
                    // to a pixel per getPixels method ( always the same ).
                    imageBytes.readBytes( tmpBytes, 0, 4 );

                    // We just need one BYTE of the 4 that are in this array.
                    tmpBytes.position = 3;

                    // THIS IS THE INDEX ON OUR COLOR TABLE ( GRAYSCALE ). 
                    bmpBytes.writeByte( tmpBytes.readUnsignedByte() );
                }
            }
        } catch(error:Error) {
            // end of file
            Alert.show( error.toString(), "I/O BMP ERROR" );
        }

        // return BMP file
        return bmpBytes;
    }

这些是我制作图像的 DisplayObjects 示例:

第一张图片生成良好,但第二张图片生成失败...

如果我用 atom 打开第二个,看起来像这样:

为什么? 有人能看到我遗漏的东西吗...这只是...啊。

提前谢谢你:)

我发现我没有在需要时添加填充... 这是生成的代码。

private static function encode( bitmapData:BitmapData ):ByteArray {
        var bytesPerPixel:int = 1;
        var bitDepth:int      = 8;

        // image/file properties
        var bmpWidth:int         = bitmapData.width;
        var bmpHeight:int        = bitmapData.height;
        var imageBytes:ByteArray = bitmapData.getPixels(bitmapData.rect);
        var imageSize:int        = imageBytes.length;

        // Offsets
        var imageDataOffset:int  = 0x436;
        var colorTableOffset:int = 0x36;

        // Pixel array
        var col:int = bmpWidth;
        var row:int = bmpHeight;
        var rowLength:int = col * bytesPerPixel; // 4 bytes per pixel (32 bit)

        // Padding
        var mod:int = ( rowLength % 4 ) != 0 ?  4 - ( rowLength % 4 ):0;
        rowLength += mod;

        // File size
        var fileSize:int = imageSize + imageDataOffset + ( mod * row );

        // binary BMP data
        var bmpBytes:ByteArray = new ByteArray();
        bmpBytes.endian        = Endian.LITTLE_ENDIAN; // byte order

        // header information
        bmpBytes.length = fileSize;

        // DIB header ( 40 bytes version )
        bmpBytes.writeByte(0x42);             // B
        bmpBytes.writeByte(0x4D);             // M (BMP identifier)
        bmpBytes.writeInt( fileSize );        // file size
        bmpBytes.position = 0x0A;             // offset to image data
        bmpBytes.writeInt(imageDataOffset);
        bmpBytes.writeInt(0x28);              // header size
        bmpBytes.position = 0x12;             // width, height
        bmpBytes.writeInt(bmpWidth);
        bmpBytes.writeInt(bmpHeight);
        bmpBytes.writeShort(1);               // planes (1)
        bmpBytes.writeShort(bitDepth);        // color depth (32 bit)
        bmpBytes.writeInt(0);                 // compression type
        bmpBytes.writeInt( ( imageSize + ( mod * row ) ) );         // image data size

        bmpBytes.writeInt( 0x2E23 );          // Horizontal resolution 
        bmpBytes.writeInt( 0x2E23 );          // Vertical resolution

        bmpBytes.writeInt( 0x100 );           // Color in the palette 

        bmpBytes.position = colorTableOffset; // start of color table...

        /* COLOR TABLE */
        for (var i:uint = 0; i < 1024; i++) {
            bmpBytes.writeByte( i ); //B
            bmpBytes.writeByte( i ); //G
            bmpBytes.writeByte( i ); //R
            bmpBytes.writeByte( 0 ); //A
        }

        /* Pixel array */
        bmpBytes.position = imageDataOffset;  // start of image data...
        var imgBmp:ByteArray;
        try {

            // make sure we're starting at the
            // beginning of the image data
            imageBytes.position = 0;

            // bottom row up
            while (row--) {
                imgBmp = new ByteArray();

                // from end of file up to imageDataOffset
                bmpBytes.position = imageDataOffset + row*rowLength;

                // read through each column writing
                // those bits to the image in normal
                // left to rightorder
                col = bmpWidth;
                while (col--) {

                    imageBytes.readBytes ( imgBmp, 0, 4 );
                    bmpBytes  .writeBytes( imgBmp, 1, 1 );
                }
                bmpBytes.position += mod;   
            }
        }catch(error:Error){
            // end of file
            Alert.show( error.toString(), "EOF" );
        }

        // return BMP file
        return bmpBytes;
    }

根据 BMP 规范,每当行字节数不是 4 的倍数时,您必须添加填充以解决该问题。

如您所见,我简化了这段代码,但如果您能看到这些行:

// Padding
var mod:int = ( rowLength % 4 ) != 0 ?  4 - ( rowLength % 4 ):0;
rowLength += mod;

我正在根据实际的行长度调整我的行长度。 那么,后面写的时候只要"take in count"多出来的字节就可以了:

bmpBytes.position += mod;

填充字节时:

/* Pixel array */
bmpBytes.position = imageDataOffset;  // start of image data...
var imgBmp:ByteArray;
try {

    // make sure we're starting at the
    // beginning of the image data
    imageBytes.position = 0;

    // bottom row up
    while (row--) {
        imgBmp = new ByteArray();

        // from end of file up to imageDataOffset
        bmpBytes.position = imageDataOffset + row*rowLength;

        // read through each column writing
        // those bits to the image in normal
        // left to rightorder
        col = bmpWidth;
        while (col--) {

            imageBytes.readBytes ( imgBmp, 0, 4 );
            bmpBytes  .writeBytes( imgBmp, 1, 1 );
        }
        bmpBytes.position += mod;   
    }
}catch(error:Error){