«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告

本站技术贴除标明为“原创”的之外,其余均为网上转载,文中我会尽量保留原作者姓名,若有侵权请与我联系,我将第一时间做出修改。谢谢!

             ——既瑜


天气预报(南京)


我的分类(专题)

首页(183)
【趣味文摘】(22)
【五子连珠】(13)
【技术文档】(136)
【电脑技术】(6)
【疑难问题】(1)
【我的心情】(5)


最新日志
花语(中英文对照版)
各种花的花语
NTFS格式的7个精彩问答(pconli
童言无忌,有趣得一蹋
给MM修电脑的三个步骤[转载]
J2EE 面试题综合
JAVA编程规则
[转] P2P之UDP穿透NAT的原理与
[转]词法分析器
文件加密技术
一个让人发狂的PI求解C程序
[转]直线生成算法之DDA
[转]利用内核对象----互斥量实现应用
[转]如何正确的计算文件收发进度
双机调试VC程序
[转]分治法优化大整数乘法 C++实现
浮点数值的内存结构
[转]双链表实现大整数的加法与乘法[VC
拜占廷将军问题[转]
某人的挂QQ的程序源代码,虽然没用了,拿

最新回复
回复:vc中的CString的操作
回复:[转]分治法优化大整数乘法 C++
回复:[转]分治法优化大整数乘法 C++
回复:花语(中英文对照版)
回复:基本排序算法比较与选择[转载]
回复:c++中强制类型转换操作符小结
回复:c++中强制类型转换操作符小结
何必那么执着于是大头猫还是愤怒的小鸟,淡
回复:浮点数值的内存结构
回复:花语(中英文对照版)
回复:花语(中英文对照版)
回复:花语(中英文对照版)
回复:花语(中英文对照版)
回复:花语(中英文对照版)
回复:32位位图到24位位图的转换
dren, ages 16 and 20
回复:花语(中英文对照版)
回复:花语(中英文对照版)
回复:花语(中英文对照版)
回复:各种花的花语

留言板
签写新留言

不是0-1背包喔
桂花的花语``
谢谢
提议
提议

统计
blog名称:★既瑜★
日志总数:183
评论数量:636
留言数量:-25
访问次数:1406019
建立时间:2005年3月12日

链接


http://www.nju.edu.cn
http://bbs.nju.edu.cn 
http://www.t7-online.com
http://www.csdn.net
http://www.91f.net
http://www.crsky.com
我的MSN BLOG 

联系我

  OICQ:215768265
  njucs2001@hotmail.com
  erichoo1982@gmail.com

 

W3CHINA Blog首页    管理页面    写新日志    退出


[【技术文档】]一个简单的windows位图文件类的实现
既瑜(224499) 发表于 2005/7/19 0:00:24

一个简单的windows位图文件类的实现(一)目的在图像处理的过程中,我们必然要对位图文件进行像素级的操作。一种办法是使用windows位图操作api或者是MFC中的CBitmap类;另外的办法是调用第三方的图像类,如CxImage类。作者在使用上述这些方案时,发现了如下的问题,首先,他们的功能要么过强(提供了许多一般很少用的功能,例如封装了很多我们不想要的图像格式处理函数),要么过弱(很多常用功能没有提供,比如对像素级的操作接口)。为此,作者根据自己的使用需要,建立了一个针对windows 24位真彩色位图的处理函数。功能目前还不是很完善,但是已经能够满足作者的使用需要。主要功能有:位图的读写、位图的建立和保存、两幅位图的比较、位图中像素颜色的获取和设置、位图中指定区域的获取和设置等等。如果有需要的话,可以进行进一步的的扩充。(二)位图处理概述1  位图在windows中以位图文件格式存放(bmp文件)。文件格式如下:[ 位图文件头 +  位图信息头 + 颜色表(24位真彩色没有这项) + 位图数据 ]2  位图文件头:位图文件头主要用于识别位图文件。以下是位图文件头结构的定义和含义:typedef struct tagBITMAPFILEHEADER{     WORD    bfType; //必须是“BM”(0x4d42),标志该文件是位图文件    DWORD   bfSize; //位图文件的总的大小    WORD    bfReserved1; //必须为0    WORD    bfReserved2;  //必须为0    DWORD   bfOffBits; //到位图数据的偏移量(字节数)} BITMAPFILEHEADER;3  位图信息头 + 颜色表以下结构体中定义了位图信息头和颜色表。typedef struct tagBITMAPINFO {    BITMAPINFOHEADER    bmiHeader;//信息头    RGBQUAD             bmiColors[1];//颜色表} BITMAPINFO;本文中只讨论24位真彩色位图,因此上述结构体不予讨论,只关注信息头就可以了。信息头定义如下:typedef struct tagBITMAPINFOHEADER{    DWORD  biSize; //等于sizeof(BITMAPINFOHEADER)    LONG   biWidth; //图像的宽度    LONG   biHeight; //高度    WORD   biPlanes; //必须为1    WORD   biBitCount //每个像素的比特数,24位真彩色图应该设成24    DWORD  biCompression; //压缩    DWORD  biSizeImage; //图像数据的大小    LONG   biXPelsPerMeter; //水平方向上的每米的像素个数    LONG   biYPelsPerMeter; //垂直方向上的每米的像素个数    DWORD  biClrUsed; //调色板中实际使用的颜色数    DWORD  biClrImportant; //现实位图时必须的颜色数} BITMAPINFOHEADER; 4  位图数据根据不同的位图,位图数据所占据的字节数也是不同的,比如,对于8位位图,每个字节代表了一个像素,对于16位位图,每两个字节代表了一个像素,对于24位位图,每三个字节代表了一个像素,对于32位位图,每四个字节代表了一个像素。本文中的位图采用的是24位位图(3字节)。这里需要说明的是:位图数据中的数据排列不是按照我们习惯的从左到右,从上到下的顺序。而是采用了从下到上,从左到右的顺序排列每个像素,且,每个像素的RGB颜色值的排列顺序是B,G,R,恰好相反。因此,我们在处理的时候需要特别的注意。(三)MyColor类定义和实现MyColor类代表了一个像素点(的颜色),为了方便后续的处理,使用double类型保存RGB值。struct MyColor{    public:        // default constructor        MyColor()        {                    }        // double initialization constructor        MyColor(double x, double y, double z)        {            X = x;            Y = y;            Z = z;        }        // int initialization constructor        MyColor(int x, int y, int z)        {            X = x;            Y = y;            Z = z;        }        // Equal operator        bool operator==(MyColor& c)        {            return ( (X == c.X) && (Y == c.Y) && (Z == c.Z));        }        // Assignment operator        MyColor& operator=(MyColor& c)        {            X = c.X;            Y = c.Y;            Z = c.Z;            return (*this);        }        // operator /        MyColor operator/(int i)        {            return MyColor(this->X / i, this->Y / i, this->Z / i);        }        MyColor operator/(double d)        {            return MyColor(this->X / d, this->Y / d, this->Z / d);        }        // operator *        MyColor operator*(int i)        {            return MyColor(this->X * i, this->Y * i, this->Z * i);        }        MyColor operator*(double d)        {            return MyColor(this->X * d, this->Y * d, this->Z * d);        }        // operator +        MyColor operator+(MyColor& c)        {            return MyColor(this->X + c.X, this->Y + c.Y, this->Z + c.Z);        }        // operator -        double operator-(MyColor& c)        {            return _Euclidean3D(c);        }        // 3-D 欧式距离(squared)        double _Euclidean3D(MyColor& c)        {            static double tmp;            tmp = (this->X - c.X) * (this->X - c.X) +                  (this->Y - c.Y) * (this->Y - c.Y) +                  (this->Z - c.Z) * (this->Z - c.Z);            return tmp;        }    public:        // 3-dimension data, eg. R, G, B        double X;        double Y;        double Z;};上面的“减号”操作符是求两个颜色值的距离,它直接调用 _Euclidean3D计算欧式距离;也可以替换成别的距离函数(如海明距离)。X,Y,Z中保存的是颜色值,double类型。还有一些别的操作,如*,/等等,主要是对颜色值进行线性运算。(四)MyBitmap类的定义MyBitmap类实现了基本的常用的位图操作。一些成员变量:LPBITMAPFILEHEADER m_lpFileHeader;//文件头的指针LPBITMAPINFOHEADER m_lpInfoHead;//信息头指针MyColor * m_Image;//位图数据指针一些成员函数:void Open(char* Filename);//打开文件(24位真彩色)void Close();//关闭文件,释放所有资源void Write2File(char* Filename);//写回bmp文件void Create(int width, int height, MyColor c = MyColor(0,0,0));//建立指定大小和颜色的位图对象MyBitmap& operator=(MyBitmap& bitmap);//复制本对象bool operator==(MyBitmap& bitmap);//比较两个位图是否相同void GetAt(int x, int y, MyColor& c);//获取坐标x,y的颜色值(左上角为0,0)void SetAt(int x, int y, MyColor& c);//设置颜色MyColor& GetRef(int x, int y);//获取某个像素对象的引用void GetImageSection(int x, int y, int width, int height, MyBitmap& bitmap);//获取指定区域void SetImageSection(int x, int y, int width, int height, MyColor& c);//设置指定区域void SetImageSection(int x, int y, int width, int height, MyBitmap& bitmap);//设置指定区域long GetWidth();//获取宽度long GetHeight();//获取高度bool IsBitmapValid();//测试对象是否有效    // 24-bit bitmap class    class MyBitmap      {    public:        // default constructor        MyBitmap();        // initialization constructor        MyBitmap(int width, int height, MyColor c = MyColor(0,0,0));        // default deconstructor        ~MyBitmap();        public:        // open a 24-bit bitmap file        void Open(char* Filename);        // close a bitmap object and release all resource it used        void Close();        // write this object to a bitmap file        void Write2File(char* Filename);        // create a new bitmap object with prefixed width and height and color        void Create(int width, int height, MyColor c = MyColor(0,0,0));        // assignment operator        MyBitmap& operator=(MyBitmap& bitmap);        // equal operator        bool operator==(MyBitmap& bitmap);        // get color element at pos(x,y) x: width y: height (0,0) at left-top        void GetAt(int x, int y, MyColor& c);        // set color element at pos(x,y)        void SetAt(int x, int y, MyColor& c);        // get reference of the m_Image        MyColor& GetRef(int x, int y);        // get section of an image        void GetImageSection(int x, int y, int width, int height, MyBitmap& bitmap);        // set section of an image to color        void SetImageSection(int x, int y, int width, int height, MyColor& c);        // set section of an image to another image        void SetImageSection(int x, int y, int width, int height, MyBitmap& bitmap);        // get bitmap width        long GetWidth();                // get bitmap height        long GetHeight();        // test if a valid bitmap is read in memory        bool IsBitmapValid();            private:        // get bytes used per line in the bitmap        int GetBytesPerLine();    private:        // true if an object is valid        bool m_bValid;        // store the image file head        LPBITMAPFILEHEADER m_lpFileHeader;        // store the image info head        LPBITMAPINFOHEADER m_lpInfoHead;                // store the image data        MyColor * m_Image;    };(五)MyBitmap类的定义以下是实现代码:    MyBitmap::MyBitmap()    {        m_bValid = false;        m_lpFileHeader = NULL;        m_lpInfoHead = NULL;        m_Image = NULL;    }    MyBitmap::MyBitmap(int width, int height, MyColor c /* = MyColor */)    {        if(!(width > 0 && height > 0))            throw "MyBitmap::MyBitmap - width / height non-positive";        m_bValid = false;        m_lpFileHeader = NULL;        m_lpInfoHead = NULL;        m_Image = NULL;                Create(width, height, c);    }        MyBitmap::~MyBitmap()    {        delete m_lpFileHeader;        delete m_lpInfoHead;        delete []m_Image;        m_bValid = false;                m_lpFileHeader = NULL;            m_lpInfoHead = NULL;                m_Image = NULL;    }    bool MyBitmap::IsBitmapValid()    {        return m_bValid;    }    void MyBitmap::Open(char* Filename)    {        if(IsBitmapValid())            Close();        FILE *fp = fopen(Filename, "rb");        if(!fp)            throw "MyBitmap::Open - file open error";        m_lpFileHeader = new BITMAPFILEHEADER;        if(m_lpFileHeader == NULL)            throw "MyBitmap::Open - out of memory";        m_lpInfoHead = new BITMAPINFOHEADER;        if(m_lpInfoHead == NULL)            throw "MyBitmap::Open - out of memory";        fread(m_lpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);        fread(m_lpInfoHead, sizeof(BITMAPINFOHEADER), 1, fp);        byte *image = new byte[m_lpInfoHead->biSizeImage];        if(image == NULL)            throw "MyBitmap::Open - out of memory";        fread(image, 1, m_lpInfoHead->biSizeImage, fp);        m_Image = new MyColor[m_lpInfoHead->biWidth * m_lpInfoHead->biHeight];        if(m_Image == NULL)            throw "MyBitmap::Open - out of memory";                double thex, they, thez;        long addr;        long bytePerline = m_lpInfoHead->biSizeImage / m_lpInfoHead->biHeight;        for(int x = 0 ; x < m_lpInfoHead->biWidth ; x++)        {            for(int y = 0 ; y < m_lpInfoHead->biHeight ; y++)            {                addr = x * 3 + (m_lpInfoHead->biHeight - y - 1) * bytePerline;                thez = image[addr];                they = image[addr+1];                thex = image[addr+2];                m_Image[y * m_lpInfoHead->biWidth + x].X = thex;                m_Image[y * m_lpInfoHead->biWidth + x].Y = they;                m_Image[y * m_lpInfoHead->biWidth + x].Z = thez;            }        }        delete []image;        m_bValid = true;    }    void MyBitmap::Close()    {        if(m_bValid)        {            delete m_lpFileHeader;            m_lpFileHeader = NULL;                        delete m_lpInfoHead;            m_lpInfoHead = NULL;                        delete []m_Image;            m_Image = NULL;            m_bValid = false;        }    }    int MyBitmap::GetBytesPerLine()    {        if(!IsBitmapValid())            throw "MyBitmap::GetBytesPerLine - open first";        int bytePerline = m_lpInfoHead->biSizeImage / m_lpInfoHead->biHeight;        return bytePerline;    }    long MyBitmap::GetWidth()    {            if(!IsBitmapValid())            throw "MyBitmap::GetWidth - open first";        return m_lpInfoHead->biWidth;    }    long MyBitmap::GetHeight()    {        if(!IsBitmapValid())            throw "MyBitmap::GetHeight - open first";        return m_lpInfoHead->biHeight;    }    void MyBitmap::Write2File(char* Filename)    {        if(!IsBitmapValid())            throw "MyBitmap::Write2File - no image exists";        FILE *fp = fopen(Filename, "w+b");        if(!fp)            throw "MyBitmap::Write2File - file open error";        fwrite(m_lpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);        fwrite(m_lpInfoHead, sizeof(BITMAPINFOHEADER), 1, fp);        byte *image = new byte[m_lpInfoHead->biSizeImage];        if(image == NULL)            throw "MyBitmap::Write2File - out of memory";        memset(image, 0, m_lpInfoHead->biSizeImage);                double thex, they, thez;        long addr;        long bytePerline = this->GetBytesPerLine();        for(int x = 0 ; x < m_lpInfoHead->biWidth ; x++)        {            for(int y = 0 ; y < m_lpInfoHead->biHeight ; y++)            {                addr = x * 3 + (m_lpInfoHead->biHeight - y - 1) * bytePerline;                thex = m_Image[y * m_lpInfoHead->biWidth + x].X;                they = m_Image[y * m_lpInfoHead->biWidth + x].Y;                thez = m_Image[y * m_lpInfoHead->biWidth + x].Z;                image[addr] = thez;                image[addr+1] = they;                image[addr+2] = thex;            }        }        fwrite(image, 1, m_lpInfoHead->biSizeImage, fp);        delete []image;        fclose(fp);    }    void MyBitmap::Create(int width, int height, MyColor c)    {        if(!(width > 0 && height > 0))            throw "MyBitmap::Create - width / height non-positive";                if(this->IsBitmapValid())            Close();        m_lpFileHeader = new BITMAPFILEHEADER;        if(m_lpFileHeader == NULL)            throw "MyBitmap::Create - out of memory";        memset(m_lpFileHeader, 0, sizeof(BITMAPFILEHEADER));                m_lpInfoHead = new BITMAPINFOHEADER;        if(m_lpInfoHead == NULL)            throw "MyBitmap::Create - out of memory";        memset(m_lpInfoHead, 0, sizeof(BITMAPINFOHEADER));        m_Image = new MyColor[width * height];        if(m_Image == NULL)            throw "MyBitmap::Create - out of memory";        int linebytes = width * 3;        while(linebytes % 4)            linebytes ++;                //位图文件大小        int ImageSize = linebytes * height +             sizeof(BITMAPFILEHEADER) +            sizeof(BITMAPINFOHEADER);                m_lpFileHeader->bfType = (WORD)0x4d42;        m_lpFileHeader->bfSize = ImageSize;        m_lpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);        m_lpInfoHead->biBitCount = 24;        m_lpInfoHead->biWidth = width;        m_lpInfoHead->biHeight = height;        m_lpInfoHead->biPlanes = 1;        m_lpInfoHead->biCompression = BI_RGB;        m_lpInfoHead->biSize = sizeof(BITMAPINFOHEADER);        m_lpInfoHead->biSizeImage = linebytes * height;        for(int x = 0 ; x < width ; x ++)        {            for(int y = 0 ; y < height ; y ++)            {                m_Image[width * y + x] = c;                            }        }        m_bValid = true;    }    MyBitmap& MyBitmap::operator=(MyBitmap& bitmap)    {        if(bitmap.IsBitmapValid()) //valid        {            this->Close();                        m_lpFileHeader = new BITMAPFILEHEADER;            if(m_lpFileHeader == NULL)                throw "MyBitmap::operator= - out of memory";            memcpy(m_lpFileHeader, bitmap.m_lpFileHeader, sizeof(BITMAPFILEHEADER));                        m_lpInfoHead = new BITMAPINFOHEADER;            if(m_lpInfoHead == NULL)                throw "MyBitmap::operator= - out of memory";            memcpy(m_lpInfoHead, bitmap.m_lpInfoHead, sizeof(BITMAPINFOHEADER));                        m_Image = new MyColor[bitmap.GetWidth() * bitmap.GetHeight()];            if(m_Image == NULL)                throw "MyBitmap::operator= - out of memory";            memcpy(m_Image, bitmap.m_Image, bitmap.GetWidth() * bitmap.GetHeight() * sizeof(MyColor));            m_bValid = true;        }        else //not valid        {            this->Close();        }        return (*this);    }    bool MyBitmap::operator==(MyBitmap& bitmap)    {        if(this->m_bValid == false && bitmap.m_bValid == false)            return true;        if( (this->m_bValid == true && bitmap.m_bValid == false) ||             (this->m_bValid == false && bitmap.m_bValid == true) )            return false;        //all valid        int ret;        ret = memcmp(this->m_lpFileHeader, bitmap.m_lpFileHeader, sizeof(BITMAPFILEHEADER));        if(ret != 0)            return false;        ret = memcmp(this->m_lpInfoHead, bitmap.m_lpInfoHead, sizeof(BITMAPINFOHEADER));        if(ret != 0)            return false;        ret = memcmp(this->m_Image,             bitmap.m_Image, sizeof(MyColor) * bitmap.GetWidth() * bitmap.GetHeight());        if(ret != 0)            return false;        return true;    }    void MyBitmap::GetAt(int x, int y, MyColor& c)    {        if( ! (x >= 0 && y >= 0 && x < this->GetWidth() && y < this->GetHeight()) )            throw "MyBitmap::GetAt - x / y beyond the bound";        if(!IsBitmapValid())            throw "MyBitmap::GetAt - no image exists";        c = m_Image[this->GetWidth() * y + x];    }    void MyBitmap::SetAt(int x, int y, MyColor& c)    {        if( ! (x >= 0 && y >= 0 && x < this->GetWidth() && y < this->GetHeight()) )            throw "MyBitmap::SetAt - x / y beyond the bound";        if(!IsBitmapValid())            throw "MyBitmap::SetAt - no image exists";        m_Image[this->GetWidth() * y + x] = c;    }    MyColor& MyBitmap::GetRef(int x, int y)    {        if( ! (x >= 0 && y >= 0 && x < this->GetWidth() && y < this->GetHeight()) )            throw "MyBitmap::GetRef - x / y beyond the bound";        if(!IsBitmapValid())            throw "MyBitmap::GetRef - no image exists";        return m_Image[this->GetWidth() * y + x];    }    void MyBitmap::GetImageSection(int x, int y, int width, int height, MyBitmap& bitmap)    {        if( ! (x >= 0 && y >= 0 && x+width-1 < this->GetWidth() && y+height-1 < this->GetHeight() &&             width > 0 && height > 0) )            throw "MyBitmap::GetImageSection - x / y / widht / height beyond the bound";        bitmap.Create(width, height);        MyColor c;        for(int i = 0 ; i < width ; i ++)        {            for(int j = 0 ; j < height ; j ++)            {                this->GetAt(i + x, j + y, c);                bitmap.SetAt(i, j, c);            }        }    }    void MyBitmap::SetImageSection(int x, int y, int width, int height, MyColor& c)    {        if( ! (x >= 0 && y >= 0 && x+width-1 < this->GetWidth() && y+height-1 < this->GetHeight() &&             width > 0 && height > 0) )            throw "MyBitmap::SetImageSection - x / y / widht / height beyond the bound";        for(int i = 0 ; i < width ; i ++)        {            for(int j = 0 ; j < height ; j ++)            {                this->GetRef(i + x, j + y) = c;            }        }    }    void MyBitmap::SetImageSection(int x, int y, int width, int height, MyBitmap& bitmap)    {        if( ! (x >= 0 && y >= 0 && x+width-1 < this->GetWidth() && y+height-1 < this->GetHeight() &&             width > 0 && height > 0 && width <= bitmap.GetWidth() && height <= bitmap.GetHeight()) )            throw "MyBitmap::SetImageSection - x / y / widht / height beyond the bound";        MyColor c;        for(int j = 0 ; j < height ; j ++)        {            for(int i = 0 ; i < width ; i ++)            {                bitmap.GetAt(i, j, c);                this->GetRef(i + x, j + y) = c;             }        }    } (六)测试 主函数: void main(void) {    MyBitmap b;    b.Open("a.bmp");    b.Write2File("b.bmp");    b.Close(); } (七)说明 本文实现了一个简单易用的24位真彩色位图类,避免了过多的接口和不必要的功能。通过对这个类进行扩充,还可以满足未来更多的需要。本文引用通告地址: http://blog.csdn.net/hitjinming/services/trackbacks/425536.aspx

阅读全文(3391) | 回复(0) | 编辑 | 精华


发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)

站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.047 second(s), page refreshed 144764184 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号