Added FITS reading

This commit is contained in:
Andrew Murray 2022-02-15 11:22:46 +11:00
parent 7b3f28047f
commit dfdb17671d
6 changed files with 23 additions and 75 deletions

Binary file not shown.

View File

@ -2,7 +2,9 @@ from io import BytesIO
import pytest import pytest
from PIL import FitsStubImagePlugin, Image from PIL import FitsImagePlugin, Image
from .helper import assert_image_equal, hopper
TEST_FILE = "Tests/images/hopper.fits" TEST_FILE = "Tests/images/hopper.fits"
@ -16,6 +18,8 @@ def test_open():
assert im.size == (128, 128) assert im.size == (128, 128)
assert im.mode == "L" assert im.mode == "L"
assert_image_equal(im, hopper("L"))
def test_invalid_file(): def test_invalid_file():
# Arrange # Arrange
@ -23,23 +27,14 @@ def test_invalid_file():
# Act / Assert # Act / Assert
with pytest.raises(SyntaxError): with pytest.raises(SyntaxError):
FitsStubImagePlugin.FITSStubImageFile(invalid_file) FitsImagePlugin.FitsImageFile(invalid_file)
def test_load():
# Arrange
with Image.open(TEST_FILE) as im:
# Act / Assert: stub cannot load without an implemented handler
with pytest.raises(OSError):
im.load()
def test_truncated_fits(): def test_truncated_fits():
# No END to headers # No END to headers
image_data = b"SIMPLE = T" + b" " * 50 + b"TRUNCATE" image_data = b"SIMPLE = T" + b" " * 50 + b"TRUNCATE"
with pytest.raises(OSError): with pytest.raises(OSError):
FitsStubImagePlugin.FITSStubImageFile(BytesIO(image_data)) FitsImagePlugin.FitsImageFile(BytesIO(image_data))
def test_naxis_zero(): def test_naxis_zero():
@ -48,16 +43,3 @@ def test_naxis_zero():
with pytest.raises(ValueError): with pytest.raises(ValueError):
with Image.open("Tests/images/hopper_naxis_zero.fits"): with Image.open("Tests/images/hopper_naxis_zero.fits"):
pass pass
def test_save():
# Arrange
with Image.open(TEST_FILE) as im:
dummy_fp = None
dummy_filename = "dummy.filename"
# Act / Assert: stub cannot save without an implemented handler
with pytest.raises(OSError):
im.save(dummy_filename)
with pytest.raises(OSError):
FitsStubImagePlugin._save(im, dummy_fp, dummy_filename)

View File

@ -1064,6 +1064,11 @@ is commonly used in fax applications. The DCX decoder can read files containing
When the file is opened, only the first image is read. You can use When the file is opened, only the first image is read. You can use
:py:meth:`~PIL.Image.Image.seek` or :py:mod:`~PIL.ImageSequence` to read other images. :py:meth:`~PIL.Image.Image.seek` or :py:mod:`~PIL.ImageSequence` to read other images.
FITS
^^^^
Pillow identifies and reads FITS files, commonly used for astronomy.
FLI, FLC FLI, FLC
^^^^^^^^ ^^^^^^^^
@ -1354,16 +1359,6 @@ Pillow provides a stub driver for BUFR files.
To add read or write support to your application, use To add read or write support to your application, use
:py:func:`PIL.BufrStubImagePlugin.register_handler`. :py:func:`PIL.BufrStubImagePlugin.register_handler`.
FITS
^^^^
.. versionadded:: 1.1.5
Pillow provides a stub driver for FITS files.
To add read or write support to your application, use
:py:func:`PIL.FitsStubImagePlugin.register_handler`.
GRIB GRIB
^^^^ ^^^^

View File

@ -41,10 +41,10 @@ Plugin reference
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
:mod:`~PIL.FitsStubImagePlugin` Module :mod:`~PIL.FitsImagePlugin` Module
-------------------------------------- --------------------------------------
.. automodule:: PIL.FitsStubImagePlugin .. automodule:: PIL.FitsImagePlugin
:members: :members:
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:

View File

@ -2,44 +2,28 @@
# The Python Imaging Library # The Python Imaging Library
# $Id$ # $Id$
# #
# FITS stub adapter # FITS file handling
# #
# Copyright (c) 1998-2003 by Fredrik Lundh # Copyright (c) 1998-2003 by Fredrik Lundh
# #
# See the README file for information on usage and redistribution. # See the README file for information on usage and redistribution.
# #
import math
from . import Image, ImageFile from . import Image, ImageFile
_handler = None
def register_handler(handler):
"""
Install application-specific FITS image handler.
:param handler: Handler object.
"""
global _handler
_handler = handler
# --------------------------------------------------------------------
# Image adapter
def _accept(prefix): def _accept(prefix):
return prefix[:6] == b"SIMPLE" return prefix[:6] == b"SIMPLE"
class FITSStubImageFile(ImageFile.StubImageFile): class FitsImageFile(ImageFile.ImageFile):
format = "FITS" format = "FITS"
format_description = "FITS" format_description = "FITS"
def _open(self): def _open(self):
offset = self.fp.tell()
headers = {} headers = {}
while True: while True:
header = self.fp.read(80) header = self.fp.read(80)
@ -75,26 +59,13 @@ class FITSStubImageFile(ImageFile.StubImageFile):
self.mode = "F" self.mode = "F"
# rawmode = "F" if number_of_bits == -32 else "F;64F" # rawmode = "F" if number_of_bits == -32 else "F;64F"
self.fp.seek(offset) offset = math.ceil(self.fp.tell() / 2880) * 2880
self.tile = [("raw", (0, 0) + self.size, offset, (self.mode, 0, -1))]
loader = self._load()
if loader:
loader.open(self)
def _load(self):
return _handler
def _save(im, fp, filename):
if _handler is None or not hasattr("_handler", "save"):
raise OSError("FITS save handler not installed")
_handler.save(im, fp, filename)
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Registry # Registry
Image.register_open(FITSStubImageFile.format, FITSStubImageFile, _accept) Image.register_open(FitsImageFile.format, FitsImageFile, _accept)
Image.register_save(FITSStubImageFile.format, _save)
Image.register_extensions(FITSStubImageFile.format, [".fit", ".fits"]) Image.register_extensions(FitsImageFile.format, [".fit", ".fits"])

View File

@ -30,7 +30,7 @@ _plugins = [
"DcxImagePlugin", "DcxImagePlugin",
"DdsImagePlugin", "DdsImagePlugin",
"EpsImagePlugin", "EpsImagePlugin",
"FitsStubImagePlugin", "FitsImagePlugin",
"FliImagePlugin", "FliImagePlugin",
"FpxImagePlugin", "FpxImagePlugin",
"FtexImagePlugin", "FtexImagePlugin",