Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-imageio for openSUSE:Factory checked in at 2026-08-21 17:00:13 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-imageio (Old) and /work/SRC/openSUSE:Factory/.python-imageio.new.1258 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-imageio" Fri Aug 21 17:00:13 2026 rev:24 rq:1372788 version:2.37.4 Changes: -------- --- /work/SRC/openSUSE:Factory/python-imageio/python-imageio.changes 2026-03-18 16:51:25.459338778 +0100 +++ /work/SRC/openSUSE:Factory/.python-imageio.new.1258/python-imageio.changes 2026-08-21 17:00:35.297470516 +0200 @@ -1,0 +2,18 @@ +Fri Aug 21 10:04:26 UTC 2026 - Dirk Müller <[email protected]> + +- update to 2.37.4: + * Set filename parameter of FileNotFoundError exception + * Fix typos in docstrings and comments + * Bump aiohttp from 3.13.3 to 3.13.4 + * Bump aiohttp from 3.13.4 to 3.14.1 + * Bump black from 26.3.0 to 26.3.1 + * Bump gdal from 3.12.2 to 3.13.1 + * Bump idna from 3.11 to 3.15 + * Bump pygments from 2.19.2 to 2.20.0 + * Bump requests from 2.32.5 to 2.33.0 + * Bump soupsieve from 2.8.3 to 2.8.4 + * Bump urllib3 from 2.6.3 to 2.7.0 + * Set readme content-type in project metadata + * Update CI to support new dependency versions + +------------------------------------------------------------------- Old: ---- imageio-2.37.3.tar.gz New: ---- imageio-2.37.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-imageio.spec ++++++ --- /var/tmp/diff_new_pack.puMCN9/_old 2026-08-21 17:00:36.734521702 +0200 +++ /var/tmp/diff_new_pack.puMCN9/_new 2026-08-21 17:00:36.738521844 +0200 @@ -19,16 +19,17 @@ %bcond_with test_extras %{?sle15_python_module_pythons} Name: python-imageio -Version: 2.37.3 +Version: 2.37.4 Release: 0 Summary: Python library for reading and writing image, video, and related formats License: BSD-2-Clause URL: https://github.com/imageio/imageio Source0: https://files.pythonhosted.org/packages/source/i/imageio/imageio-%{version}.tar.gz BuildRequires: %{python_module Pillow >= 8.3.2} -BuildRequires: %{python_module base >= 3.7} +BuildRequires: %{python_module base >= 3.10} BuildRequires: %{python_module numpy >= 2} BuildRequires: %{python_module pip} +BuildRequires: %{python_module setuptools >= 61.0} BuildRequires: %{python_module wheel} BuildRequires: fdupes BuildRequires: python-rpm-macros @@ -109,7 +110,7 @@ %files %{python_files} %license LICENSE -%doc CONTRIBUTORS.txt README.md +%doc README.md %{python_sitelib}/imageio %{python_sitelib}/imageio-%{version}*-info %python_alternative %{_bindir}/imageio_download_bin ++++++ imageio-2.37.3.tar.gz -> imageio-2.37.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/ImageIO.egg-info/PKG-INFO new/imageio-2.37.4/ImageIO.egg-info/PKG-INFO --- old/imageio-2.37.3/ImageIO.egg-info/PKG-INFO 2026-03-09 12:30:52.000000000 +0100 +++ new/imageio-2.37.4/ImageIO.egg-info/PKG-INFO 2026-07-20 07:25:52.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: ImageIO -Version: 2.37.3 +Version: 2.37.4 Summary: Read and write images and video across all major formats. Supports scientific and volumetric data. Author: ImageIO contributors Maintainer-email: Sebastian Wallkotter <[email protected]>, Almar Klein <[email protected]> @@ -24,7 +24,7 @@ Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: 3.14 Requires-Python: >=3.10 -Description-Content-Type: text/x-rst +Description-Content-Type: text/markdown License-File: LICENSE Requires-Dist: numpy Requires-Dist: pillow>=8.3.2 @@ -89,7 +89,6 @@ Requires-Dist: imageio-ffmpeg; extra == "all-plugins-pypy" Requires-Dist: pillow-heif; extra == "all-plugins-pypy" Requires-Dist: psutil; extra == "all-plugins-pypy" -Requires-Dist: tifffile; extra == "all-plugins-pypy" Provides-Extra: full Requires-Dist: astropy; extra == "full" Requires-Dist: av; extra == "full" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/ImageIO.egg-info/requires.txt new/imageio-2.37.4/ImageIO.egg-info/requires.txt --- old/imageio-2.37.3/ImageIO.egg-info/requires.txt 2026-03-09 12:30:52.000000000 +0100 +++ new/imageio-2.37.4/ImageIO.egg-info/requires.txt 2026-07-20 07:25:52.000000000 +0200 @@ -17,7 +17,6 @@ imageio-ffmpeg pillow-heif psutil -tifffile [bsdf] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/PKG-INFO new/imageio-2.37.4/PKG-INFO --- old/imageio-2.37.3/PKG-INFO 2026-03-09 12:30:52.860846000 +0100 +++ new/imageio-2.37.4/PKG-INFO 2026-07-20 07:25:52.609704000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: ImageIO -Version: 2.37.3 +Version: 2.37.4 Summary: Read and write images and video across all major formats. Supports scientific and volumetric data. Author: ImageIO contributors Maintainer-email: Sebastian Wallkotter <[email protected]>, Almar Klein <[email protected]> @@ -24,7 +24,7 @@ Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: 3.14 Requires-Python: >=3.10 -Description-Content-Type: text/x-rst +Description-Content-Type: text/markdown License-File: LICENSE Requires-Dist: numpy Requires-Dist: pillow>=8.3.2 @@ -89,7 +89,6 @@ Requires-Dist: imageio-ffmpeg; extra == "all-plugins-pypy" Requires-Dist: pillow-heif; extra == "all-plugins-pypy" Requires-Dist: psutil; extra == "all-plugins-pypy" -Requires-Dist: tifffile; extra == "all-plugins-pypy" Provides-Extra: full Requires-Dist: astropy; extra == "full" Requires-Dist: av; extra == "full" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/imageio/core/fetching.py new/imageio-2.37.4/imageio/core/fetching.py --- old/imageio-2.37.3/imageio/core/fetching.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/imageio/core/fetching.py 2026-07-20 07:25:43.000000000 +0200 @@ -112,7 +112,7 @@ if not op.isdir(op.dirname(filename)): os.makedirs(op.abspath(op.dirname(filename))) # let's go get the file - if os.getenv("CONTINUOUS_INTEGRATION", False): # pragma: no cover + if os.getenv("CI"): # pragma: no cover # On CI, we retry a few times ... for i in range(2): try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/imageio/core/legacy_plugin_wrapper.py new/imageio-2.37.4/imageio/core/legacy_plugin_wrapper.py --- old/imageio-2.37.3/imageio/core/legacy_plugin_wrapper.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/imageio/core/legacy_plugin_wrapper.py 2026-07-20 07:25:43.000000000 +0200 @@ -90,7 +90,7 @@ def legacy_get_reader(self, **kwargs): """legacy_get_reader(**kwargs) - a utility method to provide support vor the V2.9 API + a utility method to provide support for the V2.9 API Parameters ---------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/imageio/core/request.py new/imageio-2.37.4/imageio/core/request.py --- old/imageio-2.37.3/imageio/core/request.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/imageio/core/request.py 2026-07-20 07:25:43.000000000 +0200 @@ -6,6 +6,7 @@ what the user wants and what the plugins can. """ +import errno import os from io import BytesIO import zipfile @@ -52,12 +53,12 @@ ``Request.ImageMode`` and ``Request.IOMode``. The image mode that tells the plugin the desired (and expected) image shape. Available values are - - single_image ("i"): Return a single image extending in two spacial + - single_image ("i"): Return a single image extending in two spatial dimensions - - multi_image ("I"): Return a list of images extending in two spacial + - multi_image ("I"): Return a list of images extending in two spatial dimensions - single_volume ("v"): Return an image extending into multiple dimensions. - E.g. three spacial dimensions for image stacks, or two spatial and one + E.g. three spatial dimensions for image stacks, or two spatial and one time dimension for videos - multi_volume ("V"): Return a list of images extending into multiple dimensions. @@ -162,7 +163,7 @@ EXAMPLE_IMAGES = { "astronaut.png": "Image of the astronaut Eileen Collins", "camera.png": "A grayscale image of a photographer", - "checkerboard.png": "Black and white image of a chekerboard", + "checkerboard.png": "Black and white image of a checkerboard", "wood.jpg": "A (repeatable) texture of wooden planks", "bricks.jpg": "A (repeatable) texture of stone bricks", "clock.png": "Photo of a clock with motion blur (Stefan van der Walt)", @@ -407,12 +408,16 @@ if is_read_request: # Reading: check that the file exists (but is allowed a dir) if not os.path.exists(fn): - raise FileNotFoundError("No such file: '%s'" % fn) + raise FileNotFoundError( + errno.ENOENT, "No such file or directory", fn + ) else: # Writing: check that the directory to write to does exist dn = os.path.dirname(fn) if not os.path.exists(dn): - raise FileNotFoundError("The directory %r does not exist" % dn) + raise FileNotFoundError( + errno.ENOENT, "The directory does not exist", dn + ) @property def filename(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/imageio/core/util.py new/imageio-2.37.4/imageio/core/util.py --- old/imageio-2.37.3/imageio/core/util.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/imageio/core/util.py 2026-07-20 07:25:43.000000000 +0200 @@ -153,11 +153,11 @@ else: self._copy_meta({}) - def __array_wrap__(self, out, context=None): + def __array_wrap__(self, out, context=None, return_scalar=False): """So that we return a native numpy array (or scalar) when a reducting ufunc is applied (such as sum(), std(), etc.) """ - if not out.shape: + if return_scalar or not out.shape: return out.dtype.type(out) # Scalar elif out.shape != self.shape: return out.view(type=np.ndarray) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/imageio/plugins/_bsdf.py new/imageio-2.37.4/imageio/plugins/_bsdf.py --- old/imageio-2.37.3/imageio/plugins/_bsdf.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/imageio/plugins/_bsdf.py 2026-07-20 07:25:43.000000000 +0200 @@ -901,7 +901,7 @@ except ImportError: # pragma: no cover return v a = np.frombuffer(v["data"], dtype=v["dtype"]) - a.shape = v["shape"] + a = a.reshape(v["shape"]) return a diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/imageio/plugins/_freeimage.py new/imageio-2.37.4/imageio/plugins/_freeimage.py --- old/imageio-2.37.3/imageio/plugins/_freeimage.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/imageio/plugins/_freeimage.py 2026-07-20 07:25:43.000000000 +0200 @@ -1057,13 +1057,13 @@ array = numpy.frombuffer(bb, dtype=dtype).copy() # Deal with strides if len(shape) == 3: - array.shape = shape[2], strides[-1] // shape[0], shape[0] + array = array.reshape(shape[2], strides[-1] // shape[0], shape[0]) array2 = array[: shape[2], : shape[1], : shape[0]] array = numpy.zeros(shape, dtype=array.dtype) for i in range(shape[0]): array[i] = array2[:, :, i].T else: - array.shape = shape[1], strides[-1] + array = array.reshape(shape[1], strides[-1]) array = array[: shape[1], : shape[0]].T return array diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/imageio/plugins/_swf.py new/imageio-2.37.4/imageio/plugins/_swf.py --- old/imageio-2.37.3/imageio/plugins/_swf.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/imageio/plugins/_swf.py 2026-07-20 07:25:43.000000000 +0200 @@ -652,13 +652,13 @@ if tagType == 20: # DefineBitsLossless - RGB data try: - a.shape = height, width, 3 + a = a.reshape(height, width, 3) except Exception: # Byte align stuff might cause troubles logger.warning("Cannot read image due to byte alignment") if tagType == 36: # DefineBitsLossless2 - ARGB data - a.shape = height, width, 4 + a = a.reshape(height, width, 4) # Swap alpha channel to make RGBA b = a a = np.zeros_like(a) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/imageio/plugins/bsdf.py new/imageio-2.37.4/imageio/plugins/bsdf.py --- old/imageio-2.37.3/imageio/plugins/bsdf.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/imageio/plugins/bsdf.py 2026-07-20 07:25:43.000000000 +0200 @@ -101,7 +101,7 @@ if not isinstance(blob, bytes): # then it's a lazy bsdf.Blob blob = blob.get_bytes() self.array = np.frombuffer(blob, dtype=v["dtype"]) - self.array.shape = v["shape"] + self.array = self.array.reshape(v["shape"]) return self.array def get_meta(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/imageio/plugins/pillow.py new/imageio-2.37.4/imageio/plugins/pillow.py --- old/imageio-2.37.3/imageio/plugins/pillow.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/imageio/plugins/pillow.py 2026-07-20 07:25:43.000000000 +0200 @@ -126,7 +126,7 @@ warnings.warn( "Can't determine file format to write as. You _must_" " set `format` during write or the call will fail. Use " - "`extension` to supress this warning. ", + "`extension` to suppress this warning. ", UserWarning, ) return @@ -187,7 +187,7 @@ writable_output : bool If True, ensure that the image is writable before returning it to the user. This incurs a full copy of the pixel data if the data - served by pillow is read-only. Consequentially, setting this flag to + served by pillow is read-only. Consequently, setting this flag to False improves performance for some images. pilmode : str Deprecated, use `mode` instead. @@ -205,7 +205,7 @@ ----- If you read a paletted image (e.g. GIF) then the plugin will apply the palette by default. Should you wish to read the palette indices of each - pixel use ``mode="P"``. The coresponding color pallete can be found in + pixel use ``mode="P"``. The corresponding color palette can be found in the image's metadata using the ``palette`` key when metadata is extracted using the ``exclude_applied=False`` kwarg. The latter is needed, as palettes are applied by default and hence excluded by default @@ -290,7 +290,7 @@ writable_output : bool If True, ensure that the image is writable before returning it to the user. This incurs a full copy of the pixel data if the data - served by pillow is read-only. Consequentially, setting this flag to + served by pillow is read-only. Consequently, setting this flag to False improves performance for some images. """ @@ -321,7 +321,7 @@ warnings.warn( "Loading 16-bit (uint16) PNG as int32 due to limitations " "in pillow's PNG decoder. This will be fixed in a future " - "version of pillow which will make this warning dissapear.", + "version of pillow which will make this warning disappear.", UserWarning, ) elif minor < 1: # pragma: no cover @@ -442,7 +442,10 @@ ndimage = ndimage[None, ...] for frame in ndimage: - pil_frame = Image.fromarray(frame, mode=mode) + if mode is None: + pil_frame = Image.fromarray(frame) + else: + pil_frame = Image.fromarray(frame, mode=mode) if "bits" in kwargs: pil_frame = pil_frame.quantize(colors=2 ** kwargs["bits"]) self.images_to_write.append(pil_frame) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/imageio/plugins/pillow_legacy.py new/imageio-2.37.4/imageio/plugins/pillow_legacy.py --- old/imageio-2.37.3/imageio/plugins/pillow_legacy.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/imageio/plugins/pillow_legacy.py 2026-07-20 07:25:43.000000000 +0200 @@ -335,7 +335,7 @@ self._seek(i) if self._im.palette and self._im.palette.dirty: self._im.palette.rawmode_saved = self._im.palette.rawmode - self._im.getdata()[0] + self._im.load() im = pil_get_frame(self._im, **self._kwargs) return im, self._im.info @@ -642,7 +642,7 @@ def pil_try_read(im): try: # this will raise an IOError if the file is not readable - im.getdata()[0] + im.load() except IOError as e: site = "http://pillow.readthedocs.io/en/latest/installation.html" site += "#external-libraries" @@ -705,14 +705,18 @@ # We can do this ourselves. Pillow seems to sometimes screw # this up if a multi-gif has a palette for each frame ... # Create palette array - p = np.frombuffer(im.palette.getdata()[1], np.uint8) + if hasattr(im.palette, "tobytes"): + palette_bytes = im.palette.tobytes() + else: # pragma: no cover + palette_bytes = im.palette.getdata()[1] + p = np.frombuffer(palette_bytes, np.uint8) # Restore the raw mode that was saved to be used to parse the palette if hasattr(im.palette, "rawmode_saved"): im.palette.rawmode = im.palette.rawmode_saved mode = im.palette.rawmode if im.palette.rawmode else im.palette.mode nchannels = len(mode) # Shape it. - p.shape = -1, nchannels + p = p.reshape(-1, nchannels) if p.shape[1] == 3 or (p.shape[1] == 4 and mode[-1] == "X"): p = np.column_stack((p[:, :3], 255 * np.ones(p.shape[0], p.dtype))) # Swap the axes if the mode is in BGR and not RGB @@ -766,7 +770,7 @@ if "S" in im.mode: dtype = dtype.replace("u", "i") frame = np.frombuffer(frame.tobytes(), dtype).copy() - frame.shape = shape[::-1] + frame = frame.reshape(shape[::-1]) else: # Use uint16 for PNG's in mode I if im.format == "PNG" and im.mode == "I" and dtype is None: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/imageio/plugins/pillowmulti.py new/imageio-2.37.4/imageio/plugins/pillowmulti.py --- old/imageio-2.37.3/imageio/plugins/pillowmulti.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/imageio/plugins/pillowmulti.py 2026-07-20 07:25:43.000000000 +0200 @@ -134,7 +134,7 @@ im_rect, rect = self.getSubRectangle(im) im_pil = self.converToPIL(im_rect, self.opt_quantizer, self.opt_palette_size) - # Get pallette - apparently, this is the 3d element of the header + # Get palette - apparently, this is the 3d element of the header # (but it has not always been). Best we've got. Its not the same # as im_pil.palette.tobytes(). from PIL.GifImagePlugin import getheader @@ -215,7 +215,7 @@ Modified by Alex Robinson in Janurari 2011 to implement subrectangles. """ - # Defaule use full image and place at upper left + # Default: use full image and place at upper left if xy is None: xy = (0, 0) @@ -232,7 +232,7 @@ # reserved00, lct size111=7=2^(7 + 1)=256. bb += b"\x87" - # LZW minimum size code now comes later, begining of [imagedata] blocks + # LZW minimum size code now comes later, beginning of [imagedata] blocks return bb def getAppExt(self, loop): @@ -254,7 +254,7 @@ def getGraphicsControlExt(self, duration=0.1, dispose=2): """Graphics Control Extension. A sort of header at the start of - each image. Specifies duration and transparancy. + each image. Specifies duration and transparency. Dispose ------- @@ -274,7 +274,7 @@ # 2nd bit 1 == user input , next 3 bits, the low two of which are used, # are dispose. bb += intToBin(int(duration * 100 + 0.5)) # in 100th of seconds - bb += b"\x00" # no transparant color + bb += b"\x00" # no transparent color bb += b"\x00" # end return bb diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/imageio/plugins/pyav.py new/imageio-2.37.4/imageio/plugins/pyav.py --- old/imageio-2.37.3/imageio/plugins/pyav.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/imageio/plugins/pyav.py 2026-07-20 07:25:43.000000000 +0200 @@ -516,7 +516,7 @@ variable_fps = bool(self._container.format.flags & 0x400) constant_framerate = not variable_fps - # note: cheap for contigous incremental reads + # note: cheap for contiguous incremental reads self._seek(index, constant_framerate=constant_framerate) desired_frame = next(self._decoder) self._next_idx += 1 @@ -1150,7 +1150,7 @@ planes.append(np_plane) if len(planes) > 1: - # Note: the planes *should* exist inside a contigous memory block + # Note: the planes *should* exist inside a contiguous memory block # somewhere inside av.Frame however pyAV does not appear to expose this, # so we are forced to copy the planes individually instead of wrapping # them :( @@ -1198,7 +1198,7 @@ index_pts = int(index * pts_delta) - # this only seeks to the closed (preceeding) keyframe + # this only seeks to the closest (preceding) keyframe self._container.seek(index_pts, stream=self._video_stream) self._decoder = self._container.decode(video=0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/imageio/plugins/tifffile_v3.py new/imageio-2.37.4/imageio/plugins/tifffile_v3.py --- old/imageio-2.37.3/imageio/plugins/tifffile_v3.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/imageio/plugins/tifffile_v3.py 2026-07-20 07:25:43.000000000 +0200 @@ -215,13 +215,29 @@ create new series unless ``contiguous=True`` is used, in which case the call to write will append to the current series. + When ``photometric`` / ``planarconfig`` are omitted, ImageIO sets + defaults for common RGB layouts so tifffile does not emit deprecation + warnings about ambiguous channel-axis interpretation: + + - channel-last arrays (shape ``(..., 3)`` or ``(..., 4)``): + ``photometric="rgb"`` + - channel-first arrays (shape ``(3, ...)`` or ``(4, ...)`` on the + third-to-last axis): ``photometric="rgb"`` and + ``planarconfig="separate"`` """ if not is_batch: ndimage = np.asarray(ndimage)[None, :] for image in ndimage: - self._fh.write(image, **kwargs) + write_kwargs = dict(kwargs) + arr = np.asarray(image) + if arr.ndim >= 3 and arr.shape[-1] in (3, 4): + write_kwargs.setdefault("photometric", "rgb") + elif arr.ndim >= 3 and arr.shape[-3] in (3, 4): + write_kwargs.setdefault("photometric", "rgb") + write_kwargs.setdefault("planarconfig", "separate") + self._fh.write(image, **write_kwargs) if self._request._uri_type == URI_BYTES: self._fh.close() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/pyproject.toml new/imageio-2.37.4/pyproject.toml --- old/imageio-2.37.3/pyproject.toml 2026-03-09 12:30:49.000000000 +0100 +++ new/imageio-2.37.4/pyproject.toml 2026-07-20 07:25:48.000000000 +0200 @@ -4,7 +4,7 @@ [project] name = "ImageIO" -version = "2.37.3" +version = "2.37.4" authors = [ {name = "ImageIO contributors"} ] @@ -123,7 +123,6 @@ "imageio-ffmpeg", "pillow-heif", "psutil", - "tifffile", ] full = [ "astropy", @@ -149,7 +148,7 @@ packages = ["imageio", "imageio.core", "imageio.plugins", "imageio.config"] [tool.setuptools.dynamic] -readme = {file = ["README.md"]} +readme = {file = ["README.md"], content-type = "text/markdown"} [tool.setuptools.package-data] imageio = ["py.typed", "**/*.pyi", "*.pyi"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/tests/test_freeimage.py new/imageio-2.37.4/tests/test_freeimage.py --- old/imageio-2.37.3/tests/test_freeimage.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/tests/test_freeimage.py 2026-07-20 07:25:43.000000000 +0200 @@ -4,44 +4,45 @@ import shutil import sys import platform +import time import warnings -import fsspec # type: ignore import imageio.plugins import imageio.v3 as iio3 import imageio.v2 as iio import numpy as np import pytest from imageio import core -from imageio.core import IS_PYPY +from imageio.core import IS_PYPY, get_platform +from imageio.plugins._freeimage import FNAME_PER_PLATFORM, download from pytest import raises from conftest import deprecated_test @pytest.fixture(scope="module") -def vendored_lib(request, tmp_path_factory): - lib_dir = tmp_path_factory.mktemp("freeimage_dir") +def vendored_lib(tmp_path_factory): + """Download FreeImage binaries via raw.githubusercontent.com (with retries).""" + plat = get_platform() + if not plat or plat not in FNAME_PER_PLATFORM: + pytest.skip("No FreeImage binary for this platform") - if platform.system() == "Linux": - lib_extension = ".so" - elif platform.system() == "Darwin": - lib_extension = ".dylib" - elif platform.system() == "Windows": - lib_extension = ".dll" - - fs = fsspec.filesystem( - "github", - org="imageio", - repo="imageio-binaries", - username=request.config.getoption("--github-username"), - token=request.config.getoption("--github-token"), - ) - fs.get( - [x for x in fs.ls("freeimage/") if x.endswith(lib_extension)], - lib_dir.as_posix(), - ) + lib_dir = tmp_path_factory.mktemp("freeimage_dir") + last_exc = None + for attempt in range(4): + try: + download(directory=str(lib_dir)) + break + except Exception as exc: + last_exc = exc + time.sleep(0.5 * (2**attempt)) + else: + pytest.skip(f"Could not download FreeImage binaries: {last_exc}") + + freeimage_dir = lib_dir / "freeimage" + if not freeimage_dir.is_dir() or not any(freeimage_dir.iterdir()): + pytest.skip("FreeImage download did not produce expected files") - yield lib_dir + yield freeimage_dir # TODD: update fixture once we transition into v3 @@ -616,7 +617,7 @@ im = get_ref_im(4, 0, 0)[:32, :32] ims = [np.repeat(np.repeat(im, i, 1), i, 0) for i in (1, 2)] # SegF on win - ims = im, np.column_stack((im, im)), np.row_stack((im, im)) # error on win + ims = im, np.column_stack((im, im)), np.vstack((im, im)) # error on win iio.mimsave(fnamebase + "I2.ico", ims, format="ICO-FI") ims2 = iio.mimread(fnamebase + "I2.ico", format="ICO-FI") for im1, im2 in zip(ims, ims2): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/imageio-2.37.3/tests/test_tifffile_v3.py new/imageio-2.37.4/tests/test_tifffile_v3.py --- old/imageio-2.37.3/tests/test_tifffile_v3.py 2026-03-09 12:30:43.000000000 +0100 +++ new/imageio-2.37.4/tests/test_tifffile_v3.py 2026-07-20 07:25:43.000000000 +0200 @@ -94,7 +94,12 @@ if tuple(int(x) for x in tifffile.__version__.split(".")) <= (2021, 11, 2): assert tif.series[0].pages[0].tags[284].value == 2 else: - assert tif.series[0].dims == ("sample", "height", "width") + # tifffile 2026.6.1+ (Python >= 3.12) uses axes codes; earlier + # releases still report long dim names. + assert tif.series[0].dims in ( + ("sample", "height", "width"), + ("S", "Y", "X"), + ) def test_metadata_reading(test_images):
