Compare commits

..

No commits in common. "e57d63f562f80785d00673c2cf93c00886d6b2dd" and "1d4e2242cd7ac37799d2c448f2aafa67c1326e50" have entirely different histories.

4 changed files with 41 additions and 63 deletions

View File

@ -2,11 +2,7 @@
A pythonesque binding to FloatImg library available at https://git.tetalab.org/tTh/FloatImg A pythonesque binding to FloatImg library available at https://git.tetalab.org/tTh/FloatImg
python-FloatImg requires a Python 3 implementation (tested with 3.6.9). python-FloatImg requires a quite recent Python 3 implementation (tested with 3.6.9).
Most function are wrapped into a similar api, sometime with a more consistent naming and an object-oriented approach.
Color values are specified using triplets of float values, like (128.5, 34.234, 242.23).
## Installation ## Installation
@ -44,15 +40,13 @@ Or completely duplicate an existing image:
new_img = img.clone() new_img = img.clone()
# with copying data # with copying data
new_img = img.clone(True) new_img = img.clone(1)
``` ```
### Image manipulation ### Image manipulation
#### Clear image #### Clear image
Reset all pixels to zero.
```python ```python
img.clear() img.clear()
``` ```
@ -66,13 +60,13 @@ img.copy_data(another_img)
#### Set pixel value #### Set pixel value
```python ```python
img.put(x, y, (r, g, b)) img.put_rgb(x, y, (r, g, b))
``` ```
#### Get pixel value #### Get pixel value
```python ```python
color = (r, g, b) = img.get(x, y) r, g, b = img.get_rgb(x, y)
``` ```
### File manipulation ### File manipulation
@ -80,13 +74,13 @@ color = (r, g, b) = img.get(x, y)
#### Dump image to file #### Dump image to file
```python ```python
img.dump("/tmp/image_dump") img.dump_to_file("/tmp/image_dump")
``` ```
#### Restore image data from a dump file #### Restore image data from a dump file
```python ```python
img.load("/tmp/image_dump") img.load_from_dump("/tmp/image_dump")
``` ```
#### Create a new image from a dump file #### Create a new image from a dump file
@ -96,8 +90,6 @@ img = floatimg.create_from_dump("/tmp/image_dump")
``` ```
#### Get dump metadata #### Get dump metadata
TODO create a FileInfo named tuple.
```python ```python
witdh, height, img_type = floatimg.fileinfos("/tmp/image_dump") witdh, height, img_type = floatimg.fileinfos("/tmp/image_dump")
``` ```

View File

