123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- import numpy
- import Tool
- class Contrast(Tool.Tool):
- def on_init(self):
- self.id = "contrast"
- self.name = "Brightness and Contrast"
- self.icon_path = "ui/PF2_Icons/Contrast.png"
- self.properties = [
- Tool.Property("header", "Brightness and Contrast", "Header", None, has_toggle=False, has_button=False),
- Tool.Property("overall_brightness", "Brightness", "Slider", 0, max=50, min=-50),
- Tool.Property("overall_contrast", "Contrast", "Slider", 0, max=50, min=-50),
- Tool.Property("hist_stretch", "Histogram Strecthing", "Header", None, has_toggle=False, has_button=False),
- Tool.Property("left_stretch", "Left Stretch", "Slider", 0, max=50, min=-50),
- Tool.Property("right_stretch", "Right Stretch", "Slider", 0, max=50, min=-50),
- Tool.Property("tonal_header", "Tonal Brightness and Contrast", "Header", None, has_toggle=False, has_button=False),
- Tool.Property("highlight_brightness", "Highlight Brightness", "Slider", 0, max=50, min=-50),
- Tool.Property("highlight_contrast", "Highlight Contrast", "Slider", 0, max=50, min=-50),
- Tool.Property("midtone_brightness", "Midtone Brightness", "Slider", 0, max=50, min=-50),
- Tool.Property("midtone_contrast", "Midtone Contrast", "Slider", 0, max=50, min=-50),
- Tool.Property("shadow_brightness", "Shadow Brightness", "Slider", 0, max=50, min=-50),
- Tool.Property("shadow_contrast", "Shadow Contrast", "Slider", 0, max=50, min=-50),
- Tool.Property("tonal_header", "Tonal Bleed Fraction", "Header", None, has_toggle=False,
- has_button=False),
- Tool.Property("highlight_bleed", "Highlight Bleed", "Slider", 0.5, max=1, min=0.001),
- Tool.Property("midtone_bleed", "Midtone Bleed", "Slider", 0.5, max=1, min=0.001),
- Tool.Property("shadow_bleed", "Shadow Bleed", "Slider", 0.5, max=1, min=0.001),
- ]
- def on_update(self, im):
- # Apply Contrast Stuff
- if(not self.is_default()):
- ob = self.props["overall_brightness"].get_value()
- oc = -self.props["overall_contrast"].get_value()
- ls = -self.props["left_stretch"].get_value()
- rs = -self.props["right_stretch"].get_value()
- hb = self.props["highlight_brightness"].get_value()
- hc = self.props["highlight_contrast"].get_value()
- mb = self.props["midtone_brightness"].get_value()
- mc = self.props["midtone_contrast"].get_value()
- sb = self.props["shadow_brightness"].get_value()
- sc = self.props["shadow_contrast"].get_value()
- hbl = self.props["highlight_bleed"].get_value()
- mbl = self.props["midtone_bleed"].get_value()
- sbl = self.props["shadow_bleed"].get_value()
- # Add overall brightness
- hb += ob
- mb += ob
- sb += ob
- # Add overall contrast
- hc -= oc
- mc -= oc
- sc -= oc
- # Bits per pixel
- bpp = float(str(im.dtype).replace("uint", "").replace("float", ""))
- # Pixel value range
- np = float(2 ** bpp - 1)
- out = im.astype(numpy.float32)
- # Histogram Stretch
- if(rs != 0 or ls != 0):
- maxpxv = np + (rs/100.0)*np
- minpxv = 0 - (ls/100.0)*np
-
- out = (out - minpxv) * (np/float(maxpxv))
-
-
- # Highlights
- isHr = self._is_highlight(out, (3.0 / hbl))
- if (hc != 0.0):
- # Highlight Contrast
- hn = np + 4
- hc = (hc / 100.0) * np + 0.8
- out = (((hn * ((hc * isHr) + np)) / (np * (hn - (hc * isHr)))) * (out - np / 2.0) + np / 2.0)
- if (hb != 0.0):
- # Highlight Brightness
- out = (out + ((hb * isHr) / 100.0) * np)
- # Midtones
- isMr = self._is_midtone(out, (3.0 / mbl))
- if (mc != 0.0):
- # Midtone Contrast
- hn = np + 4
- mc = (mc / 100.0) * np + 0.8
- out = (((hn * ((mc * isMr) + np)) / (np * (hn - (mc * isMr)))) * (out - np / 2.0) + np / 2.0)
- if (mb != 0.0):
- # Midtone Brightness
- out = (out + ((mb * isMr) / 100.0) * np)
- # Shadows
- isSr = self._is_shadow(out, (3.0 / sbl))
- if (sc != 0.0):
- # Shadow Contrast
- hn = np + 4
- sc = (sc / 100.0) * np + 0.8
- out = (((hn * ((sc * isSr) + np)) / (np * (hn - (sc * isSr)))) * (out - np / 2.0) + np / 2.0)
- if (sb != 0.0):
- # Shadow Brightness
- out = (out + ((sb * isSr) / 100.0) * np)
- # Clip any values out of bounds
- out[out < 0.0] = 0.0
- out[out > np] = np
- return out.astype(im.dtype)
- else:
- return im
- def _is_highlight(self, image, bleed_value = 6.0):
- bleed = float(image.max() / bleed_value)
- mif = image.max() / 3.0 * 2.0
- icopy = image.copy()
- icopy[icopy < mif - bleed] = 0.0
- icopy[(icopy < mif) * (icopy != 0.0)] = ((mif - (icopy[(icopy < mif) * (icopy != 0.0)])) / bleed) * -1 + 1
- icopy[icopy >= mif] = 1.0
- return icopy
- def _is_midtone(self, image, bleed_value = 6.0):
- bleed = float(image.max() / bleed_value)
- mif = image.max() / 3.0
- mir = image.max() / 3.0 * 2.0
- icopy = image.copy()
- icopy[icopy < mif - bleed] = 0.0
- icopy[icopy > mir + bleed] = 0.0
- icopy[(icopy < mif) * (icopy != 0.0)] = ((mif - (icopy[(icopy < mif) * (icopy != 0.0)])) / bleed) * -1 + 1
- icopy[(icopy > mir) * (icopy != 0.0)] = (((icopy[(icopy > mir) * (icopy != 0.0)]) - mir) / bleed) * -1 + 1
- icopy[(icopy >= mif) * (icopy <= mir)] = 1.0
- return icopy
- def _is_shadow(self, image, bleed_value=6.0):
- bleed = float(image.max() / bleed_value)
- mir = image.max() / 3.0
- icopy = image.copy()
- icopy[icopy <= mir] = 1.0
- icopy[icopy > mir + bleed] = 0.0
- icopy[icopy > mir] = (((icopy[(icopy > mir) * (icopy != 0.0)]) - mir) / bleed) * -1 + 1
- return icopy
|