首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >重构TGA图像解析器

重构TGA图像解析器
EN

Code Review用户
提问于 2012-08-11 03:37:04
回答 2查看 936关注 0票数 2

我遵循了这里描述的TGA规范(页面末尾的信息是该方法的基础),并编写了一种方法,该方法获取TGA文件的像素数据部分,并在其中创建位图。

它很有效,但是代码看起来很草率。特别是当我在读字节的时候。您会注意到,为了重复地将相同的字节添加到数组中,我执行了一些奇怪的foreach循环。

这是读取像素的方法。它返回一个表示像素的字节数组。

是否有一种方法可以让我重写128情况下的内部循环,而不使用foreach来将相同的字节序列设置为数组?我想我会经常将字节放入数组中,如果知道其他方法会更好。

代码语言:javascript
运行
复制
private byte[] getImageType10()
{
    // header stores total bits per pixel
    int bytesPerPixel = header.bpp / 8; 
    int total = header.width * header.height * bytesPerPixel;

    // number of bytes we've read so far
    int count = 0;                      
    int repeat;
    byte packetHdr;
    int packetType;

    // temp storage
    byte[] bytes;                       
    byte[] pixData = new byte[total];

    while (count < total)
    {
        packetHdr = inFile.ReadByte();
        packetType = packetHdr & (1 << 7);

        // RLE packet
        if (packetType == 128)
        {
            // packet stores number of times following pixel is repeated
            repeat = (packetHdr & ~(1 << 7)) + 1;
            bytes = inFile.ReadBytes(bytesPerPixel);
            for (int j = 0; j < repeat; j++)
            {
                foreach (byte b in bytes)
                {
                    pixData[count] = b;
                    count += 1;
                }
            }
        }

        // raw packet
        else if (packetType == 0)
        {
            // packet stores number of pixels that follow
            repeat = ((packetHdr & ~(1 << 7)) + 1) * bytesPerPixel;
            for (int j = 0; j < repeat; j++)
            {
                pixData[count] = inFile.ReadByte();
                count += 1;
            }
        }
    }
    return pixData;
}
EN

回答 2

Code Review用户

回答已采纳

发布于 2012-08-11 03:57:38

这128种情况可以优化如下:

代码语言:javascript
运行
复制
    if (packetType == 128) 
    { 
        // packet stores number of times following pixel is repeated 
        repeat = (packetHdr & ~(1 << 7)) + 1; 
        bytes = inFile.ReadBytes(bytesPerPixel);
        for (int j = 0; j < repeat; j++) 
        {
            bytes.CopyTo(pixData, count);
            count += bytes.Length;
        }
    } 

0的情况可以优化如下:

代码语言:javascript
运行
复制
    if (packetType == 0) 
    { 
        // packet stores number of pixels that follow 
        repeat = ((packetHdr & ~(1 << 7)) + 1) * bytesPerPixel;
        bytes = inFile.ReadBytes(repeat);
        bytes.CopyTo(pixData, count);
        count += bytes.Length;
    } 
票数 4
EN

Code Review用户

发布于 2012-08-13 19:14:53

我的回答很大程度上是基于@WouterH,所以如果你投我的票,那么你必须投两次票。我所做的是提供一个“完整”的代码列表,清理一些变量名称和注释(在使用了正确的变量名之后删除了许多注释),为图像标题添加了一个类,并添加了用于错误检查的占位符。我对神奇常数positiveMask不太满意,因为我不完全理解它的作用。您可以替换例外情况下的代码契约,以减少程序集的使用。通过预计算ImageHeader类中的一些变量,您可以稍微加快代码的速度。其他的改进是可能的,但是我们还没有看到您的全部代码,所以很难说。我还会把这个文件分成两个不同的文件--每个班级一个。

代码语言:javascript
运行
复制
namespace TGAImageParser
{
    using System;
    using System.Diagnostics.Contracts;
    using System.IO;

    // Using a class like this helps to avoid http://c2.com/cgi/wiki?DataEnvy
    internal class TGAImageHeader
    {
        public const int BitsInByte = 8; // const is ok over readonly here since this will not change in the future, right?

        public readonly int BytesPerPixel;
        public readonly int Width;
        public readonly int Height;

        public TGAImageHeader(int bytesPerPixel, int width, int height)
        {
            // Check the inputs thoroughly here.
            Contract.Requires(width > 0, "Image must be at least one pixel wide."); // Or is it zero pixels wide?
            // ... and so on.

            this.BytesPerPixel = bytesPerPixel;
            this.Width = width;
            this.Height = height;
        }

        public int BitsPerPixel
        {
            get
            {
                return this.BytesPerPixel * BitsInByte;
            }
        }

        // If this gets called often, then pre-compute it once.
        public int TotalBytes
        {
            get
            {
                return this.BytesPerPixel * this.TotalPixels;
            }
        }

        // If this gets called often, then pre-compute it once.
        public int TotalPixels
        {
            get
            {
                return this.Width * this.Height;
            }
        }
    }

    public class TGAImageParser
    {
        public const int RLEPacketType = 128;
        public const int RawPacketType = 0;

        private const byte positiveMask = 1 << 7; // TODO: Come up with a better name! What does it do?

        public static byte[] GetImageType10Bytes(BinaryReader inFile, TGAImageHeader imageHeader)
        {
            int numBytesReadSoFar = 0;
            int numTimesPixelIsRepeated;
            byte packetHeaderByte;
            int packetType;

            byte[] tempStorageBuffer;
            byte[] pixData = new byte[imageHeader.TotalBytes];

            while (numBytesReadSoFar < imageHeader.TotalBytes)
            {
                packetHeaderByte = inFile.ReadByte();
                packetType = packetHeaderByte & positiveMask;

                if (packetType == RLEPacketType)
                {
                    numTimesPixelIsRepeated = (packetHeaderByte & ~positiveMask) + 1;
                    tempStorageBuffer = inFile.ReadBytes(imageHeader.BytesPerPixel);
                    for (int i = 0; i < numTimesPixelIsRepeated; i++)
                    {
                        tempStorageBuffer.CopyTo(pixData, numBytesReadSoFar);
                        numBytesReadSoFar += tempStorageBuffer.Length;
                    }

                    continue;
                }

                if (packetType == RawPacketType)
                {
                    numTimesPixelIsRepeated = ((packetHeaderByte & ~positiveMask) + 1) * imageHeader.BytesPerPixel;
                    tempStorageBuffer = inFile.ReadBytes(numTimesPixelIsRepeated);
                    tempStorageBuffer.CopyTo(pixData, numBytesReadSoFar);
                    numBytesReadSoFar += tempStorageBuffer.Length;

                    continue;
                }

                // TODO: report an error here?
            }

            return pixData;
        }
    }
}
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/14593

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档