@ -126,24 +126,22 @@ class FloatImg:
""" """
# proxy attributes to the C_FloatImg structure # proxy attributes to the C_FloatImg structure
# TODO: now more about them
magic = property(lambda self: self.c_img.magic) magic = property(lambda self: self.c_img.magic)
width = property(lambda self: self.c_img.width)
height = property(lambda self: self.c_img.height)
type_id = property(lambda self: self.c_img.type)
fval = property(lambda self: self.c_img.fval) fval = property(lambda self: self.c_img.fval)
count = property(lambda self: self.c_img.count) count = property(lambda self: self.c_img.count)
# oh yeah, really really sluggish access to pixels img.R[0].contents # oh yeah, really really sluggish access to pixels img.R[0].contents
# however, pixel data are not designed to be accessed this way # however, pixel data are not designed to be accessed this way
# R = property( R = property(
# lambda self: pointer(self.c_img.contents.R)[: self.width * self.height] lambda self: pointer(self.c_img.contents.R)[: self.width * self.height]
# ) )
####################################################################################################### #######################################################################################################
def __init__(self, c_img): def __init__(self, c_img):
self.c_img = c_img self.c_img = c_img
self.width = c_img.width
self.height = c_img.height
self.type_id = c_img.type
# convenient pointer for later calls to C library
self.c_img_p = ct.pointer(c_img) self.c_img_p = ct.pointer(c_img)
####################################################################################################### #######################################################################################################
@ -162,15 +160,11 @@ class FloatImg:
####################################################################################################### #######################################################################################################
def clear(self): def clear(self):
"""clear data""" """clear data"""
assert c_fimg_clear(self.c_img_p) == 0 return c_fimg_clear(self.c_img_p)
####################################################################################################### #######################################################################################################
def clone(self, copy_data=False): def clone(self, flags=0):
"""return a clone of the current instance""" """return a clone of the current instance"""
if copy_data:
flags = 1
else:
flags = 0
new_pic = C_FloatImg() new_pic = C_FloatImg()
assert c_fimg_clone(self.c_img_p, ct.pointer(new_pic), flags) == 0 assert c_fimg_clone(self.c_img_p, ct.pointer(new_pic), flags) == 0
return FloatImg(new_pic) return FloatImg(new_pic)
@ -186,18 +180,18 @@ class FloatImg:
return c_fimg_str_type(self.c_img.type).decode("utf-8") return c_fimg_str_type(self.c_img.type).decode("utf-8")
####################################################################################################### #######################################################################################################
def fill(self, color): def rgb_constant(self, r, v, b):
assert c_fimg_rgb_constant(self.c_img_p, *color) == 0 assert c_fimg_rgb_constant(self.c_img_p, r, v, b) == 0
####################################################################################################### #######################################################################################################
def get(self, x, y): def get_rgb(self, x, y):
"""get r,g,b triplet from a pixel""" """get r,g,b triplet from a pixel"""
rgb = (ct.c_float * 3)() rgb = (ct.c_float * 3)()
assert c_fimg_get_rgb(self.c_img_p, x, y, ct.pointer(rgb)) == 0 assert c_fimg_get_rgb(self.c_img_p, x, y, ct.pointer(rgb)) == 0
return rgb[:3] return rgb[:3]
####################################################################################################### #######################################################################################################
def put(self, x, y, rgb): def put_rgb(self, x, y, rgb):
"""put r,g,b triplet to a pixel""" """put r,g,b triplet to a pixel"""
# TODO may be a better way to create the array rather than iterating # TODO may be a better way to create the array rather than iterating
c_rgb = (ct.c_float * 3)() c_rgb = (ct.c_float * 3)()
@ -206,7 +200,7 @@ class FloatImg:
assert c_fimg_put_rgb(self.c_img_p, x, y, ct.pointer(c_rgb)) == 0 assert c_fimg_put_rgb(self.c_img_p, x, y, ct.pointer(c_rgb)) == 0
####################################################################################################### #######################################################################################################
def dump(self, fname): def dump_to_file(self, fname):
"""save data to a dump file""" """save data to a dump file"""
# TODO use system encoding instead of utf-8 # TODO use system encoding instead of utf-8
assert ( assert (
@ -217,7 +211,7 @@ class FloatImg:
) )
####################################################################################################### #######################################################################################################
def load(self, fname): def load_from_dump(self, fname):
"""load data from a dump. size and type have to be compatible""" """load data from a dump. size and type have to be compatible"""
assert ( assert (
c_fimg_load_from_dump( c_fimg_load_from_dump(
@ -226,12 +220,6 @@ class FloatImg:
== 0 == 0
) )
# TODO
# fimg_plot_rgb
# fimg_add_rgb
# export(fname, flags) : depending file extension, save to the correct format
########################################################################################################### ###########################################################################################################
def fileinfos(fname): def fileinfos(fname):
@ -264,7 +252,7 @@ def create_from_dump(fname):
"""Create a new instance from a dump file""" """Create a new instance from a dump file"""
witdh, height, img_type = fileinfos(fname) witdh, height, img_type = fileinfos(fname)
img = create(witdh, height, img_type) img = create(witdh, height, img_type)
img.load(fname) img.load_from_dump(fname)
return img return img

View File

@ -21,26 +21,26 @@ def test_clone():
width = 5 width = 5
height = 5 height = 5
img = floatimg.create(width, height, floatimg.RGB) img = floatimg.create(width, height, floatimg.RGB)
img.fill((127.0, 127.0, 127.0)) img.rgb_constant(127.0, 127.0, 127.0)
# clone without copying pixel values # clone without copying pixel values
img2 = img.clone(False) img2 = img.clone()
assert img.width == img2.width assert img.width == img2.width
assert img.height == img2.height assert img.height == img2.height
assert img.type_id == img2.type_id assert img.type_id == img2.type_id
# TODO inspect RVB and do pixel per pixel comparison # TODO inspect RVB and do pixel per pixel comparison
for y in range(height): for y in range(height):
for x in range(width): for x in range(width):
assert img.get(x, y) != img2.get(x, y) assert img.get_rgb(x, y) != img2.get_rgb(x, y)
img2 = img.clone(True) img2 = img.clone(1)
assert img.width == img2.width assert img.width == img2.width
assert img.height == img2.height assert img.height == img2.height
assert img.type_id == img2.type_id assert img.type_id == img2.type_id
# TODO inspect RVB and do pixel per pixel comparison # TODO inspect RVB and do pixel per pixel comparison
for y in range(height): for y in range(height):
for x in range(width): for x in range(width):
assert img.get(x, y) == img2.get(x, y) assert img.get_rgb(x, y) == img2.get_rgb(x, y)
def test_rgb_constant(): def test_rgb_constant():
@ -48,11 +48,10 @@ def test_rgb_constant():
height = 5 height = 5
color = [127.0, 127.0, 127.0] color = [127.0, 127.0, 127.0]
img = floatimg.create_rgb(width, height) img = floatimg.create_rgb(width, height)
img.fill(color) img.rgb_constant(*color)
for y in range(height): for y in range(height):
for x in range(width): for x in range(width):
assert img.get(x, y) == color assert img.get_rgb(x, y) == color
def test_copy_data(): def test_copy_data():
@ -60,27 +59,27 @@ def test_copy_data():
height = 5 height = 5
color = [127.0, 127.0, 127.0] color = [127.0, 127.0, 127.0]
img = floatimg.create_rgb(width, height) img = floatimg.create_rgb(width, height)
img.fill(color) img.rgb_constant(*color)
img2 = floatimg.create_rgb(width, height) img2 = floatimg.create_rgb(width, height)
img2.fill((64.0, 64.0, 64.0)) img2.rgb_constant(64.0, 64.0, 64.0)
img.copy_data(img2) img.copy_data(img2)
for y in range(height): for y in range(height):
for x in range(width): for x in range(width):
assert img.get(x, y) == img2.get(x, y) assert img.get_rgb(x, y) == img2.get_rgb(x, y)
def test_clear(): def test_clear():
width, height = 5, 5 width, height = 5, 5
color = [127.0, 127.0, 127.0] color = [127.0, 127.0, 127.0]
img = floatimg.create_rgb(width, height) img = floatimg.create_rgb(width, height)
img.fill(color) img.rgb_constant(*color)
img.clear() img.clear()
for y in range(height): for y in range(height):
for x in range(width): for x in range(width):
assert img.get(x, y) == [0.0, 0.0, 0.0] assert img.get_rgb(x, y) == [0.0, 0.0, 0.0]
def test_str_type(): def test_str_type():
@ -101,6 +100,6 @@ def test__str__():
def test_put_rgb(): def test_put_rgb():
width, height = 5, 5 width, height = 5, 5
img = floatimg.create_rgb(width, height) img = floatimg.create_rgb(width, height)
assert img.get(0, 0) == [0.0, 0.0, 0.0] assert img.get_rgb(0, 0) == [0.0, 0.0, 0.0]
img.put(0, 0, (127.0, 127.0, 127.0)) img.put_rgb(0, 0, [127.0, 127.0, 127.0])
assert img.get(0, 0) == [127.0, 127.0, 127.0] assert img.get_rgb(0, 0) == [127.0, 127.0, 127.0]

View File

@ -10,8 +10,8 @@ def create_dump():
width, height = 5, 5 width, height = 5, 5
img = floatimg.create_rgb(width, height) img = floatimg.create_rgb(width, height)
# fill it to have something to compare # fill it to have something to compare
img.fill((64.0, 64.0, 64.0)) img.rgb_constant(64.0, 64.0, 64.0)
img.dump(TEST_PATH) img.dump_to_file(TEST_PATH)
def test_dump_to_file(): def test_dump_to_file():
@ -34,11 +34,10 @@ def test_load():
create_dump() create_dump()
width, height = 5, 5 width, height = 5, 5
img = floatimg.create_rgb(width, height) img = floatimg.create_rgb(width, height)
img.load_from_dump(TEST_PATH)
img.load(TEST_PATH)
for y in range(height): for y in range(height):
for x in range(width): for x in range(width):
assert img.get(x, y) == [64.0, 64.0, 64.0] assert img.get_rgb(x, y) == [64.0, 64.0, 64.0]
os.remove(TEST_PATH) os.remove(TEST_PATH)
@ -47,5 +46,5 @@ def test_create():
img = floatimg.create_from_dump(TEST_PATH) img = floatimg.create_from_dump(TEST_PATH)
for y in range(img.height): for y in range(img.height):
for x in range(img.width): for x in range(img.width):
assert img.get(x, y) == [64.0, 64.0, 64.0] assert img.get_rgb(x, y) == [64.0, 64.0, 64.0]
os.remove(TEST_PATH) os.remove(TEST_PATH)