/* 16真彩To 256灰度,还有更快的算法吗?*/
#include <time.h>
#include <conio.h>
#include <direct.h>
#include <string.h>
#include "windows.h"void Trace( // 通过错略计算函数fun1,fun2的速度比较哪个在速度上最优
    const char *msg, // 显示信息
    DWORD cirtimes,  // 循环次数
    void (*fun1)(void),
    void (*fun2)(void)
    )
{
    time_t dd;
    DWORD i;
    // 显示信息
    printf("\n--------< %s",msg);
    // 让程序抢占CPU,消除部分由于程序启动造成的干扰
    printf("\n Full cpu...");
    dd=time(0);
    for(i=0;i<0x10000000;i++);
    printf("%d",time(0)-dd);    // 粗略计算单循环需要的时间
    printf("\n Circle...");
    dd=time(0);
    for(i=0;i<cirtimes;i++);
    printf("%d",time(0)-dd);    printf("\n Process times = %d",cirtimes);    // 粗略计算fun1需要的时间
    printf("\n Process fun1...");
    dd=time(0);
    for(i=0;i<cirtimes;i++)
        (*fun1)();
    printf("%d",time(0)-dd);    // 粗略计算fun2需要的时间
    printf("\n Process fun2...");
    dd=time(0);
    for(i=0;i<cirtimes;i++)
        (*fun2)();
    printf("%d",time(0)-dd);
    printf("\n--------< end\n");
}
#define TIM_TRY4  0xFF1    // 循环次数
// 图象显示区域
#define NES_DISP_WIDTH      256
#define NES_DISP_HEIGHT     240// 存储图象的内存区域
BYTE pScreenMem[NES_DISP_WIDTH*NES_DISP_HEIGHT*2];/* 经过计算得到的16真彩图象
   需要将这个图象进行灰度化然后拷贝到存储图象的内存区域
   */
WORD workframe[NES_DISP_WIDTH*NES_DISP_HEIGHT];/* 算法:
   算法依据为:
   已知某16真彩的象素数值为A, 由于16真彩采用15bit 即5,5,5表示红绿蓝
        1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  
           |<--  红 -->|  |<--  绿 -->|  |<--  蓝 -->|   设     红=R   绿=G   蓝=B
   则:灰度级Gr=(R*0.299+G*0.587+B*0.114), 为了计算数度快,不采用浮点数,
      即使用: Gr=(R*(0.299<<15)+G*(0.587<<15)+B*(0.114<<15))>>15
      即: Gr= ( ( 9798*R + 19235*G + 3735*B)>>15);
     则该象素的256灰度数值为RGB(Gr<<3,Gr<<3,Gr<<3);
     需要得到的不是象素的256灰度数值RGB(Gr<<3,Gr<<3,Gr<<3);
    而是以16真彩方式表示的数值即:
      1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  
         |<--  Gr -->|  |<--  Gr -->|  |<--  Gr -->|*//*  算法1   */
void Tool4Fun1()
{
    int x,y,idx=0;
    DWORD R,G,B,Gr,wColor;
    WORD *lpbuf=(WORD*)pScreenMem;
    /* Exchange 16-bit to 256 gray  */
    for (  y = 0; y < NES_DISP_HEIGHT; y++ )
    {
        for (  x = 0; x < NES_DISP_WIDTH; x++ )
        {  
            wColor = workframe[ ( y << 8 ) + x ];
            R = ( ( wColor & 0x7c00 ) >>10 );
            G = ( ( wColor & 0x03e0 ) >>5 );
            B = ( ( wColor & 0x001f ) );            
            Gr= ( ( 9798*R + 19235*G + 3735*B)>>15);
            lpbuf[idx]=(WORD)((Gr<<10)|(Gr<<5)|Gr);
            idx++;
        }
    }
}
           
/*  算法2   */
                                       
