//函数说明:将源文件中的bmp图像读出缩放后,保存在目标文件里
//输入参数:srcFile源文件名
//         destFile目录文件名
//         nNewWidth缩放后图片宽
//         nNewHeight缩放后图片高
//输出参数:无
//返回值:如果缩放成功返回1,否则返回0
//其它说明:图片是32位真彩色,若能用24位保存最好
BOOL BMPZoom(char * srcFile,char *destFile,int nNewWidth,int nNewHeight)

解决方案 »

  1.   

    需要查一下bmp文件的存储格式了
      

  2.   

    我没有完全合适的函数,我以前写的函数是针对位图内存操作缩放的。
    做位图高效率的缩放必须用到汇编语言,要做到平滑缩放,则要求位图具有alpha通道/*
    转换主函数
    pSrc 源数据 要求32位
    widthSrc 源宽
    heightSrc 源高
    pDst 转换后数据 32位,要求先创建
    widthDst 要求目标宽
    heightDst 要求目标高
    */
    void Image::BltStretch(void * pSrc,int widthSrc,int heightSrc,void *pDst,int widthDst,int heightDst);
    /*
    图片从24位转换为32位
    */
    void Image::_convert_24_32(void * src,void * dst,int src_len);
    /*
    将位图数据保持为完整BMP数据
    */
    bool Image::_build_bitmap(int width,int height,int bits,char * src,int srclen,std::auto_ptr<char> & dst,int & dstlen)
      

  3.   


    // Alpha表尺寸
    #define _IRWE_THUM_APLHATAB_SIZE 129
    // 四字类型对定义
    typedef __int64 QWORD;
    static QWORD s_AlphaTable[_IRWE_THUM_APLHATAB_SIZE];
    static BOOL s_bAlphaTableInit=FALSE;
    // 初始化Alpha表(此函数应该在主程序初始化时就调用)
    static void InitAlphaTable()
    {
    QWORD temp;
    for(int i=0;i<_IRWE_THUM_APLHATAB_SIZE;i++)
    {
    temp = (QWORD)i;
    s_AlphaTable[i] = temp<<48 | temp<<32 | temp<<16 | temp;
    }
    }
    // 行缩放函数(内部函数)
    static void DrawScanLine(DWORD* DestAddr, DWORD* SrcAddr, int Width, DWORD dU)
    {
    __asm{
    mov esi, SrcAddr;
    mov edi, DestAddr;
    mov ecx, Width;
    xor edx, edx;  //edx = U1
    mov ebx, dU;
    pxor mm7, mm7; LoopX:
    mov eax, edx;
    and eax, 0xffff;
    shr eax, 9;
    movq mm6, [s_AlphaTable + eax * 8]; //mm6 = a2
    neg eax;
    add eax, 128;
    movq mm5, [s_AlphaTable + eax * 8]; //mm5 = a1 mov eax, edx;
    shr eax, 16;
    movq mm0, [esi + eax * 4];
    movq mm1, mm0;
    PUNPCKLBW mm0, mm7;  //mm0 = 0a10r10g10b1
    PUNPCKHBW mm1, mm7;  //mm1 = 0a20r20g20b2 pmullw mm0, mm5;
    pmullw mm1, mm6;
    paddw  mm0, mm1;
    psrlw  mm0, 7;
    packuswb mm0, mm0;
    movd eax, mm0;
    add edx, ebx;
    stosd; dec ecx;
    jnz LoopX;
    emms;
    }
    }static void DrawScanLineAlpha(DWORD* DestAddr, DWORD* SrcAddr, int Width, DWORD dU, DWORD Alpha)
    {
    if(!Alpha)
    return; __asm{
    mov esi, SrcAddr;
    mov edi, DestAddr;
    mov ecx, Width;
    xor edx, edx;  //edx = U1
    mov ebx, dU;
    mov eax, Alpha;
    pxor mm7, mm7;
    movq mm4, [s_AlphaTable + eax * 8]; //mm4 = alpha LoopX:
    mov eax, edx;
    and eax, 0xffff;
    shr eax, 9;
    movq mm6, [s_AlphaTable + eax * 8]; //mm6 = a2
    neg eax;
    add eax, 128;
    movq mm5, [s_AlphaTable + eax * 8]; //mm5 = a1 mov eax, edx;
    shr eax, 16;
    movq mm0, [esi + eax * 4];
    movq mm1, mm0;
    PUNPCKLBW mm0, mm7;  //mm0 = 0a10r10g10b1
    movd mm2, [edi];
    PUNPCKHBW mm1, mm7;  //mm1 = 0a20r20g20b2 pmullw mm0, mm5;
    punpcklbw mm2, mm7;
    pmullw mm1, mm6;
    paddw  mm0, mm1;
    psrlw  mm0, 7; psubw mm0, mm2;
    pmullw mm0, mm4;
    psraw  mm0, 7;
    paddw  mm0, mm2; packuswb mm0, mm0;
    movd eax, mm0;
    add edx, ebx;
    stosd; dec ecx;
    jnz LoopX;
    emms;
    }
    }int _get_image_line(int iWidth)
    {
    return iWidth*4;
    }
    void * _get_address_of_pixel(void * data,int width,int height,int x,int y)
    {
    int iLine= _get_image_line(width);
        return (char*)data + y * iLine + x * sizeof(RGBTRIPLE);
    }
    void * _get_address_of_line(void * data,int width,int height,int line)
    {
    return _get_address_of_pixel(data,width,height,0,line);
    }
    int _byte_per_line(int width)
    {
    return _get_image_line(width);
    }using namespace OpenCam::Media;
    void Image::_width_adjuest(int & width)
    {
    int idle = width%4;
    int a = width/4;
    width = a*4;
    if(idle>0)
    width+=4;
    }
    void Image::BltStretch(void * pSrc,int widthSrc,int heightSrc,void *pDst,int widthDst,int heightDst)
    {
    if (!s_bAlphaTableInit) InitAlphaTable();
    DWORD dU = (widthSrc<< 16) / widthDst;
    DWORD dV = (heightSrc<< 16) / heightDst;
    DWORD V1 = 0; DWORD *ps,*pd;
    pd=(DWORD *)_get_address_of_pixel(pDst,widthDst,heightDst,widthDst-1,0);
    int i = 0;
    for(i = 0; i < heightDst-1; i++)
    {
    DrawScanLine((DWORD*)(_get_address_of_line(pDst,widthDst,heightDst,i))
    ,(DWORD *)(_get_address_of_line(pSrc,widthSrc,heightSrc,V1>>16))
    ,widthDst, dU);
    DrawScanLineAlpha((DWORD*)(_get_address_of_line(pDst,widthDst,heightDst,i)), 
    (DWORD *)(_get_address_of_line(pSrc,widthSrc,heightSrc,(V1>>16)+1))
    ,widthDst
    ,dU
    ,(V1>>9)&0x7f);
    ps=(DWORD *)_get_address_of_pixel(pSrc,widthSrc,heightSrc,widthSrc-1,(V1>>16));
    *pd=*ps;
    pd+=_byte_per_line(widthDst)/4;
    V1 += dV;
    }
    DrawScanLine((DWORD*)(_get_address_of_line(pDst,widthDst,heightDst,i)), 
    (DWORD *)(_get_address_of_line(pSrc,widthSrc,heightSrc,V1>>16))
    ,widthDst, dU);
    DrawScanLineAlpha((DWORD*)(_get_address_of_line(pDst,widthDst,heightDst,i)), 
    (DWORD *)(_get_address_of_line(pSrc,widthSrc,heightSrc,heightSrc-1))
    ,widthDst
    ,dU
    ,0x7f);
    ps=(DWORD *)_get_address_of_pixel(pSrc,widthSrc,heightSrc,widthSrc-1,heightSrc-1);
    *pd=*ps;
    }
    void Image::_convert_24_32(void * src,void * dst,int src_len)
    {
    int dst_len = (src_len*4)/3;
    char * pTemp,*ptr;
    pTemp = (char*)src;
    ptr = (char*)dst;
    for(int index=0;index<src_len/3;index++)
    {
    unsigned char r = *(pTemp++);
    unsigned char g = *(pTemp++);
    unsigned char b = *(pTemp++);
    *(ptr++) = r;
    *(ptr++) = g;
    *(ptr++) = b;
    ptr++;
    }
    }bool Image::_build_bitmap(int width,int height,int bits,char * src,int srclen,std::auto_ptr<char> & dst,int & dstlen)
    {
    try
    {
    int HEADER_SIZE = 0x36;
    int DESC_SIZE = 0x28;
    if(width==0 || height==0 || (bits!=24&&bits!=32))
    throw std::string("do not support");
    dstlen = HEADER_SIZE+srclen;
    dst.reset(new char[dstlen]);
    char * pdst = dst.get();
    //header
    *pdst = 0x42; pdst++;
    *pdst = 0x4D; pdst++;
    *((int*)pdst) = dstlen; pdst+=4;
    *((int*)pdst) = 0; pdst+=4;
    *((int*)pdst) = HEADER_SIZE; pdst+=4;
    //desc
    *((int*)pdst) = DESC_SIZE; pdst+=4;
    *((int*)pdst) = width; pdst+=4;
    *((int*)pdst) = height; pdst+=4;
    *pdst = 0x01; pdst++;
    *pdst = 0x00; pdst++;
    *pdst = bits; pdst++;
    *pdst = 0x00; pdst++;
    *((int*)pdst) = 0; pdst+=4;
    *((int*)pdst) = srclen; pdst+=4;
    *((int*)pdst) = 0; pdst+=4;
    *((int*)pdst) = 0; pdst+=4;
    *((int*)pdst) = 0; pdst+=4;
    //reserve
    *((int*)pdst) = 0; pdst+=4;
    //data
    memcpy(pdst,src,srclen);
    return true;
    }
    catch(std::string)
    {
    return false;
    }
    }
      

  4.   

    bmp里面就是从下往上把每个点的RGB列出来,放缩就是取相应的比例值
      

  5.   

    晕 这么长的代码,给你个简单的
    #include<atlimage.h>
    CImage* pImage;
    pImage=new CImage;
    pImage->Load(你的路劲);
    pImage->draw(任何你要缩放的尺寸)
      

  6.   

    这要看了,如果是处理1张2张图片用简单CImage可以,但是对于性能要求比较高的程序,还是要使用到复杂甚至汇编基本才行。
    这就是为什么ffmpeg,xvid等SDK源码中处处可见汇编的缘故。
    像xImage类库也能实现简单的处理,例如
    CxImage a;
    a.Load(...);
    a.Scale(...);
    但是看了源码就知道,其实性能很差的,缩放处理也不平滑。
      

  7.   

    这种说法也有问题,简单的比例缩放当然不行,不会出现平滑效果
    从1024*768缩放到200×200,明显可以看到图像变形了,
    真正的缩放,是需要通过alpha通道,应用相应的图形算法计算像素才行。
      

  8.   

    我是楼主
    Email:[email protected]
    谢谢各位