|
samadhi
Гость
|
 |
« : 16-09-2003 17:14 » |
|
Непонимаю, что делаю не так. Есть массив unsigned char*, там находится картинка (монохромная), и нужно вывести её на контекст устройства. Вот код, который пробовал я: void CBitmapView::DrawGlyph( int x, int y, int w, int h, // координаты и размеры картинки на экране int W, int H, // реальные размеры const Byte *bitmap, CDC *pDC // сама картинка и контекст устройства ) {
if ( !pDC ) return;
CRect rect( x, y, x + w - 1, y + h - 1 ); if ( !pDC->RectVisible( rect ) ) return;
/* Способ № 1 */ UINT nColorsBits = 8; UINT nColors = 1 << nColorsBits;
HPALETTE hPal = CreateGlyphPalette( nColors );
HPALETTE hOldPal = SelectPalette(pDC->GetSafeHdc(), hPal, TRUE); UINT N = pDC->RealizePalette (); BITMAPINFO *bm = ( BITMAPINFO * )LocalAlloc( LMEM_FIXED, sizeof(BITMAPINFO) + sizeof(WORD) * nColors );
bm->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bm->bmiHeader.biPlanes = 1; bm->bmiHeader.biBitCount = nColorsBits; bm->bmiHeader.biCompression = BI_RGB; bm->bmiHeader.biClrUsed = nColors; bm->bmiHeader.biClrImportant = 0;
bm->bmiHeader.biWidth = W; bm->bmiHeader.biHeight = -H; // картинка прямостояшая bm->bmiHeader.biSizeImage = (DWORD) W * H; bm->bmiHeader.biXPelsPerMeter = (300 * 10000) / 254; bm->bmiHeader.biYPelsPerMeter = (300 * 10000) / 254;
LPWORD pCol = reinterpret_cast<LPWORD>(bm->bmiColors); for (WORD i = 0; i < nColors; i++ ) pCol[i] = i; int n = StretchDIBits(pDC->GetSafeHdc(), x, y, w, h, 0, 0, W, H, (const void*)( bitmap ), bm, DIB_PAL_COLORS, SRCCOPY );
/* ...ну или вот так */
int n = SetDIBitsToDevice( pDC->GetSafeHdc(), x, y, w, h, 0, 0, 0, H, (const void*)( bitmap ), bm, DIB_PAL_COLORS );
/* Способ № 2 */
HBITMAP m_hBitmap = CreateCompatibleBitmap( pDC->GetSafeHdc(), W, H ); int image_size = W*H; ULONG* bitmap_buf = new ULONG [image_size]; for(int i = 0;i<image_size; i++) bitmap_buf[i] = RGB(bitmap[i],bitmap[i],bitmap[i]); LONG n = SetBitmapBits( m_hBitmap, W*H*sizeof ULONG, (VOID *)bitmap_buf );
delete bitmap_buf;
/* ... ну или вот так */ HBITMAP m_hBitmap = CreateBitmap( W, H, 1, nColors, (const void *)bitmap );
HDC hDCMem = CreateCompatibleDC (pDC->m_hDC);
HBITMAP hOldBitmap = (HBITMAP)SelectObject (hDCMem, m_hBitmap);
SetStretchBltMode( pDC->m_hDC, HALFTONE ); StretchBlt (pDC->m_hDC, x, y, w, h, hDCMem, 0, 0, W, H, SRCCOPY);
DeleteObject( (HBITMAP)SelectObject (pDC->m_hDC, hOldBitmap) );
DeleteDC (hDCMem);
SelectPalette( pDC->GetSafeHdc(), hOldPal, FALSE );
DeleteObject( (HPALETTE)hOldPal ); DeleteObject( (HPALETTE)hPal );
LocalFree( (HLOCAL) bm );
}
HPALETTE CBitmapView::CreateGlyphPalette( size_t numcol ) { COLORREF backcolor = RGB(255, 255, 255); COLORREF forecolor = RGB(0, 0, 0); size_t palsize = (sizeof(LOGPALETTE) * (numcol) );// - 1) * // sizeof(PALETTEENTRY)); LPLOGPALETTE pLogPal = reinterpret_cast<LPLOGPALETTE>(new BYTE[palsize]); pLogPal->palVersion = 0x300; pLogPal->palNumEntries = static_cast<WORD>(numcol); pLogPal->palPalEntry[0].peRed = GetRValue(backcolor); pLogPal->palPalEntry[0].peGreen = GetGValue(backcolor); pLogPal->palPalEntry[0].peBlue = GetBValue(backcolor); pLogPal->palPalEntry[0].peFlags = 0; pLogPal->palPalEntry[numcol-1].peRed = GetRValue(forecolor); pLogPal->palPalEntry[numcol-1].peGreen = GetGValue(forecolor); pLogPal->palPalEntry[numcol-1].peBlue = GetBValue(forecolor); pLogPal->palPalEntry[numcol-1].peFlags = 0; for (size_t i = 1; i < numcol - 1; ++ i) { double frac = pow(static_cast<double>(i) / (numcol - 1), 1 ); double r = GetRValue(backcolor); r -= frac * (GetRValue(backcolor) - GetRValue(forecolor)); double g = GetGValue(backcolor); g -= frac * (GetGValue(backcolor) - GetGValue(forecolor)); double b = GetBValue(backcolor); b -= frac * (GetBValue(backcolor) - GetBValue(forecolor));
pLogPal->palPalEntry[i].peRed = static_cast<BYTE>(r + 0.5); pLogPal->palPalEntry[i].peGreen = static_cast<BYTE>(g + 0.5); pLogPal->palPalEntry[i].peBlue = static_cast<BYTE>(b + 0.5); pLogPal->palPalEntry[i].peFlags = 0; }
HPALETTE ret = CreatePalette(pLogPal); delete pLogPal;
return ret;
}
А так же использовал IImgCtx, но результат все равно один и тот же - либо чёрная область (W*H), либо мусор какой-то тех же размеров. Картинку я создаю сам, а не считываю из файла
|
|
|
|
« Последнее редактирование: 19-11-2007 19:34 от Алексей1153++ »
|
Записан
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
 |
