如何由已有的真彩色图象数据生成新的图象文件并显示它?

解决方案 »

  1.   

    BOOL SaveFile(HDC hdc,HBITMAP hBitmap ,CString strFileName);
    BOOL SaveFile(HDC hdc, HBITMAP hBitmap, CString strFileName)
    {
    HDC  hDC;  
        int iBits; 
    WORD wBitCount;    
    DWORD dwPaletteSize=0;
    DWORD dwBmBitsSize, dwDIBSize, dwWritten;
    BITMAP Bitmap; 
    BITMAPFILEHEADER bmfHdr; 
    BITMAPINFOHEADER  bi; 
    LPBITMAPINFOHEADER lpbi;
    HANDLE hFile, hDib, hPal,hOldPal=NULL;  
    try
    {
    int ilength = strFileName.Find(":\\");
    ilength = strFileName.Find("\\",ilength+2);
    while(ilength !=-1)
    {
    CString strDirectory =strFileName.Left(ilength);
    CFileFind  FileFind;
    if(!FileFind.FindFile(strDirectory,0))
    if(!CreateDirectory(strDirectory,NULL))
    {
    ::MessageBeep(MB_ICONHAND);
    // MessageBox("フォルダクリエートに失敗しました。", "情報", MB_OK + MB_APPLMODAL + MB_ICONEXCLAMATION);
    }
    else
    return FALSE;
    ilength = strFileName.Find("\\",ilength+1);
    }
    hDC = CreateDC("DISPLAY",NULL,NULL,NULL);
    iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
    DeleteDC(hDC);
    if (iBits <= 1)
    wBitCount = 1;
    else if (iBits <=  4)
    wBitCount = 4;
    else if (iBits <=  8)
    wBitCount = 8;
    else if (iBits <=  24)
    wBitCount = 24;
    else if (iBits <=  32)
    wBitCount = 32;
    if (wBitCount <=   8)
    dwPaletteSize = (1 <<  wBitCount) * sizeof(RGBQUAD);
    GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
    bi.biSize            = sizeof(BITMAPINFOHEADER);
    bi.biWidth           = Bitmap.bmWidth;
    bi.biHeight          = Bitmap.bmHeight;
    bi.biPlanes          = 1;
    bi.biBitCount         = wBitCount;
    bi.biCompression      = BI_RGB;
    bi.biSizeImage        = 0;
    bi.biXPelsPerMeter     = 0;
    bi.biYPelsPerMeter     = 0;
    bi.biClrUsed         = 0;
    bi.biClrImportant      = 0;
    dwBmBitsSize = ((Bitmap.bmWidth *wBitCount+31)/32)* 4*Bitmap.bmHeight ;
    hDib  = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
    *lpbi = bi;
    hPal = GetStockObject(DEFAULT_PALETTE);
    // CClientDC dc(this);

    GetDIBits(hdc, hBitmap, 0, (UINT) Bitmap.bmHeight,(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
    +dwPaletteSize,(BITMAPINFO *)lpbi, DIB_RGB_COLORS);

    hFile = CreateFile(strFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL 
    | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    return FALSE;

    bmfHdr.bfType = 0x4D42;  
    dwDIBSize    = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+ dwPaletteSize 
    + dwBmBitsSize;  
    bmfHdr.bfSize = dwDIBSize;
    bmfHdr.bfReserved1 = 0;
    bmfHdr.bfReserved2 = 0;
    bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)
    +dwPaletteSize;
    WriteFile(hFile, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
    WriteFile(hFile, (LPSTR)lpbi, dwDIBSize,&dwWritten, NULL);
    GlobalUnlock(hDib);
    GlobalFree(hDib);
    CloseHandle(hFile);
    }
    catch(...)
    {
    return FALSE;
    }
    return TRUE;
    }
    void main{
       HBITMAP hBitmap
    CClientDC dc(this);
    hBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),FileName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_DEFAULTSIZE); if(hBitmap==NULL)
    {
    ::MessageBeep(MB_ICONHAND);
    MessageBox("画像が見つかりません。", "情報", MB_OK + MB_ICONSTOP + MB_SYSTEMMODAL);
    return -1;
    }
    if(SaveFile(dc,hBitmap,FileName))
    {
    return 0;
    }
    }
      

  2.   

    int SaveBitmapToFile(CBitmap *bitmap,LPSTR lpFileName) //hBitmap 为刚才的屏幕位图句柄 lpFileName 为位图文件名
    {      
            HBITMAP hBitmap;
            HDC hDC; //设备描述表
        int iBits; //当前显示分辨率下每个像素所占字节数
    WORD            wBitCount; //位图中每个像素所占字节数
       DWORD           dwPaletteSize=0, //定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数
         dwBmBitsSize,
    dwDIBSize, dwWritten;
    BITMAP          Bitmap; //位图属性结构
    BITMAPFILEHEADER   bmfHdr; //位图文件头结构
        BITMAPINFOHEADER   bi; //位图信息头结构 
    LPBITMAPINFOHEADER lpbi; //指向位图信息头结构
        HANDLE          fh, hDib, hPal,hOldPal=NULL; //定义文件,分配内存句柄,调色板句柄
      
    //计算位图文件每个像素所占字节数
    hBitmap = (HBITMAP)*bitmap;
             hDC = CreateDC("DISPLAY",NULL,NULL,NULL);
    iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
    DeleteDC(hDC); if (iBits <= 1)
    wBitCount = 1;
    else if (iBits <= 4)
    wBitCount = 4;
    else if (iBits <= 8)
    wBitCount = 8;
    else if (iBits <= 24)
    wBitCount = 24;

    //计算调色板大小
    if (wBitCount <= 8)
          dwPaletteSize = (1 <<  wBitCount) * sizeof(RGBQUAD);
       
    //设置位图信息头结构
    GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
    bi.biSize            = sizeof(BITMAPINFOHEADER);
    bi.biWidth           = Bitmap.bmWidth;
    bi.biHeight          = Bitmap.bmHeight;
    bi.biPlanes          = 1;
    bi.biBitCount         = wBitCount;
    bi.biCompression      = BI_RGB;
    bi.biSizeImage        = 0;
    bi.biXPelsPerMeter     = 0;
    bi.biYPelsPerMeter     = 0;
    bi.biClrUsed         = 0;
    bi.biClrImportant      = 0; dwBmBitsSize = ((Bitmap.bmWidth * wBitCount+31)/32) * 4 * Bitmap.bmHeight ;

    //为位图内容分配内存
    hDib  = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
    *lpbi = bi;
       
    // 处理调色板   
    hPal = GetStockObject(DEFAULT_PALETTE);
    if (hPal)
    {
    hDC  = ::GetDC(NULL);
    hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
    RealizePalette(hDC);
    }
       
    // 获取该调色板下新的像素值
    GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
     (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
          +dwPaletteSize,
     (LPBITMAPINFO )
          lpbi, DIB_RGB_COLORS);
       
    //恢复调色板   
    if (hOldPal)
    {
    SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
    RealizePalette(hDC);
    ::ReleaseDC(NULL, hDC);
    }
       
    //创建位图文件    
    fh = CreateFile(lpFileName, GENERIC_WRITE, 
    0, NULL, CREATE_ALWAYS,
    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
       
    if (fh == INVALID_HANDLE_VALUE)
          return FALSE;
       
    // 设置位图文件头
    bmfHdr.bfType = 0x4D42;  // "BM"
    dwDIBSize    = sizeof(BITMAPFILEHEADER) 
               + sizeof(BITMAPINFOHEADER)
            + dwPaletteSize + dwBmBitsSize;  
    bmfHdr.bfSize = dwDIBSize;
    bmfHdr.bfReserved1 = 0;
    bmfHdr.bfReserved2 = 0;
    bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) 
    + (DWORD)sizeof(BITMAPINFOHEADER)
    + dwPaletteSize;
       
    // 写入位图文件头
    WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
       
    // 写入位图文件其余内容
    WriteFile(fh, (LPSTR)lpbi, dwDIBSize, 
    &dwWritten, NULL);
       
    //清除   
    GlobalUnlock(hDib);
    GlobalFree(hDib);
    CloseHandle(fh);
    return TRUE;
    }
      

  3.   

    { // 位图文件头结构
    BITMAPFILEHEADER bmfHdr;
    // 指向BITMAPINFOHEADER结构的指针
    LPBITMAPINFOHEADER lpbmiHdr;
    // DIB大小
    DWORD dwDIBSize;

    // 如果DIB为空,返回FALSE
    if(m_hBmp==NULL) return FALSE; // 读取BITMAPINFO结构,并锁定
    lpbmiHdr=(LPBITMAPINFOHEADER)GlobalLock((HGLOBAL)m_hBmp);
    if(lpbmiHdr==NULL)
    {
    GlobalFree((HGLOBAL)m_hBmp);
    m_hBmp=NULL;
    return FALSE;
    } // 默认保存WIN32位图格式,以下保存代码
    // 填充位图文件头
    // 文件类型"BM"
    bmfHdr.bfType=BITMAP_FILE_MARKER;

    // 计算DIB大小最简单的方法是调用GlobalSize()函数。但是全局内存大小并不是
    // DIB真正的大小(总是多几个字节),因此需要计算DIB的真正大小。 // 文件头大小+颜色表大小
    dwDIBSize=lpbmiHdr->biSize+RasterImagePaletteSize(); // 计算图象大小
    if((lpbmiHdr->biCompression==BI_RLE8)||(lpbmiHdr->biCompression==BI_RLE4))
    {
    // 对于RLE压缩的位图,没法计算大小,只能信任biSizeImage的值
    dwDIBSize+=lpbmiHdr->biSizeImage;
    }
    else
    {
    // 图象象素大小
    DWORD dwBitsSize;
    // 大小Width*Height
    dwBitsSize=WIDTHBYTES((lpbmiHdr->biWidth)*(lpbmiHdr->biBitCount))*lpbmiHdr->biHeight;
    // 计算DIB真正的大小
    dwDIBSize+=dwBitsSize;
    // 更新biSizeImage(很多位图文件头中biSizeImage的值是错误的)
    lpbmiHdr->biSizeImage=dwBitsSize;
    }

    // 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小
    bmfHdr.bfSize=dwDIBSize+sizeof(BITMAPFILEHEADER); // 填充保留字
    bmfHdr.bfReserved1=0;
    bmfHdr.bfReserved2=0; // 计算偏移量bfOffBits,等于:位图文件头大小+位图信息头大小+颜色表大小
    // sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADR)+sizeof(PALETTE)
    bmfHdr.bfOffBits=(DWORD)(sizeof(BITMAPFILEHEADER)+lpbmiHdr->biSize+RasterImagePaletteSize()); // 尝试写文件
    TRY
    {
    // 写位图文件头
    pFile->Write(&bmfHdr,sizeof(BITMAPFILEHEADER));
    // 写DIB头(位图信息头+调色板)和象素
    pFile->WriteHuge(lpbmiHdr,dwDIBSize);
    }
    CATCH(CFileException,e)
    {
    // 解除锁定
    GlobalUnlock((HGLOBAL)m_hBmp);
    // 异常
    CString eMsg;
    eMsg.Format("保存文件出错,原因:%s",e->m_cause);
    AfxMessageBox(eMsg,MB_ICONERROR);
    e->Delete();
    }
    END_CATCH

    // 解除锁定
    GlobalUnlock((HGLOBAL)m_hBmp);

    // 返回TRUE
    return TRUE;
    }
      

  4.   

    BOOL CPcxImage::WriteImageFile(CFile *pFile)
    {
    // ASSERT(m_hBmp!=NULL);
    // 如果DIB为空,返回FALSE
    if(m_hBmp==NULL) return FALSE;
    // 1.生成PCXHEAD结构

    PCXHEAD pcxHdr;
    ZeroMemory(&pcxHdr, sizeof(PCXHEAD));

    // 指向BITMAPINFOHEADER结构的指针
    LPBITMAPINFOHEADER lpbmiHdr;

    // 读取DIB句柄BITMAPINFOHEADER内容
    lpbmiHdr=(LPBITMAPINFOHEADER)GlobalLock((HGLOBAL)m_hBmp);
    if(lpbmiHdr==NULL)
    {
    GlobalFree((HGLOBAL)m_hBmp);
    m_hBmp=NULL;
    return FALSE;
    }

    // 翻译为PCX头结构,以下转换代码
    // 填充PCX文件头
    // 文件类型"0x0a"
    pcxHdr.PcxFlag=(BYTE)PCXHEAD_MARKER;
    pcxHdr.Version=5;
    pcxHdr.Encoding=1;
    pcxHdr.XMin=pcxHdr.YMin=0;
    // 参考当前图象句柄
    pcxHdr.XMax=(WORD)(lpbmiHdr->biWidth-1);
    pcxHdr.YMax=(WORD)(-1*lpbmiHdr->biHeight-1);
    pcxHdr.HRes=(WORD)lpbmiHdr->biXPelsPerMeter;
    pcxHdr.VRes=(WORD)lpbmiHdr->biYPelsPerMeter;

    if(RasterImagePaletteSize()!=0)
    {
    // 有调色板情况下
    pcxHdr.BitPlane=1;
    pcxHdr.BitPerPixel=(BYTE)lpbmiHdr->biBitCount;
    }
    else
    {
    // 无调色板情况下
    if(RasterImageNumBits()==24)
    {
    pcxHdr.BitPlane=3;
    pcxHdr.BitPerPixel=8; 
    }
    else
    {
    AfxMessageBox("Unknow error!", MB_ICONERROR);
    return FALSE;
    }
    }
    // BytePerLine必须是四字节的整数倍?
    // 查看过了,不是。
    pcxHdr.BytePerLine=(WORD)lpbmiHdr->biWidth;
    pcxHdr.PaletteType=(RasterImageNumBits()!=1)? 2: 1;
    pFile->Write(&pcxHdr, sizeof(PCXHEAD));

    const LONG clScanLineSize = WIDTHBYTES((pcxHdr.BitPlane)*(pcxHdr.BytePerLine)*8);

    LPBYTE ppcxBits=(LPBYTE)lpbmiHdr+sizeof(BITMAPINFOHEADER)+RasterImagePaletteSize();

    // 写PCXHEAD结束
    //----------------------------------------
    // RLE压缩-------------> 已经包含8、24bit图象
    // 最坏情况下申请2倍的缓冲,相邻都不重复,并且都大于0xc0
    LPBYTE ppcxImg=new BYTE[2*pcxHdr.BitPlane*pcxHdr.BytePerLine]; // 存放临时扫描行
    UINT rec(0); // 计数器,写如PCX文件字节数
    for( int iY=0; iY<=pcxHdr.YMax; iY++ )
    {
    // ☆RLE编码,最大重复<=63☆
    ZeroMemory(ppcxImg,2*pcxHdr.BitPlane*pcxHdr.BytePerLine);
    rec=PackPCXLine(&pcxHdr, ppcxBits, ppcxImg);

    // DIB 扫描行递增
    ppcxBits+=clScanLineSize;

    pFile->Write(ppcxImg,rec);
    }
    delete []ppcxImg;

    // 写图象数据结束
    //----------------
    // 如果是256色,写调色板数据
    // 注意还原=>去除RGBQUAD结构中rgbReserved字段
    if(pcxHdr.BitPlane==1&&pcxHdr.BitPerPixel==8) // 256 色图象
    {
    // 256色8bit,1plane
    BYTE palFlg=0x0c;
    pFile->Write(&palFlg,1);
    // 调色板地址
    LPBYTE lpPal=(LPBYTE)lpbmiHdr+sizeof(BITMAPINFOHEADER);
    RGBQUAD *prgbQuad;
    for( UINT npal=0; npal<256; npal++)
    {
    prgbQuad=(RGBQUAD*)lpPal;

    pFile->Write(&(prgbQuad->rgbRed),1);
    pFile->Write(&(prgbQuad->rgbGreen),1);
    pFile->Write(&(prgbQuad->rgbBlue),1);

    lpPal+=sizeof(RGBQUAD);
    }
    }

    GlobalUnlock((HGLOBAL)m_hBmp);

    return TRUE;
    }
      

  5.   

    谢谢各位大侠!让我去试试,成功了一定给分!!
    情况是这样的:一幅真彩色图象,由于纵向上R,G,B通道存在错位,导致同一物体的图象的R,G,B分量没有重合在一起,现在想纠正这种纵向错位,由原始图象,根据错位的偏移量将三个通道分量的数据重组,由此生成一幅真实的图象。请问各位高手,怎样实现它呢?