Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Из CView в *jpg, Как сохранить графики? 
:(
    Опции темы
Adry
Дата 19.8.2011, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Здравствуйте, уважаемые эксперты!

У меня есть небольшое приложение MFC, которое должно рисовать графики. И оно как ни удивительно даже это делает..smile Но нужно их еще и сохранить. Хоть в jpg, хоть в bmp хоть в чем-нибудь! 
Рисую функцией OnDrow в СView. В шаблонном фрейме кнопка "Save" присутствует и в меню, и в ТулБаре, но сохраняют они пустой файл.

Подскажите, как это делается?
PM MAIL   Вверх
Earnest
Дата 19.8.2011, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Было бы странно, если бы созданная мастером заготовка функции Save сохраняла что-то разумное.
Если тебе нужна растровая картинка, то это не сложно. Нужно создать совместимый контекст и совместимый битмап, выбрать битмап в контекст и вызывать OnDraw с этим контекстом. НО: нужно подумать о координатах. Если у тебя режим MM_TEXT, то ты получишь картинку в разрешении экрана. Если тебя это устраивает - то больше ничего и не надо. Ну и затем записать картинку (битмап) в файл, разумеется.
Можно сразу рисовать твои графики во внеэкранный буфер (тот самый битмап, заранее созданный), а не на экран. А на экран просто копировать. Тогда для сохранения все будет готово, не надо будет еще раз рисовать. Заодно проблемы с мерцанием решишь, если они тебя волнуют...  


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


Новичок



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

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



Цитата(Earnest @ 19.8.2011,  15:40)
Можно сразу рисовать твои графики во внеэкранный буфер (тот самый битмап, заранее созданный), а не на экран. 




А можно подробнее, как это делается?
Просто я привыкла работать в Матлабе, там все сохранения рисунков отработаны даже для самых непроходимых идиотов...smile А с рисованием в VS сталкиваюсь впервые.
В примере, их которого я поднатаскала идей для своей программы, есть функция печати. Но там чуть ли не все, что было нарисовано в OnDraw, в функции Print перерисовывается заново



В общем, мое сумбурное словоизлияние можно свести к тому, что я плохо представляю, как работать с изображениями. Может быть, подкините ссылочку?

Это сообщение отредактировал(а) Adry - 19.8.2011, 20:33
PM MAIL   Вверх
Earnest
Дата 22.8.2011, 09:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Тебе нужны функции CreateCompatibleDC и CreateCompatibleBitmap. Можешь поискать по форуму эти слова, рисование во внеэкранный буфер многократно обсуждалось и код приводился. Тема не сложная, но в двух словах не опишешь тем не менее. И лучше бы почитать сначала любую ликбез-литературу по WinAPI \ MFC


--------------------
...
PM   Вверх
Adry
Дата 23.8.2011, 09:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Спасибо за подсказку. Теперь ясно, в какую сторону копать.
И последний вопрос, не по теме, правда.

Что Вы посоветуете из "ликбез-литературы по WinAPI \ MFC"?
У меня есть Черносвитов "Учебный курс программирования на visual C++ 7", но там в первом же примере я нашла 3 или 4 ошибки, есть Мешков, Тихомиров "Visual C++ и MFC", но оно ближе к справочнику
PM MAIL   Вверх
Earnest
Дата 23.8.2011, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Мне сложно советовать базовые книги; я это дело изучала довольно давно, и с тех пор наверняка много чего понаписано.

Первую книгу не знаю; вторая когда-то понравилась. Однако Мешков-Тихомиров хорош для изучения именно оболочки MFC - как там окна, команды и т.д. взаимодействуют. Графика там описана, имхо, не очень. Что касается ошибок в примерах, так и бог с ними. Если в книге хорошо изложена суть, то ошибки в примерах не мешают. Я примеры обычно по диагонали просматриваю, чисто чтобы убедиться, что правильно понимаю...


--------------------
...
PM   Вверх
Adry
Дата 16.9.2011, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Здравствуйте снова.


Почему-то у меня сохраняется "Черный квадрат". Вот все пиксели в *.bmp-файле черные и все....:(((

Где проблема? Помогите, плиз!! 

Код

void CGraphicaView::SaveingGraph()
{
    HBITMAP hBitmap=NULL;
    HDC hDCMem=NULL;
    HDC hDC;
    BITMAP bmpScreen;
        
    
    RECT rcClient;
    GetClientRect(&rcClient);
    int iWidth=rcClient.right-rcClient.left;
    int iHeight=rcClient.bottom-rcClient.top;
    

    hDC= ::GetDC(NULL);
    
    hDCMem = ::CreateCompatibleDC (hDC);
    
    BitBlt (hDCMem,  0, 0, iWidth, iHeight, hDC, 0, 0, SRCCOPY);
    hBitmap = ::CreateCompatibleBitmap (hDCMem, iWidth, iHeight);
    hBitmap = (HBITMAP)SelectObject (hDCMem, hBitmap);

    
    // Get the BITMAP from the HBITMAP
    GetObject(hBitmap,sizeof(BITMAP),&bmpScreen);
     
    BITMAPFILEHEADER   bmfHeader;    
    BITMAPINFOHEADER   bi;
     
    bmpScreen.bmWidth=iWidth;
    bmpScreen.bmHeight=iHeight;
    bi.biSize = sizeof(BITMAPINFOHEADER);    
    bi.biWidth = bmpScreen.bmWidth;    
    bi.biHeight = bmpScreen.bmHeight;  
    bi.biPlanes = 1;    
    bi.biBitCount = 32;    
    bi.biCompression = BI_RGB;    
    bi.biSizeImage = 0;  
    bi.biXPelsPerMeter = 1000;    
    bi.biYPelsPerMeter = 1000;    
    bi.biClrUsed = 0;    
    bi.biClrImportant = 0;


    DWORD dwBmpSize = ((iWidth * bi.biBitCount + 31) / 32) * 4 * iHeight;

        // Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that 
    // call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc 
    // have greater overhead than HeapAlloc.
    HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize); 
    char *lpbitmap = (char *)GlobalLock(hDIB);    

    // Gets the "bits" from the bitmap and copies them into a buffer 
    // which is pointed to by lpbitmap.
    BOOL bSuccess=GetDIBits(hDC, hBitmap, 0,
        (UINT)bmpScreen.bmHeight,
        lpbitmap,
        (BITMAPINFO *)&bi, DIB_RGB_COLORS);

    // A file is created, this is where we will save the screen capture.
    CString bmpFileName=".bmp";
    bmpFileName=SpectTitle+bmpFileName;

    HANDLE hFile = CreateFile(bmpFileName,
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL, NULL);   
    
    // Add the size of the headers to the size of the bitmap to get the total file size
    DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
 
    //Offset to where the actual bitmap bits start.
    bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); 
    
    //Size of the file
    bmfHeader.bfSize = dwSizeofDIB; 
    
    //bfType must always be BM for Bitmaps
    bmfHeader.bfType = 0x4D42; //BM   
 
    DWORD dwBytesWritten = 0;
    WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
    
    //Unlock and Free the DIB from the heap
    GlobalUnlock(hDIB);    
    GlobalFree(hDIB);

    //Close the handle for the file that was created
    CloseHandle(hFile);
       
    //Clean up
done:
    DeleteObject(hBitmap);
    DeleteObject(hDCMem);
    //ReleaseDC(&hDC);

}


PM MAIL   Вверх
Earnest
Дата 16.9.2011, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



А вы ничего и не рисуете в этот битмап. Где код отрисовки собственно?
А если имеется в виду, что хотите скопировать с экрана, то последовательность действий неправильная

Код

 hDC= ::GetDC(NULL);   // берем dc экрана
    
    hDCMem = ::CreateCompatibleDC (hDC);  // создаем контекст в памяти
    
    BitBlt (hDCMem,  0, 0, iWidth, iHeight, hDC, 0, 0, SRCCOPY); // копируем! куда?
    hBitmap = ::CreateCompatibleBitmap (hDCMem, iWidth, iHeight); // создаем битмап
    hBitmap = (HBITMAP)SelectObject (hDCMem, hBitmap); // выбираем в контекст?


Кроме этого никакого рисования не нашла. И как ваши пикселы окажутся в битмапе, если вы его только создали и все?
Это примерно то же самое, что вылить воду в дачную раковину, и только потом подставить снизу ведро. Вы же не ждете, что при таком подходе вода окажется в ведре?
Здесь то же самое. Сначала нужно создать-выбрать битмап, а уже потом на нем рисовать.
Контекст в памяти всегда создается с битмапом по умолчанию - черно-белым и размеров в пиксел, если не ошибаюсь. Нет смысла там что-то рисовать, не выбрав нормальный битмап.

Дальше операции по вытаскиванию пикселов из битмапа не особо смотрела, много букв. Не уверена, что биты витмапа можно записывать в bmp сплошным куском - у bmp и у битмапа разное выравнивание строк, а в каком виде их возвращает GetDIBits - не знаю.

Я бы делала не так. А создала бы сразу независимый dib (CreateDibSection). Его хандл можно использовать так же как битмап (выбирать в контекст), но кроме прочего, он имеет еще 2 преимущества: 1) предоставляет прямой доступ к пикселам 2) имеет такое же выравнивание строк, как bmp-файл, ибо bmp-файл и есть DIB.


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


