Поиск:

Ответ в темуСоздание новой темы Создание опроса
> CBitmap сериализация 
V
    Опции темы
Competitor
Дата 24.2.2009, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 440
Регистрация: 23.3.2005
Где: Tula

Репутация: нет
Всего: -1



Привет всем,
Хочу сериализовать CBitmap на диск, и потом загрузить обратно. Делаю так:
Код

void CSerialBitmap::Serialize(CArchive &ar)
{
    if(ar.IsStoring())
    {
        BITMAP hBmp;
        GetBitmap(&hBmp);

        WORD cClrBits = (WORD)(hBmp.bmPlanes * hBmp.bmBitsPixel); //Number of Bit use per Pixel
        DWORD bmpByte = ((hBmp.bmWidth * cClrBits +31) & ~31) /8 * hBmp.bmHeight; //Number of Byte

        ar << (long)hBmp.bmWidth
            << (long)hBmp.bmHeight
            << (long)hBmp.bmType
            << (long)hBmp.bmWidthBytes
            << (WORD)hBmp.bmPlanes
            << (WORD)hBmp.bmBitsPixel;

        ar << (DWORD)bmpByte;

        ar.Write(hBmp.bmBits , bmpByte );
    }
    else
    {
        static BITMAP hBmp;
        static CBitmap tempBmp;
        DWORD bmpByte;

        ar >> hBmp.bmWidth
            >> hBmp.bmHeight
            >> hBmp.bmType
            >> hBmp.bmWidthBytes
            >> hBmp.bmPlanes
            >> hBmp.bmBitsPixel ;

        ar >> bmpByte;
        hBmp.bmBits = new BYTE[bmpByte];
        ar.Read(hBmp.bmBits, bmpByte );

        HBITMAP hLoadedBmp = CreateBitmapFromPixel(NULL, hBmp.bmWidth, hBmp.bmHeight, hBmp.bmBitsPixel, hBmp.bmBits);

        if(this->DeleteObject())
            this->Detach();
        this->Attach(hLoadedBmp);

        delete[] hBmp.bmBits;
    }
}

HBITMAP CSerialBitmap::CreateBitmapFromPixel( HDC hDC, UINT uWidth, UINT uHeight, UINT uBitsPerPixel, LPVOID pBits )
{
    HBITMAP hBitmap = 0;
    if ( !uWidth || !uHeight || !uBitsPerPixel )
        return hBitmap;
    LONG lBmpSize = uWidth * uHeight * (uBitsPerPixel/8) ;       
    BITMAPINFO bmpInfo = { 0 };
    bmpInfo.bmiHeader.biBitCount = uBitsPerPixel;
    bmpInfo.bmiHeader.biHeight = (-1) * uHeight;
    bmpInfo.bmiHeader.biWidth = uWidth;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biCompression = BI_RGB;
    bmpInfo.bmiHeader.biClrUsed = 0;
    bmpInfo.bmiHeader.biClrImportant = 0;
    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfo.bmiHeader.biSizeImage = lBmpSize;
    // Pointer to access the pixels of bitmap       
    UINT * pPixels = 0;
    hBitmap = CreateDIBSection( hDC, &bmpInfo, DIB_RGB_COLORS, (void **)&pPixels , NULL, 0);

    if ( !hBitmap )
        return hBitmap; // return if invalid bitmaps
    ::SetBitmapBits( hBitmap, lBmpSize, pBits);
    /* Or Directly Write
    memcpy(ptPixels, pBitmapBitmapBits, lBmpSize );
    */
    return hBitmap;
}


Объект сериализуется на диск, потом загружается, но отрисовывается черно-белым и перевернутым. Пробовал брать высоту с минусом, все-равно перевернутый. Главное не понятно, почему черно-белым получается.
Подскажите плиз, в чем ошибка?
PM MAIL WWW   Вверх
Earnest
Дата 24.2.2009, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



