Skip to content

feat(reader): night mode object mask keeps images undistorted - #377

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
add-uos:fix-376493-night-image-lab-invert
Sep 10, 2026
Merged

deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
add-uos:fix-376493-night-image-lab-invert

Conversation

@add-uos

@add-uos add-uos commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Invert page content via CIELAB lightness flip with a two-level 65^3/128^3 RGB LUT (28x vs exact path, 13ms per 2M-pixel page), keep image objects out of the inverted area via a grayscale mask fetched on the render thread, and generate the night pixmap asynchronously (QtConcurrent) so paint never blocks. While the async job is in flight, paint composes an instant approximate night frame from the latest day render (fast full-page Difference invert plus image rects pasted back), so zooming responds in step with day mode instead of stretching a stale night pixmap. Mask rects are recorded with their fetch render size and scaled to the current render size before building the mask, so the mask stays aligned after zoom/rotation. Page filter only activates in EyeProtection Night mode; image dim factor defaults to 1.0 so photos keep original colors under the page overlay.

夜间模式页面内容按 CIELAB 明度反转,两级 65^3/128^3 RGB LUT 提速
28 倍(2M 像素 13ms);图片对象经灰度蒙版排除在反色区外,bbox 由
渲染线程随整页渲染预取并记录对应渲染尺寸,构建蒙版前按当前渲染
尺寸等比换算,缩放/旋转后蒙版不错位。夜间图经 QtConcurrent 异步
生成,paint 不阻塞;任务在途期间用最新日间渲染即时合成近似夜间帧
(整页 Difference 快速反相 + 图片 bbox 回贴原图),缩放与日间模式
同拍响应,不再拉伸旧夜间图,照片不出现负片。页面滤镜仅在护眼
夜间档生效;侧边栏缩略图仍随系统深色主题反色;图片调暗系数默认
1.0,照片保持原色。

Log: 夜间模式图片对象蒙版反色不失真
PMS: BUG-376493
Influence: 夜间模式下文字/背景反色为黑底白字,图片区域保持原色不
被反色,扫描页(图片覆盖>70%)整页反色;缩放/旋转与日间模式同拍
响应,过渡帧与最终渲染蒙版始终对齐;页面滤镜仅在夜间档生效,
经典/绿色护眼不受影响;侧边栏缩略图逻辑不变,仍随系统主题变化;
DOCX/DJVU 无对象信息走整页反色。

Summary by Sourcery

Keep night-mode page content responsive and perceptually inverted while excluding document images from the filter and maintaining mask alignment across rendering changes.

New Features:

  • Preserve PDF image objects during Eye Protection Night mode while applying perceptual page-content inversion to surrounding text and backgrounds.
  • Add image-object bounding-box discovery across the rendering pipeline to keep night-mode masks aligned with page rotation and render-size changes.
  • Provide configurable image handling policies and dimming controls for night-mode rendering, defaulting to preserving image colors.

Bug Fixes:

  • Prevent image regions from appearing as distorted or negative imagery during night-mode zooming, rotation, and asynchronous rendering transitions.
  • Avoid blocking painting while generating night-mode page images and discard stale asynchronous results after newer renders complete.

Enhancements:

  • Replace the previous page filter with a CIELAB lightness-based inversion optimized through lookup tables and scanned-page coverage handling.
  • Render an immediate approximate night frame during background filter generation so zoom and rotation remain responsive.

Invert page content via CIELAB lightness flip with a two-level
65^3/128^3 RGB LUT (28x vs exact path, 13ms per 2M-pixel page),
keep image objects out of the inverted area via a grayscale mask
fetched on the render thread, and generate the night pixmap
asynchronously (QtConcurrent) so paint never blocks. While the
async job is in flight, paint composes an instant approximate
night frame from the latest day render (fast full-page Difference
invert plus image rects pasted back), so zooming responds in step
with day mode instead of stretching a stale night pixmap. Mask
rects are recorded with their fetch render size and scaled to the
current render size before building the mask, so the mask stays
aligned after zoom/rotation. Page filter only activates in
EyeProtection Night mode; image dim factor defaults to 1.0 so
photos keep original colors under the page overlay.

