black_hex & white_hex added

This commit is contained in:
keringo
2025-06-25 21:11:20 +03:00
parent 633e5c8bd4
commit 0a523f9ecf
14 changed files with 116 additions and 39 deletions

2
.gitmodules vendored
View File

@@ -1,6 +1,6 @@
[submodule "koreader-base"]
path = base
url = https://github.com/koreader/koreader-base.git
url = https://github.com/kerivin/koreader-base.git
[submodule "platform/android/luajit-launcher"]
path = platform/android/luajit-launcher
url = https://github.com/koreader/android-luajit-launcher.git

2
base

Submodule base updated: 63f95f0f2a...003e635a56

View File

@@ -83,6 +83,8 @@ DKOPTREADER_CONFIG_AUTO_STRAIGHTEN = 0, -- range from 0 to 10
DKOPTREADER_CONFIG_JUSTIFICATION = 3, -- -1 = auto, 0 = left, 1 = center, 2 = right, 3 = full
DKOPTREADER_CONFIG_MAX_COLUMNS = 2, -- range from 1 to 4
DKOPTREADER_CONFIG_CONTRAST = 1.0, -- range from 0.2 to 2.0
DKOPTREADER_CONFIG_BLACK_HEX = 0x000000, -- color defined blackness
DKOPTREADER_CONFIG_WHITE_HEX = 0xFFFFFF, -- color defined whiteness
-- word spacing for reflow
DKOPTREADER_CONFIG_WORD_SPACINGS = {0.05, -0.2, 0.375}, -- range from (+/-)0.05 to (+/-)0.5

View File

@@ -18,7 +18,9 @@ function ReaderHinting:onHintPage()
self.view.state.page + i,
self.zoom:getZoom(self.view.state.page + i),
self.view.state.rotation,
self.view.state.gamma)
self.view.state.gamma,
self.view.state.black_hex,
self.view.state.white_hex)
end
end
return true

View File

@@ -22,6 +22,8 @@ function ReaderKoptListener:onReadSettings(config)
self.normal_zoom_mode = normal_zoom_mode
self:setZoomMode(normal_zoom_mode)
self.ui:handleEvent(Event:new("GammaUpdate", self.document.configurable.contrast, true)) -- no notification
self.ui:handleEvent(Event:new("BlackLevelUpdate", self.document.configurable.black_hex, true)) -- no notification
self.ui:handleEvent(Event:new("WhiteLevelUpdate", self.document.configurable.white_hex, true)) -- no notification
-- since K2pdfopt v2.21 negative value of word spacing is also used, for config
-- compatibility we should manually change previous -1 to a more reasonable -0.2
if self.document.configurable.word_spacing == -1 then

View File

@@ -705,6 +705,20 @@ function ReaderPaging:onUpdateScrollPageGamma(gamma)
return true
end
function ReaderPaging:onUpdateScrollPageBlackLevel(black_hex)
for _, state in ipairs(self.view.page_states) do
state.black_hex = black_hex
end
return true
end
function ReaderPaging:onUpdateScrollPageWhiteLevel(white_hex)
for _, state in ipairs(self.view.page_states) do
state.white_hex = white_hex
end
return true
end
function ReaderPaging:getNextPageState(blank_area, image_offset)
local page_area = self.view:getPageArea(
self.view.state.page,

View File

@@ -1092,6 +1092,26 @@ function ReaderView:onGammaUpdate(gamma, no_notification)
end
end
function ReaderView:onBlackLevelUpdate(black_hex, no_notification)
self.state.black_hex = black_hex
if self.page_scroll then
self.ui:handleEvent(Event:new("UpdateScrollPageBlackLevel", black_hex))
end
if not no_notification then
Notification:notify(T(_("Black level set to: %1."), black_hex))
end
end
function ReaderView:onWhiteLevelUpdate(white_hex, no_notification)
self.state.white_hex = white_hex
if self.page_scroll then
self.ui:handleEvent(Event:new("UpdateScrollPageWhiteLevel", white_hex))
end
if not no_notification then
Notification:notify(T(_("White level set to: %1."), white_hex))
end
end
-- For ReaderKOptListener
function ReaderView:onDitheringUpdate()
-- Do the device cap checks again, to avoid snafus when sharing configs between devices

View File

@@ -136,16 +136,16 @@ function DjvuDocument:findAllText(pattern, case_insensitive, nb_context_words, m
return self.koptinterface:findAllText(self, pattern, case_insensitive, nb_context_words, max_hits)
end
function DjvuDocument:renderPage(pageno, rect, zoom, rotation, gamma, hinting)
return self.koptinterface:renderPage(self, pageno, rect, zoom, rotation, gamma, hinting)
function DjvuDocument:renderPage(pageno, rect, zoom, rotation, gamma, black_hex, white_hex, hinting)
return self.koptinterface:renderPage(self, pageno, rect, zoom, rotation, gamma, black_hex, white_hex, hinting)
end
function DjvuDocument:hintPage(pageno, zoom, rotation, gamma)
return self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma)
function DjvuDocument:hintPage(pageno, zoom, rotation, gamma, black_hex, white_hex)
return self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma, black_hex, white_hex)
end
function DjvuDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma)
return self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, gamma)
function DjvuDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, black_hex, white_hex)
return self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, gamma, black_hex, white_hex)
end
function DjvuDocument:register(registry)

View File

@@ -390,31 +390,33 @@ function Document:resetTileCacheValidity()
self.tile_cache_validity_ts = os.time()
end
function Document:getFullPageHash(pageno, zoom, rotation, gamma)
function Document:getFullPageHash(pageno, zoom, rotation, gamma, black_hex, white_hex)
return "renderpg|"..self.file.."|"..self.mod_time.."|"..pageno.."|"
..zoom.."|"
..rotation.."|"..gamma.."|"..self.render_mode..(self.render_color and "|color" or "|bw")
..rotation.."|"..gamma.."|"..black_hex.."|"..white_hex
..self.render_mode..(self.render_color and "|color" or "|bw")
..(self.reflowable_font_size and "|"..self.reflowable_font_size or "")
end
function Document:getPagePartHash(pageno, zoom, rotation, gamma, rect)
function Document:getPagePartHash(pageno, zoom, rotation, gamma, black_hex, white_hex, rect)
return "renderpgpart|"..self.file.."|"..self.mod_time.."|"..pageno.."|"
..tostring(rect).."|"..zoom.."|"..tostring(rect.scaled_rect).."|"
..rotation.."|"..gamma.."|"..self.render_mode..(self.render_color and "|color" or "|bw")
..rotation.."|"..gamma.."|"..black_hex.."|"..white_hex
..self.render_mode..(self.render_color and "|color" or "|bw")
..(self.reflowable_font_size and "|"..self.reflowable_font_size or "")
end
function Document:renderPage(pageno, rect, zoom, rotation, gamma, hinting)
function Document:renderPage(pageno, rect, zoom, rotation, gamma, black_hex, white_hex, hinting)
-- If rect contains a nested scaled_rect object, our caller handled scaling itself (e.g., drawPagePart)
local is_prescaled = rect and rect.scaled_rect ~= nil or false
local hash, hash_excerpt, tile
if is_prescaled then
hash = self:getPagePartHash(pageno, zoom, rotation, gamma, rect)
hash = self:getPagePartHash(pageno, zoom, rotation, gamma, black_hex, white_hex, rect)
tile = DocCache:check(hash, TileCacheItem)
else
hash = self:getFullPageHash(pageno, zoom, rotation, gamma)
hash = self:getFullPageHash(pageno, zoom, rotation, gamma, black_hex, white_hex)
tile = DocCache:check(hash, TileCacheItem)
@@ -502,6 +504,9 @@ function Document:renderPage(pageno, rect, zoom, rotation, gamma, hinting)
dc:setGamma(gamma)
end
dc:setBlackHex(black_hex)
dc:setWhiteHex(white_hex)
-- And finally, render the page in our BB
local page = self._document:openPage(pageno)
page:draw(dc, tile.bb, size.x, size.y, self.render_mode)
@@ -516,9 +521,9 @@ end
-- a hint for the cache engine to paint a full page to the cache
--- @todo this should trigger a background operation
function Document:hintPage(pageno, zoom, rotation, gamma)
function Document:hintPage(pageno, zoom, rotation, gamma, black_hex, white_hex)
logger.dbg("hinting page", pageno)
self:renderPage(pageno, nil, zoom, rotation, gamma, true)
self:renderPage(pageno, nil, zoom, rotation, gamma, black_hex, white_hex, true)
end
--[[
@@ -529,8 +534,8 @@ Draw page content to blitbuffer.
@target: target blitbuffer
@rect: visible_area inside document page
--]]
function Document:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma)
local tile = self:renderPage(pageno, rect, zoom, rotation, gamma)
function Document:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, black_hex, white_hex)
local tile = self:renderPage(pageno, rect, zoom, rotation, gamma, black_hex, white_hex)
-- Enable SW dithering if requested (only available in koptoptions)
if self.sw_dithering then
target:ditherblitFrom(tile.bb,
@@ -570,7 +575,7 @@ function Document:drawPagePart(pageno, native_rect, rotation)
rect.scaled_rect = scaled_rect
-- Enable SMP via the hinting flag
local tile = self:renderPage(pageno, rect, zoom, rotation, 1.0, true)
local tile = self:renderPage(pageno, rect, zoom, rotation, 1.0, 0x000000, 0xFFFFFF, true)
return tile.bb, rotate
end

View File

@@ -99,6 +99,8 @@ function KoptInterface:setDefaultConfigurable(configurable)
configurable.page_margin = G_defaults:readSetting("DKOPTREADER_CONFIG_PAGE_MARGIN")
configurable.quality = G_defaults:readSetting("DKOPTREADER_CONFIG_RENDER_QUALITY")
configurable.contrast = G_defaults:readSetting("DKOPTREADER_CONFIG_CONTRAST")
configurable.black_hex = G_defaults:readSetting("DKOPTREADER_CONFIG_BLACK_HEX")
configurable.white_hex = G_defaults:readSetting("DKOPTREADER_CONFIG_WHITE_HEX")
configurable.defect_size = G_defaults:readSetting("DKOPTREADER_CONFIG_DEFECT_SIZE")
configurable.line_spacing = G_defaults:readSetting("DKOPTREADER_CONFIG_LINE_SPACING")
configurable.word_spacing = G_defaults:readSetting("DKOPTREADER_CONFIG_DEFAULT_WORD_SPACING")
@@ -150,6 +152,8 @@ function KoptInterface:createContext(doc, pageno, bbox)
kc:setQuality(doc.configurable.quality)
-- k2pdfopt (for reflowing) and mupdf use different algorithms to apply gamma when rendering
kc:setContrast(1 / doc.configurable.contrast)
kc:setForegroundHex(doc.configurable.black_hex)
kc:setBackgroundHex(doc.configurable.white_hex)
kc:setDefectSize(doc.configurable.defect_size)
kc:setLineSpacing(doc.configurable.line_spacing)
kc:setWordSpacing(doc.configurable.word_spacing)
@@ -384,19 +388,19 @@ function KoptInterface:getCoverPageImage(doc)
local native_size = Document.getNativePageDimensions(doc, 1)
local canvas_size = CanvasContext:getSize()
local zoom = math.min(canvas_size.w / native_size.w, canvas_size.h / native_size.h)
local tile = Document.renderPage(doc, 1, nil, zoom, 0, 1.0)
local tile = Document.renderPage(doc, 1, nil, zoom, 0, 1.0, 0x000000, 0xFFFFFF)
if tile then
return tile.bb:copy()
end
end
function KoptInterface:renderPage(doc, pageno, rect, zoom, rotation, gamma, hinting)
function KoptInterface:renderPage(doc, pageno, rect, zoom, rotation, gamma, black_hex, white_hex, hinting)
if doc.configurable.text_wrap == 1 then
return self:renderReflowedPage(doc, pageno, rect, zoom, rotation, hinting)
elseif doc.configurable.page_opt == 1 or doc.configurable.auto_straighten > 0 then
return self:renderOptimizedPage(doc, pageno, rect, zoom, rotation, hinting)
else
return Document.renderPage(doc, pageno, rect, zoom, rotation, gamma, hinting)
return Document.renderPage(doc, pageno, rect, zoom, rotation, gamma, black_hex, white_hex, hinting)
end
end
@@ -491,16 +495,16 @@ function KoptInterface:renderOptimizedPage(doc, pageno, rect, zoom, rotation, hi
end
end
function KoptInterface:hintPage(doc, pageno, zoom, rotation, gamma)
function KoptInterface:hintPage(doc, pageno, zoom, rotation, gamma, black_hex, white_hex)
--- @note: Crappy safeguard around memory issues like in #7627: if we're eating too much RAM, drop half the cache...
DocCache:memoryPressureCheck()
if doc.configurable.text_wrap == 1 then
self:hintReflowedPage(doc, pageno, zoom, rotation, gamma, true)
self:hintReflowedPage(doc, pageno, zoom, rotation, gamma, black_hex, white_hex, true)
elseif doc.configurable.page_opt == 1 or doc.configurable.auto_straighten > 0 then
self:renderOptimizedPage(doc, pageno, nil, zoom, rotation, gamma, true)
self:renderOptimizedPage(doc, pageno, nil, zoom, rotation, gamma, black_hex, white_hex, true)
else
Document.hintPage(doc, pageno, zoom, rotation, gamma)
Document.hintPage(doc, pageno, zoom, rotation, gamma, black_hex, white_hex)
end
end

View File

@@ -344,16 +344,16 @@ function PdfDocument:findAllText(pattern, case_insensitive, nb_context_words, ma
return self.koptinterface:findAllText(self, pattern, case_insensitive, nb_context_words, max_hits)
end
function PdfDocument:renderPage(pageno, rect, zoom, rotation, gamma, hinting)
return self.koptinterface:renderPage(self, pageno, rect, zoom, rotation, gamma, hinting)
function PdfDocument:renderPage(pageno, rect, zoom, rotation, gamma, black_hex, white_hex, hinting)
return self.koptinterface:renderPage(self, pageno, rect, zoom, rotation, gamma, black_hex, white_hex, hinting)
end
function PdfDocument:hintPage(pageno, zoom, rotation, gamma)
return self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma)
function PdfDocument:hintPage(pageno, zoom, rotation, gamma, black_hex, white_hex)
return self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma, black_hex, white_hex)
end
function PdfDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma)
return self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, gamma)
function PdfDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, black_hex, white_hex)
return self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, gamma, black_hex, white_hex)
end
function PdfDocument:register(registry)

