精华内容
下载资源
问答
  • 图形图像区别与联系.图形图像区别与联系.图形图像区别与联系.
  • 多媒体图形图像技术

    千次阅读 2004-08-30 20:24:00
    3多媒体图形图像技术现在我们讲述windows多媒体中最重要,最核心的技术──图形技术。对于Windows的图形图像技术来说,包括基本的GDI绘制对像如点、线、矩形、图像位图文件,引而广之所有的动画文件都要利用到...

    3多媒体图形图像技术

    现在我们讲述windows多媒体中最重要,最核心的技术──图形技术。对于Windows的图形图像技术来说,包括基本的GDI绘制对像如点、线、矩形、图像和位图文件,引而广之所有的动画文件都要利用到windows图像图形技术编程。

    本章节我们主要讲述Bmp文件实现过程、调色板应用,及一些Bmp图像合成技术,例如:透空技术、Bmp动画技术等。

    Bmp文件结构

    Bmp文件由以下几个部分组成:文件头、位图信息头、调色板、数据区。下面这张图显示了Bmp文件结构:

    Image66.gif

    Windows位图显示的必要条件:

    我们分析一下一个Windows API函数:

    int SetDIBitsToDevice(hdc,uXDest,uYDest,uWidth,uHeight,uXSrc,uYSre,

    uStartScan,cScanLines,lpvBits,lpbmi,fuColorUse)

    请查看这个函数的第十、十一个参数lpvBits,lpbmi。其中lpvBits指明了指向内存中BMP数据的地址,lpbmi指向一个BITMAPINFO的数据结构,只要有了这两个参数,一个BMP位图就被确定了。大家可以看到绝大多数的Windows图形图像浏览软件所能分析的文件格式,例如jpg、gif、pcx、tif等等,都是先在内存中建一个数据缓冲区,再根据图形图像格式建立一个BITMAPINFO的数据结构,再利用SetDIBitsToDevice函数写到屏幕上。我们下面几个实例,也基本上采用这个方式。

    Windows的调色板

    Windows的显示设备可以显示出成千上万种颜色,但是,在同一个屏幕上能同时显示的颜色数并不是成千上万种,我们把显示设备分为单色、十六色、二百五十六色、增强色、真彩色,或者是按照显示位区分成1bit,4bit,8bit,16bit,24bit。由于Windows的理论显示数和实际显示数并不相符,因此需要一个方案来解决这个问题,这就要用到调色板这个概念。为何要使用调色板我们在此并不作详细讨论,只是有一点要弄明白,只有十六色和二百五十六色位图才需要调色板。

    下面是使用调色板的方法

    首先要读入一个位图文件,再判断这个位图文件的颜色数,假如这个文件是十六色或是二百五六色,那么这个文件中必会有一个调色板信息,读取这个调色板信息,将这个调色板信息转为一个LOGPALETTE的结构,根据这个结构生成逻辑调色板,然后每次在要显示位图前,使用SelectPalette函数将逻辑调色板选入设备描述表hDC,再使用RealizePalette函数实现这个调色板,当显示完成后再使用SelectPalette函数,将旧的调色板选择回来,一个调色板调用过程就完成了。

    构造windows图像处理类库

    我们假设这个类库包含以下功能:

    1. 处理调色板;
      1. .生成逻辑调色板;
      2. 实现调色板;
    2. 处理BMP文件
      1. 读取BMP图像;
      2. 显示图像;
      3. 实现以上“处理调色板”的功能;
    3. 处理FLC动画
      1. 读取FLC动画文件;
      2. 播放参数设置;
      3. 显示图像;
      4. 实现以上“处理调色板”的功能;

    通过以上假设我们看到要设计的类库有一些公共特点:

    1.都要处理调色板;

    2.除了“1”以外,“2”和“3”均包含了windows图像显示的必要条件:结构

    BITMAPINFO和一块bitmap数据区。

    为此我们首先构造一个处理调色板的类,这个类的实现上述“处理调色板”的功能。为什么要单独处理调色板而不让它附属于“处理BMP文件”或是“处理FLC动画”,其原因是:在大规模多媒体编程中,往往有几十或几百个BMP图像或动画,却只需要一两个调色板,过度泛滥的调色板往往造成版面切换过程中的闪烁,并浪费内存空间,因此要单独处理调色板。

    其次我们构造一个处理DIB图像的类:在这个类里,核心为两个参数(结构BITMAPINFO和一块bitmap数据区)和一个调用API函数SetDIBitsToDevice()的显示函数Show()。这个类继承于调色板类,因为处理图像文件必须处理调色板。并成为其他图像文件的基类,因为要处理图像文件必须要有这两个结构和函数。

    有了这两个基类后,我们再在这两个基类的基础上构造其他类。

    // MyBmp.h: interface for the MyBmp class.
    //
    //
    
    #if !defined(AFX_MYBMP_H__34151075_C57B_11D1_94F8_0000B431BBA1__INCLUDED_)
    #define AFX_MYBMP_H__34151075_C57B_11D1_94F8_0000B431BBA1__INCLUDED_
    
    #if _MSC_VER >= 1000
    #pragma once
    #endif // _MSC_VER >= 1000
    
    #define FALSERETURN {_lclose(hFile);return 0;}
    #define IMAGECOLORS(x,y)(1<<((x)*(y)))
    //单行BMP数据的字节数
    #define DWORD_WBYTES(x)((((x)+31UL)>>5)<<2)
    
    #define min(a, b)  (((a) < (b)) ? (a) : (b))
    
    #ifdef WIN32
    #define BMPDATABYTE
    #else
    #define BMPDATABYTE _huge
    #endif
    // #include "test.cpp"
    
    #define PALVERSION      0x0300
    #define DIB_STORAGEWIDTH(x) ((x + 3) & ~3)
    #define WIDTHBYTES(i)((i+31)/32*4)
    #define MAXPALETTE256  /* max. # supported palette entries */
    #define MAXLOADFLCNUMBER255
    
    class PALETTE
    {
    private:
    HPALETTE             hOldPal;
    protected:
    HPALETTE hPal;
    
    public:
    PALETTE(){memset(this,0,sizeof(PALETTE));}
    ~PALETTE(){if(hPal)DeleteObject(hPal);};
    HPALETTE CreatePal(BITMAPINFO*);
    HPALETTE CreatePal(LPLOGPALETTE Pal);
    HPALETTE GetPal(){return hPal;}
    UINT SetPal(HDC);
        void ResetPal(HDC);
    
    };
    
    
    class MYDIB : public PALETTE  
    {
    
    protected:
    HGLOBALhData;
    struct
    {
    BITMAPINFOHEADERb;
    RGBQUADr[256];
    }p;
    
    public:
    LPBITMAPINFO lpInfo;
    LPBITMAPINFOHEADER lpInfoHead;
    
    MYDIB();
    ~MYDIB();
    int Show(HDC,int,int,int,int,int,int,int,int,DWORD);
    inline int Show(HDC hDC,int x1,int y1,int x2,int y2,
                                      int x3,int y3,int x4,int y4)
    {return Show(hDC,x1,y1,x2,y2,x3,y3,x4,y4,SRCCOPY);}
    inline int Show(HDC hDC,int x,int y)
    {return Show(hDC,x,y,0,0,0,0,0,0,SRCCOPY);}
    inline int Show(HDC hDC)
    {return Show(hDC,0,0,0,0,0,0,0,0,SRCCOPY);}
    
    Show(MYDIB*,int,int,int,int,int,int,BYTE,BYTE,BYTE,
                                                   BYTE,BYTE,BYTE);
    Show(MYDIB*,int,int,int,int,int,int,register 
                                               BYTE,register BYTE);
    
    };
    
    class BMP : public MYDIB 
    {
    
    public:
    int Open(LPCSTR,int);
    int inline Open(LPCSTR name){return Open(name,0);}
    };
    
    #endif // !defined(AFX_MYBMP_H__34151075_C57B_11D1_94F8_0000B431BBA1__INCLUDED_)
    
    // MyBmp.cpp: implementation of the MyBmp class.
    //
    //
    
    #include "stdafx.h"
    #include "MyBmp.h"
    
    #ifdef _DEBUG
    #undef THIS_FILE
    static char THIS_FILE[]=__FILE__;
    #define new DEBUG_NEW
    #endif
    
    //
    // Construction/Destruction
    //
    
    //
    //class PALETTE
    //
    
    UINT PALETTE::SetPal(HDC hDC)
    {
    if(hPal)
    {
    SelectPalette(hDC,hPal,0);
    return RealizePalette(hDC);
    }
    else return FALSE;
    }
    
    void PALETTE::ResetPal(HDC hDC)
    {
    if(hOldPal)
    {
    SelectPalette(hDC,hOldPal,0);
                hOldPal=0;
    }
       }
    
    HPALETTE PALETTE::CreatePal(LPLOGPALETTE Pal)
    {
    if(hPal)DeleteObject(hPal);
    if(Pal_>palNumEntries<=256)hPal=CreatePalette(Pal);
    return hPal;
    }
    
    //
    //class DIBPALETTE
    //
    
    HPALETTE PALETTE::CreatePal(BITMAPINFO* info)
    {
    
    struct
    {
    WORD         palVersion;
    WORD         palNumEntries;
    PALETTEENTRY palPalEntry[256];
    } p;
    LPLOGPALETTE Pal=(LPLOGPALETTE)&p;
    
    Pal_>palVersion=0x300;
    Pal_>palNumEntries=
    /*min*/((WORD)IMAGECOLORS(info_>bmiHeader.biBitCount,1));//,info_>bmiHeader.biClrUsed);
    
    for(int i=0;i<Pal_>palNumEntries;i++)
    {
    Pal_>palPalEntry[i].peRed=info_>bmiColors[i].rgbRed;
    Pal_>palPalEntry[i].peGreen=
                            info_>bmiColors[i].rgbGreen;
    Pal_>palPalEntry[i].peBlue=info_>bmiColors[i].rgbBlue;
    Pal_>palPalEntry[i].peFlags=PC_NOCOLLAPSE;
    }
    
    return PALETTE::CreatePal(Pal);
    }
    
    //
    // MYDIB Class
    //
    
    MYDIB::MYDIB()
    {
    memset(this,0,sizeof(BMP));
    lpInfo=(LPBITMAPINFO)&p;
    lpInfoHead=(LPBITMAPINFOHEADER)&p;
    }
    
    MYDIB::~MYDIB()
    {
    if(hData)GlobalFree(hData);
    }
    
    int MYDIB::Show(HDC hDC,int x1,int y1,int x2,int y2,int x3,
                                 int y3,int x4,int y4,DWORD Rop)
    {
    if(x2<=0)x2=(int)lpInfoHead_>biWidth+x2;
    if(y2<=0)y2=(int)lpInfoHead_>biHeight+y2;
    if(x4<=0)x4=(int)lpInfoHead_>biWidth+x4;
    if(y4<=0)y4=(int)lpInfoHead_>biHeight+y4;
    //if(w_hp)SetPalette(hDC);
    BMPDATA* Data=(BMPDATA*)GlobalLock(hData);
    //int i=StretchDIBits(hDC,x1,y1,x2,y2,x3,y3,x4,y4,
                                     Data,Info,DIB_RGB_COLORS,Rop);
    int i=StretchDIBits(hDC,x1,y1,x2,y2,x3,
            (int)lpInfoHead_>biHeight_y3_y4,x4,y4,Data,lpInfo,
                                              DIB_RGB_COLORS,Rop);
    GlobalUnlock(hData);
    return i;
    }
    
    int MYDIB::Show(MYDIB* dib,int x1,int y1,int x2,int y2,int x3,int y3,
    BYTE r1,BYTE g1,BYTE b1,BYTE r2,BYTE g2,BYTE b2)
    {
    register DWORD c1=(((DWORD)r1)<<16)+(((DWORD)g1)<<8)+b1;
    register DWORD c2=(((DWORD)r2)<<16)+(((DWORD)g2)<<8)+b2;
    register DWORD c;
    register DWORD *rq=(DWORD*)p.r;
    if(!dib_>hData)
    {
    memcpy(dib,this,sizeof(MYDIB));
    dib_>lpInfo=(LPBITMAPINFO)&(dib_>p);
    dib_>lpInfoHead=(LPBITMAPINFOHEADER)&(dib_>p);
    dib_>lpInfoHead_>biWidth=x2+x1;
    dib_>lpInfoHead_>biHeight=y2+y1;
    DWORD Size=dib_>lpInfoHead_>biWidth
                     *dib_>lpInfoHead_>biHeight
                     *IMAGECOLORS(dib_>lpInfoHead_>biBitCount,1)/8;
    dib_>hData=GlobalAlloc(GMEM_FIXED,Size);
    }
    
    x2=min(x2,(int)dib_>lpInfoHead_>biWidth _x1);
    y2=min(y2,(int)dib_>lpInfoHead_>biHeight_y1);
    
    BMPDATA *Data1=(BMPDATA*)GlobalLock(hData);
    BMPDATA *Data2=(BMPDATA*)GlobalLock(dib_>hData);
    DWORD w1=DWORD_WBYTES(lpInfoHead_>biWidth
                           *lpInfoHead_>biBitCount);
    DWORD w2=DWORD_WBYTES(dib_>lpInfoHead_>biWidth
                           *dib_>lpInfoHead_>biBitCount);
    Data1+=(w1*(lpInfoHead_>biHeight_y3_y2)
                              +x3*lpInfoHead_>biBitCount/8);
    Data2+=(w2*(dib_>lpInfoHead_>biHeight_y1_y2)
                           +x1*dib_>lpInfoHead_>biBitCount/8);
    for(int j=0;j<y2;j++)
    {
    for(register int i=0;i<x2;i++)
    {
    c=*(rq+*(Data1+i));
    if((c<c1)||(c>c2)||((WORD)c<(WORD)c1)
                          ||((WORD)c>(WORD)c2)
                          ||((BYTE)c<(BYTE)c1)
                    ||((BYTE)c>(BYTE)c2))*(Data2+i)=*(Data1+i);
    }
    Data1+=w1;
    Data2+=w2;
    }
    
    GlobalUnlock(hData);
    GlobalUnlock(dib_>hData);
    return TRUE;
    }
    
    int MYDIB::Show(MYDIB* dib,int x1,int y1,int x2,int y2,int x3,
                           int y3,register BYTE x,register BYTE y)
    {
    register BMPDATA d;
    
    if(!dib_>hData)
    {
    memcpy(dib,this,sizeof(MYDIB));
    dib_>lpInfo=(LPBITMAPINFO)&(dib_>p);
    dib_>lpInfoHead=(LPBITMAPINFOHEADER)&(dib_>p);
    dib_>lpInfoHead_>biWidth=x2+x1;
    dib_>lpInfoHead_>biHeight=y2+y1;
    DWORD Size=(dib_>lpInfoHead_>biWidth+1)
                      *dib_>lpInfoHead_>biHeight
                      *dib_>lpInfoHead_>biBitCount/8;
                    //IMAGECOLORS(dib_>lpInfoHead_>biBitCount,1)/8;
    dib_>hData=GlobalAlloc(GMEM_FIXED,Size);
    }
    
    x2=min(x2,(int)dib_>lpInfoHead_>biWidth _x1);
    y2=min(y2,(int)dib_>lpInfoHead_>biHeight_y1);
    BMPDATA *Data1=(BMPDATA*)GlobalLock(hData);
    BMPDATA *Data2=(BMPDATA*)GlobalLock(dib_>hData);
    DWORD w1=DWORD_WBYTES(lpInfoHead_>biWidth
                                  *lpInfoHead_>biBitCount);
    DWORD w2=DWORD_WBYTES(dib_>lpInfoHead_>biWidth
                                  *dib_>lpInfoHead_>biBitCount);
    Data1+=(w1*(lpInfoHead_>biHeight_y3_y2)
                  +x3*lpInfoHead_>biBitCount/8);
    Data2+=(w2*(dib_>lpInfoHead_>biHeight_y1_y2)
                  +x1*dib_>lpInfoHead_>biBitCount/8);
    
    for(int j=0;j<y2;j++)
    {
    for(register int i=0;i<x2;i++)
    {
    d=*(Data1+i);
    if((d<x)||(d>y))*(Data2+i)=d;
    }
    Data1+=w1;
    Data2+=w2;
    }
    
    GlobalUnlock(hData);
    GlobalUnlock(dib_>hData);
    return TRUE;
    }
    
    //
    //class bmp
    //
    
    int BMP::Open(LPCSTR File,int sty)  //sty:   0:enable hpal  1:disnnable hpal
    {
    BITMAPFILEHEADER FileHead;
    int i;//,j,k;
    HFILEhFile;
    DWORDuBytes;
    DWORDSize;
    
    hFile=_lopen(File,OF_READ);
    if(hFile==HFILE_ERROR)return 0;
    
    i=_lread(hFile,&FileHead,sizeof(BITMAPFILEHEADER)); if(i==HFILE_ERROR) FALSERETURN;//goto BMP_FALSE_END; //Type=FileHead.bfType; //读取信息头 i=sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256; _lread(hFile,lpInfoHead,i); if(!sty)CreatePal(lpInfo); uBytes=_llseek(hFile,0,2); if ((FileHead.bfSize)>uBytes) FALSERETURN;//goto BMP_FALSE_END; if(hData)GlobalFree(hData); Size=uBytes_FileHead.bfOffBits; hData=GlobalAlloc(GMEM_FIXED,Size); BMPDATA * Data=(BMPDATA*)GlobalLock(hData); //读取数据 _llseek(hFile,FileHead.bfOffBits,0); for(;_lread(hFile,Data,RBLOCK)==RBLOCK;Data+=RBLOCK); GlobalUnlock(hData); _lclose(hFile); return TRUE; }

    在MyBmp.h文件中为了构造BMP框架,我们定义了三个类:class PALETTE

    class DIBPALETTE 、class MYDIB 。其中PALETTE是基类。DIBPALETTE继承了类PALETTE,而类MYDIB又继承了类DIBPALETTE。

    • class PALETTE:

    在此类中,我们定义了两个成员变量hPal和hOldPal、七个成员函数。这七个成员函数功能如下:其中两个分别是构造函数和析构函数,两个函数CreatePal

    (BITMAPINFO*)、CreatePal(LPLOGPALETTE )根据指定参数完成构造调色板的作用,一个函数SetPal(HDC)实现调色板,一个函数ResetPal(HDC)恢复调色板,一个函数GetPal()获得调色板。

    • class MYDIB:

    在此类中,我们定义了两个核心成员变量p和hData,其中p是一个自定义结构,它包含一个BMPINFO头信息和一个调色板,hData是指向内存中一块数据的句柄,另外两个参数lpInfo和lpInfoHead实际上是指向结构p的指针。四个成员函数Show()的内核是API函数SetDIBitsToDevice()。它们的功能是根据结构p和句柄hData把图像显示到屏幕上。

    • class BMP:

    在此类中,我们只定义了两个成员函数Open,它们的功能是打开一个BMP文件,并将文件内容填入其基类的参数中。前面我们提到过在多媒体编程中需要用公共调色板,但有时也需要用私有调色板,因此在Open函数中第二个参数指定了这个区别,若参数为0则构造自己的hPal,否则自己的hPal无效。

    实例分析

    在这个实例中,我们将调入一个BMP文件,并把它显示到屏幕上,程序过程如下:

    建立一个对话框属性的应用程序,然后是加入光盘中提供的源文件“mybmp.h”和“mybmp.cpp”,在文件“showbmpdlg.h”头加上“#include "mybmp.h"”,在类“CShowbmpDlg”定义中加入成员变量“BMP bmp”,在类“CShowbmpDlg”的成员函数OnInitDialog()中用“bmp.Open("1.bmp")”读取文件“1.bmp”,在OnPaint()中加入以下调色板实现函数和显示函数

    bmp.SetPal(dc.m_hDC)

    bmp.Show(dc.m_hDC)

    bmp.ResetPal(dc.m_hDC)

    注意SetPal()和ResetPal()要配对使用,SetPal()用在Show()前,ResetPal()用在Show()后。编译并运行之。

    4图像合成

    假如要实现一个动画例如一只老鼠从屏幕左边往右边跑过去,一般的书上是这么介绍的:首先做一个老鼠的画片,再画一张黑白老鼠掩模图片。首先用掩模图处理屏幕,再用掩模处理老鼠图片,最后把处理过的老鼠贴到屏幕上,前后要处理三个BitBlt函数。而且这样处理过程会使屏幕出现明显闪烁。要想制止闪烁还要先做一个兼容DC,先把屏幕图片拷贝至兼容DC,再在兼容DC上处理完老鼠后在再拷贝回屏幕。前后要用到五个BitBlt函数。图片比较小还好,若是图片很大,那速度简直就是“去年今日此电脑,人面老鼠相映红,人面不知何处去,老鼠还在慢慢爬”。是否有其他的解决方法呢?

    实现透明位图的方式

    1. 最愚蠢的办法:直接在屏幕上逐点用SetPixel函数画图。
    2. 一般的方法:用BitBlt函数作至少三个运算。
    3. 最快的方法:直接写屏。
    4. 性价比最高的办法:直接写数据缓冲区。

    四种方式的讨论:

    1. 对于初搞图像处理的程序员来说,似乎逐点画过去的办法是第一选择,然而事实证明这是世界上速度最慢的方法,用它实现的最理想的动画效果是“去年一滴相思泪,今日方流到嘴边”。
    2. BitBlt:前面已介绍过,此处不再介绍。
    3. 直接写屏:Dos下这种方式用得比较多,在windows环境下编程,windows3.1环境下只能加挂WinG才能实现,在win95或NT下可用函数CreateDIBSection()或是使用MicroSoftDirectX函数实现。这种方式我们将出专著介绍。此处不作讨论。
    4. 写数据缓冲区:这个方法对环境要求较小,不需外挂软件,兼容于3.1和95、NT,速度也还可以,它的原理与直接写屏相似,而且可以方便地移植到直接写屏方式中去。我们将在此介绍此方法。

    读写数据缓冲区:

    大家可能还记得在前面介绍的class MYDIB,里面有两个参数,一个是bmp信息头,一个是bmp数据区,大家是否能想象得到假如修改了bmp数据区的数据,再显示图像会有什么结果?这块数据区,就是我们要使用的数据缓冲区。

    透明位图

    要想实现透明位图,首先要有两张图片,一张作为源位图,一张作为目的位图,程序员要把源位图贴到目的位图上,并且要指明什么颜色要屏蔽掉,为此,我们在class MYDIB上增加了一个函数Show(MYDIB* dib,int x1,int y1,int x2,int y2,int x3,int y3,BYTE r1, BYTE g1,BYTE b1,BYTE r2,BYTE g2,BYTE b2),这个函数的用法有点类似于BitBlt函数,它的意思为:把己方缓冲区内的数据拷贝到类dib的缓冲区中去,其中从RGB(r1,g1,b1)至RGB(r2,g2,b2)的颜色为透明色,x1、y1、x2、y2、x3、y3为目标坐标、拷贝范围、源坐标,其意义与BitBlt相同。在Show函数的实现过程中,我们首先算出要改变的源数据、目标数据地址,然后分析要拷贝的数据颜色是否属于屏蔽色,假如是屏蔽色,则不拷贝数据,否则拷贝。

    另外一种透明位图方式

    透明色固然是一种比较简单的实现方式,但是有的时候也需要另外一种实现方式,这就是直接指定颜色索引方式,我们可以指定在调色板中某某号至某某号为透明色。因此,在class MYDIB中再增加一个函数Show(MYDIB* dib,int x1,int y1,int x2,int y2,int x3,int y3,register BYTE x,register BYTE y),这个函数的原理与前一种方式差不多,只是比前一种方式少了四个参数,由以颜色指定透明色改成以颜色索引指定透明色。

    透明位图的刷新速度

    到底更改数据缓冲区方式的速度快,还是BitBlt速度快?要是BitBlt速度快的话,以前的一番心血岂非成了滚滚长江东逝水,为此我们要用实例分析一下,建立一个名为Tp的基于对话框的程序,加入源程序mybmp.cpp和mybmp.h,在tpdlg.h文件头中加入#include "mybmp.h",在类CTPDlg中加入两个成员变量bmp1和bmp2。在窗口初始化时设置定时器,打开文件“1.bmp”、“2.bmp”,在定时器消息响应过程中完成拷贝和刷新过程,编译并运行程序。我们可以看到一个“AllTime”参数,它显示刷新256张位图需要大约20_21秒左右。现在注释掉定时器消息响应过程中的透底函数bmp1.Show((MYDIB*)&bmp2,0,0,640,480,0,0, 0,0,0,i,i,i),再看刷新256张位图大约需要15_16秒,这是单纯使用函数StretchDIBits所需的时间。可见此处一个透明位图完成时间相当于一点四个BitBlt时间,比照BitBlt方式的三个BitBlt时间(差效果)、五个BitBlt时间(好效果)要好得多。当然,这与直接写屏比又差得多了。

    现在再将透底函数换成bmp1.Show((MYDIB*)&bmp2,0,0,640,480,0,0, 0,i),我们不由惊喜地看到现在刷新256张位图的时间为16_17秒,几乎可以认为,缓冲区读写时间已经

    可以忽略不计。

    图5.3

    实例分析

    在这个实例中,我们要实现一个动画,背景是一位绝代佳人,前面有一只狗牵着它的宠物跑来跑去。素材需要五张图片,其中背景一张,动画四张。我们分析一下它的实现方式:

    在类CMovieDlg中,我们首先用语句BMP bmp[5]定义了五张图片,然后用语句MYDIB temp定义了一个临时图片。在对话框初始化过程函数中分别读入五张位图,设定定时器为一百毫秒,在定时器响应函数中操作过程如下:首先将背景写入临时图片,再将小狗透去白色写入临时图片,最后将临时图片写上屏幕。

    Image68.jpg 图5.4

    展开全文
  • iOS图形图像、动画和多媒体编程技术最佳实践
  • iOS图形图像多媒体技术最佳实践 源码
  • 处理二维图形图像等功能主要是通过GDI+技术实现的。   1.图形缩放、旋转、平移  Graphics类的ScaleTransform()方法可以实现图形的缩放  Graphics类的RotateTransform()方法可以实现图形的旋转  ...

        处理二维图形、图像等功能主要是通过GDI+技术实现的。

     

    1.图形缩放、旋转、平移

        Graphics类的ScaleTransform()方法可以实现图形的缩放

        Graphics类的RotateTransform()方法可以实现图形的旋转

        Graphics类的TranslateTransform()方法可以实现图形的平移

     

    2.Windows Media Player组件

        (1)在工具箱中的选项卡上右击,在弹出的快捷菜单中选择“选择项”命令

        (2)在“选择工具箱”对话框中,选择“COM组件”选项卡,在其中选择Windows Media Player组件,在工具箱中添加成功

     

    3.Microsoft.DirectX.AudioVideoPlayback

        DirectX是一个基于Windows平台的多媒体API函数库,它提供标准接口来与显卡和声卡、输入设备等进行交互。

        (1)在计算机中安装DirectX SDK

        (2)在项目中引用Microsfot.DirectX.AudioVideoPlayback组件

        (3)在代码编写中引入命名空间:Microsoft.DirectX.AudioVideoPlayback

     

    4.检测是否安装声卡

        可以使用Windows的API函数waveOutNumDevs()检测

     

    最后欢迎大家访问我的个人网站: 1024s

     

    展开全文
  • iOS图形图像多媒体技术最佳实践源码
  • iOS图形图像、动画和多媒体编程技术最佳实践配套源码
  • 第2章图形图像处理 主要内容 基本概念 图像处理大师 Photoshop 23 Photoshop图像处理綜合食...2.1基本概念 为了更好地学习掌握图形图像处理的实用 技术,了解相关的一些基本概念是必要的 2.1.1位图与矢量图 数字图像分
  • 多媒体应用】图形和图像

    千次阅读 2016-11-03 19:20:11
    图形和图像在一定的条件下也是可以转换的。 图形 由矢量表示的图形是一系列计算机指令来描述记录的一幅图的内容,即通过指令描述构成一幅图的所有直线、曲线、圆、圆弧、矩形等图元的位置、维数形状,也可以用...

    前言

     

           计算机中的“图”有两种常用的表示形式,一种被称为“图形”(graphic)的矢量图,它是由叫作矢量的数学对象所以定义的直线和曲线等组成的;另一种被称为“图像”(image),也叫作点阵图像或位图图像,它是用像素来代表图像,每个像素被分配一个特定位置和颜色值。图形和图像在一定的条件下也是可以转换的。

     

    图形

     

           由矢量表示的图形是一系列计算机指令来描述和记录的一幅图的内容,即通过指令描述构成一幅图的所有直线、曲线、圆、圆弧、矩形等图元的位置、维数和形状,也可以用更加复杂的形式表示图中的曲面、光照、材质等效果。在屏幕上显示一幅图形时,首先要解释这些指令,然后将描述图形的指令转换成屏幕上显示的形状和颜色。

           编辑矢量图的软件通常称为绘图软件,如适于绘制机械图、电路图的AutoCAD软件等。

     

     

    图像

     

           图像是指用像素点来描述的图,一般是用摄像机或扫描仪等输入设备捕捉实际场景画面,在计算机内存中由一组二进制位组成,这些位,定义图像中每个像素点的颜色和亮度。

          屏幕上的一个点也称为一个像素,显示一幅图像时,屏幕上的像素与图像中的点相对应。图像适合表现比较细腻、层次较多、色彩较丰富、包含大量细节的图,并可直接、快速的显示在屏幕上。

     

     

    图像的获取

     

           将现实世界的景物或物理介质的图文输入计算机的过程称为图像的获取。多媒体应用中基本图像可通过不同的方式获得,如:可以直接利用数字图像库的图像;可以利用绘图软件创建的图像;可以利用数字转换设备采集图像。

     

           1)利用数字图像库的图像

                是利用已有的图像,哪里有呢?光盘和因特网上。图像内容丰富,基本可以满足用户要求,但有时候缺乏创意性。用户可以根据自己需要进一步编辑和处理。

     

           2)利用绘图软件创建图像

                通过画图、Photoshop、美图秀秀都可以自制一个图像。

     

           3)利用数字转换设备采集图像

                数字转换设备可以把采集到的图像转换成计算机能够记录和处理的数字图像数据。

     

           例如:用扫描仪扫描一本书,用手机拍摄一张图等。从现实世界中获取图像所使用的设备统称为图像获取设备。

    数字转换设备获取图像的过程实质上是信号扫描和数字化的过程,分为采样,量化和编码。

     

    图像的属性

          

           描述一幅图像需要使用图像的属性。图像的属性包含分辨率、像素深度、真/伪彩色、图像的表示法和种类等。

     

     

           1)分辨率

     

           平常我们遇到的分辨率有两种,即图像分辨率和显示分辨率。

     

           图像分辨率,确定的是组成一幅图像的像素数目。

           显示分辨率,指的是显示设备能够显示图像的区域大小。

     

           关系:当图像分辨率大于显示分辨率时,在屏幕上只能显示部分图像;图像分辨率小于显示分辨率时,图像只占屏幕的一部分。比如,我们设置桌面背景的图片,在图片分辨率大于显示分辨率的时候,这个图片在桌面上就显示不全;如果图片的分辨率小于显示分辨率的时候,这个图片就只占桌面的一部分。你可以在自己电脑上做实验,要注意的一点就是,系统有时候会自动调整要成为桌面壁纸的图片,为了我们看出区别,我们要避免这种情况。所以要设置一下,将个性化里面的显示设置,背景设置为适应模式,如下图所示:

           显示分辨率一般用显示设备水平方向和垂直方向上的最大像素数目来表示。例如,显示分辨率为1600×900表示显示屏分成1600行(垂直分辨率),每行(水平分辨率)显示1024个像素。图像分辨率也是这样的。

     

           对应打印设备或图像扫描设备,一般使用其处理能力即每英寸的像素点数(dpi,Dots Per Inch)来表示其分辨率。例如,用200dpi来扫描一幅2×2.5英寸的彩色照片,可以得到一幅400×500个像素点的图像。

     

           2)像素深度

     

           是指存储每个像素所用的二进制位数,它也是用来度量图像的色彩分辨率的。像素深度确定彩色图像的每个像素可能有的颜色数。它决定了彩色图像中可出现的最多颜色数。

     

           如一幅图像的图像深度为b位,则该图像的最多颜色数为2b种。

     

           一幅彩色图像的每个像素用R、G、B3个分量表示,若3个分量的像素位分别为4,4,2,则最大颜色数目是22+2+4 = 210 =1024,也就是说,像素的深度为10位,每个像素可以是1024种颜色中的一种。表示一个像素的位数越多,它能表达的颜色数目就越多,它的深度也就越深。

     

           3)真彩色和伪彩色

           

           真彩色是指组成一幅彩色图像的每个像素值中有R、G、B3个基色分量,每个基色分量直接决定显示设备的基色强度。例如,R,G,B分量都用8位来表示,可生成的颜色数就是224种,每个像素的颜色就是由其中的数值直接决定的。这样得到的色彩可以反映原图像的真实色彩,称之为真彩色。

     

           为了减少彩色图形的存储空间,在生成图像时,对图像中的不同色彩进行采样,产生包含各种颜色的颜色表,即色彩查找表。

     

           图像中的每个像素的颜色不是由3个基色分量的数值直接表达,而是把像素值作为地址索引在色彩查找表中查找这个像素实际的R、G、B分量,将图像的这种颜色表达方式称为伪彩色。需要说明的是,对于这种伪彩色图像的数据除了保存代表像素颜色的索引数据外,还要保存一个色彩查找表(调色板)。色彩查找表可以是一个预先定义的表,也可以是对图像进行优化后产生的色彩表。常用的256色的彩色图像使用了8为的索引,即每个像素占用一个字节。

     

    图像的压缩编码

     

           在扫描生成一幅图像时,实际上是按一定的图像分辨率和一定的像素深度对模拟图片或照片进行采样,从而生成一幅数字化的图像。图像的图像分辨率越高,像素度越深,则数字化后的图像效果越逼真,图像数据量越大。如果按照像素点及其深度映射的图像数据大小采样,计算数据量公式为:图像数据量=图像的总像素数×像素深度/8(Byte)。

     

           例如,一幅640×480×8/8 = 300KB

     

           可见数据量很大,可是在现代通信中,利用网络传输图像的速度是一项很重要的指标,采用压缩编码技术,减少图像的数据量是提高网络传输速度的重要手段。

     

           数据压缩分为简单的两类,即无损压缩和有损压缩。

     

           1)无损压缩:无损压缩方式是指压缩前和解压缩后的数据完全一致。

     

           2)有损压缩:意味着压缩前和解压缩后的数据并非完全一致,有丢失的信息,但对于多媒体信息的压缩编码允许一定的信息失真,比如人眼和人耳所不敏感的图像或声音信息,允许在可接受的感知失真度之下损失部分信息已获取极高的压缩率。有损压缩技术广泛应用于多媒体信息的压缩编码中。计算机中使用的静态图像压缩编码方法有多种国际标准和工业标准。目前使用最广泛的编码标准就是JPEG

     

            JPEG(Joint PhotoGraphic Experts Group)是一个由ISO和IEC两个组织机构联合组成的专家组,负责制定静态和数字图像数据压缩编码标准,这个专家组开发的算法称为JPEG算法,并且称为国际上通用的标准,因此又称为JPEG标准。JPEG是一个适用范围很广的静态图像数据压缩标准,适用于连续色调的静态图形编码,即可用于灰度图像又可用于真彩色图像。

     

    图像文件格式

     

            数字图像在计算机中存储时,其文件格式很多,下面介绍几个常用的文件格式。

     

            1)JPEG文件(.jpg)。采用JPEG压缩算法,其压缩比为5:1~50:1,甚至更高。对一幅图像按JPEG格式进行压缩时,可以根据压缩比与压缩效果要求选择压缩质量因子。JPEG格式文件的压缩比例很高,非常适用于要处理大量图像的场合,它是一种由损压缩的静态图像文件存储格式,压缩比例可以选择,支持灰度图像、RGB真彩色图像等。你可以打开两个图片算一算,有的压缩的比例大,有的压缩的比例小。

     

            2)GIF文件(.gif)。CompuServe公司开发的图像文件格式,它以数据块为单位来存储图像的相关信息。GIF文件格式采用了LZW无损压缩算法按扫描行压缩图像数据。它可以在一个文件中存放多幅彩色图像,每一幅图像都由一个图像描述符、可选的局部彩色表和图像数据组成。如果把存储于一个文件中的多幅图像逐幅读出来显示到屏幕上,可以像播放幻灯片那样显示或者构成简单的动画效果,也就是我们常见的GIF动图。GIF图像深度为1~8位,即最多支持256种色彩的图像。

     

           GIF文件格式定义了两种数据存储方式,一种是按行连续存储,存储顺序与显示器的显示顺序相同;另一种是按交叉方式存储,由于显示图像需要较长的时间,使用这种方法存放图像数据,用户可在图像数据全部收到之前浏览这幅图像的全貌,而不觉得等待时间太长。目前,GIF文件格式在HTML文档中得到广泛的应用,大多是多态图的形式。

     

            3)PNG文件格式。它是作为GIF的替代品而开发的,能够避免使用GIF文件所遇到的常见问题。它从GIF那里继承了许多特征,增加了一些GIF文件所没有的特性。当用来存储灰度图像时,灰度图像的深度可达16位;存储彩色图像时,彩色图像的深度可达48位。PNG文件支持无损数据压缩。

     

    总结

     

           以上大多是书上的知识,加了一些自己的理解,觉得还是比较深刻的,对于每天见到的图片的基本信息,也有了新的认识,之前第一遍看的时候,有一个问题不太懂,就是根据像素算大小的时候,跟实际的不对应。现在明白了,原来它以什么格式存储下来,就以什么算法相应的给压缩了。现在,图像基本属性也算了解了不少,以上知识,如有错误,敬请指出,欢迎交流。

     

     

     

    展开全文
  • 为了提高显示效果,许多应用程序都采用图像缓冲技术,即先把图像完整装入内存,在缓冲区中绘制图像图形,然后将缓冲区中绘制好的图像图形一次性输出在屏幕上。缓冲技术不仅可以解决闪烁问题,并且由于在计算机...

      当图像信息量较大,采用以上直接显示的方法,可能前面一部分显示后,显示后面一部分时,由于后面一部分还未从文件读出,使显示呈斑驳现象。为了提高显示效果,许多应用程序都采用图像缓冲技术,即先把图像完整装入内存,在缓冲区中绘制图像或图形,然后将缓冲区中绘制好的图像或图形一次性输出在屏幕上。缓冲技术不仅可以解决闪烁问题,并且由于在计算机内存中创建图像,程序可以对图像进行像素级处理,完成复杂的图像变换后再显示。
      
      【例 12-6】小应用程序程序演示图像缓冲显示技术。程序运行时,当鼠标在图像区域内按下时,图像会出现边框,托动鼠标时,图像也随之移动。抬起鼠标后,边框消失。程序将两种状态的图像先放入两个缓冲区,当鼠标拖动时,不断地在新的位置重绘鼠标按下样式的图像鼠标抬起时,重绘鼠标抬起样式的图像(查看源文件)。
      
      程序要创建缓冲区图像,需要引入java.awt.image包中的BufferedImage类。要创建一个缓冲区图,可以调用createImage()方法,该方法返回一个Image对象,然后再将它转换成一个BufferedImage对象。例如,代码:
      
      BufferedImage bimage = (BufferedImage)this.createImage(this.getWidth(),this.getHeight boayulevip.cn ());
      
      也可利用以下构造方法来建立。
      
      BufferedImage(int width,int heigh, int imageType);
      
      其中参数 imageType是图像类型。
      
      使用缓冲区显示图像,需先在缓冲区中准备好图像,再将缓冲区中的图像显示在界面上。显示图像需要图形对象Graphics,可以通过以下方法建立:
      
      Graphics2D g2d = bimge.createGraphics();

    转载于:https://www.cnblogs.com/ok932343846/p/7151197.html

    展开全文
  • 想深度学习动画,图形图像多媒体的可以学习一下,swift版本
  • 论文,具有较强实用性。详细分析小波分析在图形图像压缩上的应用
  • Mac OS X 包含好几种技术用来支持对2D/3D内容的渲染以及动画,下面开始介绍它们各自的特点。 1. Quartz Quartz 是Mac OS X图形与窗口环境(Windowing Environ-ment)的核心,它提供对2D图形的渲染,更可以对一个复杂...
  • delphi7图形图像多媒体

    2013-01-24 11:46:11
    delphi7图形图像多媒体
  • iOS 图形图像、动画和多媒体编程技术最佳实践 [关东升,董玉萍 著] 2014年版
  • iOS图形图像、动画和多媒体编程技术最佳实践主要介绍了iOS的图形图像、动画和多媒体编程技术,全部采用基于iOS7的最新API。 全书分为10章:第1章开篇综述;第2章2D图形图像技术,介绍了UIKit绘图技术、绘制视图的...
  • iOS+实战图形图像、动画和多媒体卷Swift版,图像、动画处理
  • 计算机图形图像技术

    2011-10-22 13:53:09
    --------- 多媒体技术---计算机图形图像技术
  • 多媒体技术和计算机技术的集成开辟了一个新的多学科领域. 2296以下图形图像文件格式可以设置. JPG格式2297以下选项中不属于计算机多媒体的媒体类型是视频2298. 以下四个选项中最常用的三维制作软件工具是3DMAX ...
  • 浙江农林大学 Android应用程序开发 第7章 Android图形图像和多媒体开发 * * 目录 * * 7.1 图形 7.2 图像 7.3 音频视频 7.4 OpenGL ES编程 7.5 多媒体综合应用 7.1 图形 * * 一个Android应用经常需要在界面上绘制...
  • ——图像的两种分类: 位图 例子:单色位图(只有两种颜色(黑白),每一个像素点占一位) 256位图(每一个像素点有256个颜色,每一个像素点需要占一...这些点可以进行不同的排列染色以构成图样。当放大位图时,可以
  • 多媒体技术题库 期末复习资料多媒体技术题库一、填空题1、文本、声音、__图形_、_图像 _动画等信息的载体中的两个或多个的组合构成了多媒体。2、多媒体计算机系统由 多媒体硬件系统 多媒体软件系统 组成。3、...
  • 西华大学实验报告 西华大学实验报告 PAGE PAGE # 西华大学实验报告 第 组 ...课程名称 课程代码 实验项目名称 实验五图形图像和多媒体编程练习 项目代码 指导教师 项目学分 实验目的 1 掌握使用GDI+来进行绘图的方法 2
  • 在C#.NET中,使用GDI+处理二维(2D)的图形图像,使用DirectX处理三维(3D)的图形图像。  GDI+主要有“二维矢量图形”、“图像处理”“版式”三部分组成。  GDI+提供了存储基元自身相关信息的类结构...
  • 研究方向主要负责研究探索计算机图形和图像处理领域的前沿技术及其应用。中文名图形图象处理外文名Graphics and Image Processing主要研究内容科研成果有彩色图像处理及系统、多媒体制作图形图象处理概况编辑...
  • 第十四章 图形图像多媒体编程 14.1 GDI+概述 14.2 绘制图形 14.3 图像的显示与保存 14.4 动画设计 14.5 Web应用程序中的图形图像操作 14.6 音频与视频播放 14.1 GDI+概述 ? GDI+Graphics Device Interface Plus它...
  • iOS- iOS图形图像多媒体技术最佳实践随书原始代码

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 32,014
精华内容 12,805
关键字:

多媒体技术图形和图像的区别