void Tool4Fun2()
{
    int x,y,idx=0;
    DWORD R,G,B,wColor;
    WORD Gr1,Gr2;
    WORD *lpbuf=(WORD*)pScreenMem;
    /* Exchange 16-bit to 256 gray */
    for (  y = 0; y < NES_DISP_HEIGHT; y++ )
    {
        for (  x = 0; x < NES_DISP_WIDTH; x+=2 )
        {  
            wColor = ((workframe[ ( y << 8 ) + x ])<<16)|(workframe[ ( y << 8 ) + x +1]);
            R = ( wColor & 0x7c007c00 );
            G = ( wColor & 0x03e003e0 );
            B = ( wColor & 0x001f001f );            
            Gr1= (WORD)(( 9798*(R>>26) + 19235*(G>>21) + 3735*(B>>16))>>15);    
            Gr2= (WORD)(( 9798*((R&0xFFFF)>>10) + 19235*((G&0xFFFF)>>5) + 3735*((B&0xFFFF)) )>>15);
            lpbuf[idx++]=((Gr1<<10)|(Gr1<<5)|Gr1);
            lpbuf[idx++]=((Gr2<<10)|(Gr2<<5)|Gr2);
        }
    }
}void Tool4()
{
    Trace("Tool4",TIM_TRY4,&Tool4Fun1,&Tool4Fun2);
}
int main(int argc, char* argv[])
{
    Tool4();
    return 0;
}

解决方案 »

  1.   

    http://expert.csdn.net/Expert/topic/1909/1909761.xml?temp=.4085504
      

  2.   

    用MMX啦,这是我以前写的,你自己再改一下
    void ConvertGray(PBYTE lpImgData,PBYTE lpResultImgData)
    {
    PUINT32 lpResultPtr;
    PBYTE lpPtr;
    unsigned int     x,y;
    unsigned int av=0xFFFF;
    unsigned __int64 1=0x7C007C007C007C00,2=0x03E003E003E003E0,3=0x001F001F001F001F;
    unsigned int off=(m_iDpi[m_nChannel]<<1);
    unsigned int srcoff=(off<<2);
    unsigned int GRAY;
    DWORD dwLineBytes=(m_iWidth<<1);
    DWORD dwBufSize=dwLineBytes*m_iHeight;
    for(y=0;y<HEIGHT;y++)
    {
    lpResultPtr=(PUINT32)(lpResultImgData+(GrayImgDataSize-WIDTH-y*WIDTH));
    lpPtr=lpImgData+dwBufSize-(y*m_iDpi[m_nChannel]+1)*dwLineBytes;
    for(x=0;x<(WIDTH>>2);x++)
    {
    __asm{
    pxor mm0,mm0

    mov edx,dword ptr [lpPtr] //取32bit像素地址到edx 
    movd mm1,dword ptr [edx] //把Source像素取到mm1低32bit 
    pand mm1,av add edx,off
    movd mm4,dword ptr[edx]
    pand mm4,av
    psllq mm4,16 add edx,off
    movd mm5,dword ptr[edx]
    pand mm5,av
    psllq mm5,32 add edx,off
    movd mm6,dword ptr[edx]
    psllq mm6,48 por mm1,mm4
    por mm1,mm5
    por mm1,mm6; movq mm2,mm1
    movq mm3,mm1 pand mm1,1
    psrlw mm1,7
    pand mm2,2
    psrlw mm2,1
    pand mm3,3
    psllw mm3,3 paddusw mm1,mm2
    paddusw mm1,mm3
    psrlq mm1,2 packuswb mm1,mm0
    movd GRAY,mm1
    //mov edx,dword ptr [lpResultPtr] 
    //movd dword ptr [edx],mm1 //保存结果 
    }
    lpPtr+=srcoff;
    *lpResultPtr++=GRAY;
    }
    }
    __asm emms
    }
      

  3.   

    duwenyong(啸海):
    你这个代码到底有多快?
    我写的那个东西,几乎已经达到了我的内存速度的上限了——我的是PC133的内存,PIII 700Mhz CPU