# Is it possible to revert preapplied alpha blend and find original color?

I have a color 0xADADAD, it was originally white, now it's grey, because it's been alpha blended with 30%(0.3 alpha) black + the unknown original value. In this case I know from lots of trial and error that the original color was 0xF8F8F8

Problem is I have over 20 other colors that need to be fixed like this, but I have no accurate way of finding the original colors. Is there a formula I can do to figure this out? Is it even possible?

• Given they're both in hex, if a linear transformation were applied, the number at position 1, 3, and 5 (if it's based at 1) would be shifted down by 5 while the ones at 2, 4, and 6 are shifted up by 5. If any other transformation occurred, it's impossible to tell from one example Commented Oct 4, 2016 at 1:57
• Is position 1 0xA, therefore I should subtract the value at position 5 (also 0xA) from it, or the actual number 5? Are we shifting bits? Sorry, these terms confuse me. Commented Oct 4, 2016 at 3:18
• @AlienX: "0x" is a prefix that indicates you are dealing with base-16 values (aka HEX) it is also common to use "x" or "#" as a prefix. An RGB hex color is a triplet of (3) 2-character values. So "first position" in your example is Red Value=AD (not 0xA). Occasionally you will see someone use a shorthand for values such as "FFF" this is really "x0F0F0F" Commented Oct 4, 2016 at 16:54
• Did my post really sound like I don't know what hex is? This still changes nothing, if pos 1, 2, 3 are my hex values what the heck is pos 4, 5, and 6? Commented Oct 4, 2016 at 22:53

Yeah its possible i made a quick change to the code in this post and came up with following very sloppy python 2.X code:

``````from Tkinter import *
import struct

def ablend(a, fg, bg):
return ((1-a)*fg[0]+a*bg[0],
(1-a)*fg[1]+a*bg[1],
(1-a)*fg[2]+a*bg[2])

def aunblend(a, result, bg):
return ((result[0]-a*bg[0])/(1-a),
(result[1]-a*bg[1])/(1-a),
(result[2]-a*bg[2])/(1-a))

class findUnblendedColor(object):

def __init__(self, root):
self.bg=(255,255,255)
self.alpha = 0.3

l = Label(root, text="alpha:")
l.grid(row=0, column=0)
label = '0.3'
self.a = Text(root, height=1,
relief=FLAT,
width=20,)
self.a.insert(1.0, label)
self.a.grid(row=0, column=1)
self.a.bind("<Return>", self.update)

l = Label(root, text="Result:")
l.grid(row=1, column=0)
label = '#%02x%02x%02x' % self.fg
self.e = Text(root, height=1,
relief=FLAT,
width=20,
background=label)
self.e.insert(1.0, label)
self.e.grid(row=1, column=1)
self.e.bind("<Return>", self.update)

l = Label(root, text="BG:")
l.grid(row=2, column=0)

label = '#%02x%02x%02x' % self.bg
self.b = Text(root, height=1,
relief=FLAT,
width=20,
background=label)
self.b.insert(1.0, label)
self.b.grid(row=2, column=1)
self.b.bind("<Return>", self.update)

l = Label(root, text="FG:")
l.grid(row=3, column=0)

col = aunblend(self.alpha, self.fg, self.bg)
label = '#%02x%02x%02x' % col
self.f = Text(root, height=1,
relief=FLAT,
width=20,
background=label)
self.f.insert(1.0, label)
self.f.configure(state='disabled')
self.f.grid(row=3, column=1)

l = Label(root, text="verify:")
l.grid(row=4, column=0)

col = ablend(self.alpha, col, self.bg)
label = '#%02x%02x%02x' % col
self.g = Text(root, height=1,
relief=FLAT,
width=20,
background=label)
self.g.insert(1.0, label)
self.g.configure(state='disabled')
self.g.grid(row=4, column=1)

def update(self, event):
data = self.e.get(1.0,END)
self.e.delete(1.0, END)
self.e.insert(END, data[:-1])

data2 = self.b.get(1.0,END)
self.b.delete(1.0, END)
self.b.insert(END, data2[:-1])

try:
self.alpha = float(self.a.get(1.0,END))

self.fg = struct.unpack('BBB',data[1:-1].decode('hex'))
self.e.configure(background=data[:-1])

self.bg = struct.unpack('BBB',data2[1:-1].decode('hex'))
self.b.configure(background=data2[:-1])

col = aunblend(self.alpha, self.fg, self.bg)
self.f.configure(state='normal')
self.g.configure(state='normal')

if all(i <= 256 and i >= 0 for i in col):
label = '#%02x%02x%02x' % col
self.f.configure(background=label)

col = ablend(self.alpha, col, self.bg)
label2 = '#%02x%02x%02x' % col
self.g.configure(background=label2)
else:
label = "out of range"
label2 = "out of range"
self.f.delete(1.0, END)
self.f.insert(END, label)
self.g.delete(1.0, END)
self.g.insert(END, label2)

self.f.configure(state='disabled')
self.g.configure(state='disabled')
except Exception as ex:
print "error "+repr(type(ex))
pass

return 'break'

root = Tk()
root.title("unblend")
findUnblendedColor(root)

root.mainloop()
``````

And you get a window that allows you to type alpha, resulting color and background.

Image 1: Dialog of program