Как сделать прозрачный фон в bmp файле

Добавил пользователь Алексей Ф.
Обновлено: 04.10.2024

Встречаются ситуации, когда картинка изображена на черном фоне и требуется сделать его прозрачным для сохранения в PNG. Например, брызги воды, которые невозможно сфотографировать на белом фоне. Дизайнеры для наложения таких слоёв используют в Photoshop метод наложения экран (screen), получая в итоге красивый макет. Но при резке макета на прозрачные PNG возникает неразрешимая проблема с фоном. Вырезать фон из полупрозрачных изображений обводкой и удалением не представляется возможным в Photoshop. Создать в Photoshop нужный α-канал оказалось сложнее, чем написать небольшой скрипт.

Предлагаю метод, реализованный на JavaScript. Реализация алгоритма возможна на любом языке, обладающим библиотекой попиксельной обработки изображений.

Маска прозрачности (α-канал) для каждого пикселя изображения будет формироваться из значений RGB пикселя.

Создадим обычный html файл, с заголовками (transparetbg.html)

Позовём красивую девушку, положив файл girl.jpg в корень диска


Добавим кнопки управления в body и canvas

Добавим в head стиль для кнопок

Подготовим переменные. Для доступа к пикселям изображения используем canvas. При загрузке страницы загрузится картинка black_problem.jpg из корневой директории с которой мы будем работать. При загрузке методом onload её копия сохранится в переменной original.


Напишем функцию обработки изображения

Для формирования прозрачности каждого пикселя используются различные методы, но общая суть в формировании значения прозрачности в обратной зависимости от яркости пикселя. Белый пиксель будет полностью непрозрачным. Черный пиксель будет полностью прозрачным. В большинстве случаев подходит метод усреднения значений, т.е. default по коду.

Температура позволяет регулировать порог прозрачности изображения

Поиграемся

Чтобы Chrome разрешил нам работать с локальными изображениями запустим его с нужным ключиком (сделаем ярлык на рабочем столе) и откроем в нем наш html файл.

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security"


Нажмём кнопку Avg

Черный фон изображения стал прозрачным. Чудо!


Играя разными алгоритмами, видим незначительные изменения в изображении (для ценителей прекрасного).

← →
Ольга ( 2004-09-01 12:36 ) [0]

Здравствуйте!
Подскажите, пожалуйста, можно ли в Дельфи создать из BMP-файла файл ICO С ПРОЗРАЧНЫМ ФОНОМ? ICO из BMP я сделала, а вот установить прозрачный фон у иконки никак не получается, т.е. мне нужно, чтоб прозрачный фон был уже "зашит" в файле ICO.

← →
grom ( 2004-09-01 13:28 ) [1]

Mожет Image Editor подойдёт

← →
Anderson © ( 2004-09-01 13:29 ) [2]

Во-во! Я тоже никак не могу это сделать. Кто ответит (легким способом) - тот будет просто героем в моих глазах. :-)

← →
grom ( 2004-09-01 13:54 ) [3]

программно можно так
procedure TForm1.Button1Click(Sender: TObject);
var
iml:TImageList;
begin
iml:=TImageList.CreateSize(32,32);
Iml.AddMasked(Image1.Picture.Bitmap,clWhite);
Iml.GetIcon(0,Image2.Picture.Icon);
Image2.Picture.SaveToFile("1.ico");
iml.Free;
end;

← →
Anderson © ( 2004-09-01 14:20 ) [4]

Не катит. Девушка имела не то ввиду. Вот, допустим, загружаешь ты в TImage картинку: например, машина на черном фоне. Она хочет убрать этот фон и сохранить эту BMP"шку, как иконку. Это значит, что, если, допустим, в Image1 находится эта картинка, то при вызывании Image1.Picture.Bitmap.SaveToFile("d:\icon.ico") в файл сохранялась иконка без заднего фона и БЕЗ потери цветового качества. У девушки эта иконка сохраняется БЕЗ потери качества, но фон остается, а её нужно от него избавиться.

Ольга, не обижайтесь, я воспользуюсь вашим вопросом на другом форуме. Не охота переписывать все своими словами - просто скопиру, ОК?

← →
Ольга ( 2004-09-01 14:22 ) [5]

а в чем изюминка?
в Iml.AddMasked(Image1.Picture.Bitmap,clWhite); ?
так ни фига! фон как был розовым, так и остался!

и плюс к тому ругается на Invalid image size

