Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2002.02.04;
Скачать: [xml.tar.bz2];

Вниз

Вывод bitmap из ресурса   Найти похожие ветки 

 
sandman   (2001-11-20 14:42) [0]

Имеется проблема: в файле есть несколько ресурсов типа BITMAP (256 цветов). При просмотре этих картинок в Фотошопе цвета выглядят нормально, но при загрузке их в Delphi Image Editor, а также непосредственно в программу палитра "плывёт". Есть ли какой-нибудь способ побороть это?


 
-=CrazyFish=-   (2001-11-20 17:37) [1]

Нужно воспользоваться утилитой brcc32.exe из папки bin.
нужно создать файл RC (myResFile.rc)
прописать в нем, например:

myBitmapName1 BITMAP bitmapFile1.bmp
myBitmapName2 BITMAP bitmapFile2.bmp
myBitmapName3 BITMAP bitmapFile3.bmp

и выполнить brcc32.exe myResFile.rc

получишь myResFile.res, в котором все битмэпки будут иметь нужную палитру

Так же можно пользоваться редактором ресурсов из Visual Studio, там есть возможность подгружать нужную палитру.
Удачи.


 
_mike   (2001-11-20 17:46) [2]

to CrazyFish

Всё это замечательно, но только палитра всё равно плывет. Лично у меня выводится всего 2-3 цвета (цвета монохромные, но картинка использует около 200 цветов).


 
-=CrazyFish=-   (2001-11-20 18:03) [3]

> _mike
ну... если на экран одновременно выводится несколько картинок с разными палитрами, а видеорежим на 256 цветов, то все легко можел поплыть.
Если кол-во цветов больше 256, то ничего сказать не могу, у меня таких проблем не возникало.


 
_mike   (2001-11-21 19:52) [4]

-=CrazyFish=-, посмотри своим опытным глазом, может я туфту тут написал? Ну не могут всего два цвета выводиться. Ну 20-30, но не два.
Посмотри, -=CrazyFish=-, будь другом. Пожалуйста.


var BitMap_MainBox: HBitMap;
var TheDC, hdc_Main_Box: HDC;
var Handle: HWND;

procedure LoadMyResourses;
begin
BitMap_MainBox:=LoadBitmap(hInstance,"MAINBOX");
TheDC:=GetDC(Handle);
hdc_Main_Box := CreateCompatibleDC(TheDC);
SelectObject(hdc_Main_Box, BitMap_MainBox);
ReleaseDC(Handle,TheDC);
end;

procedure DrawElement(X, Y, Width, Height: integer;
ID_Paint_Element:HDC; deltaX, DeltaY: integer; Operation: integer);
var PS: TPaintStruct;
begin
TheDC:=BeginPaint(Handle,PS);
BitBlt(TheDC,X,Y,Width,Height,ID_Paint_Element,deltaX,deltaY,Operation);
EndPaint(Handle,PS);
end;

procedure DrawMainBox;
begin
DrawElement(0,0,276,350,hdc_Main_Box,0,0,SrcCopy);
end;





 
Evgeny   (2001-11-22 14:42) [5]

Если я правильно понял, то процедура DrawElement выполняется из WM_PAINT.
Тогда этот кусок можно выполнить так:

BeginPaint(Handle,PS);
BitBlt(PS.DC,X,Y,Width,Height,ID_Paint_Element,deltaX,deltaY,Operation);
EndPaint(Handle,PS);


 
_mike   (2001-11-22 15:00) [6]

Evgeny.
Ну да.

Спасибо, я попробую. Хотя я думаю, что ошибка не в этом. В любом случае завтра напишу что у меня получилось (Все ресурсы на домашнем компе, а сейчас я на работе).

В любом случае, спасибо за отклик.


 
_mike   (2001-11-23 12:24) [7]

Evgeny, пробывал я вчера. Та же история. Я понял вчера только одно: битмэп она воспринимает с политрой в 16 цветов, почему то. У меня мысля возникла, может это из-за того, что стиль окна у меня только WS_POPUP?


 
Evgeny   (2001-11-23 14:48) [8]

Стиль здесь не причем. Не совсем понятно как у тебя взаимосвязаны процедуры. У меня вывод делается примерно таким же способом, и все идет нормально. Все битмапы я, для экономии места, всегда оптимизирую на 256 цветов и проблем пока не было. А разрешение экрана у тебя случайно не 256 цветов? При этом Windows любую картинку у которой палитра не совпадает с системной выведет в 16 цветов. Да. И укажи куда выводишь. Мне кажется непосредственно на окно.


 
_mike   (2001-11-23 15:33) [9]

Evgeny.
Суть заключается в следующем. Я хочу чтобы моя програмка работала на абсолютно любом компе и в любом режиме. Естественно, что при палитровом разрешении экрана, например в 16 и больше бит, всё выводится нормально. Тут проблем нет. Но стоит мне режим переключить в 256 цветов - программка воспринимает ресурс как 16-ти цветовой.

