Merge branch 'main' into branch_deekshu

This commit is contained in:
dutcu 2024-06-22 16:30:26 +02:00
commit 627c164363
22 changed files with 381 additions and 122 deletions

View File

@ -23,4 +23,4 @@ omit =
# Tests/check_*.py # Tests/check_*.py
# Tests/createfontdatachunk.py # Tests/createfontdatachunk.py
Tests/* Tests/*
# src/* src/*

227
README.md
View File

@ -1,115 +1,136 @@
<p align="center"> # Report for Assignment 1
<img width="248" height="250" src="https://raw.githubusercontent.com/python-pillow/pillow-logo/main/pillow-logo-248x250.png" alt="Pillow logo">
</p>
# Pillow ## Project chosen
## Python Imaging Library (Fork) Name: Pillow
Pillow is the friendly PIL fork by [Jeffrey A. Clark and URL of our repository: https://github.com/jovanovicisidora/Pillow-SEP.git
contributors](https://github.com/python-pillow/Pillow/graphs/contributors).
PIL is the Python Imaging Library by Fredrik Lundh and contributors.
As of 2019, Pillow development is
[supported by Tidelift](https://tidelift.com/subscription/pkg/pypi-pillow?utm_source=pypi-pillow&utm_medium=readme&utm_campaign=enterprise).
<table> URL of the original repo: https://github.com/python-pillow/Pillow.git
<tr>
<th>docs</th>
<td>
<a href="https://pillow.readthedocs.io/?badge=latest"><img
alt="Documentation Status"
src="https://readthedocs.org/projects/pillow/badge/?version=latest"></a>
</td>
</tr>
<tr>
<th>tests</th>
<td>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/lint.yml"><img
alt="GitHub Actions build status (Lint)"
src="https://github.com/python-pillow/Pillow/workflows/Lint/badge.svg"></a>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test.yml"><img
alt="GitHub Actions build status (Test Linux and macOS)"
src="https://github.com/python-pillow/Pillow/workflows/Test/badge.svg"></a>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-windows.yml"><img
alt="GitHub Actions build status (Test Windows)"
src="https://github.com/python-pillow/Pillow/workflows/Test%20Windows/badge.svg"></a>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-mingw.yml"><img
alt="GitHub Actions build status (Test MinGW)"
src="https://github.com/python-pillow/Pillow/workflows/Test%20MinGW/badge.svg"></a>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-cygwin.yml"><img
alt="GitHub Actions build status (Test Cygwin)"
src="https://github.com/python-pillow/Pillow/workflows/Test%20Cygwin/badge.svg"></a>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-docker.yml"><img
alt="GitHub Actions build status (Test Docker)"
src="https://github.com/python-pillow/Pillow/workflows/Test%20Docker/badge.svg"></a>
<a href="https://ci.appveyor.com/project/python-pillow/Pillow"><img
alt="AppVeyor CI build status (Windows)"
src="https://img.shields.io/appveyor/build/python-pillow/Pillow/main.svg?label=Windows%20build"></a>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml"><img
alt="GitHub Actions build status (Wheels)"
src="https://github.com/python-pillow/Pillow/workflows/Wheels/badge.svg"></a>
<a href="https://app.codecov.io/gh/python-pillow/Pillow"><img
alt="Code coverage"
src="https://codecov.io/gh/python-pillow/Pillow/branch/main/graph/badge.svg"></a>
<a href="https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:pillow"><img
alt="Fuzzing Status"
src="https://oss-fuzz-build-logs.storage.googleapis.com/badges/pillow.svg"></a>
</td>
</tr>
<tr>
<th>package</th>
<td>
<a href="https://zenodo.org/badge/latestdoi/17549/python-pillow/Pillow"><img
alt="Zenodo"
src="https://zenodo.org/badge/17549/python-pillow/Pillow.svg"></a>
<a href="https://tidelift.com/subscription/pkg/pypi-pillow?utm_source=pypi-pillow&utm_medium=badge"><img
alt="Tidelift"
src="https://tidelift.com/badges/package/pypi/pillow?style=flat"></a>
<a href="https://pypi.org/project/pillow/"><img
alt="Newest PyPI version"
src="https://img.shields.io/pypi/v/pillow.svg"></a>
<a href="https://pypi.org/project/pillow/"><img
alt="Number of PyPI downloads"
src="https://img.shields.io/pypi/dm/pillow.svg"></a>
<a href="https://www.bestpractices.dev/projects/6331"><img
alt="OpenSSF Best Practices"
src="https://www.bestpractices.dev/projects/6331/badge"></a>
</td>
</tr>
<tr>
<th>social</th>
<td>
<a href="https://gitter.im/python-pillow/Pillow?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"><img
alt="Join the chat at https://gitter.im/python-pillow/Pillow"
src="https://badges.gitter.im/python-pillow/Pillow.svg"></a>
<a href="https://fosstodon.org/@pillow"><img
alt="Follow on https://fosstodon.org/@pillow"
src="https://img.shields.io/badge/publish-on%20Mastodon-595aff.svg"
rel="me"></a>
</td>
</tr>
</table>
## Overview Number of lines of code and the tool used to count it:
- Tool used: coverage.py
- Number of lines of code: 82 KLOC
The Python Imaging Library adds image processing capabilities to your Python interpreter. Programming language: Python
This library provides extensive file format support, an efficient internal representation, and fairly powerful image processing capabilities. ## Coverage measurement
The core image library is designed for fast access to data stored in a few basic pixel formats. It should provide a solid foundation for a general image processing tool. ### Existing tool
## More Information <Inform the name of the existing tool that was executed and how it was executed>
- [Documentation](https://pillow.readthedocs.io/) <Show the coverage results provided by the existing tool with a screenshot>
- [Installation](https://pillow.readthedocs.io/en/latest/installation/basic-installation.html)
- [Handbook](https://pillow.readthedocs.io/en/latest/handbook/index.html)
- [Contribute](https://github.com/python-pillow/Pillow/blob/main/.github/CONTRIBUTING.md)
- [Issues](https://github.com/python-pillow/Pillow/issues)
- [Pull requests](https://github.com/python-pillow/Pillow/pulls)
- [Release notes](https://pillow.readthedocs.io/en/stable/releasenotes/index.html)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Pre-fork](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst#pre-fork)
## Report a Vulnerability We used Coverage.py. We executed the coverage tool by running the following command:
To report a security vulnerability, please follow the procedure described in the [Tidelift security policy](https://tidelift.com/docs/security). `python3 -bb -m pytest -v -x -W always --cov PIL --cov Tests --cov-report term Tests $REVERSE`
This resulted in the following output:
![Coverage Tool Result](report_images/isidora_images/[BEFORE]overall_coverage.png)
### Your own coverage tool
<The following is supposed to be repeated for each group member>
<Group member name>
<Function 1 name>
<Show a patch (diff) or a link to a commit made in your forked repository that shows the instrumented code to gather
coverage measurements>
<Provide a screenshot of the coverage results output by the instrumentation>
<Function 2 name>
<Provide the same kind of information provided for Function 1>
Each member of out group has chosen two functions and has instrumented our own coverage tool. For each function we
created a dictionary with the branch ID as key, and a boolean as the value. If the branch was accessed by the tests,
the boolean value would be changed from False to True. In order to calculate and display the coverage, all tests use
the shared code in **conftest.py**.
**1. Deekshu**
**2. Duru**
**3. Isidora**
- Function 1: `_save()` from **SpiderImagePlugin.py**
[Link to the commit](https://github.com/jovanovicisidora/Pillow-SEP/commit/5701d33cbb789342ca781769d4ba7cd323c9255e#diff-44debbfd4d0c5a80130a15bdcd9e0b28c1b4fef6eda0eaaef48838c954589d15)
<img src="report_images/isidora_images/our_tool_save.png" alt="Implemented Coverage Tool" width="600" />
- Function 2: `Bitstream.peek()` from **MpegImagePlugin.py**
[Link to the commit](https://github.com/jovanovicisidora/Pillow-SEP/commit/70f6735620d2f8e469cbe5b60a4586c5db95624a#diff-0272f0c6b5871be3364fe2062e50944fba30dad9625c74d13340de7d3ad8d367)
<img src="report_images/isidora_images/our_tool_peek.png" alt="Implemented Coverage Tool" width="600" />
**4. Sofija**
## Coverage improvement
### Individual tests
<The following is supposed to be repeated for each group member>
<Group member name>
<Test 1>
<Show a patch (diff) or a link to a commit made in your forked repository that shows the new/enhanced test>
<Provide a screenshot of the old coverage results (the same as you already showed above)>
<Provide a screenshot of the new coverage results>
<State the coverage improvement with a number and elaborate on why the coverage is improved>
<Test 2>
<Provide the same kind of information provided for Test 1>
**1. Deekshu**
**2. Duru**
**3. Isidora**
- Function 1: `_save()` from **SpiderImagePlugin.py**
[Link to the commit](https://github.com/jovanovicisidora/Pillow-SEP/commit/70f6735620d2f8e469cbe5b60a4586c5db95624a#diff-f0eb82b90cfc005f681c774b3bf87f19b1db010750e49f850883005f4f623202)
<img src="report_images/isidora_images/[BEFORE]_save.png" alt="Coverage Before" width="600" />
<img src="report_images/isidora_images/[AFTER]_save.png" alt="Coverage After" width="600" />
- Function 2: `Bitstream.peek()` from **MpegImagePlugin.py**
[Link to the commit](https://github.com/jovanovicisidora/Pillow-SEP/commit/70f6735620d2f8e469cbe5b60a4586c5db95624a#diff-48e5b5451c5cab3fbb758ae58649082b62ae6f2850393a332949643d75bd4ad2)
<img src="report_images/isidora_images/[BEFORE]peek.png" alt="Coverage Before" width="600" />
<img src="report_images/isidora_images/[AFTER]peek.png" alt="Coverage After" width="600" />
**4. Sofija**
### Overall
First we provide a screenshot of the old coverage results by running an existing tool:
![Coverage Results Before](report_images/isidora_images/[BEFORE]overall_coverage.png)
Here we show the improved overall coverage with all test modifications made by out group:
![Coverage Results After](path/to/image)
## Statement of individual contributions
Each group member had an equal contribution to the assignment. We first met together to determine
how we can make a coverage tool that can be used across all functions (in conftest.py). Then, each
member chose two functions to instrument our coverage tool on and to make/enhance tests for them.
The specific functions each member chose can be seen in the report above.

115
README_original.md Normal file
View File

@ -0,0 +1,115 @@
<p align="center">
<img width="248" height="250" src="https://raw.githubusercontent.com/python-pillow/pillow-logo/main/pillow-logo-248x250.png" alt="Pillow logo">
</p>
# Pillow
## Python Imaging Library (Fork)
Pillow is the friendly PIL fork by [Jeffrey A. Clark and
contributors](https://github.com/python-pillow/Pillow/graphs/contributors).
PIL is the Python Imaging Library by Fredrik Lundh and contributors.
As of 2019, Pillow development is
[supported by Tidelift](https://tidelift.com/subscription/pkg/pypi-pillow?utm_source=pypi-pillow&utm_medium=readme&utm_campaign=enterprise).
<table>
<tr>
<th>docs</th>
<td>
<a href="https://pillow.readthedocs.io/?badge=latest"><img
alt="Documentation Status"
src="https://readthedocs.org/projects/pillow/badge/?version=latest"></a>
</td>
</tr>
<tr>
<th>tests</th>
<td>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/lint.yml"><img
alt="GitHub Actions build status (Lint)"
src="https://github.com/python-pillow/Pillow/workflows/Lint/badge.svg"></a>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test.yml"><img
alt="GitHub Actions build status (Test Linux and macOS)"
src="https://github.com/python-pillow/Pillow/workflows/Test/badge.svg"></a>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-windows.yml"><img
alt="GitHub Actions build status (Test Windows)"
src="https://github.com/python-pillow/Pillow/workflows/Test%20Windows/badge.svg"></a>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-mingw.yml"><img
alt="GitHub Actions build status (Test MinGW)"
src="https://github.com/python-pillow/Pillow/workflows/Test%20MinGW/badge.svg"></a>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-cygwin.yml"><img
alt="GitHub Actions build status (Test Cygwin)"
src="https://github.com/python-pillow/Pillow/workflows/Test%20Cygwin/badge.svg"></a>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-docker.yml"><img
alt="GitHub Actions build status (Test Docker)"
src="https://github.com/python-pillow/Pillow/workflows/Test%20Docker/badge.svg"></a>
<a href="https://ci.appveyor.com/project/python-pillow/Pillow"><img
alt="AppVeyor CI build status (Windows)"
src="https://img.shields.io/appveyor/build/python-pillow/Pillow/main.svg?label=Windows%20build"></a>
<a href="https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml"><img
alt="GitHub Actions build status (Wheels)"
src="https://github.com/python-pillow/Pillow/workflows/Wheels/badge.svg"></a>
<a href="https://app.codecov.io/gh/python-pillow/Pillow"><img
alt="Code coverage"
src="https://codecov.io/gh/python-pillow/Pillow/branch/main/graph/badge.svg"></a>
<a href="https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:pillow"><img
alt="Fuzzing Status"
src="https://oss-fuzz-build-logs.storage.googleapis.com/badges/pillow.svg"></a>
</td>
</tr>
<tr>
<th>package</th>
<td>
<a href="https://zenodo.org/badge/latestdoi/17549/python-pillow/Pillow"><img
alt="Zenodo"
src="https://zenodo.org/badge/17549/python-pillow/Pillow.svg"></a>
<a href="https://tidelift.com/subscription/pkg/pypi-pillow?utm_source=pypi-pillow&utm_medium=badge"><img
alt="Tidelift"
src="https://tidelift.com/badges/package/pypi/pillow?style=flat"></a>
<a href="https://pypi.org/project/pillow/"><img
alt="Newest PyPI version"
src="https://img.shields.io/pypi/v/pillow.svg"></a>
<a href="https://pypi.org/project/pillow/"><img
alt="Number of PyPI downloads"
src="https://img.shields.io/pypi/dm/pillow.svg"></a>
<a href="https://www.bestpractices.dev/projects/6331"><img
alt="OpenSSF Best Practices"
src="https://www.bestpractices.dev/projects/6331/badge"></a>
</td>
</tr>
<tr>
<th>social</th>
<td>
<a href="https://gitter.im/python-pillow/Pillow?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"><img
alt="Join the chat at https://gitter.im/python-pillow/Pillow"
src="https://badges.gitter.im/python-pillow/Pillow.svg"></a>
<a href="https://fosstodon.org/@pillow"><img
alt="Follow on https://fosstodon.org/@pillow"
src="https://img.shields.io/badge/publish-on%20Mastodon-595aff.svg"
rel="me"></a>
</td>
</tr>
</table>
## Overview
The Python Imaging Library adds image processing capabilities to your Python interpreter.
This library provides extensive file format support, an efficient internal representation, and fairly powerful image processing capabilities.
The core image library is designed for fast access to data stored in a few basic pixel formats. It should provide a solid foundation for a general image processing tool.
## More Information
- [Documentation](https://pillow.readthedocs.io/)
- [Installation](https://pillow.readthedocs.io/en/latest/installation/basic-installation.html)
- [Handbook](https://pillow.readthedocs.io/en/latest/handbook/index.html)
- [Contribute](https://github.com/python-pillow/Pillow/blob/main/.github/CONTRIBUTING.md)
- [Issues](https://github.com/python-pillow/Pillow/issues)
- [Pull requests](https://github.com/python-pillow/Pillow/pulls)
- [Release notes](https://pillow.readthedocs.io/en/stable/releasenotes/index.html)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Pre-fork](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst#pre-fork)
## Report a Vulnerability
To report a security vulnerability, please follow the procedure described in the [Tidelift security policy](https://tidelift.com/docs/security).

View File

@ -6,6 +6,8 @@ import pytest
from PIL import Image, MpegImagePlugin from PIL import Image, MpegImagePlugin
from unittest.mock import MagicMock, patch
def test_identify() -> None: def test_identify() -> None:
# Arrange # Arrange
@ -37,3 +39,15 @@ def test_load() -> None:
# Act / Assert: cannot load # Act / Assert: cannot load
with pytest.raises(OSError): with pytest.raises(OSError):
im.load() im.load()
def test_peek_with_negative_c() -> None:
fp = MagicMock()
return_values = [-1, 255]
with patch.object(MpegImagePlugin.BitStream, 'next', side_effect=return_values):
bitstream = MpegImagePlugin.BitStream(fp)
result = bitstream.peek(8)
assert result == 255

View File

@ -4,6 +4,9 @@ import tempfile
import warnings import warnings
from io import BytesIO from io import BytesIO
from pathlib import Path from pathlib import Path
from unittest.mock import MagicMock, patch
import unittest
import struct
import pytest import pytest
@ -162,3 +165,27 @@ def test_odd_size() -> None:
data.seek(0) data.seek(0)
with Image.open(data) as im2: with Image.open(data) as im2:
assert_image_equal(im, im2) assert_image_equal(im, im2)
def test_seek_no_frame() -> None:
with Image.open(TEST_FILE) as im:
im.istack = 1
im.seek(0)
def test_save_small_header() -> None:
width, height = 10, 10
im = Image.new("F", (width, height))
fp = BytesIO()
corrupted_header = [b'\x00' * 4] * 22
with patch("PIL.SpiderImagePlugin.makeSpiderHeader", return_value=corrupted_header):
try:
im.save(fp, format="SPIDER")
except OSError as e:
assert str(e) == "Error creating Spider header"
else:
assert False, "Expected an OSError due to corrupted header"

View File

@ -4,6 +4,10 @@ import sys
from PIL import Image from PIL import Image
from PIL import PdfParser from PIL import PdfParser
from PIL import SpiderImagePlugin
from PIL import MpegImagePlugin
from PIL import ImageCms
from PIL import McIdasImagePlugin
from PIL import ImageTk from PIL import ImageTk
from PIL import ImageFile from PIL import ImageFile
@ -12,10 +16,12 @@ pytest_plugins = ["Tests.helper"]
def calculate_coverage(test_name): def calculate_coverage(test_name):
all_branches = { all_branches = {
"branches1": Image.branches, "branches1": Image.branches, # duru
"branches2": PdfParser.XrefTable.branches, "branches2": PdfParser.XrefTable.branches, # duru
"branches3": ImageTk.BitmapImage.branches, "branches3": SpiderImagePlugin.branches, # isidora
"branches4": ImageFile.PyEncoder.branches, "branches4": MpegImagePlugin.BitStream.branches, # isidora
"branches5": ImageTk.BitmapImage.branches, # deekshu
"branches6": ImageFile.PyEncoder.branches, # deekshu
# Add more # Add more
} }

BIN
libwebp-1.4.0.tar.gz Normal file

Binary file not shown.

1
myenv/lib64 Symbolic link
View File

@ -0,0 +1 @@
lib

5
myenv/pyvenv.cfg Normal file
View File

@ -0,0 +1,5 @@
home = /usr/bin
include-system-site-packages = false
version = 3.12.3
executable = /usr/bin/python3.12
command = /usr/bin/python3 -m venv /home/duru/Documents/Period_6/Pillow-SEP/myenv

1
pillowenv/lib64 Symbolic link
View File

@ -0,0 +1 @@
lib

5
pillowenv/pyvenv.cfg Normal file
View File

@ -0,0 +1,5 @@
home = /usr/bin
include-system-site-packages = false
version = 3.12.3
executable = /usr/bin/python3.12
command = /usr/bin/python3 -m venv /home/duru/Documents/Period_6/Pillow-SEP/pillowenv

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

View File

@ -242,6 +242,17 @@ _FLAGS = {
class ImageCmsProfile: class ImageCmsProfile:
branches = {
"1": False,
"2": False,
"3": False,
"4": False,
"5": False,
"6": False,
"7": False,
"8": False,
}
def __init__(self, profile: str | SupportsRead[bytes] | core.CmsProfile) -> None: def __init__(self, profile: str | SupportsRead[bytes] | core.CmsProfile) -> None:
""" """
:param profile: Either a string representing a filename, :param profile: Either a string representing a filename,
@ -251,20 +262,28 @@ class ImageCmsProfile:
""" """
if isinstance(profile, str): if isinstance(profile, str):
ImageCmsProfile.branches["1"] = True
if sys.platform == "win32": if sys.platform == "win32":
ImageCmsProfile.branches["2"] = True
profile_bytes_path = profile.encode() profile_bytes_path = profile.encode()
try: try:
ImageCmsProfile.branches["3"] = True
profile_bytes_path.decode("ascii") profile_bytes_path.decode("ascii")
except UnicodeDecodeError: except UnicodeDecodeError:
ImageCmsProfile.branches["4"] = True
with open(profile, "rb") as f: with open(profile, "rb") as f:
ImageCmsProfile.branches["5"] = True
self._set(core.profile_frombytes(f.read())) self._set(core.profile_frombytes(f.read()))
return return
self._set(core.profile_open(profile), profile) self._set(core.profile_open(profile), profile)
elif hasattr(profile, "read"): elif hasattr(profile, "read"):
ImageCmsProfile.branches["6"] = True
self._set(core.profile_frombytes(profile.read())) self._set(core.profile_frombytes(profile.read()))
elif isinstance(profile, core.CmsProfile): elif isinstance(profile, core.CmsProfile):
ImageCmsProfile.branches["7"] = True
self._set(profile) self._set(profile)
else: else:
ImageCmsProfile.branches["8"] = True
msg = "Invalid type for Profile" # type: ignore[unreachable] msg = "Invalid type for Profile" # type: ignore[unreachable]
raise TypeError(msg) raise TypeError(msg)

View File

@ -30,6 +30,14 @@ def _accept(prefix: bytes) -> bool:
class McIdasImageFile(ImageFile.ImageFile): class McIdasImageFile(ImageFile.ImageFile):
branches = {
"1": False,
"2": False,
"3": False,
"4": False,
"5": False,
}
format = "MCIDAS" format = "MCIDAS"
format_description = "McIdas area file" format_description = "McIdas area file"
@ -39,6 +47,7 @@ class McIdasImageFile(ImageFile.ImageFile):
s = self.fp.read(256) s = self.fp.read(256)
if not _accept(s) or len(s) != 256: if not _accept(s) or len(s) != 256:
McIdasImageFile.branches["1"] = True
msg = "not an McIdas area file" msg = "not an McIdas area file"
raise SyntaxError(msg) raise SyntaxError(msg)
@ -47,16 +56,20 @@ class McIdasImageFile(ImageFile.ImageFile):
# get mode # get mode
if w[11] == 1: if w[11] == 1:
McIdasImageFile.branches["2"] = True
mode = rawmode = "L" mode = rawmode = "L"
elif w[11] == 2: elif w[11] == 2:
McIdasImageFile.branches["3"] = True
# FIXME: add memory map support # FIXME: add memory map support
mode = "I" mode = "I"
rawmode = "I;16B" rawmode = "I;16B"
elif w[11] == 4: elif w[11] == 4:
McIdasImageFile.branches["4"] = True
# FIXME: add memory map support # FIXME: add memory map support
mode = "I" mode = "I"
rawmode = "I;32B" rawmode = "I;32B"
else: else:
McIdasImageFile.branches["5"] = True
msg = "unsupported McIdas format" msg = "unsupported McIdas format"
raise SyntaxError(msg) raise SyntaxError(msg)

View File

@ -21,8 +21,13 @@ from ._typing import SupportsRead
# #
# Bitstream parser # Bitstream parser
class BitStream: class BitStream:
branches = {
"1": False,
"2": False,
"3": False,
}
def __init__(self, fp: SupportsRead[bytes]) -> None: def __init__(self, fp: SupportsRead[bytes]) -> None:
self.fp = fp self.fp = fp
self.bits = 0 self.bits = 0
@ -33,12 +38,19 @@ class BitStream:
def peek(self, bits: int) -> int: def peek(self, bits: int) -> int:
while self.bits < bits: while self.bits < bits:
BitStream.branches["1"] = True
c = self.next() c = self.next()
if c < 0: if c < 0:
BitStream.branches["2"] = True
self.bits = 0 self.bits = 0
continue continue
else:
BitStream.branches["3"] = True
self.bitbuffer = (self.bitbuffer << 8) + c self.bitbuffer = (self.bitbuffer << 8) + c
self.bits += 8 self.bits += 8
return self.bitbuffer >> (self.bits - bits) & (1 << bits) - 1 return self.bitbuffer >> (self.bits - bits) & (1 << bits) - 1
def skip(self, bits: int) -> None: def skip(self, bits: int) -> None:

View File

@ -42,6 +42,7 @@ from typing import IO, TYPE_CHECKING
from . import Image, ImageFile from . import Image, ImageFile
def isInt(f): def isInt(f):
try: try:
i = int(f) i = int(f)
@ -55,6 +56,13 @@ def isInt(f):
iforms = [1, 3, -11, -12, -21, -22] iforms = [1, 3, -11, -12, -21, -22]
branches = {
"1": False,
"2": False,
"3": False,
"4": False
}
# There is no magic number to identify Spider files, so just check a # There is no magic number to identify Spider files, so just check a
# series of header locations to see if they have reasonable values. # series of header locations to see if they have reasonable values.
@ -107,19 +115,23 @@ class SpiderImageFile(ImageFile.ImageFile):
self.bigendian = 1 self.bigendian = 1
t = struct.unpack(">27f", f) # try big-endian first t = struct.unpack(">27f", f) # try big-endian first
hdrlen = isSpiderHeader(t) hdrlen = isSpiderHeader(t)
if hdrlen == 0: if hdrlen == 0:
self.bigendian = 0 self.bigendian = 0
t = struct.unpack("<27f", f) # little-endian t = struct.unpack("<27f", f) # little-endian
hdrlen = isSpiderHeader(t) hdrlen = isSpiderHeader(t)
if hdrlen == 0: if hdrlen == 0:
msg = "not a valid Spider file" msg = "not a valid Spider file"
raise SyntaxError(msg) raise SyntaxError(msg)
except struct.error as e: except struct.error as e:
msg = "not a valid Spider file" msg = "not a valid Spider file"
raise SyntaxError(msg) from e raise SyntaxError(msg) from e
h = (99,) + t # add 1 value : spider header index starts at 1 h = (99,) + t # add 1 value : spider header index starts at 1
iform = int(h[5]) iform = int(h[5])
if iform != 1: if iform != 1:
msg = "not a Spider 2D image" msg = "not a Spider 2D image"
raise SyntaxError(msg) raise SyntaxError(msg)
@ -176,8 +188,10 @@ class SpiderImageFile(ImageFile.ImageFile):
if self.istack == 0: if self.istack == 0:
msg = "attempt to seek in a non-stack file" msg = "attempt to seek in a non-stack file"
raise EOFError(msg) raise EOFError(msg)
if not self._seek_check(frame): if not self._seek_check(frame):
return return
self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes) self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes)
self.fp = self._fp self.fp = self._fp
self.fp.seek(self.stkoffset) self.fp.seek(self.stkoffset)
@ -265,12 +279,18 @@ def makeSpiderHeader(im: Image.Image) -> list[bytes]:
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None: def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if im.mode[0] != "F": if im.mode[0] != "F":
branches["1"] = True
im = im.convert("F") im = im.convert("F")
else:
branches["2"] = True
hdr = makeSpiderHeader(im) hdr = makeSpiderHeader(im)
if len(hdr) < 256: if len(hdr) < 256:
branches["3"] = True
msg = "Error creating Spider header" msg = "Error creating Spider header"
raise OSError(msg) raise OSError(msg)
else:
branches["4"] = True
# write the SPIDER header # write the SPIDER header
fp.writelines(hdr) fp.writelines(hdr)