Gdip_ExpandColor - Remove fringe from images with transparent color

Post your working scripts, libraries and tools
User avatar
boiler
Posts: 5668
Joined: 21 Dec 2014, 02:44

Gdip_ExpandColor - Remove fringe from images with transparent color

03 Jul 2020, 11:52

I wrote this in response to an Ask For Help post, and I thought I would post it here in case others find it useful. It grows the specified color by one pixel in all directions which helps remove fringe that can result when using a transparent color.
Before and after example

Function:

Code: Select all

/*
	Gdip_ExpandColor grows the specified color by one pixel in all directions.
	Helps remove fringe that can result when using a transparent color.

	pBitMap is the pointer to your bitmap which will be modified directly

	color parameter can be RGB or BGR and can include alpha channel or not.
	Alpha channel will be added/changed to be 0xFF.

	Example: Gdip_ExpandColor(pBitmap, 0xA024BA)

	by boiler
	2020-07-03
*/

Gdip_ExpandColor(pBitmap, color) {
	if (A_PtrSize = 4)
		expandColorMCodeBase64 := ""
		. "2,x86:VYnlg+wQgU0MAAAA/8dF+AAAAADrWcdF/AEAAADrRItF"
		. "+A+vRRCJwotF/AHQiUX0i0X0jRSFAAAAAItFCAHQiwA7RQx1GY"
		. "tF9AX///8/jRSFAAAAAItFCAHCi0UMiQKDRfwBi0X8O0UQfLSD"
		. "RfgBi0X4O0UUfJ/HRfgAAAAA61/HRfwAAAAA60eLRRArRfyJwo"
		. "tF+A+vRRAB0IlF9ItF9AX///8/jRSFAAAAAItFCAHQiwA7RQx1"
		. "FItF9I0UhQAAAACLRQgBwotFDIkCg0X8AYtFEIPoATtF/H+ug0"
		. "X4AYtF+DtFFHyZx0X4AAAAAOtcx0X8AAAAAOtHi0UUK0X4D69F"
		. "EInCi0X8AdCJRfSLRfSNFIUAAAAAi0UIAdCLADtFDHUZi1UQi0"
		. "X0AdCNFIUAAAAAi0UIAcKLRQyJAoNF/AGLRfw7RRB8sYNF+AGL"
		. "RRSD6AE7Rfh/mcdF+AEAAADrW8dF/AAAAADrRotF+A+vRRCJwo"
		. "tF/AHQiUX0i0X0jRSFAAAAAItFCAHQiwA7RQx1G4tFEItV9CnC"
		. "idCNFIUAAAAAi0UIAcKLRQyJAoNF/AGLRfw7RRB8soNF+AGLRf"
		. "g7RRR8nZDJww=="
	else
		expandColorMCodeBase64 := ""
		. "2,x64:VUiJ5UiD7BBIiU0QiVUYRIlFIESJTSiBTRgAAAD/x0X4"
		. "AAAAAOtfx0X8AQAAAOtKi0X4D69FIInCi0X8AdCJRfSLRfRIjR"
		. "SFAAAAAEiLRRBIAdCLADtFGHUci0X0g+gBicBIjRSFAAAAAEiL"
		. "RRBIAcKLRRiJAoNF/AGLRfw7RSB8roNF+AGLRfg7RSh8mcdF+A"
		. "AAAADrZcdF/AAAAADrTYtFICtF/InCi0X4D69FIAHQiUX0i0X0"
		. "g+gBicBIjRSFAAAAAEiLRRBIAdCLADtFGHUXi0X0SI0UhQAAAA"
		. "BIi0UQSAHCi0UYiQKDRfwBi0Ugg+gBO0X8f6iDRfgBi0X4O0Uo"
		. "fJPHRfgAAAAA62THRfwAAAAA60+LRSgrRfgPr0UgicKLRfwB0I"
		. "lF9ItF9EiNFIUAAAAASItFEEgB0IsAO0UYdR6LVSCLRfQB0InA"
		. "SI0UhQAAAABIi0UQSAHCi0UYiQKDRfwBi0X8O0UgfKmDRfgBi0"
		. "Uog+gBO0X4f5HHRfgBAAAA62PHRfwAAAAA606LRfgPr0UgicKL"
		. "RfwB0IlF9ItF9EiNFIUAAAAASItFEEgB0IsAO0UYdSCLRSCLVf"
		. "QpwonQicBIjRSFAAAAAEiLRRBIAcKLRRiJAoNF/AGLRfw7RSB8"
		. "qoNF+AGLRfg7RSh8lZBIg8QQXcOQ"

	expandColorMCode := BentschiMCode(expandColorMCodeBase64)
	Gdip_GetImageDimensions(pBitmap, w, h)
	Gdip_LockBits(pBitmap, 0, 0, w, h, stride, scan, bitmapData)
	DllCall(expandColorMCode, "uint", scan, "uint", color, "int", w, "int", h, "cdecl")
	Gdip_UnlockBits(pBitmap, bitmapData)
}

BentschiMCode(mcode)
{
  static e := {1:4, 2:1}, c := (A_PtrSize=8) ? "x64" : "x86"
  if (!regexmatch(mcode, "^([0-9]+),(" c ":|.*?," c ":)([^,]+)", m))
    return
  if (!DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", 0, "uint", e[m1], "ptr", 0, "uint*", s, "ptr", 0, "ptr", 0))
    return
  p := DllCall("GlobalAlloc", "uint", 0, "ptr", s, "ptr")
  if (c="x64")
    DllCall("VirtualProtect", "ptr", p, "ptr", s, "uint", 0x40, "uint*", op)
  if (DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", 0, "uint", e[m1], "ptr", p, "uint*", s, "ptr", 0, "ptr", 0))
    return p
  DllCall("GlobalFree", "ptr", p)
}

Demo:

Code: Select all

#Include <gdip_all>
#Include Gdip_ExpandColor.ahk

pToken := Gdip_Startup()

pBitmap := Gdip_CreateBitmapFromFile("peter_griffin.png")
Gdip_ExpandColor(pBitmap, 0xc040c0)
Gdip_SaveBitmapToFile(pBitmap, "peter_griffin_trimmed.png")
Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)

Gui, +HwndGuiID
Gui, Color, c040c0
Gui, Add, Picture,, peter_griffin.png
Gui, Add, Picture, x+5 yp, peter_griffin_trimmed.png
Gui, Show
WinSet, TransColor, c040c0, ahk_id %GuiID%
return

Esc::ExitApp

Image used for demo

Source for MCode:

Code: Select all

unsigned int Gdip_ExpandColor(unsigned int *bitmap, unsigned int targetColor, int w, int h)
{
	int x, y;
	unsigned int p;

	targetColor = targetColor | 0xFF000000; // add A channel

	// replace all the colors to the left of the target color:
	for (y = 0; y < h; ++y)	{
		for (x = 1; x < w; ++x) {
			p = x + y * w;
			if (bitmap[p] == targetColor)
				bitmap[p - 1] = targetColor;
		}
	}

	// replace all the colors to the right of the target color:
	for (y = 0; y < h; ++y)	{
		for (x = 0; x < w - 1; ++x) {
			p = w - x + y * w;
			if (bitmap[p - 1] == targetColor)
				bitmap[p] = targetColor;
		}
	}

	// replace all the colors below the target color:
	for (y = 0; y < h - 1; ++y)	{
		for (x = 0; x < w; ++x) {
			p = x + (h - y) * w;
			if (bitmap[p] == targetColor)
				bitmap[p + w] = targetColor;
		}
	}

	// replace all the colors above the target color:
	for (y = 1; y < h; ++y)	{
		for (x = 0; x < w; ++x) {
			p = x + y * w;
			if (bitmap[p] == targetColor)
				bitmap[p - w] = targetColor;
		}
	}
}
Last edited by boiler on 03 Jul 2020, 14:44, edited 3 times in total.
User avatar
boiler
Posts: 5668
Joined: 21 Dec 2014, 02:44

Re: Gdip_ExpandColor

03 Jul 2020, 13:40

Edited the first post to fix an error and replace sample with a better example.
User avatar
elModo7
Posts: 167
Joined: 01 Sep 2017, 02:38
GitHub: elModo7
Location: Spain
Contact:

Re: Gdip_ExpandColor - Remove fringe from images with transparent color

07 Jul 2020, 06:28

Looks dope!
Thank you for sharing!
:beer:
User avatar
boiler
Posts: 5668
Joined: 21 Dec 2014, 02:44

Re: Gdip_ExpandColor - Remove fringe from images with transparent color

07 Jul 2020, 09:01

You’re welcome. It may not be needed often, but when the situation arises, it can make a big difference.
User avatar
Chunjee
Posts: 608
Joined: 18 Apr 2014, 19:05
GitHub: Chunjee

Re: Gdip_ExpandColor - Remove fringe from images with transparent color

09 Jul 2020, 10:56

wow. Looks clean. I have had this issue before. Thanks! :thumbup:

Return to “Scripts and Functions”

Who is online

Users browsing this forum: Google [Bot] and 41 guests