« Ответ #1 : 17-09-2003 08:57 » |
|
Уй, с первого взгляда не разберёшь. После заполнения ВМР структуры, попробуй сохранить битмап в файл и посмотреть в графическом редакторе. Так можно проверить то, что Гром сказал.
Если картинка нормальная тогда проблемма с выводом.
Вывод можешь проверить так: сделай ВМР ресурс и выведи его по твоему алгоритму.
Ну если совсем ничего, то кричи - поможем
|
|
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
 |
« Ответ #2 : 17-09-2003 09:01 » |
|
А кстати, под какой системой дело происходит 6.0 или 7.0? MFC+GDI?
|
|
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
|
|
|
|
Lex
|
 |
« Ответ #3 : 17-09-2003 09:04 » |
|
Судя по функциям MFC + GDI. Вот весрию MFC определить трудно  Кстати, на первый беглый взгляд вроде все правильно.
|
|
|
|
|
Записан
|
Megabyte be with you!
|
|
|
|
Lex
|
 |
« Ответ #4 : 17-09-2003 09:28 » |
|
Вопрос первый, как картинка записана в массиве? Побитово или байт на точку?
На сколько я помню, в конце каждой строки в битнапке идут pad байты, для выравнивания строк но границе 4 байт.
|
|
|
|
|
Записан
|
Megabyte be with you!
|
|
|
|
samadhi
Гость
|
 |
« Ответ #5 : 17-09-2003 09:48 » |
|
Простите, что забыл упомянуть систему. Lex прав, это MFC 6.0 + GDI. (Win2k на случай предложения GDI+) картинка - байт на точку, выглядит где-то так: 00100 01010 10001 11111 10001 если кто не разобрал это буква "А" Да, ещё, в файл она сохраняется, и все редакторы её понимают, а вот на экран вывести не могу
|
|
|
|
|
Записан
|
|
|
|
|
Lex
|
 |