Не знаешь как преодолеть эту проблему?


 
_mike   (2001-11-23 15:43) [10]

Evgeny, забыл написать про взаимодействие процедур :)
Из основномо модуля процедура LoadMyResourses вызывается по событию WM_Create, a DrawMainBox - по событию WM_Paint. Вывожу сразу в окно.

Спасибо за участие.


 
Evgeny   (2001-11-26 09:59) [11]

Ну тогда все понятно. Нормальное изображение в данном случае можно получить только в случае приведения палитры в твоих файлах к системной. Во всех остальных случаях система будет скидывать цвета до 16. Обрати внимание на различные инсталляторы. Их бедные цветами картинки именно из-за желания видеть изображение одинаковым во всех цветовых разрешениях.


 
_mike   (2001-11-26 13:03) [12]

Evgeny
Да, но если использовать вместо WIN32 API, например, TImage (IDE), то эта проблема как то решается... Может всё таки можно как то её решить средствами WIN32 API?


 
Evgeny   (2001-11-26 15:03) [13]

Прочитал и усомнился. Решил проверить. Проверил. Понял, что _mike сам этого никогда не проверял. Начинаем проект, кладем на него TImage, выбираем 256-цветный битмап, палитра которого далека от системной. Все красиво. Переключаем экран в режим 256 цветов. Тихо офигеваем. И не мудрено - цвета кошмарные. Переключаюсь обратно в 16 бит. Все нормально и красиво. Так что _mike извини. Оптимизируй под системную палитру.


 
_mike   (2001-11-26 18:18) [14]

Переключаюсь в режим 256-цветов.
Открываю стандартный редактор картинок Paint.
Загружаю картинку - цвета подобраны удовлитворительно.
То же самое с другими редактарами и просмоторщиками.
При этом палитра картинки не оптимизирована под системную...


 
ggsoft   (2001-11-26 22:37) [15]

to _Mike, Delphi-йский ImageEditor тоже конкретно глючит при открытии Image-й на 256-цветах и последующего их сохранения, попробуй! VC6 не глючит.

Evgeny, не все вышесказанное правильно. При выводе изображений на 256-цветах, Windows не «скидывает» их (цвета изображения) до 16 цветов, а пытается подобрать палитру изображения к своей системной. И это происходит во время загрузки рисунка в HBITMAP т. е. из DIB-изображения Windows преобразует DDB, а значит надо при выводе рисунка создать и выбрать в контекст устройства ( HDC) свою палитру, полученную из рисунка... Ниже код, правда я писал его на VC6.

to _Mike, если не сможете перевести на Delphi пишите.



/********************************************************************/
//Загрузить изображение и создать палитру
/********************************************************************/
BOOL CGGAboutDlgLogoBmp::GetBitmapAndPalette(CBitmap &bmpPaint, CPalette &palPaint)
{
HBITMAP hBmp;
DIBSECTION ds;
BITMAPINFOHEADER &bmpInfoHdr = ds.dsBmih;
UINT nColors;
CWindowDC dcDesktop(NULL);
CDC dcMem;
CBitmap *bmpTemp;
RGBQUAD *pRGB;
LOGPALETTE *pPal;
BOOL bRet = FALSE;

if (bmpPaint.m_hObject)
bmpPaint.DeleteObject();
if (palPaint.m_hObject)
palPaint.DeleteObject();

hBmp = (HBITMAP)::LoadImage(AfxGetResourceHandle(),
MAKEINTRESOURCE(GG_IDB_LOGOABOUT), IMAGE_BITMAP,
0, 0, LR_CREATEDIBSECTION);
if (!hBmp)
return FALSE;

bmpPaint.Attach(hBmp);
bmpPaint.GetObject(sizeof(ds), &ds);
nColors = bmpInfoHdr.biClrUsed ?
bmpInfoHdr.biClrUsed : 1 << bmpInfoHdr.biBitCount;

dcMem.CreateCompatibleDC(&dcDesktop);
bmpTemp = dcMem.SelectObject(&bmpPaint);
pRGB = new RGBQUAD [nColors];
pPal = (LOGPALETTE *)new BYTE [sizeof(LOGPALETTE) +
sizeof(PALETTEENTRY) * nColors];
pPal->palNumEntries = nColors;
pPal->palVersion = PALETTEVERSION;
if (GetDIBColorTable(dcMem, 0, nColors, pRGB) == nColors) {
for (UINT i = 0; i < nColors; i++) {
pPal->palPalEntry[i].peRed = pRGB[i].rgbRed;
pPal->palPalEntry[i].peGreen = pRGB[i].rgbGreen;
pPal->palPalEntry[i].peBlue = pRGB[i].rgbBlue;
pPal->palPalEntry[i].peFlags = 0;
}
bRet = palPaint.CreatePalette(pPal);
}
else
ASSERT(FALSE); //GetDIBColorTable worked not correct

delete [] pPal;
delete [] pRGB;
dcMem.SelectObject(bmpTemp);

return bRet;
}