夜间模式页面内容按 CIELAB 明度反转,两级 65^3/128^3 RGB LUT 提速
28 倍(2M 像素 13ms);图片对象经灰度蒙版排除在反色区外,bbox 由
渲染线程随整页渲染预取并记录对应渲染尺寸,构建蒙版前按当前渲染
尺寸等比换算,缩放/旋转后蒙版不错位。夜间图经 QtConcurrent 异步
生成,paint 不阻塞;任务在途期间用最新日间渲染即时合成近似夜间帧
(整页 Difference 快速反相 + 图片 bbox 回贴原图),缩放与日间模式
同拍响应,不再拉伸旧夜间图,照片不出现负片。页面滤镜仅在护眼
夜间档生效;侧边栏缩略图仍随系统深色主题反色;图片调暗系数默认
1.0,照片保持原色。

Log: 夜间模式图片对象蒙版反色不失真
PMS: BUG-376493
Influence: 夜间模式下文字/背景反色为黑底白字,图片区域保持原色不
被反色,扫描页(图片覆盖>70%)整页反色;缩放/旋转与日间模式同拍
响应,过渡帧与最终渲染蒙版始终对齐;页面滤镜仅在夜间档生效,
经典/绿色护眼不受影响;侧边栏缩略图逻辑不变,仍随系统主题变化;
DOCX/DJVU 无对象信息走整页反色。

Signed-off-by: zhanghongyuan <zhanghongyuan@uniontech.com>

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @add-uos, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 3 hours and 10 minutes by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Sep 10, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR introduces a render-size-aware PDF image mask pipeline and an asynchronous, LUT-accelerated CIELAB night filter. Browser pages now maintain responsive approximate transition frames during background processing, preserve image regions according to configurable policy, handle scanned pages and unsupported document formats, and invalidate stale results safely as renders change.

Sequence diagram for asynchronous night-mode rendering

sequenceDiagram
    participant RenderThread
    participant SheetRenderer
    participant BrowserPage
    participant NightFilter
    participant Painter

    RenderThread->>SheetRenderer: getImageObjectRects(index, width, height)
    SheetRenderer-->>RenderThread: imageRects
    RenderThread->>BrowserPage: setImageObjectRects(rects, width, height)
    RenderThread->>BrowserPage: handleRenderFinished(pixmapId, pixmap)
    BrowserPage->>BrowserPage: startNightJob()
    BrowserPage->>NightFilter: applyPage(src, rects, opt)
    Painter->>BrowserPage: paint()
    BrowserPage-->>Painter: drawPixmap(renderPixmap)
    Painter->>Painter: Difference invert and paste image rects
    NightFilter-->>BrowserPage: QImage
    BrowserPage->>BrowserPage: onNightImageReady()
    BrowserPage-->>Painter: drawPixmap(nightPixmap)
Loading

Flow diagram for render-size-aware image masking

flowchart LR
    A[PDF page render at width x height] --> B[Extract image object bounding boxes]
    B --> C[Record rects with fetch render size]
    C --> D{Current render size changed?}
    D -->|Yes| E[Scale bounding boxes to current size]
    D -->|No| F[Use recorded bounding boxes]
    E --> G[Build grayscale image mask]
    F --> G
    G --> H{Image coverage above 70 percent?}
    H -->|Yes| I[Invert entire page]
    H -->|No| J[CIELAB lightness inversion outside image areas]
    J --> K[Preserve or dim image regions by policy]
    I --> L[Night-mode image] 
    K --> L
Loading

File-Level Changes

Change Details Files
Adds PDF image-object bounding-box extraction and propagates render-size metadata into page state for aligned night-mode masking.
  • Extracts image object bounds from PDFium with page-rotation and pixel-coordinate transforms.
  • Adds a generic document-model API with PDF implementation and empty fallback for unsupported formats.
  • Prefetches bounding boxes on render-thread tasks and transfers them with completed renders.
  • Scales stored rectangles to the current pixmap dimensions before mask or transition-frame composition.
3rdparty/deepin-pdfium/include/dpdfpage.h
3rdparty/deepin-pdfium/src/dpdfpage.cpp
reader/document/Model.h
reader/document/PDFModel.h
reader/document/PDFModel.cpp
reader/uiframe/SheetRenderer.h
reader/uiframe/SheetRenderer.cpp
reader/browser/PageRenderThread.h
reader/browser/PageRenderThread.cpp
Replaces synchronous page inversion with an asynchronous CIELAB-based night filter and LUT-accelerated pixel processing.
  • Implements sRGB/CIELAB conversion with L* inversion, contrast-related clamps, alpha preservation, and a two-level lookup table for default settings.
  • Builds grayscale image masks with edge dilation and supports original, dimmed, or inverted image-object policies.
  • Adds scanned-page coverage detection that falls back to whole-page inversion when image bounds cover most of the page.
  • Runs filtering through QtConcurrent using copied image, rectangle, and option data, then installs completed results via QFutureWatcher.