« Ответ #6 : 17-09-2003 10:07 » |
|
samadhi, то, что ты привел, бит на точку. И в этом случае оба твои способа работать не будут.
|
|
|
|
|
Записан
|
Megabyte be with you!
|
|
|
|
samadhi
Гость
|
 |
« Ответ #7 : 17-09-2003 10:31 » |
|
Lex, н-н-е совсем, это всё-таки _байт_ на точку, по крайней мере она объявлена как unsigned char... в любом случае сформировать из него понятное Windows'у монохромное изображение, я думаю, возможно.
|
|
|
|
|
Записан
|
|
|
|
|
Lex
|
 |
« Ответ #8 : 17-09-2003 10:50 » |
|
samadhi, Нет ты в корне не прав, у тебя в картинке идет 1 бит на точку. Если бы был байт на точку, то вот это: 00000100 00001010 00010001 00011111 00010001 не было бы буквой "А", а было бы 8 точек с разными цветами или яркостями. ТО, что оно у тебя объявлена как unsigned char никоим образом не влияет на количество бит/байт на точку. Ты должен понять, что каждый байт твоей картинки определяет не одну, а 8 точек изображения. Соответствено в первом способе bm->bmiHeader.biClrUsed = nColors; // где nColors = 2 ну и bm->bmiHeader.biSizeImage = (DWORD) W * H / 8; во втором способее for(int i = 0;i<image_size; i++) bitmap_buf[i] = RGB(bitmap[i],bitmap[i],bitmap[i]);
должно быть похоже на что-нить такое for(int i = 0;i<image_size; i++) bitmap_buf[i] = RGB((bitmap[i / 8] << i%8) & 0x80, (bitmap[i / 8] << i%8) & 0x80, (bitmap[i / 8] << i%8) & 0x80);
|
|
|
|
« Последнее редактирование: 19-11-2007 19:36 от Алексей1153++ »
|
Записан
|
Megabyte be with you!
|
|
|
|
samadhi
Гость
|
 |
« Ответ #9 : 17-09-2003 12:06 » |
|
Lex, скорее всего я что-то не понимаю, всё-таки младенец ещё  . Объявление массива происходит так: typedef unsigned char Byte
Byte *bitmap = new Byte[w*h]; // w, h - рамеры будущей картинки
т.е. как я понимаю на каждый пиксел выделяется 1 байт (256 состояний), сохранить в файл мне удается как 256-цветную картинку. Я может не удачный пример привел, прошу пардона. Я всё равно попробовал твой код - выстраивает в вертикальную цепочку картинку.
|
|
|
|
« Последнее редактирование: 19-11-2007 19:37 от Алексей1153++ »
|
Записан
|
|
|
|
|
Lex
|
 |
« Ответ #10 : 17-09-2003 12:13 » |
|
Объявлять картинку можешь как хочешь, лишь бы памяти хватило  Сколько у нее бит на пиксел приходиться 1 или 8 зависит от того, как ты ее формируешь. Чтобы окончательно разобраться приведи код, который генерит картинку
|
|
|
|
|
Записан
|
Megabyte be with you!
|
|
|
|
samadhi
Гость
|
 |