1) А дебагер тебе зачем? Сравни данные ДО и ПОСЛЕ.
2) Зачем велосипед изобратать? Есть формат bmp, вот и читай про него (BITMAPINFOHEADER и т.д.). Там, кстати, еще таблица цветов есть, тоже читать\писать надо.


--------------------
...
PM   Вверх
Competitor
Дата 24.2.2009, 17:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 440
Регистрация: 23.3.2005
Где: Tula

Репутация: нет
Всего: -1



Цитата(Earnest @  24.2.2009,  16:46 Найти цитируемый пост)
1) А дебагер тебе зачем? Сравни данные ДО и ПОСЛЕ.

Все поля структуры BITMAP до и после одинаковы.
Цитата(Earnest @  24.2.2009,  16:46 Найти цитируемый пост)
2) Зачем велосипед изобратать? Есть формат bmp, вот и читай про него (BITMAPINFOHEADER и т.д.). Там, кстати, еще таблица цветов есть, тоже читать\писать надо. 

есть задача хранить картинки в зашифрованном виде, потому то и нужно хранить бмпшку так, чтобы ниоткуда больше она не могла быть прочитана. Если бы можно было получать массив байт из CBitmap, а потом создавать CBitmap из массива байт, это было бы идеальным решением, но похоже это не так просто, и приходится сначала сохранять все поля структуры BITMAP в файл, а потом считывать, но даже в этом случае возникают проблемы.
Цитата(Earnest @  24.2.2009,  16:46 Найти цитируемый пост)
Там, кстати, еще таблица цветов есть, тоже читать\писать надо. 

из объекта CBitmap я могу получить структуру BITMAP, все поля котороя и сохраняю, а как получить таблицу цветов?
PM MAIL WWW   Вверх
Earnest
Дата 24.2.2009, 18:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Если у тебя DDB-битмап (device-dependent), то таблицу цветов нужно брать из контекста. Это если файл картинка палитровая.
Действительно, какие-то тонкости с битмапом есть, но из твоего кода сложно понять, какаой цветности картинка, да и вообще где ты память выделяешь для GetBitmap...
Вообще, имеет смысл использовать dibSection - т.е. device-indipendent dib. ДЛя того и придуман, чтобы не паритmcz с цветами.
В коде твоем ковыряться подробно не могу; вот посмотри рабочий код, который читает-пишет bmp. Делает это он в стандартном формате, но это не важно. Там есть и создание GDI-объекта. Компилироваться он, конечно, не будет, т.к. выдран из библиотеки, но суть, я думаю, будет понятна.


Присоединённый файл ( Кол-во скачиваний: 9 )
Присоединённый файл  Bmp.rar 3,50 Kb


--------------------
...
PM   Вверх
Competitor
Дата 25.2.2009, 12:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 440
Регистрация: 23.3.2005
Где: Tula

Репутация: нет
Всего: -1



Earnest, благодарю за код  smile 
получилось так:
Код

IMPLEMENT_SERIAL(CSerialBitmap, CBitmap, 1);

void CSerialBitmap::Serialize(CArchive &ar)
{
    if(ar.IsStoring())
    {
        SavePicture(ar);
    }
    else
    {
        LoadPicture(ar);
    }
}

