From d8cb79f9d9314f3285a155bda473a06b9e8f3459 Mon Sep 17 00:00:00 2001 From: Marta Iborra Date: Mon, 11 Dec 2023 12:00:38 +0100 Subject: [PATCH 1/6] Use pillow params when possible. WIP. --- blosc2_grok/__init__.py | 44 +++++++++++------------------------------ 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/blosc2_grok/__init__.py b/blosc2_grok/__init__.py index d594efb..b6880e5 100644 --- a/blosc2_grok/__init__.py +++ b/blosc2_grok/__init__.py @@ -17,22 +17,6 @@ __version__ = "0.0.2.dev" -class GrkProgOrder(Enum): - """ - Available grok progression orders. - `L` : layer - `R` : resolution - `C` : component - `P` : precinct - """ - - LRCP = 0 - RLCP = 1 - RPCL = 2 - PCRL = 3 - CPRL = 4 - - class GrkFileFmt(Enum): """ Supported file formats in grok. @@ -125,28 +109,24 @@ def destroy(): # TODO: change these for real defaults params_defaults = { - 'tile_size_on': False, - 'tx0': 0, - 'ty0': 0, - 't_width': 0, - 't_height': 0, + 'tile_size': (0, 0), + 'tile_offset': (0, 0), # 'numlayers': 0, # blosc2_grok C func set_params will still receive this param 'quality_mode': None, 'quality_layers': np.zeros(0, dtype=np.float64), 'csty': 0, 'numgbits': 2, - 'prog_order': GrkProgOrder.LRCP, - 'numpocs': 0, - 'numresolution': 6, - 'cblockw_init': 64, - 'cblockh_init': 64, - 'cblk_sty': 0, + 'progression': "LRCP", + 'num_resolutions': 6, + 'codeblock_size': (64, 64), + 'codeblock_style': 0, # 'irreversible': False, # blosc2_grok C func set_params will still receive this param 'roi_compno': -1, 'roi_shift': 0, 'res_spec': 0, - 'image_offset_x0': 0, - 'image_offset_y0': 0, + 'prcw_init': np.zeros(0, dtype=np.int_), + 'prch_init': np.zeros(0, dtype=np.int_), + 'offset': (0, 0), 'subsampling_dx': 1, 'subsampling_dy': 1, 'decod_format': GrkFileFmt.GRK_FMT_UNK, @@ -183,10 +163,10 @@ def set_params_defaults(**kwargs): params.update(kwargs) args = params.values() args = list(args) - if args[5] is not None: - args[5] = args[5].encode('utf-8') + if args[2] is not None: + args[2] = args[2].encode('utf-8') # Get number of layers - args.insert(5, args[6].shape[0]) + args.insert(2, args[3].shape[0]) else: args.insert(5, 0) From 3d83208bd83fcfb668313d39399e927617475d9e Mon Sep 17 00:00:00 2001 From: Marta Iborra Date: Tue, 12 Dec 2023 10:15:55 +0100 Subject: [PATCH 2/6] Use pillow params when possible --- blosc2_grok/__init__.py | 53 +++++++++++++++--------- src/blosc2_grok.cpp | 91 +++++++++++++++++++++++++---------------- src/blosc2_grok.h | 11 +++-- 3 files changed, 95 insertions(+), 60 deletions(-) diff --git a/blosc2_grok/__init__.py b/blosc2_grok/__init__.py index b6880e5..520a4bd 100644 --- a/blosc2_grok/__init__.py +++ b/blosc2_grok/__init__.py @@ -119,18 +119,18 @@ def destroy(): 'progression': "LRCP", 'num_resolutions': 6, 'codeblock_size': (64, 64), + # 10 - 19 'codeblock_style': 0, # 'irreversible': False, # blosc2_grok C func set_params will still receive this param 'roi_compno': -1, 'roi_shift': 0, - 'res_spec': 0, - 'prcw_init': np.zeros(0, dtype=np.int_), - 'prch_init': np.zeros(0, dtype=np.int_), + 'precinct_size': (0, 0), 'offset': (0, 0), 'subsampling_dx': 1, 'subsampling_dy': 1, 'decod_format': GrkFileFmt.GRK_FMT_UNK, 'cod_format': GrkFileFmt.GRK_FMT_UNK, + # 20 - 29 'enableTilePartGeneration': False, 'newTilePartProgressionDivider': 0, 'mct': 0, @@ -141,6 +141,7 @@ def destroy(): 'apply_icc_': False, 'rateControlAlgorithm': GrkRateControl.PCRD_OPT, 'numThreads': 0, + # 30 - 37 'deviceId': 0, 'duration': 0, 'kernelBuildOptions': 0, @@ -163,25 +164,39 @@ def set_params_defaults(**kwargs): params.update(kwargs) args = params.values() args = list(args) - if args[2] is not None: - args[2] = args[2].encode('utf-8') - # Get number of layers - args.insert(2, args[3].shape[0]) - else: - args.insert(5, 0) - args.insert(16, False) # irreversible param is deactivated for now + # Get number of layers + args.insert(2, 0) + if args[3] is not None: + args[3] = args[3].encode('utf-8') + args[2] = args[4].shape[0] - args[10] = args[10].value - args[24] = args[24].value - args[25] = args[25].value - args[31] = args[31].value - args[34] = args[34].value + args.insert(11, False) # irreversible param is deactivated for now + + args[7] = args[7].encode('utf-8') - lib.blosc2_grok_set_default_params.argtypes = ([ctypes.c_bool] + [ctypes.c_int] * 5 + [ctypes.c_char_p] + - [np.ctypeslib.ndpointer(dtype=np.float64)] + - [ctypes.c_int] * 8 + [ctypes.c_bool] + [ctypes.c_int] * 9 + - [ctypes.c_bool] + [ctypes.c_int] * 6 + [ctypes.c_bool] + + # Convert tuples to desired NumPy arrays + args[0] = np.array(args[0], dtype=np.int64) + args[1] = np.array(args[1], dtype=np.int64) + args[9] = np.array(args[9], dtype=np.int64) + args[14] = np.array(args[14], dtype=np.int64) + args[15] = np.array(args[15], dtype=np.int64) + + # Get value of enumerate + args[18] = args[18].value + args[19] = args[19].value + args[25] = args[25].value + args[28] = args[28].value + + lib.blosc2_grok_set_default_params.argtypes = ([np.ctypeslib.ndpointer(dtype=np.int64)] * 2 + + [ctypes.c_int] + [ctypes.c_char_p] + [np.ctypeslib.ndpointer(dtype=np.float64)] + + [ctypes.c_int] * 2 + [ctypes.c_char_p] + + [ctypes.c_int] + [np.ctypeslib.ndpointer(dtype=np.int64)] + [ctypes.c_int] + + [ctypes.c_bool] + [ctypes.c_int] * 2 + [np.ctypeslib.ndpointer(dtype=np.int64)] + + [np.ctypeslib.ndpointer(dtype=np.int64)] + [ctypes.c_int] + + [ctypes.c_int] * 2 + + [ctypes.c_int] + [ctypes.c_bool] + + [ctypes.c_int] * 6 + [ctypes.c_bool] + [ctypes.c_int] * 6 + [ctypes.c_bool] * 4) lib.blosc2_grok_set_default_params(*args) diff --git a/src/blosc2_grok.cpp b/src/blosc2_grok.cpp index 2a3db3d..893fceb 100644 --- a/src/blosc2_grok.cpp +++ b/src/blosc2_grok.cpp @@ -154,6 +154,9 @@ int blosc2_grok_encoder( delete[] components; grk_object_unref(codec); grk_object_unref(&image->obj); + if (codec_params == NULL) { + free(streamParams); + } return size; } @@ -245,26 +248,29 @@ void blosc2_grok_init(uint32_t nthreads, bool verbose) { grk_compress_set_default_params(&GRK_CPARAMETERS_DEFAULTS); } -void blosc2_grok_set_default_params(bool tile_size_on, int tx0, int ty0, int t_width, int t_height, - int numlayers, char *quality_mode, double *quality_layers, - int csty, int numgbits, GRK_PROG_ORDER prog_order, - int numpocs, - int numresolution, int cblockw_init, int cblockh_init, int cblk_sty, - bool irreversible, int roi_compno, int roi_shift, int res_spec, - int image_offset_x0, int image_offset_y0, int subsampling_dx, - int subsampling_dy, GRK_SUPPORTED_FILE_FMT decod_format, - GRK_SUPPORTED_FILE_FMT cod_format, bool enableTilePartGeneration, - int newTilePartProgressionDivider, int mct, int max_cs_size, - int max_comp_size, int rsiz, int framerate, - bool apply_icc_, - GRK_RATE_CONTROL_ALGORITHM rateControlAlgorithm, int numThreads, int deviceId, - int duration, int kernelBuildOptions, int repeats, bool writePLT, - bool writeTLM, bool verbose, bool sharedMemoryInterface) { - GRK_CPARAMETERS_DEFAULTS.tile_size_on = tile_size_on; - GRK_CPARAMETERS_DEFAULTS.tx0 = tx0; - GRK_CPARAMETERS_DEFAULTS.ty0 = ty0; - GRK_CPARAMETERS_DEFAULTS.t_width = t_width; - GRK_CPARAMETERS_DEFAULTS.t_height = t_height; +void blosc2_grok_set_default_params(const int64_t *tile_size, const int64_t *tile_offset, + int numlayers, char *quality_mode, double *quality_layers, + int csty, int numgbits, char *progression, + int num_resolutions, int64_t *codeblock_size, int codeblock_style, + bool irreversible, int roi_compno, int roi_shift, const int64_t *precinct_size, + const int64_t *offset, int subsampling_dx, + int subsampling_dy, GRK_SUPPORTED_FILE_FMT decod_format, + GRK_SUPPORTED_FILE_FMT cod_format, bool enableTilePartGeneration, + int newTilePartProgressionDivider, int mct, int max_cs_size, + int max_comp_size, int rsiz, int framerate, + bool apply_icc_, + GRK_RATE_CONTROL_ALGORITHM rateControlAlgorithm, int numThreads, int deviceId, + int duration, int kernelBuildOptions, int repeats, bool writePLT, + bool writeTLM, bool verbose, bool sharedMemoryInterface) { + if (tile_size[0] == 0 && tile_size[1] == 0) { + GRK_CPARAMETERS_DEFAULTS.tile_size_on = false; + } else { + GRK_CPARAMETERS_DEFAULTS.tile_size_on = true; + } + GRK_CPARAMETERS_DEFAULTS.tx0 = tile_offset[0]; + GRK_CPARAMETERS_DEFAULTS.ty0 = tile_offset[1]; + GRK_CPARAMETERS_DEFAULTS.t_width = tile_size[0]; + GRK_CPARAMETERS_DEFAULTS.t_height = tile_size[1]; GRK_CPARAMETERS_DEFAULTS.numlayers = numlayers; if (quality_mode != nullptr) { @@ -290,26 +296,41 @@ void blosc2_grok_set_default_params(bool tile_size_on, int tx0, int ty0, int t_w GRK_CPARAMETERS_DEFAULTS.csty = csty; GRK_CPARAMETERS_DEFAULTS.numgbits = numgbits; - GRK_CPARAMETERS_DEFAULTS.prog_order = prog_order; - /*for (int i = 0; i < GRK_J2K_MAXRLVLS; ++i) { - GRK_CPARAMETERS_DEFAULTS.progression[i] = progression[i]; - GRK_CPARAMETERS_DEFAULTS.prcw_init[i] = prcw_init[i]; - GRK_CPARAMETERS_DEFAULTS.prch_init[i] = prch_init[i]; - }*/ - GRK_CPARAMETERS_DEFAULTS.numpocs = numpocs; - GRK_CPARAMETERS_DEFAULTS.numresolution = numresolution; - - GRK_CPARAMETERS_DEFAULTS.cblockw_init = cblockw_init; - GRK_CPARAMETERS_DEFAULTS.cblockh_init = cblockh_init; + if (strcmp(progression, "LRCP") == 0) { + GRK_CPARAMETERS_DEFAULTS.prog_order = GRK_LRCP; + } else if (strcmp(progression, "RLCP") == 0) { + GRK_CPARAMETERS_DEFAULTS.prog_order = GRK_RLCP; + } else if (strcmp(progression, "RPCL") == 0) { + GRK_CPARAMETERS_DEFAULTS.prog_order = GRK_RPCL; + } else if (strcmp(progression, "PCRL") == 0) { + GRK_CPARAMETERS_DEFAULTS.prog_order = GRK_PCRL; + } else if (strcmp(progression, "CPRL") == 0) { + GRK_CPARAMETERS_DEFAULTS.prog_order = GRK_CPRL; + } + + //for (int i = 0; i < res_spec; ++i) { + // GRK_CPARAMETERS_DEFAULTS.progression[i] = progression[i]; + // } + if (precinct_size[0] != 0 && precinct_size[1] != 0) { + GRK_CPARAMETERS_DEFAULTS.res_spec = 1; + } + GRK_CPARAMETERS_DEFAULTS.prcw_init[0] = precinct_size[0]; + GRK_CPARAMETERS_DEFAULTS.prch_init[0] = precinct_size[1]; + // GRK_CPARAMETERS_DEFAULTS.numpocs = numpocs; only one prog supported + GRK_CPARAMETERS_DEFAULTS.numresolution = num_resolutions; + + GRK_CPARAMETERS_DEFAULTS.cblockw_init = codeblock_size[0]; + GRK_CPARAMETERS_DEFAULTS.cblockh_init = codeblock_size[1]; + + GRK_CPARAMETERS_DEFAULTS.irreversible = irreversible; GRK_CPARAMETERS_DEFAULTS.roi_compno = roi_compno; GRK_CPARAMETERS_DEFAULTS.roi_shift = roi_shift; - GRK_CPARAMETERS_DEFAULTS.res_spec = res_spec; - GRK_CPARAMETERS_DEFAULTS.cblk_sty = cblk_sty; + GRK_CPARAMETERS_DEFAULTS.cblk_sty = codeblock_style; - GRK_CPARAMETERS_DEFAULTS.image_offset_x0 = image_offset_x0; - GRK_CPARAMETERS_DEFAULTS.image_offset_y0 = image_offset_y0; + GRK_CPARAMETERS_DEFAULTS.image_offset_x0 = offset[0]; + GRK_CPARAMETERS_DEFAULTS.image_offset_y0 = offset[1]; GRK_CPARAMETERS_DEFAULTS.subsampling_dx = subsampling_dx; GRK_CPARAMETERS_DEFAULTS.subsampling_dy = subsampling_dy; diff --git a/src/blosc2_grok.h b/src/blosc2_grok.h index e2ca97a..6744040 100644 --- a/src/blosc2_grok.h +++ b/src/blosc2_grok.h @@ -29,13 +29,12 @@ typedef struct { void blosc2_grok_init(uint32_t nthreads, bool verbose); void blosc2_grok_destroy(); -void blosc2_grok_set_default_params(bool tile_size_on, int tx0, int ty0, int t_width, int t_height, +void blosc2_grok_set_default_params(const int64_t *tile_size, const int64_t *tile_offset, int numlayers, char *quality_mode, double *quality_layers, - int csty, int numgbits, GRK_PROG_ORDER prog_order, - int numpocs, - int numresolution, int cblockw_init, int cblockh_init, int cblk_sty, - bool irreversible, int roi_compno, int roi_shift, int res_spec, - int image_offset_x0, int image_offset_y0, int subsampling_dx, + int csty, int numgbits, char *progression, + int num_resolutions, int64_t *codeblock_size, int codeblock_style, + bool irreversible, int roi_compno, int roi_shift, const int64_t *precinct_size, + const int64_t *offset, int subsampling_dx, int subsampling_dy, GRK_SUPPORTED_FILE_FMT decod_format, GRK_SUPPORTED_FILE_FMT cod_format, bool enableTilePartGeneration, int newTilePartProgressionDivider, int mct, int max_cs_size, From 93587bf6dd2b6f3e1bc38389959462cf6529d36c Mon Sep 17 00:00:00 2001 From: Marta Iborra Date: Wed, 13 Dec 2023 10:33:43 +0100 Subject: [PATCH 3/6] Add tests. WIP. --- blosc2_grok/__init__.py | 2 +- pytest.ini | 4 ++ tests/test_jp2.py | 89 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 pytest.ini create mode 100644 tests/test_jp2.py diff --git a/blosc2_grok/__init__.py b/blosc2_grok/__init__.py index 520a4bd..4fd5b84 100644 --- a/blosc2_grok/__init__.py +++ b/blosc2_grok/__init__.py @@ -139,7 +139,7 @@ def destroy(): 'rsiz': GrkProfile.GRK_PROFILE_NONE, 'framerate': 0, 'apply_icc_': False, - 'rateControlAlgorithm': GrkRateControl.PCRD_OPT, + 'rateControlAlgorithm': GrkRateControl.BISECT, 'numThreads': 0, # 30 - 37 'deviceId': 0, diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..ffa24ab --- /dev/null +++ b/pytest.ini @@ -0,0 +1,4 @@ +[pytest] +addopts = --doctest-modules +testpaths = + tests diff --git a/tests/test_jp2.py b/tests/test_jp2.py new file mode 100644 index 0000000..d7fbbf1 --- /dev/null +++ b/tests/test_jp2.py @@ -0,0 +1,89 @@ +####################################################################### +# Copyright (c) 2019-present, Blosc Development Team +# All rights reserved. +# +# This source code is licensed under a BSD-style license (found in the +# LICENSE file in the root directory of this source tree) +####################################################################### + +import numpy as np +import pytest +from PIL import Image + +import blosc2 +import blosc2_grok + + +@pytest.mark.parametrize('image', ['examples/kodim23.png', 'examples/MI04_020751.tif']) +@pytest.mark.parametrize( + 'args', + [ + ({}), + ({'quality_mode': 'rates', 'quality_layers': np.array([5], dtype=np.float64)}), + ({'quality_mode': 'rates', + 'quality_layers': np.array([5], dtype=np.float64), + 'rateControlAlgorithm': blosc2_grok.GrkRateControl.PCRD_OPT} + ), + ({'quality_mode': 'dB', 'quality_layers': np.array([5], dtype=np.float64)}), + # ({'enableTilePartGeneration': True}), + ({'tile_size': (100, 100)}), + # ({'tile_size': (100, 100), 'enableTilePartGeneration': True}), + # ({'csty': 1}), + ({'progression': 'RLCP'}), + ({'progression': 'RPCL'}), + ({'progression': 'PCRL'}), + ({'progression': 'CPRL'}), + ], +) +def test_jp2(image, args): + kwargs = {'cod_format': blosc2_grok.GrkFileFmt.GRK_FMT_JP2, + 'verbose': True, + } + kwargs.update(args) + + # Register codec locally for now + blosc2.register_codec('grok', 160) + + im = Image.open(image) + # Convert the image to a numpy array + np_array = np.asarray(im) + # Set the parameters that will be used by the codec + blosc2_grok.set_params_defaults(**kwargs) + + cparams = { + 'codec': 160, + # 'nthreads': nthreads, + 'filters': [], + 'splitmode': blosc2.SplitMode.NEVER_SPLIT, + } + + bl_array = blosc2.asarray( + np_array, + chunks=np_array.shape, + blocks=np_array.shape, + cparams=cparams, + ) + + tile_size = kwargs.get('tile_size', None) + if tile_size is not None: + im.save(image + '.jp2', tile_size=tile_size) + im2 = Image.open(image + '.jp2') + np_array2 = np.asarray(im2) + np.testing.assert_array_equal(bl_array[...], np_array2) + return + + progression = kwargs.get('progression', None) + if progression is not None: + im.save(image + '.jp2', progression=progression) + im2 = Image.open(image + '.jp2') + np_array2 = np.asarray(im2) + np.testing.assert_array_equal(bl_array[...], np_array2) + return + + if kwargs.get('quality_mode', None) is None: + _ = bl_array[...] + np.testing.assert_array_equal(bl_array[...], np_array) + else: + if kwargs['quality_mode'] == 'rates': + assert bl_array.schunk.cratio >= kwargs['quality_layers'][0] - 0.1 + _ = bl_array[...] From 733c0adea87270af1696da8562bf1ae5d9547731 Mon Sep 17 00:00:00 2001 From: Marta Iborra Date: Wed, 13 Dec 2023 12:56:24 +0100 Subject: [PATCH 4/6] Restore some default params && expand test --- blosc2_grok/__init__.py | 4 +-- src/blosc2_grok.cpp | 7 +++- tests/test_jp2.py | 73 ++++++++++++++++++++++++++++------------- 3 files changed, 59 insertions(+), 25 deletions(-) diff --git a/blosc2_grok/__init__.py b/blosc2_grok/__init__.py index 4fd5b84..0a082b2 100644 --- a/blosc2_grok/__init__.py +++ b/blosc2_grok/__init__.py @@ -146,8 +146,8 @@ def destroy(): 'duration': 0, 'kernelBuildOptions': 0, 'repeats': 1, - 'writePLT': False, - 'writeTLM': False, + 'plt': False, + 'tlm': False, 'verbose': False, 'sharedMemoryInterface': False, } diff --git a/src/blosc2_grok.cpp b/src/blosc2_grok.cpp index 893fceb..4be293c 100644 --- a/src/blosc2_grok.cpp +++ b/src/blosc2_grok.cpp @@ -273,6 +273,9 @@ void blosc2_grok_set_default_params(const int64_t *tile_size, const int64_t *til GRK_CPARAMETERS_DEFAULTS.t_height = tile_size[1]; GRK_CPARAMETERS_DEFAULTS.numlayers = numlayers; + // Restore default values + GRK_CPARAMETERS_DEFAULTS.allocationByRateDistoration = false; + GRK_CPARAMETERS_DEFAULTS.allocationByQuality = false; if (quality_mode != nullptr) { if (strcmp(quality_mode, "rates") == 0) { GRK_CPARAMETERS_DEFAULTS.allocationByRateDistoration = true; @@ -312,7 +315,9 @@ void blosc2_grok_set_default_params(const int64_t *tile_size, const int64_t *til // GRK_CPARAMETERS_DEFAULTS.progression[i] = progression[i]; // } if (precinct_size[0] != 0 && precinct_size[1] != 0) { - GRK_CPARAMETERS_DEFAULTS.res_spec = 1; + GRK_CPARAMETERS_DEFAULTS.res_spec = 1; // grok can support more than one, but PIL not. + } else { + GRK_CPARAMETERS_DEFAULTS.res_spec = 0; } GRK_CPARAMETERS_DEFAULTS.prcw_init[0] = precinct_size[0]; GRK_CPARAMETERS_DEFAULTS.prch_init[0] = precinct_size[1]; diff --git a/tests/test_jp2.py b/tests/test_jp2.py index d7fbbf1..804d041 100644 --- a/tests/test_jp2.py +++ b/tests/test_jp2.py @@ -9,6 +9,8 @@ import numpy as np import pytest from PIL import Image +import time + import blosc2 import blosc2_grok @@ -25,14 +27,47 @@ 'rateControlAlgorithm': blosc2_grok.GrkRateControl.PCRD_OPT} ), ({'quality_mode': 'dB', 'quality_layers': np.array([5], dtype=np.float64)}), - # ({'enableTilePartGeneration': True}), - ({'tile_size': (100, 100)}), - # ({'tile_size': (100, 100), 'enableTilePartGeneration': True}), + ({'enableTilePartGeneration': True}), + ({'tile_size': (1009, 1000)}), + ({'tile_size': (1009, 1000), 'enableTilePartGeneration': True}), # ({'csty': 1}), + ({'numgbits': 4}), ({'progression': 'RLCP'}), ({'progression': 'RPCL'}), ({'progression': 'PCRL'}), ({'progression': 'CPRL'}), + ({'num_resolutions': 8}), + ({'codeblock_size': (4, 4)}), + ({'codeblock_size': (8, 64)}), + ({'codeblock_size': (256, 8), 'codeblock_style': 1}), + ({'roi_compno': 0}), + ({'roi_compno': 1}), + ({'roi_compno': 2}), + ({'roi_compno': 3}), + ({'roi_shift': 8}), + ({'precinct_size': (32, 32)}), + ({'precinct_size': (64, 64)}), + ({'offset': (33, 40)}), + ({'subsampling_dx': 2, 'subsampling_dy': 2}), + ({'newTilePartProgressionDivider': 20}), + ({'newTilePartProgressionDivider': 4, 'enableTilePartGeneration': True}), + ({'newTilePartProgressionDivider': 1}), + ({'newTilePartProgressionDivider': 1, 'enableTilePartGeneration': True}), + ({'mct': 1}), + ({'max_cs_size': 256}), + ({'max_cs_size': 256, 'quality_mode': 'rates', 'quality_layers': np.array([5], dtype=np.float64)}), + # ({'max_comp_size': 2}), # Don't really know why this fails + # ({'rsiz': 8}), # Don't know how to use this yet + # ({'framerate': 8}), # Would make sense if we had more than one frame + ({'apply_icc_': True}), + ({'numThreads': 4}), + # ({'deviceId': 8}), # Meant for multi-GPU systems + ({'duration': 1}), + # ({'kernelBuildOptions': 8}), # NI + ({'repeats': 2}), # NI + ({'plt': True}), # TO-DO: check header + ({'tlm': True}), # NI + ({'sharedMemoryInterface': True}), ], ) def test_jp2(image, args): @@ -47,6 +82,11 @@ def test_jp2(image, args): im = Image.open(image) # Convert the image to a numpy array np_array = np.asarray(im) + print(np_array.shape) + + if kwargs.get('mct', 0) == 1 and np_array.ndim != 3: + pytest.skip("YCC conversion is only meant to be used for RGB") + # Set the parameters that will be used by the codec blosc2_grok.set_params_defaults(**kwargs) @@ -57,33 +97,22 @@ def test_jp2(image, args): 'splitmode': blosc2.SplitMode.NEVER_SPLIT, } + start = time.time() bl_array = blosc2.asarray( np_array, chunks=np_array.shape, blocks=np_array.shape, cparams=cparams, ) + stop = time.time() + if kwargs.get('duration', 0) > 0: + assert stop - start < kwargs['duration'] - tile_size = kwargs.get('tile_size', None) - if tile_size is not None: - im.save(image + '.jp2', tile_size=tile_size) - im2 = Image.open(image + '.jp2') - np_array2 = np.asarray(im2) - np.testing.assert_array_equal(bl_array[...], np_array2) - return - - progression = kwargs.get('progression', None) - if progression is not None: - im.save(image + '.jp2', progression=progression) - im2 = Image.open(image + '.jp2') - np_array2 = np.asarray(im2) - np.testing.assert_array_equal(bl_array[...], np_array2) - return - + print(bl_array.schunk.cratio) if kwargs.get('quality_mode', None) is None: - _ = bl_array[...] - np.testing.assert_array_equal(bl_array[...], np_array) + if kwargs.get('max_cs_size', None) is None: + np.testing.assert_array_equal(bl_array[...], np_array) else: - if kwargs['quality_mode'] == 'rates': + if kwargs['quality_mode'] == 'rates' and kwargs.get('max_cs_size', None) is None: assert bl_array.schunk.cratio >= kwargs['quality_layers'][0] - 0.1 _ = bl_array[...] From 56ff65320b33a86b68a1afc89a6997741a2746c7 Mon Sep 17 00:00:00 2001 From: Francesc Alted Date: Wed, 13 Dec 2023 13:41:55 +0100 Subject: [PATCH 5/6] Update metadata for the project --- pyproject.toml | 17 +++++++++++++++-- src/grok | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3f7be5f..a911246 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,17 +18,21 @@ readme = "README.md" authors = [ {name = "Blosc Development Team", email = "contact@blosc.org"}, ] -description = "Grok plugin for Blosc2. jpeg2000 for grayscale." +description = "Grok (JPEG2000 codec) plugin for Blosc2." keywords = ["plugin", "blosc2"] license = {text = "GNU Affero General Public License version 3"} classifiers = [ "Programming Language :: Python :: 3", "Programming Language :: C", "Programming Language :: C++", - "Development Status :: 5 - Production/Stable", + "Development Status :: 3 - Alpha", "Intended Audience :: Developers", + "Intended Audience :: Information Technology", + "Intended Audience :: Image Processing", "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)", "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Scientific/Engineering :: Image Processing", + "Topic :: System :: Archiving :: Compression", "Operating System :: Microsoft :: Windows", "Operating System :: Unix", ] @@ -37,6 +41,15 @@ dependencies = [ "blosc2" ] +[project.optional-dependencies] +h5py-test = [ + "pytest", # to run tests +] + +[project.urls] +Homepage = "https://github.com/Blosc/blosc2_grok" +Issues = "https://github.com/Blosc/blosc2_grok/issues" + [tool.setuptools] platforms = [ "any" ] zip-safe = false diff --git a/src/grok b/src/grok index a84ac25..6a364d7 160000 --- a/src/grok +++ b/src/grok @@ -1 +1 @@ -Subproject commit a84ac2592e581405a976a00cf9e6f03cab7e2481 +Subproject commit 6a364d7d81e07a9fdbdce74f27803288158d7a49 From 93b9fcf07fe2e81d11a671599f81fb7a6d6c2db1 Mon Sep 17 00:00:00 2001 From: Francesc Alted Date: Wed, 13 Dec 2023 14:02:38 +0100 Subject: [PATCH 6/6] Update headers in source code --- RELEASING.rst | 9 +-------- blosc2_grok/__init__.py | 12 ++++++------ examples/params.py | 9 ++++++++- examples/roundtrip.py | 9 ++++++++- pyproject.toml | 9 ++++----- setup.py | 9 ++++----- src/CMakeLists.txt | 6 ++++-- src/blosc2_grok.cpp | 10 +++++----- src/blosc2_grok.h | 10 +++++----- src/roundtrip.cpp | 12 ++++++------ src/test_grok.cpp | 25 +++++++++++++------------ tests/test_jp2.py | 12 ++++++------ 12 files changed, 70 insertions(+), 62 deletions(-) diff --git a/RELEASING.rst b/RELEASING.rst index e737438..da8e067 100644 --- a/RELEASING.rst +++ b/RELEASING.rst @@ -59,7 +59,7 @@ Announcing Post-release actions -------------------- -- Edit *VERSION* symbols in blosc2_btune/__init__.py *and* pyproject.toml in main to increment the +- Edit *VERSION* symbols in blosc2_grok/__init__.py *and* pyproject.toml in main to increment the version to the next minor one (i.e. X.Y.Z --> X.Y.(Z+1).dev). - Create new headers for adding new features in ``RELEASE_NOTES.md`` @@ -73,10 +73,3 @@ Post-release actions $ git push That's all folks! - - -.. Local Variables: -.. mode: rst -.. coding: utf-8 -.. fill-column: 70 -.. End: diff --git a/blosc2_grok/__init__.py b/blosc2_grok/__init__.py index 0a082b2..a64d9fd 100644 --- a/blosc2_grok/__init__.py +++ b/blosc2_grok/__init__.py @@ -1,10 +1,10 @@ -# Blosc - Blocked Shuffling and Compression Library +############################################################################## +# blosc2_grok: Grok (JPEG2000 codec) plugin for Blosc2 # -# Copyright (C) 2023 The Blosc Developers +# Copyright (c) 2023 The Blosc Development Team # https://blosc.org -# License: BSD 3-Clause (see LICENSE.txt) -# -# See LICENSE.txt for details about copyright and rights to use. +# License: GNU Affero General Public License v3.0 (see LICENSE.txt) +############################################################################## import ctypes import os @@ -107,7 +107,7 @@ def destroy(): lib.blosc2_grok_destroy() -# TODO: change these for real defaults +# TODO: change these by the actual defaults params_defaults = { 'tile_size': (0, 0), 'tile_offset': (0, 0), diff --git a/examples/params.py b/examples/params.py index b1fa19f..399e6d9 100644 --- a/examples/params.py +++ b/examples/params.py @@ -1,7 +1,14 @@ +############################################################################## +# blosc2_grok: Grok (JPEG2000 codec) plugin for Blosc2 +# +# Copyright (c) 2023 The Blosc Development Team +# https://blosc.org +# License: GNU Affero General Public License v3.0 (see LICENSE.txt) +############################################################################## + import blosc2 import blosc2_grok import argparse -from pathlib import Path import numpy as np from PIL import Image diff --git a/examples/roundtrip.py b/examples/roundtrip.py index 39689e7..7ce593d 100644 --- a/examples/roundtrip.py +++ b/examples/roundtrip.py @@ -1,7 +1,14 @@ +############################################################################## +# blosc2_grok: Grok (JPEG2000 codec) plugin for Blosc2 +# +# Copyright (c) 2023 The Blosc Development Team +# https://blosc.org +# License: GNU Affero General Public License v3.0 (see LICENSE.txt) +############################################################################## + import blosc2 import blosc2_grok import argparse -from pathlib import Path import numpy as np from PIL import Image diff --git a/pyproject.toml b/pyproject.toml index a911246..0ad22db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,9 @@ ############################################################################## -# Btune for Blosc2 - Automatically choose the best codec/filter for your data +# blosc2_grok: Grok (JPEG2000 codec) plugin for Blosc2 # -# Copyright (c) 2023 The Blosc Developers -# https://btune.blosc.org -# License: GNU Affero General Public License v3.0 -# See LICENSE.txt for details about copyright and rights to use. +# Copyright (c) 2023 The Blosc Development Team +# https://blosc.org +# License: GNU Affero General Public License v3.0 (see LICENSE.txt) ############################################################################## [build-system] diff --git a/setup.py b/setup.py index 277bac7..b3aa471 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,9 @@ ############################################################################## -# Btune for Blosc2 - Automatically choose the best codec/filter for your data +# blosc2_grok: Grok (JPEG2000 codec) plugin for Blosc2 # -# Copyright (c) 2023 The Blosc Developers -# https://btune.blosc.org -# License: GNU Affero General Public License v3.0 -# See LICENSE.txt for details about copyright and rights to use. +# Copyright (c) 2023 The Blosc Development Team +# https://blosc.org +# License: GNU Affero General Public License v3.0 (see LICENSE.txt) ############################################################################## from skbuild import setup diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bc23cde..f063fb8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,10 @@ -# Blosc - Blocked Shuffling and Compression Library +############################################################################## +# blosc2_grok: Grok (JPEG2000 codec) plugin for Blosc2 # -# Copyright (C) 2023 The Blosc Developers +# Copyright (c) 2023 The Blosc Development Team # https://blosc.org # License: GNU Affero General Public License v3.0 (see LICENSE.txt) +############################################################################## set(GRK_BUILD_LIBPNG OFF) set(GRK_BUILD_JPEG OFF) diff --git a/src/blosc2_grok.cpp b/src/blosc2_grok.cpp index 4be293c..56b9ba9 100644 --- a/src/blosc2_grok.cpp +++ b/src/blosc2_grok.cpp @@ -1,9 +1,9 @@ /********************************************************************* - Blosc - Blocked Shuffling and Compression Library - - Copyright (c) 2021 The Blosc Development Team - https://blosc.org - License: GNU Affero General Public License v3.0 (see LICENSE.txt) + * blosc2_grok: Grok (JPEG2000 codec) plugin for Blosc2 + * + * Copyright (c) 2023 The Blosc Development Team + * https://blosc.org + * License: GNU Affero General Public License v3.0 (see LICENSE.txt) **********************************************************************/ #include diff --git a/src/blosc2_grok.h b/src/blosc2_grok.h index 6744040..f77fb69 100644 --- a/src/blosc2_grok.h +++ b/src/blosc2_grok.h @@ -1,9 +1,9 @@ /********************************************************************* -Blosc - Blocked Shuffling and Compression Library - -Copyright (c) 2021 The Blosc Development Team -https://blosc.org -License: GNU Affero General Public License v3.0 (see LICENSE.txt) + * blosc2_grok: Grok (JPEG2000 codec) plugin for Blosc2 + * + * Copyright (c) 2023 The Blosc Development Team + * https://blosc.org + * License: GNU Affero General Public License v3.0 (see LICENSE.txt) **********************************************************************/ diff --git a/src/roundtrip.cpp b/src/roundtrip.cpp index 326edc9..0aba2a3 100644 --- a/src/roundtrip.cpp +++ b/src/roundtrip.cpp @@ -1,9 +1,9 @@ /********************************************************************* -Blosc - Blocked Shuffling and Compression Library - -Copyright (C) 2023 The Blosc Developers -https://blosc.org -License: GNU Affero General Public License v3.0 (see LICENSE.txt) +* blosc2_grok: Grok (JPEG2000 codec) plugin for Blosc2 +* +* Copyright (c) 2023 The Blosc Development Team +* https://blosc.org +* License: GNU Affero General Public License v3.0 (see LICENSE.txt) Test program demonstrating use of the Blosc filter from C code. Compile this program with cmake and run: @@ -157,4 +157,4 @@ int main(void) { blosc2_grok_destroy(); blosc2_destroy(); return error; -} \ No newline at end of file +} diff --git a/src/test_grok.cpp b/src/test_grok.cpp index c455443..d2efc25 100644 --- a/src/test_grok.cpp +++ b/src/test_grok.cpp @@ -1,16 +1,17 @@ /********************************************************************* - Blosc - Blocked Shuffling and Compression Library - - Copyright (C) 2023 The Blosc Developers - https://blosc.org - License: GNU Affero General Public License v3.0 (see LICENSE.txt) - - Test program demonstrating use of the Blosc filter from C code. - Compile this program with cmake and run: - - $ ./test_grok - Compress OK - Decompress OK + * blosc2_grok: Grok (JPEG2000 codec) plugin for Blosc2 + * + * Copyright (c) 2023 The Blosc Development Team + * https://blosc.org + * License: GNU Affero General Public License v3.0 (see LICENSE.txt) + +Test program demonstrating use of the Blosc filter from C code. + +Compile this program with cmake and run: +$ ./test_grok +Compress OK +Decompress OK +Successful image roundtrip! **********************************************************************/ diff --git a/tests/test_jp2.py b/tests/test_jp2.py index 804d041..19fc201 100644 --- a/tests/test_jp2.py +++ b/tests/test_jp2.py @@ -1,10 +1,10 @@ -####################################################################### -# Copyright (c) 2019-present, Blosc Development Team -# All rights reserved. +############################################################################## +# blosc2_grok: Grok (JPEG2000 codec) plugin for Blosc2 # -# This source code is licensed under a BSD-style license (found in the -# LICENSE file in the root directory of this source tree) -####################################################################### +# Copyright (c) 2023 The Blosc Development Team +# https://blosc.org +# License: GNU Affero General Public License v3.0 (see LICENSE.txt) +############################################################################## import numpy as np import pytest