« Ответ #11 : 17-09-2003 12:46 » |
|
Если поможет... там довольно сложно... читаю из файла, а далее: void PkRasterdata::construct_bitmap() { bitmap_ = new Byte[w_ * h_];
// rasterinfo is a pure bitmap - no decoding necessary unsigned int nbits_req = w_*h_;
Byte *p = bitmap_;
const Byte *r = rasterdata_; // rasterdata_ - прочтённое из файлика
Byte b;
while (nbits_req >= 8) { for (int i=7, bb=*r; i>=0; i--, bb>>=1) p[i] = static_cast<Byte>(bb&1);
p += 8;
r++;
nbits_req -= 8; } if (nbits_req > 0) { // get the last few bits b = static_cast<Byte>(*r >> (8-nbits_req));
for (int i=nbits_req-1; i>=0; i--, b>>=1) p[i] = static_cast<Byte>(b&1); } }
Я еще пробовал выводить в текстовый файл, когда не умел писать bmp: void CTxtBitmap::Write( CString filename, int nWidth, int nHeight, const Byte *bitmap) { CStdioFile file; try { if (!file.Open( filename, CFile::modeCreate | CFile::modeWrite | CFile::typeText )) return; } catch(CException * pE) { pE->Delete(); return; } for ( int i = 0; i < nHeight; i++ ) { CString str; const Byte *p = &bitmap[ i * nWidth ]; for ( int j = 0; j < nWidth; j++ ) {
if ( *(p + j) ) str += "0"; else str += "1";
}
str += "\n"; try { file.WriteString( str ); } catch(CException * pE) { //file.Close(); pE->Delete(); return; }
} file.Close(); }
Э-э-х, трудна и неказиста жизнь простого программиста
|
|
|
|
« Последнее редактирование: 19-11-2007 19:41 от Алексей1153++ »
|
Записан
|
|
|
|
|
Lex
|
 |
« Ответ #12 : 17-09-2003 13:21 » |
|
А файл какой читаешь? Как там данные распологаются? Проблема может быть в том, что ширина твоей картинки не кратна 8 и тогда вполе нвероятно, что присутствуют несколько лишних бит в конце каждой строки, дабы строки были выровнены по границе байта.
|
|
|
|
|
Записан
|
Megabyte be with you!
|
|
|
|
samadhi
Гость
|
 |
« Ответ #13 : 17-09-2003 14:09 » |
|
это PK-файл - шрифт для TeX/LaTeX. Я могу привести код сохранения в файл. Он выдаёт нужный результат. Bitmap::Bitmap(int nWidth, int nHeight) : m_nWidth(nWidth), m_nHeight(nHeight) {
WORD cClrBits = (WORD)8; max_colour_ = static_cast<BYTE>((1<<cClrBits) - 1); m_lpDIB = (Byte *) GlobalAlloc(GMEM_FIXED, m_nWidth * m_nHeight ); memset(m_lpDIB, max_colour_, m_nWidth * m_nHeight );
m_lpBmpInfoHdr = (LPBITMAPINFOHEADER) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) );
memset (m_lpBmpInfoHdr, 0, sizeof(BITMAPINFOHEADER)); m_lpBmpInfoHdr->biSize = sizeof(BITMAPINFOHEADER); m_lpBmpInfoHdr->biWidth = m_nWidth; m_lpBmpInfoHdr->biHeight = m_nHeight; m_lpBmpInfoHdr->biPlanes = (DWORD)1; m_lpBmpInfoHdr->biBitCount = cClrBits; m_lpBmpInfoHdr->biCompression = BI_RGB; m_lpBmpInfoHdr->biSizeImage = m_nWidth * m_nHeight; m_lpBmpInfoHdr->biClrUsed = (1 << cClrBits);
lpRGB = new RGBQUAD[256];
for(int j = 0; j < 256; j++) { lpRGB[j].rgbRed = j; lpRGB[j].rgbGreen = j; lpRGB[j].rgbBlue = j; lpRGB[j].rgbReserved = 0; }
}
BOOL Bitmap::write( CString strFileName ) { HANDLE hf; BITMAPFILEHEADER hdr; DWORD dwTmp;
// Create the .BMP file. hf = CreateFile((LPTSTR)(LPCTSTR)(strFileName), GENERIC_WRITE, (DWORD) 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); if (hf == INVALID_HANDLE_VALUE) { AfxMessageBox("write - INVALID_HANDLE_VALUE");
return FALSE; }
memset (&hdr, 0, sizeof(hdr)); hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 1024; hdr.bfSize = hdr.bfOffBits + sizeof(BYTE) * m_nWidth * m_nHeight + m_nHeight * ((3*m_nWidth) % 4);
// Copy the BITMAPFILEHEADER into the .BMP file. WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL);
// Copy the BITMAPINFOHEADER and RGBQUAD array into the file. WriteFile(hf, (LPVOID) m_lpBmpInfoHdr, sizeof(BITMAPINFOHEADER), (LPDWORD) &dwTmp, ( NULL));
WriteFile( hf, (LPVOID)lpRGB, /*lpBitmapHeader->biClrUsed*/256 * sizeof (RGBQUAD), (LPDWORD)&dwTmp, NULL );
for ( int i = m_nHeight - 1; i >= 0 ; i-- ) {
WriteFile( hf, m_lpDIB+(i*m_nWidth), m_nWidth, &dwTmp, NULL );
WriteFile (hf, lpRGB, (3 * m_nWidth) % 4, &dwTmp, NULL); // забиваем мусором }
CloseHandle(hf);
return TRUE;
}
|
|
|
|
« Последнее редактирование: 19-11-2007 19:43 от Алексей1153++ »
|
Записан
|
|
|
|
|
Lex
|
 |