Новичок



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

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



Цитата(Earnest @  16.9.2011,  14:06 Найти цитируемый пост)
А вы ничего и не рисуете в этот битмап. Где код отрисовки собственно?

Рисую..smile
Отрисовка идет функцией OnDraw 

Потом 
hDC= ::GetDC(NULL);
пытаюсь скопировать изображение из активного окна. (Поверьте - оно там есть..smile )

Вроде бы последовательнсть действий
Код

GetDC()
CreateCompatibleDC()
CreateCompatibleBitmap()
SelectObject()

сомнений не вызывает. Во всяком случае, я именно такую последовательность вижу везде. (Кстати,  BitBlt с какой-то очередной вариации остался, он тут и не нужен по идее).

Воот... 

Наверное, Вы правы: надо попробовать сразу создавать DIB. А то оно как-то нелогично получается...


Это сообщение отредактировал(а) Adry - 16.9.2011, 15:17
PM MAIL   Вверх
Earnest
Дата 16.9.2011, 15:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Adry @  16.9.2011,  16:14 Найти цитируемый пост)
Рисую..
Отрисовка идет функцией OnDraw 

Я говорила не про рисование вообще, а рисование в созданный контекст\битмап.

Цитата(Adry @  16.9.2011,  16:14 Найти цитируемый пост)
(Кстати,  BitBlt с какой-то очередной вариации остался, он тут и не нужен по идее).

А никакого другого кода по переносу изображения с экрана в совместимый контекст я не вижу.

Есть еще вариант: воздать совместимый контекст\битмап (dib), но не копировать экран, а рисовать прямо в него вашей функцией OnDraw.



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


 




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


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

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