def URL_to_ASCII(url, width=80, height=24): # good bits from http://stevendkay.wordpress.com/2009/09/08/generating-ascii-art-from-photographs-in-python/ # and http://blog.hardlycode.com/pil-image-from-url-2011-01/ # TODO: MouseText greyscale = [ " ", " ", ".,-", "_ivc=!/|\\~", "gjez2]/(YL)t[+T7Vf", "mdK4ZGbNDXY5P*Q", "W8KMA", "#%$" ] greyscale.reverse() # white on black zonebounds = [36, 72, 108, 144, 180, 216, 252] img_file = urllib.urlopen(url) im = StringIO(img_file.read()) im = Image.open(im) (w, h) = im.size # change width but not height new_width = int(width) new_height = int((float(width) / float(w)) * float(h)) im = im.resize((new_width, new_height), Image.BILINEAR) im = im.convert("L") pic = "" for y in range(0, im.size[1]): for x in range(0, im.size[0]): lum = 255 - im.getpixel((x, y)) row = bisect(zonebounds, lum) possibles = greyscale[row] pic = pic + possibles[random.randint(0, len(possibles) - 1)] pic = pic + "\n" return pic
def URL_to_ASCII(url, width=80, height=24): # good bits from http://stevendkay.wordpress.com/2009/09/08/generating-ascii-art-from-photographs-in-python/ # and http://blog.hardlycode.com/pil-image-from-url-2011-01/ # TODO: MouseText greyscale = [" ", " ", ".,-", "_ivc=!/|\\~", "gjez2]/(YL)t[+T7Vf", "mdK4ZGbNDXY5P*Q", "W8KMA", "#%$"] greyscale.reverse() # white on black zonebounds = [36, 72, 108, 144, 180, 216, 252] img_file = urllib.urlopen(url) im = StringIO(img_file.read()) im = Image.open(im) (w, h) = im.size # change width but not height new_width = int(width) new_height = int((float(width) / float(w)) * float(h)) im = im.resize((new_width, new_height), Image.BILINEAR) im = im.convert("L") pic = "" for y in range(0, im.size[1]): for x in range(0, im.size[0]): lum = 255 - im.getpixel((x, y)) row = bisect(zonebounds, lum) possibles = greyscale[row] pic = pic + possibles[random.randint(0, len(possibles) - 1)] pic = pic + "\n" return pic
def scaleImage(image, width=None, height=None, direction='down', quality=88, result=None): """Scale the given image data to another size and return the result as a string or optionally write in to the file-like `result` object. The `image` parameter can either be the raw image data (ie a `str` instance) or an open file. The `quality` parameter can be used to set the quality of the resulting image scales. The return value is a tuple with the new image, the image format and a size-tuple. Optionally a file-like object can be given as the `result` parameter, in which the generated image scale will be stored. The `width`, `height`, `direction` parameters will be passed to :meth:`scalePILImage`, which performs the actual scaling. The generated image is a JPEG image, unless the original is a PNG or GIF image. This is needed to make sure alpha channel information is not lost, which JPEG does not support. """ if isinstance(image, (bytes, str)): image = StringIO(image) image = PIL.Image.open(image) # When we create a new image during scaling we loose the format # information, so remember it here. format_ = image.format if format_ not in ('PNG', 'GIF'): # Always generate JPEG, except if format is PNG or GIF. format_ = 'JPEG' elif format_ == 'GIF': # GIF scaled looks better if we have 8-bit alpha and no palette format_ = 'PNG' icc_profile = image.info.get('icc_profile') image = scalePILImage(image, width, height, direction) # convert to simpler mode if possible colors = image.getcolors(maxcolors=256) if image.mode not in ('P', 'L') and colors: if format_ == 'JPEG': # check if it's all grey if all(rgb[0] == rgb[1] == rgb[2] for c, rgb in colors): image = image.convert('L') elif format_ == 'PNG': image = image.convert('P') if image.mode == 'RGBA' and format_ == 'JPEG': extrema = dict(zip(image.getbands(), image.getextrema())) if extrema.get('A') == (255, 255): # no alpha used, just change the mode, which causes the alpha band # to be dropped on save image.mode = "RGB" else: # switch to PNG, which supports alpha format_ = 'PNG' new_result = False if result is None: result = StringIO() new_result = True image.save(result, format_, quality=quality, optimize=True, progressive=True, icc_profile=icc_profile) if new_result: result = result.getvalue() else: result.seek(0) return result, format_, image.size
def scaleImage(image, width=None, height=None, direction="down", quality=88, result=None): """Scale an image to another size. The generated image is a JPEG image, unless the original is a PNG image. This is needed to make sure alpha channel information is not lost, which JPEG does not support. Three different scaling options are supported: * `up` scaling scales the smallest dimension up to the required size and scrops the other dimension if needed. * `down` scaling starts by scaling the largest dimension to the required size and scrops the other dimension if needed. * `thumbnail` scales to the requested dimensions without cropping. The resulting image may have a different size than requested. This option requires both width and height to be specified. `keep` is accepted as an alternative spelling for this option, but its use is deprecated. The `image` parameter can either be the raw image data (ie a `str` instance) or an open file. The `quality` parameter can be used to set the quality of the resulting image scales. The return value is a tuple with the new image, the image format and a size-tuple. Optionally a file-like object can be given as the `result` parameter, in which the generated image scale will be stored. """ if direction=="keep": direction="thumbnail" if direction=="thumbnail" and not (width and height): raise ValueError("Thumbnailing requires both width and height to be specified") elif width is None and height is None: raise ValueError("Either width or height need to be given") if isinstance(image, str): image=StringIO(image) image=PIL.Image.open(image) if image.mode=="1": # Convert black&white to grayscale image=image.convert("L") elif image.mode=="P": # Convert palette based images to 3x8bit+alpha image=image.convert("RGBA") elif image.mode=="CMYK": # Convert CMYK to RGB, allowing for web previews of print images image=image.convert("RGB") # When we create a new image during scaling we loose the format # information, so remember it here. image_format=image.format current_size=image.size # Determine scale factor needed to get the right height if height is None: scale_height=None else: scale_height=(float(height)/float(current_size[1])) if width is None: scale_width=None else: scale_width=(float(width)/float(current_size[0])) if scale_height==scale_width or direction=="thumbnail": # The original already has the right aspect ratio, so we only need # to scale. image.thumbnail((width, height), PIL.Image.ANTIALIAS) else: if direction=="down": if scale_height is None or (scale_width is not None and scale_width>scale_height): # Width is the smallest dimension (relatively), so scale up # to the desired width new_width=width new_height=int(round(current_size[1]*scale_width)) else: new_height=height new_width=int(round(current_size[0]*scale_height)) else: if scale_height is None or (scale_width is not None and scale_width<scale_height): # Width is the largest dimension (relatively), so scale up # to the desired width new_width=width new_height=int(round(current_size[1]*scale_width)) else: new_height=height new_width=int(round(current_size[0]*scale_height)) image.draft(image.mode, (new_width, new_height)) image=image.resize((new_width, new_height), PIL.Image.ANTIALIAS) if (width is not None and new_width>width) or (height is not None and new_height>height): if width is None: left=0 right=new_width else: left=int((new_width-width)/2.0) right=left+width if height is None: height=new_height image=image.crop((left, 0, right, height)) if image_format=="PNG": format="PNG" else: format="JPEG" if result is None: result=StringIO() image.save(result, format, quality=quality, optimize=True) result=result.getvalue() else: image.save(result, format, quality=quality, optimize=True) result.seek(0) return (result, format, image.size)
def scaleImage(image, width=None, height=None, direction='down', quality=88, result=None): """Scale the given image data to another size and return the result as a string or optionally write in to the file-like `result` object. The `image` parameter can either be the raw image data (ie a `str` instance) or an open file. The `quality` parameter can be used to set the quality of the resulting image scales. The return value is a tuple with the new image, the image format and a size-tuple. Optionally a file-like object can be given as the `result` parameter, in which the generated image scale will be stored. The `width`, `height`, `direction` parameters will be passed to :meth:`scalePILImage`, which performs the actual scaling. The generated image is a JPEG image, unless the original is a PNG or GIF image. This is needed to make sure alpha channel information is not lost, which JPEG does not support. """ if isinstance(image, (bytes, str)): image = StringIO(image) image = PIL.Image.open(image) # When we create a new image during scaling we loose the format # information, so remember it here. format_ = image.format if format_ not in ('PNG', 'GIF'): # Always generate JPEG, except if format is PNG or GIF. format_ = 'JPEG' elif format_ == 'GIF': # GIF scaled looks better if we have 8-bit alpha and no palette format_ = 'PNG' icc_profile = image.info.get('icc_profile') image = scalePILImage(image, width, height, direction) # convert to simpler mode if possible colors = image.getcolors(maxcolors=256) if image.mode not in ('P', 'L') and colors: if format_ == 'JPEG': # check if it's all grey if all(rgb[0] == rgb[1] == rgb[2] for c, rgb in colors): image = image.convert('L') elif format_ == 'PNG': image = image.convert('P') if image.mode == 'RGBA' and format_ == 'JPEG': extrema = dict(zip(image.getbands(), image.getextrema())) if extrema.get('A') == (255, 255): # no alpha used, just change the mode, which causes the alpha band # to be dropped on save image.mode = "RGB" else: # switch to PNG, which supports alpha format_ = 'PNG' new_result = False if result is None: result = StringIO() new_result = True image.save( result, format_, quality=quality, optimize=True, progressive=True, icc_profile=icc_profile ) if new_result: result = result.getvalue() else: result.seek(0) return result, format_, image.size
def scaleImage(image, width=None, height=None, direction='down', quality=88, result=None): """Scale the given image data to another size and return the result as a string or optionally write in to the file-like `result` object. The `image` parameter can either be the raw image data (ie a `str` instance) or an open file. The `quality` parameter can be used to set the quality of the resulting image scales. The return value is a tuple with the new image, the image format and a size-tuple. Optionally a file-like object can be given as the `result` parameter, in which the generated image scale will be stored. The `width`, `height`, `direction` parameters will be passed to :meth:`scalePILImage`, which performs the actual scaling. The generated image is a JPEG image, unless the original is a PNG or GIF image. This is needed to make sure alpha channel information is not lost, which JPEG does not support. """ if isinstance(image, str): image = StringIO(image) image = PIL.Image.open(image) # When we create a new image during scaling we loose the format # information, so remember it here. format_ = image.format if format_ not in ('PNG', 'GIF'): # Always generate JPEG, except if format is PNG or GIF. format_ = 'JPEG' elif format_ == 'GIF': # GIF scaled looks better if we have 8-bit alpha and no palette format_ = 'PNG' image = scalePILImage(image, width, height, direction) # convert to simpler mode if possible if image.mode not in ('P', 'L') and image.getcolors(maxcolors=256): if format_ == 'JPEG': image = image.convert('L') elif format_ == 'PNG': image = image.convert('P') new_result = False if result is None: result = StringIO() new_result = True image.save(result, format_, quality=quality, optimize=True, progressive=True) if new_result: result = result.getvalue() else: result.seek(0) return result, format_, image.size
def scaleImage(image, width=None, height=None, direction='down', quality=88, result=None): """Scale the given image data to another size and return the result as a string or optionally write in to the file-like `result` object. The `image` parameter can either be the raw image data (ie a `str` instance) or an open file. The `quality` parameter can be used to set the quality of the resulting image scales. The return value is a tuple with the new image, the image format and a size-tuple. Optionally a file-like object can be given as the `result` parameter, in which the generated image scale will be stored. The `width`, `height`, `direction` parameters will be passed to :meth:`scalePILImage`, which performs the actual scaling. The generated image is a JPEG image, unless the original is a PNG or GIF image. This is needed to make sure alpha channel information is not lost, which JPEG does not support. """ if isinstance(image, str): image = StringIO(image) image = PIL.Image.open(image) # When we create a new image during scaling we loose the format # information, so remember it here. format_ = image.format if format_ not in ('PNG', 'GIF'): # Always generate JPEG, except if format is PNG or GIF. format_ = 'JPEG' elif format_ == 'GIF': # GIF scaled looks better if we have 8-bit alpha and no palette format_ = 'PNG' image = scalePILImage(image, width, height, direction) # convert to simpler mode if possible if image.mode not in ('P', 'L') and image.getcolors(maxcolors=256): if format_ == 'JPEG': image = image.convert('L') elif format_ == 'PNG': image = image.convert('P') new_result = False if result is None: result = StringIO() new_result = True image.save( result, format_, quality=quality, optimize=True, progressive=True ) if new_result: result = result.getvalue() else: result.seek(0) return result, format_, image.size