Тотальная неудачница и убийца жёстких дисков.
#post-id: 2435-00-20
#original-date: 27.03.2007 Tue
#original-time: 12:20 AM
#original-day: 2435
Так, Aulith спрашивал, как я выкрутилась с растрами. Собственно вот так:
Кстати, код работает (как оказалось) и в 9x и в NT. Так что, можно смело юзать ^_^
Кстати, может показаться, что достаточно только CopyImage() с флагом LR_CREATEDIBSECTION, у меня у самой регулярно возникает такое подозрение, но когда я начинаю разбираться снова и снова, через часик-другой вспоминаю, какие были причины... Так что, считайте, что так нужно ^_^'
#original-date: 27.03.2007 Tue
#original-time: 12:20 AM
#original-day: 2435
Так, Aulith спрашивал, как я выкрутилась с растрами. Собственно вот так:
//===================================================================Это код на VC++. EXP_AJPAPI(HRESULT) означает HRESULT __stdcall, просто в виде макроса. Мне так нравится. Вот... Собственно, код делает DIB секцию вместо растра и в итоге далает растр независимым от палитр и прочего. Как я сказала в комментах, это избавляет от многих проблем при манипуляциях с растрами в памяти. А ведь на этом и спотыкался поначалу Wallpaper Changer. С JPG ресамплинг шёл нормально, а с GIF - нет. До этого я ресамплинг не делала - только делала растр по масштабу экрана, а Windows уже делала сама ресамплинг. Вот. Но когда взялась за всё сама, нашла проблему с растрами с палитрой. А потом ещё были проблемы с порчей видеопамяти на S3 ViRGE MX. За эту функцию (которую я писала три дня) видюшка до сих пор говорит мне спасибо ^_^
// Функция принимает манипулятор растра и создаёт её копию в
// двадцатичетырёхбитном цвете. Это полезно, когда требуются
// манипуляторы с копией изображения загруженного из, например, GIF
// или выбранного уже где-то.
//===================================================================
EXP_AJPAPI(HRESULT) asCopyBitmap(HBITMAP hSourceBitmap,
HBITMAP *RetVal)
{
CHECK_RETVAL;
// Проверяем тип объекта
if (GetObjectType((HGDIOBJ)hSourceBitmap) != OBJ_BITMAP)
return E_INVALIDARG;
//=================================================================
// Тут мы создаём копию растра - дело в том, что если наш растр уже
// выбран где-то, то повторно его выбрать не удастся. Так что
// копируем его через CopyImage().
//
// Внимание! Флаг LR_CREATEDIBSECTION в этой функции не был описан
// в документации. Я его использовала на свой страх и риск, и оно
// сработало! Дело в том, что при использовании 256 цветного
// рисунка, коггда мы создаём копию, при BitBlt() цвета могут
// съехать. Не помогает даже DIB секция в качестве приёмника! Но
// если скопировать изображение в DIB секцию этой функцией, то
// можно всё это решить. Не знаю, будет ли оно работать на NT...
HBITMAP hBitmap = (HBITMAP)CopyImage(hSourceBitmap, IMAGE_BITMAP,
0, 0, LR_COPYRETURNORG |
LR_CREATEDIBSECTION);
if (!hBitmap) return S_FALSE;
//=================================================================
// Создаём контекст устройства источника, где выберим тот
// скопированный растр. Также и приёмник сделаем...
HDC hCompDC = CreateCompatibleDC(0);
if (!hCompDC) {
DeleteObject(hBitmap);
return S_FALSE;
}
HDC hNewDC = CreateCompatibleDC(0);
if (!hNewDC) {
DeleteDC(hCompDC);
DeleteObject(hBitmap);
return S_FALSE;
}
//=================================================================
HBITMAP hOldCompBitmap = (HBITMAP)SelectObject(hCompDC, hBitmap);
if (!hOldCompBitmap) {
DeleteDC(hCompDC);
DeleteDC(hNewDC);
DeleteObject(hBitmap);
return S_FALSE;
}
BITMAP BM;
GetObject(hBitmap, sizeof(BM), &BM);
// Создаём растр-приёмник как DIB секцию, чтобы избежать проблем с
// цветами. Первые два варианта - на память. CreateBitmap()
// работает, но что-то не очень хочется на него полагаться, както
// он меня подвёл. А вот CreateCompatibleBitmap() создаёт в случае
// с 256 цветным рисунком точно такойже, чего нам не надо.
//
// mvarhBitmap = CreateBitmap(BM.bmWidth, BM.bmHeight, 1, 24, ByVal 0&)
// mvarhBitmap = CreateCompatibleBitmap(hCompDC, BM.bmWidth, BM.bmHeight)
BITMAPINFO BMI;
ZeroMemory(&BMI, sizeof(BMI));
BMI.bmiHeader.biSize = 40;
BMI.bmiHeader.biWidth = BM.bmWidth;
BMI.bmiHeader.biHeight = -BM.bmHeight;
BMI.bmiHeader.biPlanes = 1;
BMI.bmiHeader.biBitCount = 24; // то что надо!
BMI.bmiHeader.biCompression = BI_RGB;
HBITMAP hNewBitmap = CreateDIBSection(0, &BMI, DIB_RGB_COLORS, NULL, 0, 0);
if (!hNewBitmap) {
SelectObject(hCompDC, hOldCompBitmap);
DeleteObject(hBitmap);
DeleteDC(hCompDC);
DeleteDC(hNewDC);
return S_FALSE;
}
// Выбираем и копируем!
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hNewDC, hNewBitmap);
BitBlt(hNewDC, 0, 0, BM.bmWidth, BM.bmHeight, hCompDC, 0, 0, SRCCOPY);
//=================================================================
// А теперь отчищаем ресурсы.
SelectObject(hCompDC, hOldCompBitmap);
SelectObject(hNewDC, hOldBitmap);
DeleteDC(hCompDC);
DeleteDC(hNewDC);
DeleteObject(hBitmap);
*RetVal = hNewBitmap;
return S_OK;
}
Кстати, код работает (как оказалось) и в 9x и в NT. Так что, можно смело юзать ^_^
Кстати, может показаться, что достаточно только CopyImage() с флагом LR_CREATEDIBSECTION, у меня у самой регулярно возникает такое подозрение, но когда я начинаю разбираться снова и снова, через часик-другой вспоминаю, какие были причины... Так что, считайте, что так нужно ^_^'
и в каком месте это копирование предполагается выполнять, при загрузке bitmap'ов, дабы далее полученные копии непосредственно прорисовывать?
странно, как это может повлиять на прозрачность, если в @клиенте это - изначально 24битные BITMAP...
В Wallaper Changer я использовала так:
-- Гружу картинку через LoadPicture() для JPG, BMP и GIF или через одну библиотеку для форматов вроде PSD.
-- Копирую растр этой функцией из Pic.Handle, чтобы не зависеть от растра в объекте в StdPicture.
-- Делаю ресамплинг.
-- Копирую на пропорциональный экрану растр.
-- Новый растр загоняю в StdPicture.
-- Сохраняю картинку в BMP через SavePicture().
-- Ну и ставлю на рабочий стол ^^
в принципе в клиенте ресемплинг делается только в пределах своего формата (gif, png, jpg) и жалоб на него вроде не было... по крайней мере в последнее время)
а кстати в Delphi у TBitmap есть метод для явного создания DIB секции... только там вроде никакого копирования не используется...
мне вот действительно надо разобраться с тем глюком прозрачности и гифами анимированными, ага. я подумал, что это к тому)