def rescale_image(data, scale_news_images, compress_news_images_max_size, compress_news_images_auto_size): orig_data = data # save it in case compression fails img = image_from_data(data) orig_w, orig_h = img.width(), img.height() if scale_news_images is not None: wmax, hmax = scale_news_images if wmax < orig_w or hmax < orig_h: orig_w, orig_h, data = scale_image(img, wmax, hmax, compression_quality=95) if compress_news_images_max_size is None: if compress_news_images_auto_size is None: # not compressing return data maxsizeb = (orig_w * orig_h)/compress_news_images_auto_size else: maxsizeb = compress_news_images_max_size * 1024 if len(data) <= maxsizeb: # no compression required return data scaled_data = data # save it in case compression fails quality = 90 while len(data) >= maxsizeb and quality >= 5: data = image_to_data(image_from_data(scaled_data), compression_quality=quality) quality -= 5 if len(data) >= len(scaled_data): # compression failed return orig_data if len(orig_data) <= len(scaled_data) else scaled_data if len(data) >= len(orig_data): # no improvement return orig_data return data
def get_cover(self, id, thumbnail=False, thumb_width=60, thumb_height=80): try: cherrypy.response.headers['Content-Type'] = 'image/jpeg' cherrypy.response.timeout = 3600 cover = self.db.cover(id, index_is_id=True) if cover is None: cover = self.default_cover updated = self.build_time else: updated = self.db.cover_last_modified(id, index_is_id=True) cherrypy.response.headers['Last-Modified'] = self.last_modified(updated) if thumbnail: quality = tweaks['content_server_thumbnail_compression_quality'] if quality < 50: quality = 50 elif quality > 99: quality = 99 return scale_image(cover, thumb_width, thumb_height, compression_quality=quality)[-1] return save_cover_data_to(cover, None, minify_to=(self.max_cover_width, self.max_cover_height)) except Exception as err: import traceback cherrypy.log.error('Failed to generate cover:') cherrypy.log.error(traceback.print_exc()) raise cherrypy.HTTPError(404, 'Failed to generate cover: %r'%err)
def browse_icon(self, name='blank.png'): cherrypy.response.headers['Content-Type'] = 'image/png' cherrypy.response.headers['Last-Modified'] = self.last_modified( self.build_time) if not hasattr(self, '__browse_icon_cache__'): self.__browse_icon_cache__ = {} if name not in self.__browse_icon_cache__: if name.startswith('_'): name = sanitize_file_name2(name[1:]) try: with open(os.path.join(config_dir, 'tb_icons', name), 'rb') as f: data = f.read() except: raise cherrypy.HTTPError(404, 'no icon named: %r' % name) else: try: data = I(name, data=True) except: raise cherrypy.HTTPError(404, 'no icon named: %r' % name) self.__browse_icon_cache__[name] = scale_image(data, 48, 48, as_png=True)[-1] return self.__browse_icon_cache__[name]
def icon(ctx, rd, which): sz = rd.query.get('sz') if sz != 'full': try: sz = int(rd.query.get('sz', 48)) except Exception: sz = 48 if which in {'', '_'}: raise HTTPNotFound() if which.startswith('_'): base = os.path.join(config_dir, 'tb_icons') path = os.path.abspath(os.path.join(base, *which[1:].split('/'))) if not path.startswith(base) or ':' in which: raise HTTPNotFound('Naughty, naughty!') else: base = P('images', allow_user_override=False) path = os.path.abspath(os.path.join(base, *which.split('/'))) if not path.startswith(base) or ':' in which: raise HTTPNotFound('Naughty, naughty!') path = os.path.relpath(path, base).replace(os.sep, '/') path = P('images/' + path) if sz == 'full': try: return share_open(path, 'rb') except EnvironmentError: raise HTTPNotFound() with lock: tdir = os.path.join(rd.tdir, 'icons') cached = os.path.join(tdir, '%d-%s.png' % (sz, which)) try: return share_open(cached, 'rb') except EnvironmentError: pass try: src = share_open(path, 'rb') except EnvironmentError: raise HTTPNotFound() with src: idata = src.read() img = image_from_data(idata) scaled, width, height = fit_image(img.width(), img.height(), sz, sz) if scaled: idata = scale_image(img, width, height, as_png=True)[-1] try: ans = share_open(cached, 'w+b') except EnvironmentError: try: os.mkdir(tdir) except EnvironmentError: pass ans = share_open(cached, 'w+b') ans.write(idata) ans.seek(0) return ans
def run(self): while self._run and not self.tasks.empty(): try: result, callback, timeout = self.tasks.get() if result and result.cover_url: with closing(self.br.open(result.cover_url, timeout=timeout)) as f: result.cover_data = f.read() result.cover_data = scale_image(result.cover_data, 64, 64)[2] callback() self.tasks.task_done() except: if DEBUG: traceback.print_exc()
def run(self): while self._run and not self.tasks.empty(): try: result, callback, timeout = self.tasks.get() if result and result.cover_url: if result.cover_url.startswith('data:'): result.cover_data = decode_data_url(result.cover_url) else: with closing(self.br.open(result.cover_url, timeout=timeout)) as f: result.cover_data = f.read() result.cover_data = scale_image(result.cover_data, 256, 256)[2] callback() self.tasks.task_done() except: if DEBUG: traceback.print_exc()
def render(self): from calibre.utils.img import image_from_data, scale_image, crop_image with lopen(self.path_to_page, 'rb') as f: img = image_from_data(f.read()) width, height = img.width(), img.height() if self.num == 0: # First image so create a thumbnail from it with lopen(os.path.join(self.dest, 'thumbnail.png'), 'wb') as f: f.write(scale_image(img, as_png=True)[-1]) self.pages = [img] if width > height: if self.opts.landscape: self.rotate = True else: half = int(width/2) split1 = crop_image(img, 0, 0, half, height) split2 = crop_image(img, half, 0, width - half, height) self.pages = [split2, split1] if self.opts.right2left else [split1, split2] self.process_pages()
def upload_cover(self, path, filename, metadata, filepath): from calibre.ebooks.covers import calibre_cover2 from calibre.utils.img import scale_image coverdata = getattr(metadata, 'thumbnail', None) if coverdata and coverdata[2]: cover = coverdata[2] else: cover = calibre_cover2(metadata.get('title', _('Unknown')), metadata.get('authors', _('Unknown'))) cover = scale_image(cover, width=self.THUMBNAIL_HEIGHT, height=self.THUMBNAIL_HEIGHT, as_png=True)[-1] cpath = self.alex_cpath(os.path.join(path, filename)) cdir = os.path.dirname(cpath) if not os.path.exists(cdir): os.makedirs(cdir) with lopen(cpath, 'wb') as coverfile: coverfile.write(cover) fsync(coverfile)
def browse_icon(self, name='blank.png'): cherrypy.response.headers['Content-Type'] = 'image/png' cherrypy.response.headers['Last-Modified'] = self.last_modified(self.build_time) if not hasattr(self, '__browse_icon_cache__'): self.__browse_icon_cache__ = {} if name not in self.__browse_icon_cache__: if name.startswith('_'): name = sanitize_file_name2(name[1:]) try: with open(os.path.join(config_dir, 'tb_icons', name), 'rb') as f: data = f.read() except: raise cherrypy.HTTPError(404, 'no icon named: %r'%name) else: try: data = I(name, data=True) except: raise cherrypy.HTTPError(404, 'no icon named: %r'%name) self.__browse_icon_cache__[name] = scale_image(data, 48, 48, as_png=True)[-1] return self.__browse_icon_cache__[name]
def rescale_image(data, maxsizeb=IMAGE_MAX_SIZE, dimen=None): ''' Convert image setting all transparent pixels to white and changing format to JPEG. Ensure the resultant image has a byte size less than maxsizeb. If dimen is not None, generate a thumbnail of width=dimen, height=dimen or width, height = dimen (depending on the type of dimen) Returns the image as a bytestring ''' if dimen is not None: if hasattr(dimen, '__len__'): width, height = dimen else: width = height = dimen data = scale_image(data, width=width, height=height, compression_quality=90)[-1] else: # Replace transparent pixels with white pixels and convert to JPEG data = save_cover_data_to(data) if len(data) <= maxsizeb: return data orig_data = data # save it in case compression fails quality = 90 while len(data) > maxsizeb and quality >= 5: data = image_to_data(image_from_data(orig_data), compression_quality=quality) quality -= 5 if len(data) <= maxsizeb: return data orig_data = data scale = 0.9 while len(data) > maxsizeb and scale >= 0.05: img = image_from_data(data) w, h = img.width(), img.height() img = resize_image(img, int(scale*w), int(scale*h)) data = image_to_data(img, compression_quality=quality) scale -= 0.05 return data
def copy_func(dest): buf = BytesIO() db.copy_cover_to(book_id, buf) quality = min(99, max(50, tweaks['content_server_thumbnail_compression_quality'])) data = scale_image(buf.getvalue(), width=width, height=height, compression_quality=quality)[-1] dest.write(data)