Compare commits
3 Commits
fbea9488f0
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
| 66b1c098f5 | |||
| 2342a9e2a8 | |||
| 4b57a41705 |
41
README.md
41
README.md
@@ -49,7 +49,7 @@ new_img = img.clone()
|
|||||||
new_img = img.clone(True)
|
new_img = img.clone(True)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Basic pixel manipulation
|
### Basic pixel operations
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# Get pixel value
|
# Get pixel value
|
||||||
@@ -65,7 +65,7 @@ img.clear()
|
|||||||
img.copy_data(another_img)
|
img.copy_data(another_img)
|
||||||
```
|
```
|
||||||
|
|
||||||
### File manipulation
|
### File operations
|
||||||
|
|
||||||
#### Raw dump files
|
#### Raw dump files
|
||||||
|
|
||||||
@@ -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
|
## Development
|
||||||
|
|
||||||
@@ -135,3 +157,18 @@ Ensure `floatimg` containing path is in the `PYTHONPATH`, this will run the test
|
|||||||
pytest --cov=floatimg tests/*
|
pytest --cov=floatimg tests/*
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Status
|
||||||
|
|
||||||
|
The goal is not to bind all the functions but essential ones too build a front-end with python-tkinter.
|
||||||
|
|
||||||
|
#### Done
|
||||||
|
|
||||||
|
- lib/fimg-core.c
|
||||||
|
- lib/fimg-file.c
|
||||||
|
- lib/operator.c
|
||||||
|
- funcs/exporter.c
|
||||||
|
- funcs/fimg-png.c
|
||||||
|
|
||||||
|
#### Partial
|
||||||
|
|
||||||
|
- lib/fimg-math.c
|
||||||
@@ -10,6 +10,7 @@ from floatimg.image import (
|
|||||||
create_from_dump,
|
create_from_dump,
|
||||||
create_from_png,
|
create_from_png,
|
||||||
fileinfos,
|
fileinfos,
|
||||||
|
Contrast
|
||||||
)
|
)
|
||||||
|
|
||||||
__version__ = "0.0.1"
|
__version__ = "0.0.1"
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
|
"""Binding bases"""
|
||||||
import ctypes as ct
|
import ctypes as ct
|
||||||
|
from enum import Enum
|
||||||
|
import logging
|
||||||
|
|
||||||
from floatimg.settings import LIB, PATH_ENCODING
|
from floatimg.settings import LIB, PATH_ENCODING
|
||||||
|
|
||||||
@@ -9,6 +12,16 @@ RGB = 3
|
|||||||
RGBA = 4 # may not be used
|
RGBA = 4 # may not be used
|
||||||
RGBZ = 99 # 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
|
# Type mapping
|
||||||
class C_FloatImg(ct.Structure):
|
class C_FloatImg(ct.Structure):
|
||||||
@@ -33,6 +46,8 @@ C_FloatImg._fields_ = [
|
|||||||
|
|
||||||
############################################################################################################
|
############################################################################################################
|
||||||
# declaration of input / output types for C binding of core functions
|
# declaration of input / output types for C binding of core functions
|
||||||
|
|
||||||
|
# fimg-core.c
|
||||||
c_fimgcreate = LIB.fimg_create
|
c_fimgcreate = LIB.fimg_create
|
||||||
c_fimgcreate.argtypes = (ct.POINTER(C_FloatImg), ct.c_int, ct.c_int, ct.c_int)
|
c_fimgcreate.argtypes = (ct.POINTER(C_FloatImg), ct.c_int, ct.c_int, ct.c_int)
|
||||||
c_fimgcreate.restype = 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
|
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 = 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.argtypes = (ct.POINTER(C_FloatImg), ct.c_char_p, ct.c_int)
|
||||||
c_fimg_dump_to_file.restype = 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
|
c_fimg_add_rgb.restype = ct.c_int
|
||||||
|
|
||||||
# operators
|
# # fimg-operators.c
|
||||||
c_fimg_add_3 = LIB.fimg_add_3
|
c_fimg_add_3 = LIB.fimg_add_3
|
||||||
c_fimg_add_3.argtypes = (
|
c_fimg_add_3.argtypes = (
|
||||||
ct.POINTER(C_FloatImg),
|
ct.POINTER(C_FloatImg),
|
||||||
@@ -176,6 +192,38 @@ c_fimg_load_from_png = LIB.fimg_load_from_png
|
|||||||
c_fimg_load_from_png.argtypes = (ct.c_char_p, ct.POINTER(C_FloatImg))
|
c_fimg_load_from_png.argtypes = (ct.c_char_p, ct.POINTER(C_FloatImg))
|
||||||
c_fimg_load_from_png.restype = ct.c_int
|
c_fimg_load_from_png.restype = ct.c_int
|
||||||
|
|
||||||
|
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:
|
class FloatImg:
|
||||||
@@ -209,6 +257,7 @@ class FloatImg:
|
|||||||
#######################################################################################################
|
#######################################################################################################
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
"""destroy the underlying structure. automattically called at instance destruction"""
|
"""destroy the underlying structure. automattically called at instance destruction"""
|
||||||
|
logging.debug("Destroy %s", self)
|
||||||
assert c_fimg_destroy(self.c_img) == 0
|
assert c_fimg_destroy(self.c_img) == 0
|
||||||
|
|
||||||
#######################################################################################################
|
#######################################################################################################
|
||||||
@@ -316,7 +365,7 @@ class FloatImg:
|
|||||||
"""return a new image with minimum pixel values per channel between current and parameter"""
|
"""return a new image with minimum pixel values per channel between current and parameter"""
|
||||||
res = self.clone(False)
|
res = self.clone(False)
|
||||||
# C code inverts comparison
|
# C code inverts comparison
|
||||||
assert c_fimg_maximum(self.c_img_p, img.c_img_p, res.c_img_p) == 0
|
assert c_fimg_minimum(self.c_img_p, img.c_img_p, res.c_img_p) == 0
|
||||||
return res
|
return res
|
||||||
|
|
||||||
#######################################################################################################
|
#######################################################################################################
|
||||||
@@ -324,7 +373,7 @@ class FloatImg:
|
|||||||
"""return a new image with maximum pixel values per channel between current and parameter"""
|
"""return a new image with maximum pixel values per channel between current and parameter"""
|
||||||
res = self.clone(False)
|
res = self.clone(False)
|
||||||
# C code inverts comparison
|
# C code inverts comparison
|
||||||
assert c_fimg_minimum(self.c_img_p, img.c_img_p, res.c_img_p) == 0
|
assert c_fimg_maximum(self.c_img_p, img.c_img_p, res.c_img_p) == 0
|
||||||
return res
|
return res
|
||||||
|
|
||||||
#######################################################################################################
|
#######################################################################################################
|
||||||
@@ -337,6 +386,23 @@ class FloatImg:
|
|||||||
== 0
|
== 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#######################################################################################################
|
||||||
|
def maxvalue(self):
|
||||||
|
"""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):
|
def fileinfos(fname):
|
||||||
|
|||||||
35
tests/contrast.py
Normal file
35
tests/contrast.py
Normal 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
|
||||||
12
tests/maths.py
Normal file
12
tests/maths.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
"""test of core functions """
|
||||||
|
|
||||||
|
import floatimg
|
||||||
|
|
||||||
|
def test_maxvaalue():
|
||||||
|
width = 5
|
||||||
|
height = 5
|
||||||
|
|
||||||
|
img = floatimg.create_rgb(width, height)
|
||||||
|
color = (255.0, 255.0, 255.0)
|
||||||
|
img.put(2,2, color)
|
||||||
|
assert img.maxvalue() == 255.0
|
||||||
Reference in New Issue
Block a user