首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ Builder >

奇怪的有关问题探讨:BMP的读写和恢复有关问题

2013-04-20 
奇怪的问题探讨:BMP的读写和恢复问题如下是我要实现的问题: 1. 我想把一张BMP图片,保存为UnicodeString 2.

奇怪的问题探讨:BMP的读写和恢复问题
如下是我要实现的问题:
 1. 我想把一张BMP图片,保存为UnicodeString
 2. 然后在UnicodeString中恢复为BMP图片

得到妖哥指点:序列化。将位图的每一个字节用十六进制来表示,最后拼成一个字符串。还原的时候,从字符串每次取两个字符,转化成对应的byte。 

我是这样实现并测试的:


TBitmap *bmp = new TBitmap();
TImage *Img = new TImage(this);
TColor color;
int  GValue;
int  BValue;
int  RValue;
UnicodeString uStr = "";
bmp->LoadFromFile("d:\\test.bmp");
Img->Width =  bmp->Width;
Img->Height=  bmp->Height;
Img->Canvas->CopyRect(Rect(0,0,Img->Width,Img->Height) , bmp->Canvas,Rect(0,0,Img->Width,Img->Height));
for(int y = 0 ; y < Img->Height ; y++)
{
 for(int x = 0; x < Img->Width; x++)
 {
color = Img->Canvas->Pixels[y][x];
BValue =  GetBValue(color) ;
GValue =  GetGValue(color) ;
RValue =  GetRValue(color) ;
uStr  += IntToHex(RValue,2) ;
uStr  += IntToHex(GValue,2) ;
uStr  += IntToHex(BValue,2) ;
}
}

//-------恢复数据-------------------------------------------
UnicodeString hex_val="";
UnicodeString s1 = "0x";
UnicodeString s2 = "";

   TImage *fbmp = new TImage(this);
   fbmp->Width =  bmp->Width;
   fbmp->Height=  bmp->Height;
   fbmp->Canvas->Brush->Color = clBlack;
   fbmp->Canvas->Rectangle(0,0,fbmp->Width,fbmp->Height);


int index = 1 ;
for(int x = 0 ; x < fbmp->Height ; x++)
{
 for(int y = 0; y < fbmp->Width; y++)
 {
s2 = uStr.SubString(index,2);
hex_val = s1 +  s2;
RValue= hex_val.ToInt();
            index+=2;
s2 = uStr.SubString(index,2);
hex_val = s1 +  s2;
GValue= hex_val.ToInt();
index+=2;
s2 = uStr.SubString(index,2);
hex_val = s1 +  s2;
BValue= hex_val.ToInt();
index+=2;
fbmp->Canvas->Pixels[x][y]= RGB(RValue,  GValue, BValue);
 }
}
fbmp->Picture->Bitmap->SaveToFile("d:\\testback.bmp");


发现恢复的时候,有些图片恢复正常,有些图片会出现一半是黑色的。


[解决办法]
可能需要保存BMP图片格式:如颜色位数
[解决办法]
[/code]   
   TImage *fbmp = new TImage(this);
   fbmp->Width =  bmp->Width;
   fbmp->Height=  bmp->Height;
   fbmp->PixelFormat=pf24bit; //在创建一个位图之后,最好指定位图的颜色位数,如果你不指定,就是你当前显示器的颜色位数(一般是32位),但是你前面用到的test.bmp,是不是32位呢?一般都是24位的吧,so。。。
   fbmp->Canvas->Brush->Color = clBlack;
   fbmp->Canvas->Rectangle(0,0,fbmp->Width,fbmp->Height);
[/code]
------解决方案--------------------


直接对BMP文件进行处理,把BMP文件从头到尾转换一遍就行了
[解决办法]

#include <stdio.h>
#include <tchar.h>

BOOL __fastcall CrnBitmpaToString(Graphics::TBitmap *bmp, String &strText)
{
    BOOL bResult = FALSE;

    TMemoryStream *ms = new TMemoryStream();

    try
    {
        bmp->SaveToStream(ms);
        ms->Position = 0;

        TCHAR sz[3] = { 0x0 };
        for (int i = 0; i < ms->Size; i++)
        {
            _stprintf(sz, "%02X", ((LPBYTE)ms->Memory)[i]);
            strText += sz;
        }

        bResult = TRUE;        
    }
    __finally
    {
        delete ms;
    }

    return bResult;
}

BOOL __fastcall CrnStringToBitmap(String strText, Graphics::TBitmap *bmp)
{
    BOOL bResult = FALSE;

    TMemoryStream *ms = new TMemoryStream();

    try
    {
        int nSize = strText.Length() / 2;
        ms->SetSize(nSize);

        int p = 1;
        DWORD dw;
        TCHAR sz[3] = { 0x0 };
        for (int i = 0; i < nSize; i++)
        {
            sz[0] = strText[p++];
            sz[1] = strText[p++];
            dw = 0;
            _stscanf(sz, TEXT("%2X"), &dw);
            ((LPBYTE)ms->Memory)[i] = (BYTE)dw;
            
            if (p >= strText.Length()) break;
        }

        ms->Position = 0;
        bmp->LoadFromStream(ms);

        bResult = TRUE;
    }
    __finally
    {
        delete ms;
    }

    return bResult;


}

// ---------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    Graphics::TBitmap *bmp = new Graphics::TBitmap;
    bmp->LoadFromFile("D:\\ccrun\\123.bmp");

    String strText;
    CrnBitmpaToString(bmp, strText);

    TStringList *lst = new TStringList;
    lst->Text = strText;
    lst->SaveToFile("D:\\ccrun\\123.dat");
    delete lst;

    delete bmp;
}

// ---------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    Graphics::TBitmap *bmp = new Graphics::TBitmap;

    TStringList *lst = new TStringList;
    lst->LoadFromFile("D:\\ccrun\\123.dat");

    CrnStringToBitmap(lst->Text, bmp);

    delete lst;

    bmp->SaveToFile("D:\\ccrun\\234.bmp");

    delete bmp;
}

热点排行