mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Comic Input: When grayscaling comic images use 16bit gray for better fidelity. When using the PNG format for images this results in larger files but with better grayscaling fidelity.
Fixes #1898 (Optimized edge case for comic conversion)
This commit is contained in:
parent
1eb3d9aee5
commit
306f813566
@ -6,14 +6,16 @@ __docformat__ = 'restructuredtext en'
|
|||||||
Based on ideas from comiclrf created by FangornUK.
|
Based on ideas from comiclrf created by FangornUK.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import os, traceback, time
|
import os
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
|
||||||
from calibre import extract, prints, walk
|
from calibre import extract, prints, walk
|
||||||
from calibre.constants import filesystem_encoding
|
from calibre.constants import filesystem_encoding
|
||||||
from calibre.ptempfile import PersistentTemporaryDirectory
|
from calibre.ptempfile import PersistentTemporaryDirectory
|
||||||
from calibre.utils.icu import numeric_sort_key
|
from calibre.utils.icu import numeric_sort_key
|
||||||
from calibre.utils.ipc.server import Server
|
|
||||||
from calibre.utils.ipc.job import ParallelJob
|
from calibre.utils.ipc.job import ParallelJob
|
||||||
|
from calibre.utils.ipc.server import Server
|
||||||
from polyglot.queue import Empty
|
from polyglot.queue import Empty
|
||||||
|
|
||||||
# If the specified screen has either dimension larger than this value, no image
|
# If the specified screen has either dimension larger than this value, no image
|
||||||
@ -41,6 +43,7 @@ def extract_comic(path_to_comic_file):
|
|||||||
|
|
||||||
def generate_entries_from_dir(path):
|
def generate_entries_from_dir(path):
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from calibre import walk
|
from calibre import walk
|
||||||
ans = {}
|
ans = {}
|
||||||
for x in walk(path):
|
for x in walk(path):
|
||||||
@ -105,18 +108,21 @@ class PageProcessor(list): # {{{
|
|||||||
self.dest = dest
|
self.dest = dest
|
||||||
self.rotate = False
|
self.rotate = False
|
||||||
self.src_img_was_grayscaled = False
|
self.src_img_was_grayscaled = False
|
||||||
|
self.src_img_format = None
|
||||||
self.render()
|
self.render()
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
from qt.core import QImage
|
from qt.core import QImage
|
||||||
from calibre.utils.img import image_from_data, scale_image, crop_image
|
|
||||||
|
from calibre.utils.img import crop_image, image_from_data, scale_image
|
||||||
with open(self.path_to_page, 'rb') as f:
|
with open(self.path_to_page, 'rb') as f:
|
||||||
img = image_from_data(f.read())
|
img = image_from_data(f.read())
|
||||||
width, height = img.width(), img.height()
|
width, height = img.width(), img.height()
|
||||||
if self.num == 0: # First image so create a thumbnail from it
|
if self.num == 0: # First image so create a thumbnail from it
|
||||||
with open(os.path.join(self.dest, 'thumbnail.png'), 'wb') as f:
|
with open(os.path.join(self.dest, 'thumbnail.png'), 'wb') as f:
|
||||||
f.write(scale_image(img, as_png=True)[-1])
|
f.write(scale_image(img, as_png=True)[-1])
|
||||||
self.src_img_was_grayscaled = img.format() in (QImage.Format.Format_Grayscale8, QImage.Format.Format_Grayscale16) or (
|
self.src_img_format = img.format()
|
||||||
|
self.src_img_was_grayscaled = self.src_img_format in (QImage.Format.Format_Grayscale8, QImage.Format.Format_Grayscale16) or (
|
||||||
img.format() == QImage.Format.Format_Indexed8 and img.allGray())
|
img.format() == QImage.Format.Format_Indexed8 and img.allGray())
|
||||||
self.pages = [img]
|
self.pages = [img]
|
||||||
if width > height:
|
if width > height:
|
||||||
@ -131,10 +137,11 @@ class PageProcessor(list): # {{{
|
|||||||
|
|
||||||
def process_pages(self):
|
def process_pages(self):
|
||||||
from qt.core import QImage
|
from qt.core import QImage
|
||||||
|
|
||||||
from calibre.utils.img import (
|
from calibre.utils.img import (
|
||||||
image_to_data, rotate_image, remove_borders_from_image, normalize_image,
|
add_borders_to_image, despeckle_image, gaussian_sharpen_image,
|
||||||
add_borders_to_image, resize_image, gaussian_sharpen_image, grayscale_image,
|
image_to_data, normalize_image, quantize_image, remove_borders_from_image,
|
||||||
despeckle_image, quantize_image
|
resize_image, rotate_image,
|
||||||
)
|
)
|
||||||
for i, img in enumerate(self.pages):
|
for i, img in enumerate(self.pages):
|
||||||
if self.rotate:
|
if self.rotate:
|
||||||
@ -205,17 +212,22 @@ class PageProcessor(list): # {{{
|
|||||||
if not self.opts.dont_sharpen:
|
if not self.opts.dont_sharpen:
|
||||||
img = gaussian_sharpen_image(img, 0.0, 1.0)
|
img = gaussian_sharpen_image(img, 0.0, 1.0)
|
||||||
|
|
||||||
if not self.opts.dont_grayscale:
|
|
||||||
img = grayscale_image(img)
|
|
||||||
|
|
||||||
if self.opts.despeckle:
|
if self.opts.despeckle:
|
||||||
img = despeckle_image(img)
|
img = despeckle_image(img)
|
||||||
|
|
||||||
|
img_is_grayscale = self.src_img_was_grayscaled
|
||||||
|
if not self.opts.dont_grayscale:
|
||||||
|
img = img.convertToFormat(QImage.Format.Format_Grayscale16)
|
||||||
|
img_is_grayscale = True
|
||||||
|
|
||||||
if self.opts.output_format.lower() == 'png':
|
if self.opts.output_format.lower() == 'png':
|
||||||
if self.opts.colors:
|
if self.opts.colors:
|
||||||
img = quantize_image(img, max_colors=min(256, self.opts.colors))
|
img = quantize_image(img, max_colors=min(256, self.opts.colors))
|
||||||
elif self.src_img_was_grayscaled:
|
elif img_is_grayscale:
|
||||||
img = img.convertToFormat(QImage.Format.Format_Grayscale8)
|
uses_256_colors = self.src_img_format in (QImage.Format.Format_Indexed8, QImage.Format.Format_Grayscale8)
|
||||||
|
final_fmt = QImage.Format.Format_Indexed8 if uses_256_colors else QImage.Format.Format_Grayscale16
|
||||||
|
if img.format() != final_fmt:
|
||||||
|
img = img.convertToFormat(final_fmt)
|
||||||
dest = '%d_%d.%s'%(self.num, i, self.opts.output_format)
|
dest = '%d_%d.%s'%(self.num, i, self.opts.output_format)
|
||||||
dest = os.path.join(self.dest, dest)
|
dest = os.path.join(self.dest, dest)
|
||||||
with open(dest, 'wb') as f:
|
with open(dest, 'wb') as f:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user