/********************************************************************/
//то же самое событие OnPaint Delphi-йской формы
/********************************************************************/
void CGGAboutDlgLogoBmp::OnPaint()
{
CPaintDC dc(this);
CDC dcMem;
CRect rectClient;
CBitmap *bmpTemp;
CPalette *palTemp = NULL;
BITMAP bmpInfo;

GetClientRect(&rectClient);
if (!m_pPalette)
m_pPalette = new CPalette;

if (GetBitmapAndPalette(m_bmpLogoBitmap, *m_pPalette)) {
m_bmpLogoBitmap.GetBitmap(&bmpInfo);
dcMem.CreateCompatibleDC(&dc);
bmpTemp = dcMem.SelectObject(&m_bmpLogoBitmap);
dc.SetStretchBltMode(COLORONCOLOR);
if (dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE && m_pPalette->m_hObject) {
palTemp = dc.SelectPalette(m_pPalette, FALSE);
dc.RealizePalette();
}
dc.StretchBlt(rectClient.left, rectClient.top,
rectClient.Width() - 1, rectClient.Height() - 1,
&dcMem, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight,
SRCCOPY);
if (palTemp)
dc.SelectObject(palTemp);
dcMem.SelectObject(bmpTemp);
}
}


С уважением, Евгений!


 
Evgeny   (2001-11-27 07:37) [16]

Существует такой же вариант и на Delphi, попробуй может подойдет. Код не мой и я его не проверял, так что за работоспособность не ручаюсь.

procedure XLoadBitmap(Instance: THandle; BitmapName: PChar;
var HB: HBitmap; var HP: HPalette);
var
DC: HDC;
BI: PBitMapInfo;
Pal: PLogPalette;
I: Integer;
ResIdHandle: THandle;
ResDataHandle: THandle;
Bitmap: HBitmap;
C: HWnd;
OldPalette, Palette: HPalette;

begin
Bitmap:= 0; Palette:=0;
HB:=0; HP:=0;
{Получить ресурс из модуля}
ResIDHandle := FindResource(Instance, BitmapName, rt_BitMap);
if ResIDHandle<>0 then begin
ResDataHandle := LoadResource(Instance, ResIDHandle);
if ResDataHandle<>0 then begin
BI:= LockResource(ResDataHandle);
if BI <> nil then begin
{256-цветный битмап?}
if BI^.bmiHeader.biBitCount = 8 then begin
{Создать палитру}
GetMem(Pal, SizeOf(TLogPalette) + 256 * SizeOf(TPaletteEntry));
for I:= 0 to 255 do
with Pal^.palPalEntry[I] do begin
peRed := BI^.bmiColors[I].rgbRed;
peGreen:= BI^.bmiColors[I].rgbGreen;
peBlue := BI^.bmiColors[I].rgbBlue;
peFlags:= 0;
end;
Pal^.palNumEntries:= 256;
Pal^.palVersion := $300;
Palette:= CreatePalette(Pal^);
FreeMem(Pal, SizeOf(TLogPalette) + 256 * SizeOf(TPaletteEntry));

{Привести цвета палитры в системные}
DC:= CreateDC("Display", nil, nil, nil);
OldPalette:= SelectPalette(DC, Palette, False);
UnrealizeObject(Palette);
RealizePalette(DC);

{Создать битмап}
BitMap:= CreateDIBitmap(DC, BI^.bmiHeader, CBM_INIT,
@PByteArray(BI)^[SizeOf(TBitMapInfo) + SizeOf(TRGBQuad) * 256 - 4],
BI^, DIB_RGB_COLORS);

{Освободить ресурсы}
UnlockResource(ResDataHandle);
FreeResource(ResDataHandle);
SelectPalette(DC, OldPalette, False);
DeleteDC(DC);
end else begin
{Не 256-цветный битмап}
UnlockResource(ResDataHandle);
FreeResource(ResDataHandle);
BitMap:= LoadBitmap(Instance, BitmapName);
end;
HB := Bitmap;
HP := Palette;
end; {BI <> nil }
end; {ResDataHandle <> 0}
end; {ResIDHandle <> 0 }
end;


procedure TForm1.FormCreate(Sender: TObject);
var
HB: HBitmap;
HP: HPalette;
begin
xLoadBitmap(hInstance, "PHOTO", HB, HP);
Image1.Picture.Bitmap.Handle :=HB;
Image1.Picture.Bitmap.Palette:=HP;
end;



 
_mike   (2001-11-27 14:14) [17]