← →
Anderson © ( 2004-09-01 14:24 ) [6]

Вот-вот! Фон-то остается непрозрачным. а ошибка у меня не выскакивала.

← →
Ольга ( 2004-09-01 14:24 ) [7]

Конечно, Anderson © , я не против.

← →
Anderson © ( 2004-09-01 14:25 ) [8]

Поправлю себя: фон остается непрозрачным даже если пишешь: Iml.AddMasked(Image1.Picture.Bitmap,clРоховый\синий\или серо-буро-малиновый);

← →
Mihey_temporary © ( 2004-09-01 17:16 ) [9]

2 Ольга:

там даже 2 решения

Я не понимаю, ты ещё не сохранил?

Не катит. Девушка имела не то ввиду. Вот, допустим, загружаешь ты в TImage картинку: например, машина на черном фоне. Она хочет убрать этот фон и сохранить эту BMP"шку, как иконку. Это значит, что, если, допустим, в Image1 находится эта картинка, то при вызывании Image1.Picture.Bitmap.SaveToFile("d:\icon.ico") в файл сохранялась иконка без заднего фона и БЕЗ потери цветового качества. У девушки эта иконка сохраняется БЕЗ потери качества, но фон остается, а её нужно от него избавиться.

На самом деле это смешно и ты сам не понимаешь, что творишь.

. сохраняет именно BMP файл с расширением .ICO. Это не настоящая иконка! Просто Windows умеет считывать данные битмапа и представлять их как иконку. Но стоит открыть этот файл с помощью Irfan View, например, как программа скажет, что это на самом деле BMP, а не ICO. Делая так ты никогда не получишь полноценный иконок.

Кстати, Win 98 у меня принимает белый цвет за прозрачный в таком случае, т.е. вполне можно создать прозрачную иконку. Но не надо так.

← →
Ольга ( 2004-09-01 17:44 ) [11]

читала я предыдущую дискуссию на эту тему
можете, кокретней указать, какие два решения там есть?
пыталась переделать под себя борландовский примерчик - не понимаю я, как внедрить туда уже имеющийся файл ICO? ну или проще говоря имеющийся tImage или tBitmap(да как угодно!), а не нарисованный вручную красный кружок! как у битмапа установить черный и белый фон?

← →
Rem ( 2004-09-01 18:38 ) [12]

А у меня пример (grom (01.09.04 13:54) [3]) прекрасно работает.
Просто вместо clWhite надо написать тот цвет который нужно сделать прозрачным.
Сохраненная иконка вполне хорошего качества с прозраным фоном.
Видемо пропуская Bitmap через ImageList рисунок какимто образом там конвертируеся.
== а каковы Ваши мнения ==

← →
Mihey_temporary © ( 2004-09-01 18:44 ) [13]


> можете, кокретней указать, какие два решения там есть?

Botland"овское, через TIcon и Mihey_temporary © (30.08.04 14:32) [13], через запись напрямую. В последнем случае нужно приложить усилия, чтобы 1) записать в массив TBitmap свои изображения 2) соответсвующим образом изменить данные об иконке. Второе решение сложнее, но обходит проблему максимума в 16 цветов. Если надо, то могу над этим делом поработать, довести до ума - всё равно когда-то буду.


> пыталась переделать под себя борландовский примерчик - не понимаю я, как внедрить туда уже имеющийся файл ICO? ну или проще говоря имеющийся tImage или tBitmap(да как угодно!), а не нарисованный вручную красный кружок!

Как внедрить TBitmap? Вместо:


AndMask : TBitmap;
XOrMask : TBitmap;

использовать свои растры.

← →
Anderson © ( 2004-09-01 20:00 ) [15]

А-а-а-а-а-а. я не понимаю вас, вы не понимаете меня. Я больше не буду спрашивать у вас ничего насчет иконок, чтобы ни запутывать вас, и не запутывать себя.
Мне эти иконки месяц жизни изъели. (

← →
Mihey_temporary © ( 2004-09-01 20:50 ) [16]


> А-а-а-а-а-а. я не понимаю вас, вы не понимаете меня. Я
> больше не буду спрашивать у вас ничего насчет иконок, чтобы
> ни запутывать вас, и не запутывать себя.
> Мне эти иконки месяц жизни изъели. (

Нет, всё же разберись. Остановись на данном этапе и не продвигайся никуда дальше, пока не поймёшь, что к чему.

Кстати, по той ссылке, весьма LOL. Смотри, что пишут:

procedure DrawTransparentBmp(Cnv: TCanvas; x,y: Integer; Bmp: TBitmap; clTransparent: TColor);

Это называется масло-масляное. У TBitmap есть свойство Transparent и метод Draw, который реализован вот прям точно так же, как эта процедура.

← →
Ольга ( 2004-09-02 09:40 ) [17]

И кроме того, меня НЕ интересует ОТОБРАЖЕНИЕ картинки прозрачной (это сделать проще простого, как уже сказано, с помощью свойства Transparent), мне нужно, чтоб прозрачность была ЗАШИТА в файле с картинкой, чтоб фон картинки был сам по себе ПРОЗРАЧНЫМ, а не выглядел прозрачным!

Ладно, сейчас попробую применить советы Grom, Rem (еще раз!) и Mihey_temporary

← →
Ольга ( 2004-09-02 11:55 ) [18]

Народ! Счастье есть! У меня получилось. УРА.
Всем спасибо!
Anderson © , удачи!

procedure TForm1.Button1Click(Sender: TObject);
var
newIcon : tIcon ;
ImageList : tImageList ;
hBmp : THandle;
BkCol : TColor;
begin
// Определяем цвет фона картинки
hBmp := bmpImage.Picture.Bitmap.Canvas.Handle ;
BkCol := GetPixel(hBmp, 0, 0) ;

// Засовываем Bitmap в ImageList
ImageList := tImageList.Create(self) ;
ImageList.AddMasked (bmpImage.Picture.Bitmap, BkCol) ;

// Перекладываем Bitmap в Icon
newIcon := tIcon.Create ;
ImageList.GetIcon (0, newIcon) ;

// Сохраняем полученную иконку в файле
newIcon.SaveToFile (icoFileName) ;

>Существуют иконки более сложной структуры. Они могут содержать несколько рисунков. Я с ними не разбирался.

Кроме того, 32-битные не поддерживаются. Так что это не выход.

Слухай, ты расскажи вообще, что ты хочешь сделать то, для чего иконки мучаешь? Да, и ещё, ты разобрался с прозрачным фоном или вопрос почему-то ещё открыт?

← →
Anderson © ( 2004-09-04 12:23 ) [21]

С прозрачным фоном я разобрался. в общем, через эту статью я во всем разобрался. там очень подробные комментарии, которые помогли мне.
У тебя в программе нельзя извлекать иконки из exe, dll, icl. только из ico, но и эта статья не идеальная. Допустим, в этой процедуре, прозрачным делается ВЕСЬ белый цвет, который есть в иконке, и таким образом, мы получаем не очень красивую иконку. но в 256-цветном режиме.
Я все-таки продолжу копать инфу насчет иконок на буржуйских сайтах.

← →
Mihey_temporary © ( 2004-09-04 16:43 ) [22]

Если разбираешься в Visual Basic, то есть готовые решения на www.vbaccelerator.com

← →
Рыба © ( 2004-09-04 19:04 ) [23]

Вам необходимо создать два битмапа, битмап маски (назовём его "AND" bitmap) и битмап изображения (назовём его XOR bitmap). Вы можете пропустить обработчики для "AND" и "XOR" битмапов в Windows API функции CreateIconIndirect() и использовать обработчик возвращённой иконки в Вашем приложении.

procedure TForm1.Button1Click(Sender: TObject);
var
IconSizeX : integer;
IconSizeY : integer;
AndMask : TBitmap;
XOrMask : TBitmap;
IconInfo : TIconInfo;
Icon : TIcon;
begin

IconSizeX := GetSystemMetrics(SM_CXICON);
IconSizeY := GetSystemMetrics(SM_CYICON);


AndMask := TBitmap.Create;
AndMask.Monochrome := true;
AndMask.Width := IconSizeX;
AndMask.Height := IconSizeY;


AndMask.Canvas.Brush.Color := clWhite;
AndMask.Canvas.FillRect(Rect(0, 0, IconSizeX, IconSizeY));
AndMask.Canvas.Brush.Color := clBlack;
AndMask.Canvas.Ellipse(4, 4, IconSizeX - 4, IconSizeY - 4);


Form1.Canvas.Draw(IconSizeX * 2, IconSizeY, AndMask);


XOrMask := TBitmap.Create;
XOrMask.Width := IconSizeX;
XOrMask.Height := IconSizeY;


XOrMask.Canvas.Brush.Color := ClBlack;
XOrMask.Canvas.FillRect(Rect(0, 0, IconSizeX, IconSizeY));
XOrMask.Canvas.Pen.Color := clRed;
XOrMask.Canvas.Brush.Color := clRed;
XOrMask.Canvas.Ellipse(4, 4, IconSizeX - 4, IconSizeY - 4);


Form1.Canvas.Draw(IconSizeX * 4, IconSizeY, XOrMask);


Icon := TIcon.Create;
IconInfo.fIcon := true;
IconInfo.xHotspot := 0;
IconInfo.yHotspot := 0;
IconInfo.hbmMask := AndMask.Handle;
IconInfo.hbmColor := XOrMask.Handle;
Icon.Handle := CreateIconIndirect(IconInfo);


Form1.Canvas.Draw(IconSizeX * 6, IconSizeY, Icon);


InvalidateRect(Application.Handle, nil, true);

2 Рыба
Спасибо за "повторение - мать ученья".

P.S. И почему мне в голову пришла идея написания программы для извлечения и сохранения иконок. -)

← →
Mihey_temporary © ( 2004-09-04 22:14 ) [28]

Все объявления ты можешь найти здесь:

Ладно, усё. Когда-нибудь доделаю чтение из EXE и DLL, но сейчас не до иконок.

Добрый день.
Заказчик запросил анимацию перевести в последовательнсоть bmp файлов с прозрачным фоном.
Первый раз с таким сталкиваюсь. Искал в интернете информацию. Чаще всего находил, что прозрачного bmp вообще в природе не сущесвует
Тогда что такое во флеше экспорт в последовательнсоть bmp 32 bit с альфа?
К слову, ставлю я эти настройки и что-то никакой прозрачности не вижу.
Подскажите как быть. Может сторонние программы какие нужны или еще чего?
Вообще запутался с этим bmp.

Какой-то странный у тебя заказчик. Лично я о прозрачном bmp не слыхал.

Вобщем, ты можешь сделать анимацию из каких угодно файлов, но, если речь идет о flash, стандартный формат - JPG, в него и сконвертятся все bitmap'ы твой анимации после публикации фильма. Так что смело импортируй png или gif и не парься, мой тебе совет

Я бы послал такого заказчика плисать с бубном на площади.. ибо есть тех. среда и чего эму там надо пусть сам делает а делать надо так как того требует ГОСТ утрировано конечно но таких заказчиков строить надо.

Вобщем, ты можешь сделать анимацию из каких угодно файлов, но, если речь идет о flash, стандартный формат - JPG, в него и сконвертятся все bitmap'ы твой анимации после публикации фильма.

Надо всегда делать либо в png-24 либо гиф. В jpeg можно и самим флешом сжать, иначе будет сжатие джепегом джепега.

Но, если на столько уж принципиально сделать в bmp с прозрачным фоном, то это не проблема. Просто при создании bmp в Photoshop вместо прозрачного фона делаем чёрную заливку, а в закладке Channels создаём новый слой (тоже чёрный, он сам появится такого цвета) и делаем выделение обьекта(ов) которые должны быть на прозрачном фоне. Возвращаемся на закладку Channels и полученное выделение заливаем белым цветом. Сохраняем как bmp 32 with alfa channels и импортируем в Macromedia Flash - получаем bmp с прозрачным фоном. Только зачем столько гемора? Слушай Nils-а - он говорит тему: "Надо всегда делать либо в png-24 либо гиф"

Спасибо всем за отклики

CepaqpuM, вот и я о том Вроде как прозрачного bmp не сущесвует, тока че такое 32 бита с альфа тогда? Вобщем решил поинтересоваться у знающих людей.

Green Bob, не, караз из флеша нужно получить bmp с прозрачным фоном
Т.е. рисую я допустим квадратик во флеше, закрашиваю его. И надо сее чудо экспортировать в бмп прозрачный. Чтоб фон прозрачный был.

Так я так и не понял сущесвует такое чудо природы, как прозрачный mp или нет? И что такое 32 bit alpha?

Ты малёхо не понял.
Прозрачным *.bmp будет только во Flash и в конечном swf!
. или в *.exe какого нить авторана иль ещё где нить.
А прозрачность в обычных смотрелках (ACSee и т.д.) ты не увидишь!

Благодарсвую за отклики
Проблема была в том, что у меня фон был не белый.

Вобщем ставим белый фон -> экспортируем в bmp 32 bit с альфа -> вуаля, всё работает

Пример фотографии розовой розы без изменений и после замены однотонного фона на прозрачный, белый и зелёный:

Оригинальная фотография розы
Фотография с прозрачным фоном

Фото с однотонным белым фоном
Фото на однотонном зелёном фоне

Первый пример с цветком розы на прозрачном фоне сделан с такими настройками:
1) Интенсивность замены — 38;
2) Сглаживание по краям — 5;
3) Заменить однотонный фон на — прозрачный;
4) Обрезка ( 0) по краям — "-70";
5) Инвертировать — отключено (галка не стоит).

Исходное изображение никак не изменяется. Вам будет предоставлена другая обработанная картинка с прозрачным или указанным вами фоном.

Для этого копирую ее на десктоп через функцию BitBlt, у который есть последний параметр, отвечающий за растровую операцию - цитирую: "Каждая растровая операция использует RGB-значение цвета исходного пиксела, чтобы определить новый цвет пиксела. "

В связи с этим не могу понять:

1. Зачем, если я, например, выбираю константу - SRCERASE (Комбинирование перевернутых цветов прямоугольника адресата с цветами источника , используя поразрядный оператор AND) задавать этой константе какой-либо RGB цвет, если операция AND должна проводится между битами источника и адресата?

2. Как можно убрать фон, например белый, из BMP картинки? (или может вообще этого сделать по BitBlt нельзя, а только используя маску?)

Долгие эксперименты показали, что:

1. Если взять BLACKNESS = &H885050, белый фон станет почти невидимый, а остальные цвета (зеленый преобладает) немного испоганятся. Правда черные буквы на десктопе тогда через картинку просвечивают.

2. Если взять SRCCOPY = а цвет близкий к зеленому, то типа скопируются только цвета близкие к зеленому, а белый фон станет почти невидимый. Правда картинка все равно поганится, ведь цвета разные (фон только один), а хотелось как раз наоборот. ;-)

ICQ: 166433794

В DirectDraw ето можна через SetColorKey.
Можеш попробовать сделать так чтобы там где фон картинки формы небыло (незнаю как ето наз.), ето через маску делаетса
может хто подскажет, я не знаю как, а потом твою форму сделать parent десктопу.

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
dim t_wnd as long

Private Sub Form_Load()
t_wnd = FindWindow("Progman", "Program Manager")
SetParent Me.hwnd, t_wnd
End Sub

Спасибо за ответ. Прикольные функции, с такими еще не работал. посмотрим

Покапавшись еще в других форумах, нашел упоминание об такой, относительно новой функции (в win98 есть, в во win32API вьюере о ней молчком) - TransparentBlt.

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

Еще на MSDN написано следующее:

"Windows 95/98: TransparentBlt contains a memory leak that can exhaust system resources. To draw a transparent bitmap using BitBlt, see Knowledge Base article Q79212."

Вот и думай, что делать.. . а если сходить по ссылке Q79212 - то там есть описание функции, которая делает тоже самое, что и TransparentBlt , только используя BitBlt - можно, в принципе, брать и использовать.

Не знаю, вообщем, пока тестирую TransparentBlt, хочу проверить эту утечку.

ICQ: 134433

Я тут недавно разбирался все с функцией TransparentBlt

Впринципе. все отлично, но только вот осталась одна проблема которую я не могу решить: я "рисую" этой функцией в PictureBox и для того что бы мне на этом же месте "перерисовать" картинку еще раз приходиться применять метод Cls а это вызывает моргание этого самого PictureBox'a . Умнее пока ничего не придумал

Не совсем понятно, что ты точно делаешь в PictureBox.

А вообще, общий способ избежать моргание, заключается в предварительной буферизации изображения - это, например, вирт. окно и т.д.

Т.е. ты компануешь свою картинку в каком-либо Bitmap для временного хранения:

' получение эквивалент устройства PictureBox1.hdc для памяти

' создание битовой карты

hBit = CreateCompatibleBitmap(PictureBox1.hdc, x, y)

' выбор hBit в memDC

SelectObject memDC, hBit

' С ним работаешь как с PictureBox1

BitBlt memDC, 0, 0, 100, 100, PicBMP1, 0, 0, SRCCOPY

TransparentBlt memDC, 0, 0, 100, 100, PicBMP2, 0, 0, vbWhite

' и когда все готово, полученную итоговую картинку копируешь в PictureBox1

Читайте также: