-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Added FITS reading, deprecate FitsStubImagePlugin #6056
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
dfdb176
aca936c
2368723
7dca013
764c351
ee46ef2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| from io import BytesIO | ||
|
|
||
| import pytest | ||
|
|
||
| from PIL import FitsImagePlugin, FitsStubImagePlugin, Image | ||
|
|
||
| from .helper import assert_image_equal, hopper | ||
|
|
||
| TEST_FILE = "Tests/images/hopper.fits" | ||
|
|
||
|
|
||
| def test_open(): | ||
| # Act | ||
| with Image.open(TEST_FILE) as im: | ||
|
|
||
| # Assert | ||
| assert im.format == "FITS" | ||
| assert im.size == (128, 128) | ||
| assert im.mode == "L" | ||
|
|
||
| assert_image_equal(im, hopper("L")) | ||
|
|
||
|
|
||
| def test_invalid_file(): | ||
| # Arrange | ||
| invalid_file = "Tests/images/flower.jpg" | ||
|
|
||
| # Act / Assert | ||
| with pytest.raises(SyntaxError): | ||
| FitsImagePlugin.FitsImageFile(invalid_file) | ||
|
|
||
|
|
||
| def test_truncated_fits(): | ||
| # No END to headers | ||
| image_data = b"SIMPLE = T" + b" " * 50 + b"TRUNCATE" | ||
| with pytest.raises(OSError): | ||
| FitsImagePlugin.FitsImageFile(BytesIO(image_data)) | ||
|
|
||
|
|
||
| def test_naxis_zero(): | ||
| # This test image has been manually hexedited | ||
| # to set the number of data axes to zero | ||
| with pytest.raises(ValueError): | ||
| with Image.open("Tests/images/hopper_naxis_zero.fits"): | ||
| pass | ||
|
|
||
|
|
||
| def test_stub_deprecated(): | ||
| class Handler: | ||
| opened = False | ||
| loaded = False | ||
|
|
||
| def open(self, im): | ||
| self.opened = True | ||
|
|
||
| def load(self, im): | ||
| self.loaded = True | ||
| return Image.new("RGB", (1, 1)) | ||
|
|
||
| handler = Handler() | ||
| with pytest.warns(DeprecationWarning): | ||
| FitsStubImagePlugin.register_handler(handler) | ||
|
|
||
| with Image.open(TEST_FILE) as im: | ||
| assert im.format == "FITS" | ||
| assert im.size == (128, 128) | ||
| assert im.mode == "L" | ||
|
|
||
| assert handler.opened | ||
| assert not handler.loaded | ||
|
|
||
| im.load() | ||
| assert handler.loaded | ||
|
|
||
| FitsStubImagePlugin._handler = None | ||
| Image.register_open( | ||
| FitsImagePlugin.FitsImageFile.format, | ||
| FitsImagePlugin.FitsImageFile, | ||
| FitsImagePlugin._accept, | ||
| ) |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| # | ||
| # The Python Imaging Library | ||
| # $Id$ | ||
| # | ||
| # FITS file handling | ||
| # | ||
| # Copyright (c) 1998-2003 by Fredrik Lundh | ||
| # | ||
| # See the README file for information on usage and redistribution. | ||
| # | ||
|
|
||
| import math | ||
|
|
||
| from . import Image, ImageFile | ||
|
|
||
|
|
||
| def _accept(prefix): | ||
| return prefix[:6] == b"SIMPLE" | ||
|
|
||
|
|
||
| class FitsImageFile(ImageFile.ImageFile): | ||
|
|
||
| format = "FITS" | ||
| format_description = "FITS" | ||
|
|
||
| def _open(self): | ||
| headers = {} | ||
| while True: | ||
| header = self.fp.read(80) | ||
| if not header: | ||
| raise OSError("Truncated FITS file") | ||
| keyword = header[:8].strip() | ||
| if keyword == b"END": | ||
| break | ||
| value = header[8:].strip() | ||
| if value.startswith(b"="): | ||
| value = value[1:].strip() | ||
| if not headers and (not _accept(keyword) or value != b"T"): | ||
| raise SyntaxError("Not a FITS file") | ||
| headers[keyword] = value | ||
|
|
||
| naxis = int(headers[b"NAXIS"]) | ||
| if naxis == 0: | ||
| raise ValueError("No image data") | ||
| elif naxis == 1: | ||
| self._size = 1, int(headers[b"NAXIS1"]) | ||
| else: | ||
| self._size = int(headers[b"NAXIS1"]), int(headers[b"NAXIS2"]) | ||
|
|
||
| number_of_bits = int(headers[b"BITPIX"]) | ||
| if number_of_bits == 8: | ||
| self.mode = "L" | ||
| elif number_of_bits == 16: | ||
| self.mode = "I" | ||
| # rawmode = "I;16S" | ||
| elif number_of_bits == 32: | ||
| self.mode = "I" | ||
| elif number_of_bits in (-32, -64): | ||
| self.mode = "F" | ||
| # rawmode = "F" if number_of_bits == -32 else "F;64F" | ||
|
|
||
| offset = math.ceil(self.fp.tell() / 2880) * 2880 | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The documentation mentioned that the offset for the image data was a multiple of 2880. https://fits.gsfc.nasa.gov/fits_primer.html
|
||
| self.tile = [("raw", (0, 0) + self.size, offset, (self.mode, 0, -1))] | ||
|
|
||
|
|
||
| # -------------------------------------------------------------------- | ||
| # Registry | ||
|
|
||
| Image.register_open(FitsImageFile.format, FitsImageFile, _accept) | ||
|
|
||
| Image.register_extensions(FitsImageFile.format, [".fit", ".fits"]) | ||
Uh oh!
There was an error while loading. Please reload this page.