ggsoft, Evgeny - большое вам спасибо. У меня сырье дома лежит. Проверю сегодня вечером. Завтра напишу как сработали ваши коды.


 
_mike   (2001-11-28 12:43) [18]

Evgeny
Попробывал я этот код. Цвета он подбирает более или менее. Но этот код испольщует TBitMap. С помощью этого объекта можно было бы оптимизировать цвета лучше. Вообще говоря я хотел пользоваться исключительно средства Win32 API, поскольку в моей программке будет много графических элементов (что то вроде WinAMP). Наверное мне придётся использовать ещё более низкоуровневые операции (залезать в файл, считывать структуру и т.д.). Я надеялся, что Win32 API есть уже готовые функции, но, видимо, напрасно.


ggsoft
Код, приведённый вами так же использует уже готовые классы из библиотек VC6. Я не совсем силён в этих библиотеках и столкнулся с трудностями при переводе класса CBitmap. Этот класс напоминает дельфовский тип TBitMap, но только напоминает. В связи с большим количеством графики я не хотел бы использовать дополнительные классы или объекты. Win32 API, как мне кажется, самодостаточна, хотя с ее помощью писать приходиться дольше.

Evgeny, ggsoft
Не смотря на всё вышеописанное я обязательно более пристально изучу механизм реализованный в ваших кодах. Эти кода не пропадут напрасно. Вырожаю вам искреннюю признательность за отклик и участие в данной теме. Спасибо.


 
Evgeny   (2001-11-30 09:33) [19]

>_mike
Уважаемый, приведенный пример полностью на WinAPI. Если под TBitmap понимается Delphi-ский объект, то вы не правы. В данной процедуре (XLoadBitmap) он не применяется.


 
_mike   (2001-11-30 13:03) [20]

Evgeny

Виноват :)) Вы абсолютно правы.

Тем не менее этот код не совсем хорошо оптимизирует цвета. Я могу послать Вам по почте скомпелированный эгзешник. Если запустить его в режиме 256 цветов, то Вы увидете картинку, оптимизированную объектом TBitmap. Далее на форме есть кнопка с функцией XLoadBitmap. Вы сами сможите увидеть разницу.


 
Evgeny   (2001-11-30 14:09) [21]

Ну что же давай поэксперементируем.


 
Evgeny   (2001-12-04 10:42) [22]

Проверил. Да действительно мерзко. Посмотрим EXE файл внутри, что это? Картинка то 24 битная. Нет мы так не договаривались. Разговор шел о 256 цветной. Привожу твою картинку любым редактором в 256 цветную и повторяю эксперимент. Ну вот теперь она смотрится изумительно.

procedure TForm1.FormCreate(Sender: TObject);
var
HB: HBitmap;
HP: HPalette;
begin
// Оригинал напрямую - Терпимо
Image1.Picture.Bitmap.LoadFromResourceName(hInstance, "PHOTO_16");
// Оригинал через xLoadBitmap - Мерзко
xLoadBitmap(hInstance, "PHOTO_24", HB, HP);
Image2.Picture.Bitmap.Handle := HB;
Image2.Picture.Bitmap.Palette:= HP;
// 256 цветный через xLoadBitmap - Хорошо
xLoadBitmap(hInstance, "PHOTO_8", HB, HP);
Image3.Picture.Bitmap.Handle := HB;
Image3.Picture.Bitmap.Palette:= HP;
end;


 
_mike   (2001-12-06 12:31) [23]

Evgeny
Забегался я тут слегка, про программирование пришлось забыть, поэтому и не отвечал долго :))

Спасибо, Evgeny :)) Всё работает. :)))

P.S. Интересно, а как серьёзные программы и компоненты оптимизируют для в видеорежиме 256 цветов палитру в 24 бит?


 
Evgeny   (2001-12-07 07:27) [24]

Честно говоря не знаю. Я как-то искал ответ на нечто подобное, так облазил всю "помойку", но к сожалению ничего подходящего обнаружить не удалось. Если найдешь дай знать.


 
_mike   (2001-12-07 14:17) [25]

Хорошо, Evgeny :)



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2002.02.04;
Скачать: [xml.tar.bz2];

Наверх









Память: 0.93 MB
Время: 0.031 c
3-8762
Олег Лаукарт
2002-01-04 14:50
2002.02.04
указание значения-даты в запросе


1-8945
kserg@ukr.net
2002-01-18 13:12
2002.02.04
Как программно перевести фокус в ячейку StringGrid.Cells


1-8835
tavwizard
2002-01-19 16:49
2002.02.04
add-in для Delphi


3-8790
Ura
2001-12-28 11:02
2002.02.04
BDE


14-8988
Pat
2001-12-08 14:45
2002.02.04
Глюк FAT32





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский