Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/PIL/JpegImagePlugin.py
diff options
context:
space:
mode:
Diffstat (limited to 'PIL/JpegImagePlugin.py')
-rw-r--r--PIL/JpegImagePlugin.py430
1 files changed, 0 insertions, 430 deletions
diff --git a/PIL/JpegImagePlugin.py b/PIL/JpegImagePlugin.py
deleted file mode 100644
index b8ba8e4..0000000
--- a/PIL/JpegImagePlugin.py
+++ /dev/null
@@ -1,430 +0,0 @@
-#
-# The Python Imaging Library.
-# $Id: JpegImagePlugin.py 2763 2006-06-22 21:43:28Z fredrik $
-#
-# JPEG (JFIF) file handling
-#
-# See "Digital Compression and Coding of Continous-Tone Still Images,
-# Part 1, Requirements and Guidelines" (CCITT T.81 / ISO 10918-1)
-#
-# History:
-# 1995-09-09 fl Created
-# 1995-09-13 fl Added full parser
-# 1996-03-25 fl Added hack to use the IJG command line utilities
-# 1996-05-05 fl Workaround Photoshop 2.5 CMYK polarity bug
-# 1996-05-28 fl Added draft support, JFIF version (0.1)
-# 1996-12-30 fl Added encoder options, added progression property (0.2)
-# 1997-08-27 fl Save mode 1 images as BW (0.3)
-# 1998-07-12 fl Added YCbCr to draft and save methods (0.4)
-# 1998-10-19 fl Don't hang on files using 16-bit DQT's (0.4.1)
-# 2001-04-16 fl Extract DPI settings from JFIF files (0.4.2)
-# 2002-07-01 fl Skip pad bytes before markers; identify Exif files (0.4.3)
-# 2003-04-25 fl Added experimental EXIF decoder (0.5)
-# 2003-06-06 fl Added experimental EXIF GPSinfo decoder
-# 2003-09-13 fl Extract COM markers
-#
-# Copyright (c) 1997-2003 by Secret Labs AB.
-# Copyright (c) 1995-1996 by Fredrik Lundh.
-#
-# See the README file for information on usage and redistribution.
-#
-
-__version__ = "0.5"
-
-import array, string
-import Image, ImageFile
-
-def i16(c,o=0):
- return ord(c[o+1]) + (ord(c[o])<<8)
-
-def i32(c,o=0):
- return ord(c[o+3]) + (ord(c[o+2])<<8) + (ord(c[o+1])<<16) + (ord(c[o])<<24)
-
-#
-# Parser
-
-def Skip(self, marker):
- n = i16(self.fp.read(2))-2
- ImageFile._safe_read(self.fp, n)
-
-def APP(self, marker):
- #
- # Application marker. Store these in the APP dictionary.
- # Also look for well-known application markers.
-
- n = i16(self.fp.read(2))-2
- s = ImageFile._safe_read(self.fp, n)
-
- app = "APP%d" % (marker&15)
-
- self.app[app] = s # compatibility
- self.applist.append((app, s))
-
- if marker == 0xFFE0 and s[:4] == "JFIF":
- # extract JFIF information
- self.info["jfif"] = version = i16(s, 5) # version
- self.info["jfif_version"] = divmod(version, 256)
- # extract JFIF properties
- try:
- jfif_unit = ord(s[7])
- jfif_density = i16(s, 8), i16(s, 10)
- except:
- pass
- else:
- if jfif_unit == 1:
- self.info["dpi"] = jfif_density
- self.info["jfif_unit"] = jfif_unit
- self.info["jfif_density"] = jfif_density
- elif marker == 0xFFE1 and s[:5] == "Exif\0":
- # extract Exif information (incomplete)
- self.info["exif"] = s # FIXME: value will change
- elif marker == 0xFFE2 and s[:5] == "FPXR\0":
- # extract FlashPix information (incomplete)
- self.info["flashpix"] = s # FIXME: value will change
- elif marker == 0xFFEE and s[:5] == "Adobe":
- self.info["adobe"] = i16(s, 5)
- # extract Adobe custom properties
- try:
- adobe_transform = ord(s[1])
- except:
- pass
- else:
- self.info["adobe_transform"] = adobe_transform
-
-def COM(self, marker):
- #
- # Comment marker. Store these in the APP dictionary.
-
- n = i16(self.fp.read(2))-2
- s = ImageFile._safe_read(self.fp, n)
-
- self.app["COM"] = s # compatibility
- self.applist.append(("COM", s))
-
-def SOF(self, marker):
- #
- # Start of frame marker. Defines the size and mode of the
- # image. JPEG is colour blind, so we use some simple
- # heuristics to map the number of layers to an appropriate
- # mode. Note that this could be made a bit brighter, by
- # looking for JFIF and Adobe APP markers.
-
- n = i16(self.fp.read(2))-2
- s = ImageFile._safe_read(self.fp, n)
- self.size = i16(s[3:]), i16(s[1:])
-
- self.bits = ord(s[0])
- if self.bits != 8:
- raise SyntaxError("cannot handle %d-bit layers" % self.bits)
-
- self.layers = ord(s[5])
- if self.layers == 1:
- self.mode = "L"
- elif self.layers == 3:
- self.mode = "RGB"
- elif self.layers == 4:
- self.mode = "CMYK"
- else:
- raise SyntaxError("cannot handle %d-layer images" % self.layers)
-
- if marker in [0xFFC2, 0xFFC6, 0xFFCA, 0xFFCE]:
- self.info["progression"] = 1
-
- for i in range(6, len(s), 3):
- t = s[i:i+3]
- # 4-tuples: id, vsamp, hsamp, qtable
- self.layer.append((t[0], ord(t[1])/16, ord(t[1])&15, ord(t[2])))
-
-def DQT(self, marker):
- #
- # Define quantization table. Support baseline 8-bit tables
- # only. Note that there might be more than one table in
- # each marker.
-
- # FIXME: The quantization tables can be used to estimate the
- # compression quality.
-
- n = i16(self.fp.read(2))-2
- s = ImageFile._safe_read(self.fp, n)
- while len(s):
- if len(s) < 65:
- raise SyntaxError("bad quantization table marker")
- v = ord(s[0])
- if v/16 == 0:
- self.quantization[v&15] = array.array("b", s[1:65])
- s = s[65:]
- else:
- return # FIXME: add code to read 16-bit tables!
- # raise SyntaxError, "bad quantization table element size"
-
-
-#
-# JPEG marker table
-
-MARKER = {
- 0xFFC0: ("SOF0", "Baseline DCT", SOF),
- 0xFFC1: ("SOF1", "Extended Sequential DCT", SOF),
- 0xFFC2: ("SOF2", "Progressive DCT", SOF),
- 0xFFC3: ("SOF3", "Spatial lossless", SOF),
- 0xFFC4: ("DHT", "Define Huffman table", Skip),
- 0xFFC5: ("SOF5", "Differential sequential DCT", SOF),
- 0xFFC6: ("SOF6", "Differential progressive DCT", SOF),
- 0xFFC7: ("SOF7", "Differential spatial", SOF),
- 0xFFC8: ("JPG", "Extension", None),
- 0xFFC9: ("SOF9", "Extended sequential DCT (AC)", SOF),
- 0xFFCA: ("SOF10", "Progressive DCT (AC)", SOF),
- 0xFFCB: ("SOF11", "Spatial lossless DCT (AC)", SOF),
- 0xFFCC: ("DAC", "Define arithmetic coding conditioning", Skip),
- 0xFFCD: ("SOF13", "Differential sequential DCT (AC)", SOF),
- 0xFFCE: ("SOF14", "Differential progressive DCT (AC)", SOF),
- 0xFFCF: ("SOF15", "Differential spatial (AC)", SOF),
- 0xFFD0: ("RST0", "Restart 0", None),
- 0xFFD1: ("RST1", "Restart 1", None),
- 0xFFD2: ("RST2", "Restart 2", None),
- 0xFFD3: ("RST3", "Restart 3", None),
- 0xFFD4: ("RST4", "Restart 4", None),
- 0xFFD5: ("RST5", "Restart 5", None),
- 0xFFD6: ("RST6", "Restart 6", None),
- 0xFFD7: ("RST7", "Restart 7", None),
- 0xFFD8: ("SOI", "Start of image", None),
- 0xFFD9: ("EOI", "End of image", None),
- 0xFFDA: ("SOS", "Start of scan", Skip),
- 0xFFDB: ("DQT", "Define quantization table", DQT),
- 0xFFDC: ("DNL", "Define number of lines", Skip),
- 0xFFDD: ("DRI", "Define restart interval", Skip),
- 0xFFDE: ("DHP", "Define hierarchical progression", SOF),
- 0xFFDF: ("EXP", "Expand reference component", Skip),
- 0xFFE0: ("APP0", "Application segment 0", APP),
- 0xFFE1: ("APP1", "Application segment 1", APP),
- 0xFFE2: ("APP2", "Application segment 2", APP),
- 0xFFE3: ("APP3", "Application segment 3", APP),
- 0xFFE4: ("APP4", "Application segment 4", APP),
- 0xFFE5: ("APP5", "Application segment 5", APP),
- 0xFFE6: ("APP6", "Application segment 6", APP),
- 0xFFE7: ("APP7", "Application segment 7", APP),
- 0xFFE8: ("APP8", "Application segment 8", APP),
- 0xFFE9: ("APP9", "Application segment 9", APP),
- 0xFFEA: ("APP10", "Application segment 10", APP),
- 0xFFEB: ("APP11", "Application segment 11", APP),
- 0xFFEC: ("APP12", "Application segment 12", APP),
- 0xFFED: ("APP13", "Application segment 13", APP),
- 0xFFEE: ("APP14", "Application segment 14", APP),
- 0xFFEF: ("APP15", "Application segment 15", APP),
- 0xFFF0: ("JPG0", "Extension 0", None),
- 0xFFF1: ("JPG1", "Extension 1", None),
- 0xFFF2: ("JPG2", "Extension 2", None),
- 0xFFF3: ("JPG3", "Extension 3", None),
- 0xFFF4: ("JPG4", "Extension 4", None),
- 0xFFF5: ("JPG5", "Extension 5", None),
- 0xFFF6: ("JPG6", "Extension 6", None),
- 0xFFF7: ("JPG7", "Extension 7", None),
- 0xFFF8: ("JPG8", "Extension 8", None),
- 0xFFF9: ("JPG9", "Extension 9", None),
- 0xFFFA: ("JPG10", "Extension 10", None),
- 0xFFFB: ("JPG11", "Extension 11", None),
- 0xFFFC: ("JPG12", "Extension 12", None),
- 0xFFFD: ("JPG13", "Extension 13", None),
- 0xFFFE: ("COM", "Comment", COM)
-}
-
-
-def _accept(prefix):
- return prefix[0] == "\377"
-
-##
-# Image plugin for JPEG and JFIF images.
-
-class JpegImageFile(ImageFile.ImageFile):
-
- format = "JPEG"
- format_description = "JPEG (ISO 10918)"
-
- def _open(self):
-
- s = self.fp.read(1)
-
- if ord(s[0]) != 255:
- raise SyntaxError("not a JPEG file")
-
- # Create attributes
- self.bits = self.layers = 0
-
- # JPEG specifics (internal)
- self.layer = []
- self.huffman_dc = {}
- self.huffman_ac = {}
- self.quantization = {}
- self.app = {} # compatibility
- self.applist = []
-
- while 1:
-
- s = s + self.fp.read(1)
-
- i = i16(s)
-
- if MARKER.has_key(i):
- name, description, handler = MARKER[i]
- # print hex(i), name, description
- if handler is not None:
- handler(self, i)
- if i == 0xFFDA: # start of scan
- rawmode = self.mode
- if self.mode == "CMYK":
- rawmode = "CMYK;I"
- self.tile = [("jpeg", (0,0) + self.size, 0, (rawmode, ""))]
- # self.__offset = self.fp.tell()
- break
- s = self.fp.read(1)
- elif i == 0 or i == 65535:
- # padded marker or junk; move on
- s = "\xff"
- else:
- raise SyntaxError("no marker found")
-
- def draft(self, mode, size):
-
- if len(self.tile) != 1:
- return
-
- d, e, o, a = self.tile[0]
- scale = 0
-
- if a[0] == "RGB" and mode in ["L", "YCbCr"]:
- self.mode = mode
- a = mode, ""
-
- if size:
- scale = max(self.size[0] / size[0], self.size[1] / size[1])
- for s in [8, 4, 2, 1]:
- if scale >= s:
- break
- e = e[0], e[1], (e[2]-e[0]+s-1)/s+e[0], (e[3]-e[1]+s-1)/s+e[1]
- self.size = ((self.size[0]+s-1)/s, (self.size[1]+s-1)/s)
- scale = s
-
- self.tile = [(d, e, o, a)]
- self.decoderconfig = (scale, 1)
-
- return self
-
- def load_djpeg(self):
-
- # ALTERNATIVE: handle JPEGs via the IJG command line utilities
-
- import tempfile, os
- file = tempfile.mktemp()
- os.system("djpeg %s >%s" % (self.filename, file))
-
- try:
- self.im = Image.core.open_ppm(file)
- finally:
- try: os.unlink(file)
- except: pass
-
- self.mode = self.im.mode
- self.size = self.im.size
-
- self.tile = []
-
- def _getexif(self):
- # Extract EXIF information. This method is highly experimental,
- # and is likely to be replaced with something better in a future
- # version.
- import TiffImagePlugin, StringIO
- def fixup(value):
- if len(value) == 1:
- return value[0]
- return value
- # The EXIF record consists of a TIFF file embedded in a JPEG
- # application marker (!).
- try:
- data = self.info["exif"]
- except KeyError:
- return None
- file = StringIO.StringIO(data[6:])
- head = file.read(8)
- exif = {}
- # process dictionary
- info = TiffImagePlugin.ImageFileDirectory(head)
- info.load(file)
- for key, value in info.items():
- exif[key] = fixup(value)
- # get exif extension
- file.seek(exif[0x8769])
- info = TiffImagePlugin.ImageFileDirectory(head)
- info.load(file)
- for key, value in info.items():
- exif[key] = fixup(value)
- # get gpsinfo extension
- try:
- file.seek(exif[0x8825])
- except KeyError:
- pass
- else:
- info = TiffImagePlugin.ImageFileDirectory(head)
- info.load(file)
- exif[0x8825] = gps = {}
- for key, value in info.items():
- gps[key] = fixup(value)
- return exif
-
-# --------------------------------------------------------------------
-# stuff to save JPEG files
-
-RAWMODE = {
- "1": "L",
- "L": "L",
- "RGB": "RGB",
- "RGBA": "RGB",
- "RGBX": "RGB",
- "CMYK": "CMYK;I",
- "YCbCr": "YCbCr",
-}
-
-def _save(im, fp, filename):
-
- try:
- rawmode = RAWMODE[im.mode]
- except KeyError:
- raise IOError("cannot write mode %s as JPEG" % im.mode)
-
- info = im.encoderinfo
-
- dpi = info.get("dpi", (0, 0))
-
- # get keyword arguments
- im.encoderconfig = (
- info.get("quality", 0),
- # "progressive" is the official name, but older documentation
- # says "progression"
- # FIXME: issue a warning if the wrong form is used (post-1.1.5)
- info.has_key("progressive") or info.has_key("progression"),
- info.get("smooth", 0),
- info.has_key("optimize"),
- info.get("streamtype", 0),
- dpi[0], dpi[1]
- )
-
- ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)])
-
-def _save_cjpeg(im, fp, filename):
- # ALTERNATIVE: handle JPEGs via the IJG command line utilities.
- import os
- file = im._dump()
- os.system("cjpeg %s >%s" % (file, filename))
- try: os.unlink(file)
- except: pass
-
-# -------------------------------------------------------------------q-
-# Registry stuff
-
-Image.register_open("JPEG", JpegImageFile, _accept)
-Image.register_save("JPEG", _save)
-
-Image.register_extension("JPEG", ".jfif")
-Image.register_extension("JPEG", ".jpe")
-Image.register_extension("JPEG", ".jpg")
-Image.register_extension("JPEG", ".jpeg")
-
-Image.register_mime("JPEG", "image/jpeg")