Skip to content

jpeg

jpeg

Objects related to parsing headers of JPEG image streams.

Includes both JFIF and Exif sub-formats.

Jpeg

Jpeg(
    px_width: int,
    px_height: int,
    horz_dpi: int,
    vert_dpi: int,
    orientation: int = 1,
)

Bases: BaseImageHeader

Base class for JFIF and EXIF subclasses.

Source code in src/docx/image/image.py
def __init__(
    self,
    px_width: int,
    px_height: int,
    horz_dpi: int,
    vert_dpi: int,
    orientation: int = 1,
):
    self._px_width = px_width
    self._px_height = px_height
    self._horz_dpi = horz_dpi
    self._vert_dpi = vert_dpi
    self._orientation = orientation

content_type property

content_type

MIME content type for this image, unconditionally image/jpeg for JPEG images.

default_ext property

default_ext

Default filename extension, always 'jpg' for JPG images.

Exif

Exif(
    px_width: int,
    px_height: int,
    horz_dpi: int,
    vert_dpi: int,
    orientation: int = 1,
)

Bases: Jpeg

Image header parser for Exif image format.

Source code in src/docx/image/image.py
def __init__(
    self,
    px_width: int,
    px_height: int,
    horz_dpi: int,
    vert_dpi: int,
    orientation: int = 1,
):
    self._px_width = px_width
    self._px_height = px_height
    self._horz_dpi = horz_dpi
    self._vert_dpi = vert_dpi
    self._orientation = orientation

from_stream classmethod

from_stream(stream)

Return Exif instance having header properties parsed from Exif image in stream.

Source code in src/docx/image/jpeg.py
@classmethod
def from_stream(cls, stream):
    """Return |Exif| instance having header properties parsed from Exif image in
    `stream`."""
    markers = _JfifMarkers.from_stream(stream)
    # print('\n%s' % markers)

    px_width = markers.sof.px_width
    px_height = markers.sof.px_height
    horz_dpi = markers.app1.horz_dpi
    vert_dpi = markers.app1.vert_dpi
    orientation = markers.app1.orientation

    return cls(px_width, px_height, horz_dpi, vert_dpi, orientation)

Jfif

Jfif(
    px_width: int,
    px_height: int,
    horz_dpi: int,
    vert_dpi: int,
    orientation: int = 1,
)

Bases: Jpeg

Image header parser for JFIF image format.

Source code in src/docx/image/image.py
def __init__(
    self,
    px_width: int,
    px_height: int,
    horz_dpi: int,
    vert_dpi: int,
    orientation: int = 1,
):
    self._px_width = px_width
    self._px_height = px_height
    self._horz_dpi = horz_dpi
    self._vert_dpi = vert_dpi
    self._orientation = orientation

from_stream classmethod

from_stream(stream)

Return a Jfif instance having header properties parsed from image in stream.

Source code in src/docx/image/jpeg.py
@classmethod
def from_stream(cls, stream):
    """Return a |Jfif| instance having header properties parsed from image in
    `stream`."""
    markers = _JfifMarkers.from_stream(stream)

    px_width = markers.sof.px_width
    px_height = markers.sof.px_height
    horz_dpi = markers.app0.horz_dpi
    vert_dpi = markers.app0.vert_dpi

    return cls(px_width, px_height, horz_dpi, vert_dpi)

_JfifMarkers

_JfifMarkers(markers)

Sequence of markers in a JPEG file, perhaps truncated at first SOS marker for performance reasons.

Source code in src/docx/image/jpeg.py
def __init__(self, markers):
    super(_JfifMarkers, self).__init__()
    self._markers = list(markers)

app0 property

app0

First APP0 marker in image markers.

app1 property

app1

First APP1 marker in image markers.

sof property

sof

First start of frame (SOFn) marker in this sequence.

from_stream classmethod

from_stream(stream)

Return a _JfifMarkers instance containing a _JfifMarker subclass instance for each marker in stream.

Source code in src/docx/image/jpeg.py
@classmethod
def from_stream(cls, stream):
    """Return a |_JfifMarkers| instance containing a |_JfifMarker| subclass instance
    for each marker in `stream`."""
    marker_parser = _MarkerParser.from_stream(stream)
    markers = []
    for marker in marker_parser.iter_markers():
        markers.append(marker)
        if marker.marker_code == JPEG_MARKER_CODE.SOS:
            break
    return cls(markers)

_MarkerParser

_MarkerParser(stream_reader)

Service class that knows how to parse a JFIF stream and iterate over its markers.

Source code in src/docx/image/jpeg.py
def __init__(self, stream_reader):
    super(_MarkerParser, self).__init__()
    self._stream = stream_reader

from_stream classmethod

from_stream(stream)

Return a _MarkerParser instance to parse JFIF markers from stream.

