· Начало · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.WIN32 —› Порт кода с Unix для работы с графикой

Посл.отвђт Сообщенiе


Дата: Июн 23, 2004 14:10:47
Правка

Доброе время суток!

есть код:
XVisualInfo *visualList;
	int nVisuals,depth;
	ulong rShift,gShift,bShift,rDiv,gDiv,bDiv;
	...
	visualList = XGetVisualInfo(display, VisualNoMask, &visualTempl,&nVisuals);
	if (visualList->c_class == TrueColor) {
		trueColor = gTrue;
		for (mask = visualList->red_mask, rShift = 0;
			mask && !(mask & 1);
			mask >>= 1, ++rShift);
		for (rDiv = 8; mask; mask >>= 1, --rDiv);
		for (mask = visualList->green_mask, gShift = 0;
			mask && !(mask & 1);
			mask >>= 1, ++gShift);
		for (gDiv = 8; mask; mask >>= 1, --gDiv);
		for (mask = visualList->blue_mask, bShift = 0;
			mask && !(mask & 1);
			mask >>= 1, ++bShift);
		for (bDiv = 8; mask; mask >>= 1, --bDiv);
		}



Как я понял, он получает информацию из графич. окружения и на основе её формирует
маски для цветов.


В дальшейшем они используются так:
XImage *image;

	p = dataPtr.rgb8 + (y + srcY) * bw + srcX; // получение указателя на масив цветов картинки
	for (x = 0; x < width; ++x) {
		rgb = *p++;
		r = splashRGB8R(rgb) >> rDiv;
		g = splashRGB8G(rgb) >> gDiv;
		b = splashRGB8B(rgb) >> bDiv;
		pixel = ((Gulong)r << rShift) +
				((Gulong)g << gShift) +
				((Gulong)b << bShift);
		XPutPixel(image, x, y, pixel);


Как сделать порт этого кода для Win32? Т.е., сам код я портировал, но не полностью понимаю, для чего используются xDiv?

И ещё: Вместо XPutPixel я сделал SetPixel(hMemDc,x,y,pixel),

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

Пинки приветствуются :)
Если что-то нужно пояснить подробнее, поясню.


Дата: Июн 23, 2004 15:22:35 · Поправил: Shift

можно посмотреть, как люди делают:
http://www.hal9k.com/cug/links/subject35.htm
ещё можно посёрчить в исходниках wine - как они делают.


Дата: Июн 23, 2004 23:55:12

IceStudent
В BITMAPINFOHEADER заполняем поля biSize, biWidth, biHeight, biPlanes=1 и biBitCount, функцией GreateDIBSection создаем картинку, а затем через указатель сохраненный в ppvBits рисуем в ней.


Дата: Июн 29, 2004 11:11:15
Правка

Black_mirror
Спасибо, так действительно быстрее…

Насчёт первого вопроса - просто xDiv ставлю в 0, а xShift — по 00BBGGRR. Вроде бы работает правильно. И можно вовсе убрать xDiv.


Дата: Июл 5, 2004 14:05:48
Правка

Black_mirror
Да, кстати, а создавать это надо на Memory context (hMemDC) или на текущем (GetDC)?


Дата: Июл 6, 2004 16:28:10

Из описания CreateDIBSection:

hdc
[in] Handle to a device context. If the value of iUsage is DIB_PAL_COLORS, the function uses this device context's logical palette to initialize the DIB's colors.

Так что думаю что для iUsage=DIB_RGB_COLORS пофиг.


Дата: Июл 7, 2004 12:29:24
Правка

Black_mirror
Я имею ввиду, если сделать на memory context: это будет быстрее? или наоборот, медленнее, из-за создания, копирования и удаления его?


Дата: Июл 7, 2004 13:21:28

IceStudent
Если в том месте, где требуется создать картинку, можно дотянутся до какого-нибудь hDC, то я бы его и использовал, потому что если картинка RGB, то CreateDIBSection к этому контексту скорее всего вообще обращатся не будет. Намного большее влияние на скорость будет оказывать размер создаваемой картинки, особенно если винда начнет свопиться, чтобы нужный кусок памяти выделить.


Дата: Июл 7, 2004 13:28:07
Правка

Black_mirror
Понятно, спасибо!


Дата: Июл 9, 2004 11:24:34
Правка

Хотя, нет. Делаю
HDC hDc = GetDC(hdrawWnd);
hDib = CreateDIBSection(hDc,…);
SelectObject(hDc,hDib);
…
DeleteObject(hDib);
ReleaseDC(hDc);


но окошко остаётся белым. А если через memory device context, то отрисовывается нормально. Я что-то делаю не так?


Дата: Июл 9, 2004 13:48:29

IceStudent
У меня есть подозрение контект полученый через GetDC совпадает с контекстом полученный через BeginPaint, а при вызове BeginPaint винда создает картинку в которой приложение может рисовать, а после вызова EndPaint, винда скопирует данные из этой картинки на экран. А так как мы эту картинку заменили на свою, то та картинка из которой винда берет данные не изменится, поэтому на экране никаких изменений не произойдет. Чтобы скопировать картинку нужно 2 контескта. А вот какой из них передавать в CreateDIBSection совершенно не важно.


Дата: Июл 11, 2004 11:14:26
Правка

Black_mirror
Спасибо за ответы!

BeginPaint я не вызываю, а отрисовываю по WM_Paint., потом BitBlt. Кажется, это наиболее быстро?


Дата: Июл 11, 2004 12:20:30

IceStudent
„BeginPaint я не вызываю, а отрисовываю по WM_Paint“
Я имел ввиду случай когда картинку создаем при обработке WM_PAINT.
Вроде если при обработке WM_PAINT не вызывать BeginPaint/EndPaint, это сообщение удаляться из очереди не будет и программа будет постоянно занималься перерисовкой.


Дата: Июл 11, 2004 12:38:07 · Поправил: IceStudent
Правка

Black_mirror
„это сообщение удаляться из очереди не будет “
Да нет, перерисовывает только когда надо, только надо отреагировать правильно. А Begin/End paint не обязательно, кажется (An application returns zero if it processes this message)....


Дата: Июл 12, 2004 17:42:48
Правка

Наткнулся на интересный баг:
если ширина рисунка больше или равна 0х400, то возникает исключение (попятка записи по неверному указателю). С чем это связано, даже не представляю.

Попробовал выделить больше памяти в BITMAPINFOHEADER (что-то подобное видел в коде ATL), но это не помогло.
Попытался увеличить ширину в структуре, но даже при изменении на 1 пиксел картинка искажается самым неожиданным образом.

Почему именно 0х400 — даже не представляю, когда пробегаюсь по 0х3FF и менее — всё нормально, дальше - AccessViolation. Причём если режим экрана 800х600, то до ошибки вообще дело не доходит, проблемы возникают при бОльших расширениях…

Замаскировал сее недоразумение умешьшением цикла, в котором отрисовываю картинку, на единицу по ширине.

Но мне кажется, что это не выход, хотелось бы разобраться до конца.