Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Приглашаем принять участие в работе над нашей Wiki.
  • Наша рассылка: subscribe.ru, content.mail.ru и Google groups.
  • Есть желающие вести новостную ленту "В мире технологий"?
  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
   Начало   Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: (?)Вывод массива на Контекст Устройства  (Прочитано 10457 раз)
0 Пользователей и 1 Гость смотрят эту тему.
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++ » Записан
Джон
просто
Администратор

de
Offline 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
Джон
просто
Администратор

de
Offline 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
Специалист

ru
Offline Offline

WWW
« Ответ #3 : 17-09-2003 09:04 » 

Судя по функциям MFC + GDI. Вот весрию MFC определить трудно Улыбаюсь
Кстати, на первый беглый взгляд вроде все правильно.
Записан

Megabyte be with you!
Lex
Специалист

ru
Offline Offline

WWW
« Ответ #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
Специалист

ru
Offline Offline

WWW
« Ответ #6 : 17-09-2003 10:07 » 

samadhi, то, что ты привел, бит на точку. И в этом случае оба твои способа работать не будут.
Записан

Megabyte be with you!
samadhi
Гость
« Ответ #7 : 17-09-2003 10:31 » 

Lex, н-н-е совсем, это всё-таки _байт_ на точку, по крайней мере она объявлена как unsigned char... в любом случае сформировать из него понятное Windows'у монохромное изображение, я думаю, возможно.
Записан
Lex
Специалист

ru
Offline Offline

WWW
« Ответ #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
Специалист

ru
Offline Offline

WWW
« Ответ #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
Специалист

ru
Offline Offline

WWW
« Ответ #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
Специалист

ru
Offline Offline

WWW
« Ответ #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
Специалист

ru
Offline Offline

WWW
« Ответ #17 : 18-09-2003 14:07 » 

Пажалуйста, обращайся еще
Записан

Megabyte be with you!
Джон
просто
Администратор

de
Offline 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-битный целочисленный тип. У меня, почему-то только так получилось. Н-н-е, понимаю :?.
Записан
Джон
просто
Администратор

de
Offline 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
Специалист

ru
Offline Offline

WWW
« Ответ #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
Специалист

ru
Offline Offline

WWW
« Ответ #23 : 19-09-2003 12:00 » 

А поподробнее с объявлением преременных. и как у вас вначале это было
Записан

Megabyte be with you!
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.16 | SMF © 2011, Simple Machines