def convert_image(image_path): # Take an image pathname # Returns an Image object with the profile converted img = Image.open(image_path) # If there is an embedded profile, write it and use it for conversion if 'icc_profile' in img.info: with open('/tmp/profile.icc', 'wb') as f: f.write(img.info.get('icc_profile')) result = profileToProfile(img, '/tmp/profile.icc', 'sRGB.icm', outputMode='RGB') return result elif 'CMYK' in img.mode: result = profileToProfile(img, 'CMYK.icc', 'sRGB.icm', outputMode='RGB') return result else: return img
def _run_transform(self, target_fp, image_request, kdu_cmd, fifo_fp): try: # Start the kdu shellout. Blocks until the pipe is empty kdu_expand_proc = subprocess.Popen(kdu_cmd, shell=True, bufsize=-1, stderr=subprocess.PIPE, env=self.env) with open(fifo_fp, 'rb') as f: # read from the named pipe p = Parser() while True: s = f.read(1024) if not s: break p.feed(s) im = p.close() # a PIL.Image finally: stdoutdata, stderrdata = kdu_expand_proc.communicate() kdu_exit = kdu_expand_proc.returncode if kdu_exit != 0: map(logger.error, stderrdata) unlink(fifo_fp) if self.map_profile_to_srgb and image_request.info.color_profile_bytes: # i.e. is not None emb_profile = cStringIO.StringIO( image_request.info.color_profile_bytes) im = profileToProfile(im, emb_profile, self.srgb_profile_fp) self._derive_with_pil(im, target_fp, image_request, crop=False)
def transform(self, src_fp, target_fp, image_request): # kdu writes to this: fifo_fp = self._make_tmp_fp() # kdu command #q = '-quiet' t = '-num_threads %s' % (self.num_threads,) i = '-i "%s"' % (src_fp,) o = '-o %s' % (fifo_fp,) reduce_arg = self._scales_to_reduce_arg(image_request) red = '-reduce %s' % (reduce_arg,) if reduce_arg else '' region_arg = self._region_to_kdu_arg(image_request.region_param) reg = '-region %s' % (region_arg,) if region_arg else '' #kdu_cmd = ' '.join((self.kdu_expand,q,i,t,reg,red,o)) kdu_cmd = 'LD_LIBRARY_PATH=/opt/kakadu/current/apps/make ' + ' '.join((self.kdu_expand,i,t,reg,red,o)) # make the named pipe mkfifo_call = '%s %s' % (self.mkfifo, fifo_fp) logger.debug('Calling %s' % (mkfifo_call,)) resp = subprocess.check_call(mkfifo_call, shell=True) try: # Start the kdu shellout. Blocks until the pipe is empty logger.debug('Calling: %s' % (kdu_cmd,)) kdu_expand_proc = subprocess.Popen(kdu_cmd, shell=True, bufsize=-1, stderr=subprocess.PIPE, env=self.env) f = open(fifo_fp, 'rb') logger.debug('Opened %s' % fifo_fp) # read from the named pipe p = Parser() while True: s = f.read(1024) if not s: break p.feed(s) im = p.close() # a PIL.Image # finish kdu kdu_exit = kdu_expand_proc.wait() if kdu_exit != 0: map(logger.error, kdu_expand_proc.stderr) if self.map_profile_to_srgb and image_request.info.color_profile_bytes: # i.e. is not None emb_profile = cStringIO.StringIO(image_request.info.color_profile_bytes) im = profileToProfile(im, emb_profile, self.srgb_profile_fp) self._derive_with_pil(im, target_fp, image_request, crop=False) except: raise finally: kdu_exit = kdu_expand_proc.wait() if kdu_exit != 0: map(logger.error, map(string.strip, kdu_expand_proc.stderr)) unlink(fifo_fp)
def transform(self, src_fp, target_fp, image_request): # opj writes to this: fifo_fp = self._make_tmp_fp() # make the named pipe mkfifo_call = '%s %s' % (self.mkfifo, fifo_fp) logger.debug('Calling %s' % (mkfifo_call, )) resp = subprocess.check_call(mkfifo_call, shell=True) if resp != 0: logger.error('Problem with mkfifo') # how to handle CalledProcessError; would have to be a 500? # opj_decompress command i = '-i "%s"' % (src_fp, ) o = '-o %s' % (fifo_fp, ) region_arg = self._region_to_opj_arg(image_request.region_param) reg = '-d %s' % (region_arg, ) if region_arg else '' reduce_arg = self._scales_to_reduce_arg(image_request) red = '-r %s' % (reduce_arg, ) if reduce_arg else '' opj_cmd = ' '.join((self.opj_decompress, i, reg, red, o)) logger.debug('Calling: %s' % (opj_cmd, )) # Start the shellout. Blocks until the pipe is empty with open(devnull, 'w') as fnull: opj_decompress_proc = subprocess.Popen(opj_cmd, shell=True, bufsize=-1, stderr=fnull, stdout=fnull, env=self.env) f = open(fifo_fp, 'rb') logger.debug('Opened %s' % fifo_fp) # read from the named pipe p = Parser() while True: s = f.read(1024) if not s: break p.feed(s) im = p.close() # a PIL.Image # finish opj opj_exit = opj_decompress_proc.wait() if opj_exit != 0: map(logger.error, opj_decompress_proc.stderr) unlink(fifo_fp) if self.map_profile_to_srgb and image_request.info.color_profile_bytes: # i.e. is not None emb_profile = cStringIO.StringIO( image_request.info.color_profile_bytes) im = profileToProfile(im, emb_profile, self.srgb_profile_fp) self._derive_with_pil(im, target_fp, image_request, crop=False)
def transform(self, src_fp, target_fp, image_request): # opj writes to this: fifo_fp = self._make_tmp_fp() # make the named pipe mkfifo_call = '%s %s' % (self.mkfifo, fifo_fp) logger.debug('Calling %s' % (mkfifo_call,)) resp = subprocess.check_call(mkfifo_call, shell=True) if resp != 0: logger.error('Problem with mkfifo') # how to handle CalledProcessError; would have to be a 500? # opj_decompress command i = '-i "%s"' % (src_fp,) o = '-o %s' % (fifo_fp,) region_arg = self._region_to_opj_arg(image_request.region_param) reg = '-d %s' % (region_arg,) if region_arg else '' reduce_arg = self._scales_to_reduce_arg(image_request) red = '-r %s' % (reduce_arg,) if reduce_arg else '' opj_cmd = ' '.join((self.opj_decompress,i,reg,red,o)) logger.debug(fifo_fp) logger.debug('Calling: %s' % (opj_cmd,)) logger.debug(fifo_fp) # Start the shellout. Blocks until the pipe is empty with open(devnull, 'w') as fnull: logger.debug('opening devnull') opj_decompress_proc = subprocess.Popen(opj_cmd, shell=True, bufsize=-1, stderr=fnull, stdout=fnull, env=self.env) logger.debug('opening fifo') f = open(fifo_fp, 'rb') logger.debug('Opened %s' % fifo_fp) # read from the named pipe p = Parser() while True: s = f.read(1024) if not s: break p.feed(s) im = p.close() # a PIL.Image # finish opj opj_exit = opj_decompress_proc.wait() if opj_exit != 0: map(logger.error, opj_decompress_proc.stderr) unlink(fifo_fp) if self.map_profile_to_srgb and image_request.info.color_profile_bytes: # i.e. is not None emb_profile = cStringIO.StringIO(image_request.info.color_profile_bytes) im = profileToProfile(im, emb_profile, self.srgb_profile_fp) self._derive_with_pil(im, target_fp, image_request, crop=False)
def convert_to_rgb(img): """ Convert an image to RGB if it isn't already RGB or grayscale """ if img.mode == 'CMYK' and HAS_PROFILE_TO_PROFILE: profile_dir = os.path.join(os.path.dirname(__file__), 'profiles') input_profile = os.path.join(profile_dir, "USWebUncoated.icc") output_profile = os.path.join(profile_dir, "sRGB_v4_ICC_preference.icc") return profileToProfile(img, input_profile, output_profile, outputMode='RGB') return img
def get_tiff_from_pillow(filepath): print 'making tiff using pillow from', filepath new_file_path = get_output_file_path(filepath, 'tiff') im = Image.open(filepath) if 'icc_profile' in im.info: print "converting profile" src_profile = cStringIO.StringIO(im.info['icc_profile']) im = profileToProfile(im, src_profile, srgb_profile_fp) im.save(new_file_path) # , compression=None) image_mode = im.mode return new_file_path, image_mode
def __generate_master__(self): """ create a master file from the original already in the package and set all metadata """ # open original # capture existing ICC profile (if there is one) # if no ICC profile, assign sRGB # if ICC profile and != sRGB, convert to sRGB # save as uncompressed TIFF logger = logging.getLogger(sys._getframe().f_code.co_name) profile_srgb2 = os.path.join( os.path.dirname(os.path.abspath(__file__)), 'icc', 'sRGB_IEC61966-2-1_black_scaled.icc') profile_srgb4 = os.path.join( os.path.dirname(os.path.abspath(__file__)), 'icc', 'sRGB_v4_ICC_preference.icc') original_path = os.path.join(self.path, self.original) original_image = Image.open(original_path) try: raw_profile = original_image.info['icc_profile'] except KeyError: raw_profile = getOpenProfile(profile_srgb2).tobytes() logger.warning( '{original} does not have an internal ICC color profile'. format(original=self.original)) else: logger.debug( 'detected internal ICC color profile in {original}'.format( original=self.original)) original_profile = getOpenProfile(BytesIO(raw_profile)) original_profile_name = getProfileName(original_profile).strip() target_profile = getOpenProfile(profile_srgb4) target_profile_name = getProfileName(target_profile).strip() logger.debug( 'attempting to convert from "{original}" to "{target}"'.format( original=original_profile_name, target=target_profile_name)) converted_image = profileToProfile(original_image, original_profile, target_profile) master_path = os.path.join(self.path, 'master.tif') tiffinfo = TiffImagePlugin.ImageFileDirectory() tiffinfo[TiffImagePlugin.ICCPROFILE] = target_profile.tobytes() tiffinfo.tagtype[ TiffImagePlugin.ICCPROFILE] = 1 # byte according to TiffTags.TYPES converted_image.DEBUG = True converted_image.save(master_path, tiffinfo=tiffinfo) hash_master = hash_of_file(master_path) logger.debug('saved converted master image to {master}'.format( master=master_path)) self.__append_event__( 'created master.tif file at {master}'.format(master=master_path)) self.manifest.set('master.tif', hash_master)
def get_tiff_from_pillow(filepath): print 'making tiff using pillow from', filepath new_file_path = get_output_file_path(filepath, 'tiff') im = Image.open(filepath) orientation = get_orientation(im) if orientation is not None and orientation > 1: im = rotate_as_required(im, orientation) if 'icc_profile' in im.info: print "converting profile" src_profile = cStringIO.StringIO(im.info['icc_profile']) im = profileToProfile(im, src_profile, srgb_profile_fp, outputMode='RGB') im.save(new_file_path) # , compression=None) image_mode = im.mode return new_file_path, image_mode
def __generate_master__(self): """ create a master file from the original already in the package and set all metadata """ # open original # capture existing ICC profile (if there is one) # if no ICC profile, assign sRGB # if ICC profile and != sRGB, convert to sRGB # save as uncompressed TIFF logger = logging.getLogger(sys._getframe().f_code.co_name) profile_srgb2 = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'icc', 'sRGB_IEC61966-2-1_black_scaled.icc') profile_srgb4 = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'icc', 'sRGB_v4_ICC_preference.icc') original_path = os.path.join(self.path, self.original) original_image = Image.open(original_path) try: raw_profile = original_image.info['icc_profile'] except KeyError: raw_profile = getOpenProfile(profile_srgb2).tobytes() logger.warning('{original} does not have an internal ICC color profile'.format(original=self.original)) else: logger.debug('detected internal ICC color profile in {original}'.format(original=self.original)) original_profile = getOpenProfile(BytesIO(raw_profile)) original_profile_name = getProfileName(original_profile).strip() target_profile = getOpenProfile(profile_srgb4) target_profile_name = getProfileName(target_profile).strip() logger.debug('attempting to convert from "{original}" to "{target}"'.format(original=original_profile_name, target=target_profile_name)) converted_image = profileToProfile(original_image, original_profile, target_profile) master_path = os.path.join(self.path, 'master.tif') tiffinfo = TiffImagePlugin.ImageFileDirectory() tiffinfo[TiffImagePlugin.ICCPROFILE] = target_profile.tobytes() tiffinfo.tagtype[TiffImagePlugin.ICCPROFILE] = 1 # byte according to TiffTags.TYPES converted_image.DEBUG=True converted_image.save(master_path, tiffinfo=tiffinfo) hash_master = hash_of_file(master_path) logger.debug('saved converted master image to {master}'.format(master=master_path)) self.__append_event__('created master.tif file at {master}'.format(master=master_path)) self.manifest.set('master.tif', hash_master)
def _map_im_profile_to_srgb(self, im, input_profile): return profileToProfile(im, input_profile, self.srgb_profile_fp)
def transform(self, src_fp, target_fp, image_request): # kdu writes to this: fifo_fp = self._make_tmp_fp() # kdu command q = '-quiet' t = '-num_threads %s' % (self.num_threads, ) i = '-i "%s"' % (src_fp, ) o = '-o %s' % (fifo_fp, ) reduce_arg = self._scales_to_reduce_arg(image_request) red = '-reduce %s' % (reduce_arg, ) if reduce_arg else '' region_arg = self._region_to_kdu_arg(image_request.region_param) reg = '-region %s' % (region_arg, ) if region_arg else '' kdu_cmd = ' '.join((self.kdu_expand, q, i, t, reg, red, o)) # make the named pipe mkfifo_call = '%s %s' % (self.mkfifo, fifo_fp) logger.debug('Calling %s' % (mkfifo_call, )) resp = subprocess.check_call(mkfifo_call, shell=True) try: # Start the kdu shellout. Blocks until the pipe is empty logger.debug('Calling: %s' % (kdu_cmd, )) kdu_expand_proc = subprocess.Popen(kdu_cmd, shell=True, bufsize=-1, stderr=subprocess.PIPE, env=self.env) f = open(fifo_fp, 'rb') logger.debug('Opened %s' % fifo_fp) # read from the named pipe p = Parser() while True: s = f.read(1024) if not s: break p.feed(s) im = p.close() # a PIL.Image # finish kdu kdu_exit = kdu_expand_proc.wait() if kdu_exit != 0: map(logger.error, kdu_expand_proc.stderr) if self.map_profile_to_srgb and image_request.info.color_profile_bytes: # i.e. is not None emb_profile = cStringIO.StringIO( image_request.info.color_profile_bytes) im = profileToProfile(im, emb_profile, self.srgb_profile_fp) self._derive_with_pil(im, target_fp, image_request, crop=False) except: raise finally: kdu_exit = kdu_expand_proc.wait() if kdu_exit != 0: map(logger.error, map(string.strip, kdu_expand_proc.stderr)) unlink(fifo_fp)
import sys import os import time from PIL import Image from PIL.ImageCms import profileToProfile files = sys.argv[1]#drag and drop if os.path.exists(files): filename = os.path.basename(files) DisplayP3_PROFILE = "icc/DisplayP3-v4.icc" Acer_X27_PROFILE = "icc/Acer_X27.icm" SRGB_PROFILE = "icc/sRGB.icm" oldImg = Image.open(sys.argv[1]) newImg = profileToProfile(oldImg, Acer_X27_PROFILE, DisplayP3_PROFILE)# path before after newImg_path = "DisplayP3_"+filename newImg.save(newImg_path) print(filename+" change successfully!") time.sleep( 2 )
def lambda_handler(event, context, size=(256, 256)): """ This lambda function triggered by AWS S3 when any file uploaded to media bucket, and tries to create thumbnails to target bucket with desired sizes. """ s3_client = boto3.client('s3') for record in event['Records']: bucket_name = record['s3']['bucket']['name'] object_key = record['s3']['object']['key'] local_key = '/tmp/{}'.format(object_key) s3_client.download_file(bucket_name, object_key, local_key) try: with Image.open(open(local_key, 'rb')) as image: image.thumbnail(size) # Check and convert icc profile if required and set alpha layer if image.mode in ('RGBA', 'LA') or (image.mode == 'P' and 'transparency' in image.info): output_mode = 'RGBA' else: output_mode = 'RGB' if image.info.get('icc_profile', None): try: temp_icc_path = tempfile.mkstemp(suffix='.icc')[1] with open(temp_icc_path, 'w+b') as image_orginal_icc: image_orginal_icc.write( image.info.get('icc_profile')) if not getProfileName(temp_icc_path) == getProfileName( desired_icc): image = profileToProfile(image, temp_icc_path, desired_icc, outputMode=output_mode, renderingIntent=0) if output_mode == 'RGBA' and image.split()[-1]: image.putalpha(image.split()[-1]) except Exception: pass # icc related failure is not important! else: image = image.convert(output_mode) # Rotate image if required (for mostly smart phone pictures) for tag in ExifTags.TAGS.keys(): if ExifTags.TAGS[tag] == 'Orientation': break exif = dict(image._getexif().items()) if exif[tag] == 3: image = image.rotate(180, expand=True) elif exif[tag] == 6: image = image.rotate(270, expand=True) elif exif[tag] == 8: image = image.rotate(90, expand=True) thumbnail_key = '{}_resized.png'.format(local_key) image.save(thumbnail_key, "PNG", optimize=True, dpi=[72, 72], compress_level=5, icc_profile=image.info.get('icc_profile')) s3_client.upload_file(thumbnail_key, target_bucket_name, '{}_resized.png'.format(object_key)) except IOError: pass # PIL could not open file as image.
def transform(self, src_fp, target_fp, image_request): # kdu writes to this: fifo_fp = JP2_Transformer._make_tmp_fp(self.tmp_dp, 'bmp') # make the named pipe mkfifo_call = '%s %s' % (self.mkfifo, fifo_fp) logger.debug('Calling %s' % (mkfifo_call,)) resp = subprocess.check_call(mkfifo_call, shell=True) if resp == 0: logger.debug('OK') # how to handle CalledProcessError; would have to be a 500? # kdu command q = '-quiet' t = '-num_threads 8' i = '-i %s' % (src_fp,) o = '-o %s' % (fifo_fp,) region_arg = JP2_Transformer._region_to_kdu(image_request.region_param) reduce_arg = JP2_Transformer._scales_to_kdu_reduce(image_request) # kdu can do the rotation if it's a multiple of 90: if int(image_request.rotation_param.uri_value) % 90 == 0: rotate_downstream = False kdu_rotation_arg = JP2_Transformer._rotation_to_kdu(image_request.rotation_param) kdu_cmd = ' '.join((self.kdu_expand,q,i,t,region_arg,reduce_arg,kdu_rotation_arg,o)) else: rotate_downstream = True kdu_cmd = ' '.join((self.kdu_expand,q,i,t,region_arg,reduce_arg,o)) logger.debug('Calling: %s' % (kdu_cmd,)) # Start the kdu shellout. Blocks until the pipe is empty kdu_expand_proc = subprocess.Popen(kdu_cmd, shell=True, bufsize=-1, stderr=subprocess.PIPE, env=self.env) f = open(fifo_fp, 'rb') logger.debug('Opened %s' % fifo_fp) # read from the named pipe p = Parser() while True: s = f.read(1024) if not s: break p.feed(s) im = p.close() # a PIL.Image # finish kdu kdu_exit = kdu_expand_proc.wait() if kdu_exit != 0: map(logger.error, kdu_expand_proc.stderr) unlink(fifo_fp) if self.map_profile_to_srgb and image_request.info.color_profile_bytes: # i.e. is not None emb_profile = cStringIO.StringIO(image_request.info.color_profile_bytes) im = profileToProfile(im, emb_profile, self.srgb_profile_fp) JP2_Transformer._derive_with_pil(im, target_fp, image_request, rotate=rotate_downstream, crop=False)