« Ответ #14 : 17-09-2003 17:21 » |
|
Ничего не понимаю. Скинь мне свою прогу на lex@hotmail.ruГде-то у тебя идет путаница с форматами представления твоей картинки
|
|
|
|
|
Записан
|
Megabyte be with you!
|
|
|
|
samadhi
Гость
|
 |
« Ответ #15 : 18-09-2003 12:22 » |
|
Lex, это будет тяжеловато сделать, поскольку прога разбитта на библиотечку и саму прогу, кроме того нужно перекачивать шрифты и файлик с dvi - документ. Я попробовал предложенный Джоном вариант, запихнул в ресурс бмп-шку и вывел её - вывод работает, правда, через создание hMemDC (второй способ), что медленнее работает; первый - выдал фантан пикселей  . Попытаюсь поиграться с ним.
|
|
|
|
|
Записан
|
|
|
|
|
samadhi
Гость
|
 |
« Ответ #16 : 18-09-2003 13:53 » |
|
Эге-ге-е-й, мужики, уменя ПОЛУЧИЛОСЬ  . Lex, ты АБСОЛЮТНО прав. Я залез в класс, который сохраняет картинку на диск, биты там объявлены как BYTE в MSDN'е читаю : BYTE - An 8-bit integer that is not signed, а я в перерисовке использовал unsigned char. ПАСИБА!!!
|
|
|
|
|
Записан
|
|
|
|
|
Lex
|
 |
« Ответ #17 : 18-09-2003 14:07 » |
|
Пажалуйста, обращайся еще
|
|
|
|
|
Записан
|
Megabyte be with you!
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
 |
« Ответ #18 : 18-09-2003 14:48 » |
|
samadhi, рад за тебя, только я теперь нифига не понял - разве BYTE это не то-же самое, что "unsigned char"?
typedef byte BYTE; typedef unsigned char byte;
|
|
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
|
|
|
|
samadhi
Гость
|
 |
« Ответ #19 : 18-09-2003 15:47 » |
|
Джон, вообще-то, да char - 8-битный целочисленный тип. У меня, почему-то только так получилось. Н-н-е, понимаю :?.
|
|
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
 |
« Ответ #20 : 19-09-2003 07:56 » |
|
Вот и я не понял... "Да есть, друг Горацио, на свете вещи, которые не снились вашим мудрецам"
|
|
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
|
|
|
|
Lex
|
 |
« Ответ #21 : 19-09-2003 08:47 » |
|
samadhi, ты скорее всего где о потерял unsigned и использовал просто char, который знаковый. BYTE в заголовках объявляется как typedef unsigned char BYTE
|
|
|
|
|
Записан
|
Megabyte be with you!
|
|
|
|
samadhi
Гость
|
 |
« Ответ #22 : 19-09-2003 11:48 » |
|
нет, что вы, Бил Гейтс с вами, как такое можно забыть, тогда у меня бы вся длл-ка материлась.
В том классе, где пользую BYTE, я копирую картинку, где-то так:
Берём каждый unsigned char и if (*p) *P=*p;
и всё
|
|
|
|
|
Записан
|
|
|
|
|
Lex
|
 |
« Ответ #23 : 19-09-2003 12:00 » |
|
А поподробнее с объявлением преременных. и как у вас вначале это было
|
|
|
|
|
Записан
|
Megabyte be with you!
|
|
|
|