reader/browser/NightFilter.h
reader/browser/NightFilter.cpp
reader/browser/browser.pri
reader/browser/BrowserPage.h
reader/browser/BrowserPage.cpp
Improves BrowserPage rendering responsiveness and limits the page filter to Night eye-protection mode.
  • Uses the latest day render for an immediate Difference-mode approximation while the exact night pixmap is being generated.
  • Pastes image rectangles back into the approximation and discards asynchronous results made stale by newer renders.
  • Starts jobs after render completion or on demand, tracks dirty/running state, and cleans up the watcher during page destruction.
  • Retains existing thumbnail/system-theme behavior and exposes configurable image policy and dimming settings.
reader/browser/BrowserPage.cpp
reader/browser/BrowserPage.h
reader/eyeprotection/EyeProtectionManager.h
reader/eyeprotection/EyeProtectionManager.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 87 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 未发现安全漏洞,代码架构设计优秀(CIELAB色彩空间反转+LUT加速+异步处理),但存在1处数学函数逻辑缺陷

🔍 详细分析

1. 语法逻辑 ❌

评价: 一般 ❌ 不通过

潜在问题:

  1. reader/browser/NightFilter.cpp:36 - linearChannelToSrgb 函数线性分支缺少 * 255.0 乘法。函数应返回 0-255 范围的 sRGB 值,但第一分支 (c <= 0.0031308) 返回 12.92 * c(范围 0-0.04),而第二分支正确乘以 255.0(范围 10.3-255)。导致线性值 ≤ 0.0031308 的极暗色彩输出 0 而非正确值,分支边界处产生不连续跳变。默认参数下由于 minLightness=11.0 钳制实际影响有限,但代码正确性存在问题。

建议: 修复 linearChannelToSrgb 函数中线性分支缺失的 * 255.0 乘法,确保两分支返回值范围一致(0-255)。


2. 代码质量 ✅

评价: 良好 ✅ 通过

潜在问题:

  1. reader/browser/PageRenderThread.cpp:422 - 图片对象 bbox 预取逻辑在 run() 和 execNextDocPageNormalImageTask() 中重复出现,可提取为辅助函数。
  2. reader/browser/BrowserPage.cpp:192 - 图片对象 bbox 缩放换算逻辑在 paint() 和 startNightJob() 中重复,可提取为工具函数。
  3. reader/browser/BrowserPage.h:458 - BrowserPage 新增 6 个夜间模式相关成员变量,类复杂度增加,可考虑封装为独立结构体。

建议: 代码注释质量优秀,算法原理和设计决策均有详细说明。建议减少重复代码,封装夜间模式状态。


3. 代码性能 ✅

评价: 优秀 ✅ 通过

潜在问题:

  1. reader/browser/NightFilter.cpp:117 - 128³ 直查表占用约 8MB 静态内存,对于桌面应用可接受但值得关注。
  2. 3rdparty/deepin-pdfium/src/dpdfpage.cpp:669 - 每次调用 imageObjectRects 都执行 FPDF_LoadPage/FPDF_ClosePage,虽有线程安全考虑但增加了开销。

建议: LUT 加速路径设计优秀(O(1) 查表替代逐像素 CIELAB 转换),异步处理消除 UI 阻塞,过渡帧渲染提供即时反馈。整体性能设计合理。


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: 无安全风险。线程安全设计完善(QFutureWatcher + DPdfMutexLocker + C++11 静态初始化),缓冲区操作有边界检查,环境变量处理有验证和钳制,资源管理无泄漏。


💡 改进建议代码示例

// 修复 NightFilter.cpp 中 linearChannelToSrgb 函数
// 修改前(第36行):
inline double linearChannelToSrgb(double c)
{
    c = qBound(0.0, c, 1.0);
    return (c <= 0.0031308) ? (12.92 * c) : (1.055 * qPow(c, 1.0 / 2.4) - 0.055) * 255.0;
}

// 修改后:
inline double linearChannelToSrgb(double c)
{
    c = qBound(0.0, c, 1.0);
    return (c <= 0.0031308) ? (12.92 * c * 255.0) : (1.055 * qPow(c, 1.0 / 2.4) - 0.055) * 255.0;
}

本报告由 AI 代码审查工具自动生成

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: add-uos, lzwind

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@add-uos

add-uos commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

/merge

@deepin-bot
deepin-bot Bot merged commit 6ef2d97 into linuxdeepin:master Sep 10, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants