Что нового

Как можно поменять цвет фона изображения?

Andrey_A

Продвинутый
Сообщения
323
Репутация
68
Добрый день. Подскажите, можно ли поменять фон PNG изображения. Берётся первый пиксель и по периметру заменить его на другой.
Может кто-то уже делал подобное (многое что просмторел, но точного примера не нашёл). Есть функции, где идёт замена одного цвета на другой во всём изображении, но это здесь не подойдёт.
Интересует только методы Autoit.
Вот примеры исходного изображения и что должно получиться в конце:
sssb.png
sssg.png
 
Автор
A

Andrey_A

Продвинутый
Сообщения
323
Репутация
68
InnI , спасибо за наводку, но можно ли реальный пример:
Нужно взять один файл, заменить в нём цвет первого пикселя на заданный цвет по периметру и сохранить в другой.

Я попытался так:

Код:
#include <GDIPlus.au3>

$sFile='C:\0Test\02511377\sssb.png'
$sFile2='C:\0Test\02511377\sssb_.png'
_GDIPlus_Startup ()

$hImage=_GDIPlus_ImageLoadFromFile($sFile)

$iW=_GDIPlus_ImageGetWidth($hImage)
$iH=_GDIPlus_ImageGetHeight($hImage)

$iColorGet=Hex(_GDIPlus_BitmapGetPixel($hImage,0,0),8)

$hDDC=_WinAPI_GetDC(0)
$hCDC=_WinAPI_CreateCompatibleDC($hDDC)
$hBmp=_WinAPI_CreateCompatibleBitmap($hDDC,$iW,$iH)

; А тут загвоздка

_GDIPlus_ImageSaveToFile($hImage,$sFile2)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_ShutDown ()


Но с серединой возникли проблемы, не хватает фантазии, кроме того появились вопросы:

1. Можно ли заменить на прозрачный пиксель?
2. Из примера "Post #4" видно что там указывается 1 цвет и вот такое изображение "убивается"
sssbr.png


т.е. можно ли в таком изображении менять фон по периметру?
Заранее спасибо за помощь.
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
Andrey_A
реальный пример

Вариант 1
Код:
#include <GDIPlus.au3>

$sFile  = "sssb.png"
$sFile2 = "sssg.png"

_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile($sFile)
$iW = _GDIPlus_ImageGetWidth($hImage)
$iH = _GDIPlus_ImageGetHeight($hImage)

$iColorGet = _GDIPlus_BitmapGetPixel($hImage, 0, 0)
$iColorSet = 0x008000

$hDDC = _WinAPI_GetDC(0)
$hCDC = _WinAPI_CreateCompatibleDC($hDDC)
$hBmp = _WinAPI_CreateCompatibleBitmap($hDDC, $iW, $iH)
$hOldBmp = _WinAPI_SelectObject($hCDC, $hBmp)

$hGraphics = _GDIPlus_GraphicsCreateFromHDC($hCDC)
_GDIPlus_GraphicsDrawImage($hGraphics, $hImage, 0, 0)

$hBrush = _WinAPI_CreateSolidBrush($iColorSet)
$hOldBrush = _WinAPI_SelectObject($hCDC, $hBrush)
_WinAPI_ExtFloodFill($hCDC, 0, 0, $iColorGet, 1)

_GDIPlus_ImageSaveToFile(_GDIPlus_BitmapCreateFromHBITMAP($hBmp), $sFile2)

_WinAPI_SelectObject($hCDC, $hOldBrush)
_WinAPI_DeleteObject($hBrush)
_WinAPI_SelectObject($hCDC, $hOldBmp)
_WinAPI_DeleteObject($hBmp)
_WinAPI_DeleteDC($hCDC)
_WinAPI_ReleaseDC(0, $hDDC)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_ShutDown()

Вариант 2
Код:
#include <GDIPlus.au3>

$sFile  = "sssb.png"
$sFile2 = "sssg.png"

_GDIPlus_Startup ()
$hImage = _GDIPlus_ImageLoadFromFile($sFile)
$iW = _GDIPlus_ImageGetWidth($hImage)
$iH = _GDIPlus_ImageGetHeight($hImage)
$hSrcBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
_GDIPlus_ImageDispose($hImage)

$hDC = _WinAPI_GetDC(0)
$hDestDC = _WinAPI_CreateCompatibleDC($hDC)
$hDestBmp = _WinAPI_CreateCompatibleBitmap($hDC, $iW, $iH)
$hOldDestBmp = _WinAPI_SelectObject($hDestDC, $hDestBmp)
$hSrcDC = _WinAPI_CreateCompatibleDC($hDC)
$hOldSrcBmp = _WinAPI_SelectObject($hSrcDC, $hSrcBmp)
_WinAPI_BitBlt($hDestDC, 0, 0, $iW, $iH, $hSrcDC, 0, 0, 0x00CC0020) ; $SRCCOPY

$iColorGet = _WinAPI_GetPixel($hDestDC, 0, 0)
$iColorSet = 0x008000

$hBrush = _WinAPI_CreateSolidBrush($iColorSet)
$hOldBrush = _WinAPI_SelectObject($hDestDC, $hBrush)
_WinAPI_ExtFloodFill($hDestDC, 0, 0, $iColorGet, 1)

_GDIPlus_ImageSaveToFile(_GDIPlus_BitmapCreateFromHBITMAP($hDestBmp), $sFile2)

_WinAPI_SelectObject($hDestDC, $hOldBrush)
_WinAPI_DeleteObject($hBrush)
_WinAPI_SelectObject($hDestDC, $hOldDestBmp)
_WinAPI_DeleteObject($hDestBmp)
_WinAPI_DeleteDC($hDestDC)
_WinAPI_SelectObject($hSrcDC, $hOldSrcBmp)
_WinAPI_DeleteObject($hSrcBmp)
_WinAPI_DeleteDC($hSrcDC)
_WinAPI_ReleaseDC(0, $hDC)
_GDIPlus_ShutDown()


Можно ли заменить на прозрачный пиксель?
Функция _WinAPI_ExtFloodFill() прозрачность не поддерживает. Смотрите
Код:
_GDIPlus_ImageAttributesSetColorKeys()


такое изображение "убивается"
Ничего не "убивается". Нормально работает - синий фон меняет на зелёный.
 
Автор
A

Andrey_A

Продвинутый
Сообщения
323
Репутация
68
InnI
Огромное спасибо, почти сам дошёл, не хватило _WinAPI_BitBlt
С остальным сам справлюсь: замена на прозрачный пиксель, прогон по периметру первого пикселя (когда фон прерывается), сохранение существующей прозрачности PNG (если есть)... Спасибо за основу!
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
Andrey_A
не хватило _WinAPI_BitBlt
С _WinAPI_BitBlt() это я перемудрил :smile:
Можно и без неё
Код:
#include <GDIPlus.au3>

$sFile  = "sssb.png"
$sFile2 = "sssg.png"

_GDIPlus_Startup ()
$hImage = _GDIPlus_ImageLoadFromFile($sFile)
$iW = _GDIPlus_ImageGetWidth($hImage)
$iH = _GDIPlus_ImageGetHeight($hImage)
$hBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
_GDIPlus_ImageDispose($hImage)

$hDC = _WinAPI_GetDC(0)
$hCDC = _WinAPI_CreateCompatibleDC($hDC)
$hOldBmp = _WinAPI_SelectObject($hCDC, $hBmp)

$iColorGet = _WinAPI_GetPixel($hCDC, 0, 0)
$iColorSet = 0x008000

$hBrush = _WinAPI_CreateSolidBrush($iColorSet)
$hOldBrush = _WinAPI_SelectObject($hCDC, $hBrush)
_WinAPI_ExtFloodFill($hCDC, 0, 0, $iColorGet, 1)

$hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBmp)
_GDIPlus_ImageSaveToFile($hImage, $sFile2)
_GDIPlus_ImageDispose($hImage)

_WinAPI_SelectObject($hCDC, $hOldBrush)
_WinAPI_DeleteObject($hBrush)
_WinAPI_SelectObject($hCDC, $hOldBmp)
_WinAPI_DeleteObject($hBmp)
_WinAPI_DeleteDC($hCDC)
_WinAPI_ReleaseDC(0, $hDC)
_GDIPlus_ShutDown()
 
A

Alofa

Гость
InnI сказал(а):
... Можно и без неё
Чудеса какие-то.

InnI
Код:
;$hDC = _WinAPI_GetDC(0) ; Это не обязательно...
$hCDC = _WinAPI_CreateCompatibleDC(0) ; можно и так

OffTopic:
InnI если вас не затруднит могли бы вы пояснить что делает _WinAPI_SelectObject(), в коде основной упор идет на это, а я не могу понять что происходит.
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
Alofa
В данном случае - да, согласен.

OffTopic:
что делает _WinAPI_SelectObject
При создании контекста устройства создаются объекты по умолчанию. Нас они не устраивают. Мы создаём нужный нам и выбираем его в DC (подменяем). После этого можем с ним работать. Чтобы этот объект удалить его нужно освободить. Поэтому "подменяем" его обратно объектом по умолчанию и удаляем.
http://www.vsokovikov.narod.ru/New_MSDN_API/D_context/graphic_objects.htm
 
Верх