add contrast binding

This commit is contained in:
Mutah 2021-05-20 08:34:10 +02:00
parent 2342a9e2a8
commit 66b1c098f5
4 changed files with 117 additions and 2 deletions

View File

@ -118,6 +118,28 @@ res_img = img.max(img2)
```
## Contrast operations
Contrast types are defined in the Contrast enumeration:
```
floatimg.Contrast.SQRT
floatimg.Contrast.POW2
floatimg.Contrast.COS01
floatimg.Contrast.COS010
```
To apply contrast:
```
# Return a new image
res = img.contrast(value, floatimg.Contrast.SQRT)
# set contrast in-place
img.contrast(value, floatimg.Contrast.SQRT, True)
```
## Development

View File

@ -10,6 +10,7 @@ from floatimg.image import (
create_from_dump,
create_from_png,
fileinfos,
Contrast
)
__version__ = "0.0.1"

View File

@ -1,4 +1,7 @@
"""Binding bases"""
import ctypes as ct
from enum import Enum
import logging
from floatimg.settings import LIB, PATH_ENCODING
@ -9,6 +12,16 @@ RGB = 3
RGBA = 4 # may not be used
RGBZ = 99 # may not be used
############################################################################################################
# Contrast enumeration
class Contrast(Enum):
NONE = 0
SQRT = 1
POW2 = 2
COS01 = 3
COS010 = 4
############################################################################################################
# Type mapping
class C_FloatImg(ct.Structure):
@ -33,6 +46,8 @@ C_FloatImg._fields_ = [
############################################################################################################
# declaration of input / output types for C binding of core functions
# fimg-core.c
c_fimgcreate = LIB.fimg_create
c_fimgcreate.argtypes = (ct.POINTER(C_FloatImg), ct.c_int, ct.c_int, ct.c_int)
c_fimgcreate.restype = ct.c_int
@ -99,6 +114,7 @@ c_fimg_rgb_constant.argtypes = (
)
c_fimg_rgb_constant.restype = ct.c_int
# fimg-file.c
c_fimg_dump_to_file = LIB.fimg_dump_to_file
c_fimg_dump_to_file.argtypes = (ct.POINTER(C_FloatImg), ct.c_char_p, ct.c_int)
c_fimg_dump_to_file.restype = ct.c_int
@ -122,7 +138,7 @@ c_fimg_add_rgb.argtypes = (
)
c_fimg_add_rgb.restype = ct.c_int
# operators
# # fimg-operators.c
c_fimg_add_3 = LIB.fimg_add_3
c_fimg_add_3.argtypes = (
ct.POINTER(C_FloatImg),
@ -180,6 +196,35 @@ c_fimg_get_maxvalue = LIB.fimg_get_maxvalue
c_fimg_get_maxvalue.argtypes = (ct.POINTER(C_FloatImg),)
c_fimg_get_maxvalue.restype = ct.c_float
# contrast
c_fimg_square_root = LIB.fimg_square_root
c_fimg_square_root.argtypes = (
ct.POINTER(C_FloatImg),
ct.POINTER(C_FloatImg),
ct.c_double,
)
c_fimg_square_root.restype = ct.c_int
c_fimg_power_2 = LIB.fimg_power_2
c_fimg_power_2.argtypes = (ct.POINTER(C_FloatImg), ct.POINTER(C_FloatImg), ct.c_double)
c_fimg_power_2.restype = ct.c_int
c_fimg_cos_01 = LIB.fimg_cos_01
c_fimg_cos_01.argtypes = (ct.POINTER(C_FloatImg), ct.POINTER(C_FloatImg), ct.c_double)
c_fimg_cos_01.restype = ct.c_int
c_fimg_cos_010 = LIB.fimg_cos_010
c_fimg_cos_010.argtypes = (ct.POINTER(C_FloatImg), ct.POINTER(C_FloatImg), ct.c_double)
c_fimg_cos_010.restype = ct.c_int
# contrast function map
CONTRAST_FUNC_DICT = {
Contrast.SQRT: c_fimg_square_root,
Contrast.POW2: c_fimg_power_2,
Contrast.COS01: c_fimg_cos_01,
Contrast.COS010: c_fimg_cos_010,
}
############################################################################################################
class FloatImg:
"""
@ -212,6 +257,7 @@ class FloatImg:
#######################################################################################################
def destroy(self):
"""destroy the underlying structure. automattically called at instance destruction"""
logging.debug("Destroy %s", self)
assert c_fimg_destroy(self.c_img) == 0
#######################################################################################################
@ -322,7 +368,6 @@ class FloatImg:
assert c_fimg_minimum(self.c_img_p, img.c_img_p, res.c_img_p) == 0
return res
#######################################################################################################
def max(self, img):
"""return a new image with maximum pixel values per channel between current and parameter"""
@ -346,6 +391,18 @@ class FloatImg:
"""return the maximum value for any channel in the image"""
return c_fimg_get_maxvalue(self.c_img_p)
#######################################################################################################
def contrast(self, max_value, contrast_id=Contrast.SQRT, in_place=False):
""""""
func = CONTRAST_FUNC_DICT[contrast_id]
dest = None
dest_c_img = None
if not in_place:
dest = self.clone(False)
dest_c_img = dest.c_img_p
assert (func(self.c_img, dest_c_img, max_value)) == 0
return dest
###########################################################################################################
def fileinfos(fname):

35
tests/contrast.py Normal file
View File

@ -0,0 +1,35 @@
import floatimg
import logging
def test_square():
width, height = 5, 5
color = [127.0, 127.0, 127.0]
img = floatimg.create_rgb(width, height)
img.fill(color)
img.put(2, 2, [200, 200, 200])
result_dict = {
floatimg.Contrast.SQRT: (
[225.83180236816406, 225.83180236816406, 225.83180236816406],
[179.9583282470703, 179.9583282470703, 179.9583282470703],
),
floatimg.Contrast.POW2: (
[156.8627471923828, 156.8627471923828, 156.8627471923828],
[63.250980377197266, 63.250980377197266, 63.250980377197266],
),
floatimg.Contrast.COS01: (
[226.83277893066406, 226.83277893066406, 226.83277893066406],
[126.71460723876953, 126.71460723876953, 126.71460723876953],
),
floatimg.Contrast.COS010: (
[100.2235336303711, 100.2235336303711, 100.2235336303711],
[254.99032592773438, 254.99032592773438, 254.99032592773438],
),
}
for contrast_type, (center, outer) in result_dict.items():
res = img.contrast(255, contrast_type)
assert res.get(2, 2) == center
assert res.get(2, 3) == outer