View File

@@ -501,6 +501,34 @@ Some of the other settings are only available when reflow mode is enabled.]]),
precision = "%.1f",
},
},
{
name = "black_hex",
name_text = _("Black Level"),
buttonprogress = true,
-- For pdf reflowing mode (kopt_contrast):
values = {0x808080, 0x606060, 0x404040, 0x202020, 0x000000},
default_pos = 2,
default_value = G_defaults:readSetting("DKOPTREADER_CONFIG_BLACK_HEX"),
event = "BlackLevelUpdate",
-- For pdf non-reflowing mode (mupdf):
args = {0x808080, 0x606060, 0x404040, 0x202020, 0x000000},
labels = { #808080, #606060, #404040, #202020, #000000},
name_text_hold_callback = optionsutil.showValues,
},
{
name = "white_hex",
name_text = _("White Level"),
buttonprogress = true,
-- For pdf reflowing mode (kopt_contrast):
values = {0xFFFFFF, 0xE0E0E0, 0xC0C0C0, 0xA0A0A0, 0x808080},
default_pos = 2,
default_value = G_defaults:readSetting("DKOPTREADER_CONFIG_WHITE_HEX"),
event = "WhiteLevelUpdate",
-- For pdf non-reflowing mode (mupdf):
args = {0xFFFFFF, 0xE0E0E0, 0xC0C0C0, 0xA0A0A0, 0x808080},
labels = { #FFFFFF, #E0E0E0, #C0C0C0, #A0A0A0, #808080},
name_text_hold_callback = optionsutil.showValues,
},
{
name = "page_opt",
name_text = _("Dewatermark"),

View File

@@ -20,7 +20,7 @@ describe("Cache module", function()
it("should serialize blitbuffer", function()
for pageno = 1, math.min(max_page, doc.info.number_of_pages) do
doc:renderPage(pageno, nil, 1, 0, 1.0)
doc:renderPage(pageno, nil, 1, 0, 1.0, 0x000000, 0xFFFFFF)
DocCache:serialize()
end
DocCache:clear()
@@ -28,7 +28,7 @@ describe("Cache module", function()
it("should deserialize blitbuffer", function()
for pageno = 1, math.min(max_page, doc.info.number_of_pages) do
doc:hintPage(pageno, 1, 0, 1.0, 0)
doc:hintPage(pageno, 1, 0, 1.0, 0x000000, 0xFFFFFF)
end
DocCache:clear()
end)
@@ -36,7 +36,7 @@ describe("Cache module", function()
it("should serialize koptcontext", function()
doc.configurable.text_wrap = 1
for pageno = 1, math.min(max_page, doc.info.number_of_pages) do
doc:renderPage(pageno, nil, 1, 0, 1.0)
doc:renderPage(pageno, nil, 1, 0, 1.0, 0x000000, 0xFFFFFF)
doc:getPageDimensions(pageno)
DocCache:serialize()
end
@@ -46,7 +46,7 @@ describe("Cache module", function()
it("should deserialize koptcontext", function()
for pageno = 1, math.min(max_page, doc.info.number_of_pages) do
doc:renderPage(pageno, nil, 1, 0, 1.0)
doc:renderPage(pageno, nil, 1, 0, 1.0, 0x000000, 0xFFFFFF)
end
DocCache:clear()
end)

View File

@@ -23,7 +23,7 @@ describe("PDF benchmark:", function()
end
for pageno = 1, math.min(9, doc.info.number_of_pages) do
local secs, usecs = util.gettime()
assert.truthy(doc:renderPage(pageno, nil, 1, 0, 1.0))
assert.truthy(doc:renderPage(pageno, nil, 1, 0, 1.0, , 0x000000, 0xFFFFFF))
local nsecs, nusecs = util.gettime()
local dur = nsecs - secs + (nusecs - usecs) / 1000000
logDuration(logfile, pageno, dur)