Source code in src/docx/image/jpeg.py
@classmethod
def from_stream(cls, stream):
    """Return a |_MarkerParser| instance to parse JFIF markers from `stream`."""
    stream_reader = StreamReader(stream, BIG_ENDIAN)
    return cls(stream_reader)

iter_markers

iter_markers()

Generate a (marker_code, segment_offset) 2-tuple for each marker in the JPEG stream, in the order they occur in the stream.

Source code in src/docx/image/jpeg.py
def iter_markers(self):
    """Generate a (marker_code, segment_offset) 2-tuple for each marker in the JPEG
    `stream`, in the order they occur in the stream."""
    marker_finder = _MarkerFinder.from_stream(self._stream)
    start = 0
    marker_code = None
    while marker_code != JPEG_MARKER_CODE.EOI:
        marker_code, segment_offset = marker_finder.next(start)
        marker = _MarkerFactory(marker_code, self._stream, segment_offset)
        yield marker
        start = segment_offset + marker.segment_length

_MarkerFinder

_MarkerFinder(stream)

Service class that knows how to find the next JFIF marker in a stream.

Source code in src/docx/image/jpeg.py
def __init__(self, stream):
    super(_MarkerFinder, self).__init__()
    self._stream = stream

from_stream classmethod

from_stream(stream)

Return a _MarkerFinder instance to find JFIF markers in stream.

Source code in src/docx/image/jpeg.py
@classmethod
def from_stream(cls, stream):
    """Return a |_MarkerFinder| instance to find JFIF markers in `stream`."""
    return cls(stream)

next

next(start)

Return a (marker_code, segment_offset) 2-tuple identifying and locating the first marker in stream occuring after offset start.

The returned segment_offset points to the position immediately following the 2-byte marker code, the start of the marker segment, for those markers that have a segment.

Source code in src/docx/image/jpeg.py
def next(self, start):
    """Return a (marker_code, segment_offset) 2-tuple identifying and locating the
    first marker in `stream` occuring after offset `start`.

    The returned `segment_offset` points to the position immediately following the
    2-byte marker code, the start of the marker segment, for those markers that have
    a segment.
    """
    position = start
    while True:
        # skip over any non-\xFF bytes
        position = self._offset_of_next_ff_byte(start=position)
        # skip over any \xFF padding bytes
        position, byte_ = self._next_non_ff_byte(start=position + 1)
        # 'FF 00' sequence is not a marker, start over if found
        if byte_ == b"\x00":
            continue
        # this is a marker, gather return values and break out of scan
        marker_code, segment_offset = byte_, position + 1
        break
    return marker_code, segment_offset

_Marker

_Marker(marker_code, offset, segment_length)

Base class for JFIF marker classes.

Represents a marker and its segment occuring in a JPEG byte stream.

Source code in src/docx/image/jpeg.py
def __init__(self, marker_code, offset, segment_length):
    super(_Marker, self).__init__()
    self._marker_code = marker_code
    self._offset = offset
    self._segment_length = segment_length

marker_code property

marker_code

The single-byte code that identifies the type of this marker, e.g. 'à' for start of image (SOI).

segment_length property

segment_length

The length in bytes of this marker's segment.

from_stream classmethod

from_stream(stream, marker_code, offset)

Return a generic _Marker instance for the marker at offset in stream having marker_code.

Source code in src/docx/image/jpeg.py
@classmethod
def from_stream(cls, stream, marker_code, offset):
    """Return a generic |_Marker| instance for the marker at `offset` in `stream`
    having `marker_code`."""
    if JPEG_MARKER_CODE.is_standalone(marker_code):
        segment_length = 0
    else:
        segment_length = stream.read_short(offset)
    return cls(marker_code, offset, segment_length)

_App0Marker

_App0Marker(
    marker_code,
    offset,
    length,
    density_units,
    x_density,
    y_density,
)

Bases: _Marker

Represents a JFIF APP0 marker segment.

Source code in src/docx/image/jpeg.py
def __init__(self, marker_code, offset, length, density_units, x_density, y_density):
    super(_App0Marker, self).__init__(marker_code, offset, length)
    self._density_units = density_units
    self._x_density = x_density
    self._y_density = y_density

horz_dpi property

horz_dpi

Horizontal dots per inch specified in this marker, defaults to 72 if not specified.

vert_dpi property

vert_dpi

Vertical dots per inch specified in this marker, defaults to 72 if not specified.

from_stream classmethod

from_stream(stream, marker_code, offset)

Return an _App0Marker instance for the APP0 marker at offset in stream.

