+    def __init__(self, file: Union[str, BinaryIO]) -> None:
+        # pylint: disable=too-many-locals, too-many-branches, too-many-statements
+        """
+        Create an OnDiskBitmap object with the given file.
+
+        :param file file: The name of the bitmap file. For backwards compatibility, a file opened
+            in binary mode may also be passed.
+
+        Older versions of CircuitPython required a file opened in binary mode. CircuitPython 7.0
+        modified OnDiskBitmap so that it takes a filename instead, and opens the file internally.
+        A future version of CircuitPython will remove the ability to pass in an opened file.
+        """
+
+        if isinstance(file, str):
+            file = open(file, "rb")  # pylint: disable=consider-using-with
+
+        if not (file.readable() and file.seekable()):
+            raise TypeError("file must be a file opened in byte mode")
+
+        self._pixel_shader_base: Union[ColorConverter, Palette, None] = None
+
+        try:
+            self._file = file
+            file.seek(0)
+            bmp_header = file.read(138)
+
+            if len(bmp_header) != 138 or bmp_header[0:2] != b"BM":
+                raise ValueError("Invalid BMP file")
+
+            self._data_offset = _read_word(bmp_header, 5)
+
+            header_size = _read_word(bmp_header, 7)
+            bits_per_pixel = bmp_header[14 * 2] | bmp_header[14 * 2 + 1] << 8
+            compression = _read_word(bmp_header, 15)
+            number_of_colors = _read_word(bmp_header, 23)
+
+            indexed = bits_per_pixel <= 8
+            self._bitfield_compressed = compression == 3
+            self._bits_per_pixel = bits_per_pixel
+            self._width = _read_word(bmp_header, 9)
+            self._height = _read_word(bmp_header, 11)
+
+            self._colorconverter = ColorConverter()
+
+            if bits_per_pixel == 16:
+                if header_size >= 56 or self._bitfield_compressed:
+                    self._r_bitmask = _read_word(bmp_header, 27)
+                    self._g_bitmask = _read_word(bmp_header, 29)
+                    self._b_bitmask = _read_word(bmp_header, 31)
+                else:
+                    # No compression or short header mean 5:5:5
+                    self._r_bitmask = 0x7C00
+                    self._g_bitmask = 0x03E0
+                    self._b_bitmask = 0x001F
+            elif indexed:
+                if number_of_colors == 0:
+                    number_of_colors = 1 << bits_per_pixel
+
+                palette = Palette(number_of_colors)
+
+                if number_of_colors > 1:
+                    palette_size = number_of_colors * 4
+                    palette_offset = 0xE + header_size
+
+                    file.seek(palette_offset)
+
+                    palette_data = file.read(palette_size)
+                    if len(palette_data) != palette_size:
+                        raise ValueError("Unable to read color palette data")
+
+                    for i in range(number_of_colors):
+                        palette[i] = _read_uint32(palette_data, i * 4)
+                else:
+                    palette[0] = 0x000000
+                    palette[1] = 0xFFFFFF
+                self._palette = palette
+            elif header_size not in (12, 40, 108, 124):
+                raise ValueError(
+                    "Only Windows format, uncompressed BMP supported: "
+                    f"given header size is {header_size}"
+                )
+
+            if bits_per_pixel == 8 and number_of_colors == 0:
+                raise ValueError(
+                    "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: "
+                    f"{bits_per_pixel} bpp given"
+                )
+
+            bytes_per_pixel = (
+                self._bits_per_pixel // 8 if (self._bits_per_pixel // 8) else 1
+            )
+            pixels_per_byte = 8 // self._bits_per_pixel
+            if pixels_per_byte == 0:
+                self._stride = self._width * bytes_per_pixel
+                if self._stride % 4 != 0:
+                    self._stride += 4 - self._stride % 4
+            else:
+                bit_stride = self._width * self._bits_per_pixel
+                if bit_stride % 32 != 0:
+                    bit_stride += 32 - bit_stride % 32
+                self._stride = bit_stride // 8
+        except IOError as error:
+            raise OSError from error