def extractJPEG(self): """ extract the raw image to its right place """ extension = op.splitext(self.strRawFile)[1].lower() strJpegFullPath = op.join(config.DefaultRepository, self.getJpegPath()) if extension in config.RawExtensions: process = subprocess.Popen("%s %s" % (config.Dcraw, self.strRawFile), shell=True, stdout=subprocess.PIPE) ret = process.wait() if ret != 0: logger.error("'%s %s' ended with error %s" % (config.Dcraw, self.strRawFile, ret)) data = process.stdout.readlines() img = Image.fromstring("RGB", tuple([int(i) for i in data[1].split()]), "".join(tuple(data[3:]))) img.save(strJpegFullPath, format='JPEG') #Copy all metadata useful for us. exifJpeg = Exif(strJpegFullPath) exifJpeg.read() exifJpeg['Exif.Image.Orientation'] = 1 exifJpeg["Exif.Photo.UserComment"] = self.strRawFile for metadata in [ 'Exif.Image.Make', 'Exif.Image.Model', 'Exif.Photo.DateTimeOriginal', 'Exif.Photo.ExposureTime', 'Exif.Photo.FNumber', 'Exif.Photo.ExposureBiasValue', 'Exif.Photo.Flash', 'Exif.Photo.FocalLength', 'Exif.Photo.ISOSpeedRatings']: try: exifJpeg[metadata] = self.exif[metadata] except: logger.error("Unable to copying metadata %s in file %s, value: %s" % (metadata, self.strRawFile, self.exif[metadata])) #self.exif.copyMetadataTo(self.strJepgFile) exifJpeg.write() else: #in config.Extensions, i.e. a JPEG file shutil.copy(self.strRawFile, strJpegFullPath) Exiftran.autorotate(strJpegFullPath) os.chmod(strJpegFullPath, config.DefaultFileMode)
def autoWB(self, outfile): """ apply Auto White - Balance to the current image @param: the name of the output file (JPEG) @return: filtered Photo instance """ try: import numpy except: logger.error("This filter needs the numpy library available on http://numpy.scipy.org/") return t0 = time.time() position = 5e-4 rgb1 = numpy.fromstring(self.pil.tostring(), dtype="uint8") rgb1.shape = -1, 3 rgb = rgb1.astype("float32") rgb1.sort(axis=0) pos_min = int(round(rgb1.shape[0] * position)) pos_max = rgb1.shape[0] - pos_min rgb_min = rgb1[pos_min] rgb_max = rgb1[pos_max] rgb[:, 0] = 255.0 * (rgb[:, 0].clip(rgb_min[0], rgb_max[0]) - rgb_min[0]) / (rgb_max[0] - rgb_min[0]) rgb[:, 1] = 255.0 * (rgb[:, 1].clip(rgb_min[1], rgb_max[1]) - rgb_min[1]) / (rgb_max[1] - rgb_min[1]) rgb[:, 2] = 255.0 * (rgb[:, 2].clip(rgb_min[2], rgb_max[2]) - rgb_min[2]) / (rgb_max[2] - rgb_min[2]) out = Image.fromstring("RGB", (self.pixelsX, self.pixelsY), rgb.round().astype("uint8").tostring()) exitJpeg = op.join(config.DefaultRepository, outfile) out.save(exitJpeg, quality=80, progressive=True, Optimize=True) try: os.chmod(exitJpeg, config.DefaultFileMode) except IOError: logger.error("Unable to chmod %s" % outfile) exifJpeg = Exif(exitJpeg) exifJpeg.read() self.exif.copy(exifJpeg) logger.debug("Write metadata to %s", exitJpeg) exifJpeg.write() logger.info("The whoole Auto White-Balance took %.3f" % (time.time() - t0)) return Photo(outfile)
def contrastMask(self, outfile): """Ceci est un filtre de debouchage de photographies, aussi appelé masque de contraste, il permet de rattrapper une photo trop contrasté, un contre jour, ... Écrit par Jérôme Kieffer, avec l'aide de la liste python@aful, en particulier A. Fayolles et F. Mantegazza avril 2006 necessite numpy et PIL. @param: the name of the output file (JPEG) @return: filtered Photo instance """ try: import numpy # import scipy.signal as signal except: logger.error("This filter needs the numpy library available on https://sourceforge.net/projects/numpy/files/") return t0 = time.time() dimX, dimY = self.pil.size ImageFile.MAXBLOCK = dimX * dimY img_array = numpy.fromstring(self.pil.tostring(), dtype="UInt8").astype("float32") img_array.shape = (dimY, dimX, 3) red, green, blue = img_array[:, :, 0], img_array[:, :, 1], img_array[:, :, 2] #nota: this is faster than desat2=(ar.max(axis=2)+ar.min(axis=2))/2 desat_array = (numpy.minimum(numpy.minimum(red, green), blue) + numpy.maximum(numpy.maximum(red, green), blue)) / 2.0 inv_desat = 255. - desat_array blured_inv_desat = self._gaussian.blur(inv_desat, config.ContrastMaskGaussianSize) bisi = numpy.round(blured_inv_desat).astype("uint8") k = Image.fromarray(bisi, "L").convert("RGB") S = ImageChops.screen(self.pil, k) M = ImageChops.multiply(self.pil, k) F = ImageChops.add(ImageChops.multiply(self.pil, S), ImageChops.multiply(ImageChops.invert(self.pil), M)) exitJpeg = op.join(config.DefaultRepository, outfile) F.save(exitJpeg, quality=80, progressive=True, Optimize=True) try: os.chmod(exitJpeg, config.DefaultFileMode) except IOError: logger.error("Unable to chmod %s" % outfile) exifJpeg = Exif(exitJpeg) exifJpeg.read() self.exif.copy(exifJpeg) exifJpeg.comment = self.exif.comment # # for metadata in [ 'Exif.Image.Make', 'Exif.Image.Model', 'Exif.Photo.DateTimeOriginal', # 'Exif.Photo.ExposureTime', 'Exif.Photo.FNumber', 'Exif.Photo.ExposureBiasValue', # 'Exif.Photo.Flash', 'Exif.Photo.FocalLength', 'Exif.Photo.ISOSpeedRatings', # "Exif.Image.Orientation", "Exif.Photo.UserComment" # ]: # if metadata in self.exif: # logger.debug("Copying metadata %s", metadata) # try: # exifJpeg[metadata] = self.exif[metadata] # except KeyError: # pass #'Tag not set'-> unable to copy it # except: # logger.error("Unable to copying metadata %s in file %s, value: %s" % (metadata, self.filename, self.exif[metadata])) logger.debug("Write metadata to %s", exitJpeg) exifJpeg.write() logger.info("The whoole contrast mask took %.3f" % (time.time() - t0)) return Photo(outfile)