Source code in src/docx/image/jpeg.py
@classmethod
def from_stream(cls, stream, marker_code, offset):
    """Return an |_App0Marker| instance for the APP0 marker at `offset` in
    `stream`."""
    # field               off  type   notes
    # ------------------  ---  -----  -------------------
    # segment length       0   short
    # JFIF identifier      2   5 chr  'JFIF\x00'
    # major JPEG version   7   byte   typically 1
    # minor JPEG version   8   byte   typically 1 or 2
    # density units        9   byte   1=inches, 2=cm
    # horz dots per unit  10   short
    # vert dots per unit  12   short
    # ------------------  ---  -----  -------------------
    segment_length = stream.read_short(offset)
    density_units = stream.read_byte(offset, 9)
    x_density = stream.read_short(offset, 10)
    y_density = stream.read_short(offset, 12)
    return cls(marker_code, offset, segment_length, density_units, x_density, y_density)

_App1Marker

_App1Marker(
    marker_code,
    offset,
    length,
    horz_dpi,
    vert_dpi,
    orientation=1,
)

Bases: _Marker

Represents a JFIF APP1 (Exif) marker segment.

Source code in src/docx/image/jpeg.py
def __init__(self, marker_code, offset, length, horz_dpi, vert_dpi, orientation=1):
    super(_App1Marker, self).__init__(marker_code, offset, length)
    self._horz_dpi = horz_dpi
    self._vert_dpi = vert_dpi
    self._orientation = orientation

horz_dpi property

horz_dpi

Horizontal dots per inch specified in this marker, defaults to 72 if not specified.

vert_dpi property

vert_dpi

Vertical dots per inch specified in this marker, defaults to 72 if not specified.

orientation property

orientation

EXIF Orientation specified in this marker, 1 if it specifies none.

from_stream classmethod

from_stream(stream, marker_code, offset)

Extract the horizontal and vertical dots-per-inch value from the APP1 header at offset in stream.

Source code in src/docx/image/jpeg.py
@classmethod
def from_stream(cls, stream, marker_code, offset):
    """Extract the horizontal and vertical dots-per-inch value from the APP1 header
    at `offset` in `stream`."""
    # field                 off  len  type   notes
    # --------------------  ---  ---  -----  ----------------------------
    # segment length         0    2   short
    # Exif identifier        2    6   6 chr  'Exif\x00\x00'
    # TIFF byte order        8    2   2 chr  'II'=little 'MM'=big endian
    # meaning of universe   10    2   2 chr  '*\x00' or '\x00*' depending
    # IFD0 off fr/II or MM  10   16   long   relative to ...?
    # --------------------  ---  ---  -----  ----------------------------
    segment_length = stream.read_short(offset)
    if cls._is_non_Exif_APP1_segment(stream, offset):
        return cls(marker_code, offset, segment_length, 72, 72)
    tiff = cls._tiff_from_exif_segment(stream, offset, segment_length)
    return cls(
        marker_code,
        offset,
        segment_length,
        tiff.horz_dpi,
        tiff.vert_dpi,
        tiff.orientation,
    )

_SofMarker

_SofMarker(
    marker_code, offset, segment_length, px_width, px_height
)

Bases: _Marker

Represents a JFIF start of frame (SOFx) marker segment.

Source code in src/docx/image/jpeg.py
def __init__(self, marker_code, offset, segment_length, px_width, px_height):
    super(_SofMarker, self).__init__(marker_code, offset, segment_length)
    self._px_width = px_width
    self._px_height = px_height

px_height property

px_height

Image height in pixels.

px_width property

px_width

Image width in pixels.

from_stream classmethod

from_stream(stream, marker_code, offset)

Return an _SofMarker instance for the SOFn marker at offset in stream.

Source code in src/docx/image/jpeg.py
@classmethod
def from_stream(cls, stream, marker_code, offset):
    """Return an |_SofMarker| instance for the SOFn marker at `offset` in stream."""
    # field                 off  type   notes
    # ------------------  ---  -----  ----------------------------
    # segment length       0   short
    # Data precision       2   byte
    # Vertical lines       3   short  px_height
    # Horizontal lines     5   short  px_width
    # ------------------  ---  -----  ----------------------------
    segment_length = stream.read_short(offset)
    px_height = stream.read_short(offset, 3)
    px_width = stream.read_short(offset, 5)
    return cls(marker_code, offset, segment_length, px_width, px_height)

_MarkerFactory

_MarkerFactory(marker_code, stream, offset)

Return _Marker or subclass instance appropriate for marker at offset in stream having marker_code.

Source code in src/docx/image/jpeg.py
def _MarkerFactory(marker_code, stream, offset):
    """Return |_Marker| or subclass instance appropriate for marker at `offset` in
    `stream` having `marker_code`."""
    if marker_code == JPEG_MARKER_CODE.APP0:
        marker_cls = _App0Marker
    elif marker_code == JPEG_MARKER_CODE.APP1:
        marker_cls = _App1Marker
    elif marker_code in JPEG_MARKER_CODE.SOF_MARKER_CODES:
        marker_cls = _SofMarker
    else:
        marker_cls = _Marker
    return marker_cls.from_stream(stream, marker_code, offset)