void CSerialBitmap::SavePicture(CArchive &ar)
{
    BITMAP hBmp;
    GetBitmap(&hBmp);
    SaveBITMAPStructure(ar, hBmp);

    BITMAPINFO *pbmi;
    BITMAPFILEHEADER bmfh;
    HDC hDC = NULL;
    DWORD wHeaderSize;
    void * pBits;
    wHeaderSize = sizeof(BITMAPINFOHEADER);
    pbmi = (PBITMAPINFO) new char[wHeaderSize];
    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    pbmi->bmiHeader.biPlanes = hBmp.bmPlanes;
    pbmi->bmiHeader.biBitCount = hBmp.bmBitsPixel;
    pbmi->bmiHeader.biHeight = hBmp.bmHeight;
    pbmi->bmiHeader.biWidth = hBmp.bmWidth;
    pbmi->bmiHeader.biCompression = BI_RGB;
    pbmi->bmiHeader.biClrUsed = 0;
    pbmi->bmiHeader.biClrImportant = 0;
    pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biBitCount +31) & ~31)/8 * pbmi->bmiHeader.biHeight;
    hDC = ::CreateCompatibleDC(NULL);
    if(!hDC)
    {
        CSerialBitmapException *e = new CSerialBitmapException(_T("CreateCompatibleDC() returned NULL"));
        throw(e);
    }
    pBits = new char[pbmi->bmiHeader.biSizeImage];
    HBITMAP hBitmap = (HBITMAP)(this->GetSafeHandle());
    if(!hBitmap)
    {
        CSerialBitmapException *e = new CSerialBitmapException(_T("GetSafeHandle() returned NULL"));
        throw(e);
    }
    if(!::GetDIBits(hDC, hBitmap, 0, (WORD)pbmi->bmiHeader.biHeight, pBits, pbmi, DIB_RGB_COLORS))
    {
        CSerialBitmapException *e = new CSerialBitmapException(_T("::GetDIBits failure"));
        throw(e);
    }
    bmfh.bfType = 0x4d42;
    bmfh.bfReserved1 = 0;
    bmfh.bfReserved2 = 0;
    bmfh.bfSize = sizeof(BITMAPFILEHEADER) + wHeaderSize + pbmi->bmiHeader.biSizeImage;
    bmfh.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbmi->bmiHeader.biSize + pbmi->bmiHeader.biClrUsed * sizeof (RGBQUAD);
    ar.Write(&bmfh, sizeof(BITMAPFILEHEADER));
    ar.Write(pbmi, wHeaderSize);
    ar.Write(pBits, pbmi->bmiHeader.biSizeImage);
    delete[] pBits;
    delete[] pbmi;
}

void CSerialBitmap::SaveBITMAPStructure(CArchive &ar, BITMAP hBmp)
{
    ar << (long)hBmp.bmWidth
        << (long)hBmp.bmHeight
        << (long)hBmp.bmType
        << (long)hBmp.bmWidthBytes
        << (WORD)hBmp.bmPlanes
        << (WORD)hBmp.bmBitsPixel;
}

void CSerialBitmap::LoadPicture(CArchive &ar)
{
    static BITMAP hBmp;
    LoadBITMAPStructure(ar, hBmp);

    BITMAPINFO *pbmi;
    BITMAPFILEHEADER bmfh;
    DWORD wHeaderSize;
    void * pBits;
    wHeaderSize = sizeof(BITMAPINFOHEADER);
    pbmi = (PBITMAPINFO) new char[wHeaderSize];

    ar.Read(&bmfh, sizeof(BITMAPFILEHEADER));
    ar.Read(pbmi, wHeaderSize);
    pBits = new char[pbmi->bmiHeader.biSizeImage];
    ar.Read(pBits, pbmi->bmiHeader.biSizeImage);

    m_hLoadedBmp = ::CreateDIBitmap(CWindowDC(CWnd::GetDesktopWindow()), &pbmi->bmiHeader, CBM_INIT, pBits, pbmi, DIB_RGB_COLORS);

    if(this->DeleteObject())
        this->Detach();
    this->Attach(m_hLoadedBmp);

    delete[] pBits;
    delete[] pbmi;
}

void CSerialBitmap::LoadBITMAPStructure(CArchive &ar, BITMAP& hBmp)
{
    ar >> hBmp.bmWidth
        >> hBmp.bmHeight
        >> hBmp.bmType
        >> hBmp.bmWidthBytes
        >> hBmp.bmPlanes
        >> hBmp.bmBitsPixel ;
}

PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0449 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.