diff --git a/README.md b/README.md index 8d9827b..1e2dd9a 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,12 @@ Load a RAW file and save the postprocessed image using default [parameters](http ```python import rawpy -import imageio +import imageio.v3 as iio path = 'image.nef' with rawpy.imread(path) as raw: rgb = raw.postprocess() -imageio.imsave('default.tiff', rgb) +iio.imwrite('default.tiff', rgb) ``` Save as 16-bit linear image: @@ -28,7 +28,7 @@ Save as 16-bit linear image: ```python with rawpy.imread(path) as raw: rgb = raw.postprocess(gamma=(1,1), no_auto_bright=True, output_bps=16) -imageio.imsave('linear.tiff', rgb) +iio.imwrite('linear.tiff', rgb) ``` Extract embedded thumbnail/preview image and save as JPEG: @@ -44,7 +44,7 @@ if thumb.format == rawpy.ThumbFormat.JPEG: f.write(thumb.data) elif thumb.format == rawpy.ThumbFormat.BITMAP: # thumb.data is an RGB numpy array, convert with imageio - imageio.imsave('thumb.jpeg', thumb.data) + iio.imwrite('thumb.jpeg', thumb.data) ``` Find bad pixels using multiple RAW files and repair them: @@ -59,7 +59,7 @@ for path in paths: with rawpy.imread(path) as raw: rawpy.enhance.repair_bad_pixels(raw, bad_pixels, method='median') rgb = raw.postprocess() - imageio.imsave(path + '.tiff', rgb) + iio.imwrite(path + '.tiff', rgb) ``` ## Installation diff --git a/dev-requirements.txt b/dev-requirements.txt index b550b16..b4dae9c 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -11,9 +11,9 @@ scikit-image # test dependencies pytest -imageio +imageio>=2.21 # for imageio.v3 / iio support setuptools # documentation dependencies sphinx_rtd_theme -sphinx \ No newline at end of file +sphinx diff --git a/rawpy/_rawpy.pyx b/rawpy/_rawpy.pyx index 1b8a535..3da8f85 100644 --- a/rawpy/_rawpy.pyx +++ b/rawpy/_rawpy.pyx @@ -866,6 +866,9 @@ cdef class RawPy: If no image exists or the format is unsupported, an exception is raised. .. code-block:: python + import imageio.v3 as iio + + ... with rawpy.imread('image.nef') as raw: try: @@ -879,7 +882,7 @@ cdef class RawPy: with open('thumb.jpg', 'wb') as f: f.write(thumb.data) elif thumb.format == rawpy.ThumbFormat.BITMAP: - imageio.imsave('thumb.tiff', thumb.data) + iio.imwrite('thumb.tiff', thumb.data) :rtype: :class:`rawpy.Thumbnail` """ diff --git a/rawpy/enhance.py b/rawpy/enhance.py index 32fe46a..7d6ef52 100644 --- a/rawpy/enhance.py +++ b/rawpy/enhance.py @@ -350,11 +350,11 @@ def save_dcraw_bad_pixels(path, bad_pixels): paths = [os.path.join(prefix, f) for f in testfiles] coords = find_bad_pixels(paths) - import imageio + import imageio.v3 as iio raw = rawpy.imread(paths[0]) if not os.path.exists('test_original.png'): rgb = raw.postprocess() - imageio.imsave('test_original.png', rgb) + iio.imwrite('test_original.png', rgb) # A. use dcraw repair # Note that this method fails when two bad pixels are direct neighbors. @@ -365,7 +365,7 @@ def save_dcraw_bad_pixels(path, bad_pixels): save_dcraw_bad_pixels(bad_pixels_path, coords) rgb = raw.postprocess(bad_pixels_path=bad_pixels_path) print('badpixel dcraw repair+postprocessing:', time.time()-t0, 's') - imageio.imsave('test_hotpixels_repaired_dcraw.png', rgb) + iio.imwrite('test_hotpixels_repaired_dcraw.png', rgb) # B. use own repair function # With method='median' we still consider each bad pixel separately @@ -374,7 +374,7 @@ def save_dcraw_bad_pixels(path, bad_pixels): repair_bad_pixels(raw, coords, method='median') rgb = raw.postprocess() print('badpixel repair+postprocessing:', time.time()-t0, 's') - imageio.imsave('test_hotpixels_repaired.png', rgb) + iio.imwrite('test_hotpixels_repaired.png', rgb) # TODO method 'mean' not implemented yet diff --git a/test/test_basic.py b/test/test_basic.py index a7a7624..b870922 100644 --- a/test/test_basic.py +++ b/test/test_basic.py @@ -10,7 +10,7 @@ import rawpy import rawpy.enhance -import imageio +import imageio.v3 as iio from rawpy.enhance import _repair_bad_pixels_bayer2x2,\ _repair_bad_pixels_generic, find_bad_pixels @@ -52,48 +52,48 @@ def testFileOpenAndPostProcess(): rgb = raw.postprocess(no_auto_bright=True, user_wb=raw.daylight_whitebalance) assert_array_equal(rgb.shape, [2844, 4284, 3]) print_stats(rgb) - save('test_8daylight.tiff', rgb) + iio.imwrite('test_8daylight.tiff', rgb) print('daylight white balance multipliers:', raw.daylight_whitebalance) rgb = raw.postprocess(no_auto_bright=True, user_wb=raw.daylight_whitebalance) print_stats(rgb) - save('test_8daylight2.tiff', rgb) + iio.imwrite('test_8daylight2.tiff', rgb) rgb = raw.postprocess(no_auto_bright=True, user_wb=raw.daylight_whitebalance, output_bps=16) print_stats(rgb) - save('test_16daylight.tiff', rgb) + iio.imwrite('test_16daylight.tiff', rgb) # linear images are more useful for science (=no gamma correction) # see http://www.mit.edu/~kimo/blog/linear.html rgb = raw.postprocess(no_auto_bright=True, user_wb=raw.daylight_whitebalance, gamma=(1,1), output_bps=16) print_stats(rgb) - save('test_16daylight_linear.tiff', rgb) + iio.imwrite('test_16daylight_linear.tiff', rgb) def testFoveonFileOpenAndPostProcess(): raw = rawpy.imread(raw4TestPath) assert_array_equal(raw.raw_image.shape, [1531, 2304, 3]) - save('test_foveon_raw.tiff', raw.raw_image) + iio.imwrite('test_foveon_raw.tiff', raw.raw_image) rgb = raw.postprocess() assert_array_equal(rgb.shape, [1510, 2266, 3]) print_stats(rgb) - save('test_foveon.tiff', rgb) + iio.imwrite('test_foveon.tiff', rgb) def testSRawFileOpenAndPostProcess(): raw = rawpy.imread(raw5TestPath) assert_array_equal(raw.raw_image.shape, [1296, 1944, 4]) assert_equal(raw.raw_image[:,:,3].max(), 0) - save('test_sraw_raw.tiff', raw.raw_image[:,:,:3]) + iio.imwrite('test_sraw_raw.tiff', raw.raw_image[:,:,:3]) rgb = raw.postprocess() assert_array_equal(rgb.shape, [1296, 1944, 3]) print_stats(rgb) - save('test_sraw.tiff', rgb) + iio.imwrite('test_sraw.tiff', rgb) def testFileOpenWithNonAsciiCharacters(): raw = rawpy.imread(raw6TestPath) @@ -104,7 +104,7 @@ def testBufferOpen(): assert_array_equal(raw.raw_image.shape, [2844, 4288]) rgb = raw.postprocess() print_stats(rgb) - save('test_buffer.tiff', rgb) + iio.imwrite('test_buffer.tiff', rgb) def testContextManager(): with rawpy.imread(rawTestPath) as raw: @@ -140,7 +140,7 @@ def testThumbExtractJPEG(): with rawpy.imread(rawTestPath) as raw: thumb = raw.extract_thumb() assert thumb.format == rawpy.ThumbFormat.JPEG - img = imageio.v3.imread(thumb.data) + img = iio.imread(thumb.data) assert_array_equal(img.shape, [2832, 4256, 3]) def testThumbExtractBitmap(): @@ -278,16 +278,6 @@ def testCorruptFile(): with pytest.raises(rawpy.LibRawDataError): im.extract_thumb() -def save(path, im): - # both imageio and skimage currently save uint16 images with 180deg rotation - # as they both use freeimage and this has some weird internal formats - # see https://github.com/scikit-image/scikit-image/issues/1101 - # and https://github.com/imageio/imageio/issues/3 - from packaging.version import Version - if im.dtype == np.uint16 and Version(imageio.__version__) <= Version('0.5.1'): - im = im[::-1,::-1] - imageio.v3.imwrite(path, im) - def print_stats(rgb): print(rgb.dtype, np.min(rgb, axis=(0,1)), np.max(rgb, axis=(0,1)), # range for each channel