Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,20 @@ 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:

```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:
Expand All @@ -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:
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
sphinx
5 changes: 4 additions & 1 deletion rawpy/_rawpy.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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`
"""
Expand Down
8 changes: 4 additions & 4 deletions rawpy/enhance.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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

Expand Down
32 changes: 11 additions & 21 deletions test/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand All @@ -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:
Expand Down Expand Up @@ -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():
Expand Down Expand Up @@ -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
Expand Down