Skip to content

Fix alpha upscaling artifacts and add CUDA fallback (addresses #3)#4

Open
mgagvani wants to merge 2 commits into
mainfrom
codex/investigate-issue-#3-in-repository
Open

Fix alpha upscaling artifacts and add CUDA fallback (addresses #3)#4
mgagvani wants to merge 2 commits into
mainfrom
codex/investigate-issue-#3-in-repository

Conversation

@mgagvani

@mgagvani mgagvani commented Feb 10, 2026

Copy link
Copy Markdown
Owner

Motivation

  • The upscaler produced transparent/halos when holding items because alpha channels for binary masks were upscaled with cubic interpolation and dimensions were swapped for non-square images.
  • The pipeline also assumed CUDA by default which caused failures on CPU-only systems when OpenCV was not built with CUDA support.

Description

  • Detect CUDA availability with cv2.cuda.getCudaEnabledDeviceCount() and only set the CUDA backend/target when a device exists, otherwise continue on CPU. (texturepack.py).
  • Fix alpha resize argument ordering to use (width, height) so non-square RGBA textures are upscaled without merge-size mismatches. (texturepack.py).
  • Preserve hard alpha edges for binary-alpha textures by selecting cv2.INTER_NEAREST when the alpha channel is binary, and use cv2.INTER_CUBIC for textures containing semi-transparency. (texturepack.py).
  • Add ISSUE_3_INVESTIGATION.md documenting reproduction steps, findings, and the proposed/implemented solution for issue Transparent When Holding #3.

Testing

  • Downloaded the reported Furfsky pack and executed the upscaler end-to-end to reproduce the failure modes, which succeeded in reproducing the reported artifacts and CUDA failure. (reproduction run).
  • Ran focused validation scripts that extract representative PNGs, run the SR model (EDSR_x2.pb) and compare alpha channels; tests show binary-alpha images remain binary after the patch and non-square RGBA images upscale without merge errors. (validation scripts executed successfully).
  • Created a minimal mini-pack and ran texturepack.extract() + texturepack.upscale() to confirm shapes and alpha counts were correct, and ran python -m py_compile texturepack.py which succeeded.

Codex Task


Note

Low Risk
Scoped changes to image-processing behavior and a documentation add; main risk is subtle differences in output alpha interpolation for some textures.

Overview
Fixes RGBA upscaling issues that caused skipped non-square textures and semi-transparent/fringed edges in binary-alpha textures.

texturepack.upscale() now checks cv2.cuda.getCudaEnabledDeviceCount() before enabling the CUDA backend (otherwise continues on CPU), corrects alpha resize argument order to (width, height), and chooses INTER_NEAREST for binary alpha masks while keeping INTER_CUBIC for already-soft alpha.

Adds ISSUE_3_INVESTIGATION.md documenting reproduction steps, root causes, and before/after verification for issue #3.

Written by Cursor Bugbot for commit 7a64b64. This will update automatically on new commits. Configure here.

Copilot AI review requested due to automatic review settings February 10, 2026 04:55

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3943208598

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread texturepack.py
newalpha = cv2.resize(alpha, (alpha.shape[0]*scalefactor, alpha.shape[1]*scalefactor), interpolation=cv2.INTER_CUBIC)
# Preserve hard edges for textures with binary alpha (common in item icons).
# Fall back to cubic for textures that already contain semi-transparency.
alpha_interpolation = cv2.INTER_NEAREST if len(set(alpha.flatten())) <= 2 else cv2.INTER_CUBIC

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restrict nearest-alpha path to true binary masks

The new len(set(alpha.flatten())) <= 2 check treats any two-level alpha image as “binary,” so textures with semi-transparency encoded as two values (for example {0, 128} or {128, 255}) will incorrectly use INTER_NEAREST instead of cubic and lose soft edges. This contradicts the stated behavior of preserving semi-transparent textures and can visibly degrade icons/GUI assets that use quantized alpha ramps.

Useful? React with 👍 / 👎.

Copilot AI 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.

Pull request overview

Fixes texture upscaling artifacts and improves runtime portability by correcting alpha-channel resizing behavior and avoiding unconditional CUDA configuration when CUDA isn’t available.

Changes:

  • Detect CUDA device availability before selecting OpenCV DNN CUDA backend/target, otherwise fall back to CPU.
  • Fix alpha resize (width, height) ordering and preserve hard edges by using nearest-neighbor interpolation for binary-alpha textures.
  • Add an investigation write-up documenting reproduction, findings, and validation for issue #3.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
texturepack.py Adds CUDA fallback logic and correct/edge-preserving alpha upscaling behavior.
ISSUE_3_INVESTIGATION.md Documents root cause analysis and validation steps for issue #3.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread texturepack.py
Comment on lines +39 to +44
if use_cuda:# Set CUDA backend and target to enable GPU inference
if cv2.cuda.getCudaEnabledDeviceCount() > 0:
sr.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
sr.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)
else:
print("CUDA backend unavailable. Falling back to CPU.")

Copilot AI Feb 10, 2026

Copy link

Choose a reason for hiding this comment

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

cv2.cuda.getCudaEnabledDeviceCount() can raise cv2.error (and/or cv2.cuda may be absent) when OpenCV is built without CUDA support. In that case this fallback logic will still crash before reaching the CPU path. Consider guarding with hasattr(cv2, "cuda") and wrapping the call in try/except cv2.error, defaulting to CPU when CUDA APIs are unavailable.

Suggested change
if use_cuda:# Set CUDA backend and target to enable GPU inference
if cv2.cuda.getCudaEnabledDeviceCount() > 0:
sr.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
sr.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)
else:
print("CUDA backend unavailable. Falling back to CPU.")
if use_cuda: # Set CUDA backend and target to enable GPU inference
if hasattr(cv2, "cuda"):
try:
if cv2.cuda.getCudaEnabledDeviceCount() > 0:
sr.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
sr.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)
else:
print("CUDA backend unavailable. Falling back to CPU.")
except cv2.error:
print("OpenCV CUDA support not available in this build. Falling back to CPU.")
else:
print("OpenCV CUDA module not found. Falling back to CPU.")

Copilot uses AI. Check for mistakes.
Comment thread texturepack.py
newalpha = cv2.resize(alpha, (alpha.shape[0]*scalefactor, alpha.shape[1]*scalefactor), interpolation=cv2.INTER_CUBIC)
# Preserve hard edges for textures with binary alpha (common in item icons).
# Fall back to cubic for textures that already contain semi-transparency.
alpha_interpolation = cv2.INTER_NEAREST if len(set(alpha.flatten())) <= 2 else cv2.INTER_CUBIC

Copilot AI Feb 10, 2026

Copy link

Choose a reason for hiding this comment

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

Binary-alpha detection via len(set(alpha.flatten())) <= 2 is both expensive (creates a Python set over every pixel) and not equivalent to “binary alpha”: an alpha channel with exactly two non-{0,255} levels (e.g., {0, 64}) will be treated as binary and forced to INTER_NEAREST. Prefer a vectorized NumPy check like np.any((alpha != 0) & (alpha != 255)) (or np.isin) to decide between nearest/cubic, which avoids Python-level per-pixel work and matches the stated intent.

Copilot uses AI. Check for mistakes.

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Comment thread texturepack.py
sr.readModel(path)

if use_cuda:# Set CUDA backend and target to enable GPU inference
if cv2.cuda.getCudaEnabledDeviceCount() > 0:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CUDA check can crash without exception handling

Low Severity

The call to cv2.cuda.getCudaEnabledDeviceCount() at line 40 is not wrapped in a try/except. On some OpenCV installations (older versions, custom builds, or minimal packages), the cv2.cuda submodule may not exist, raising an unhandled AttributeError that crashes the entire upscale() function before processing any images. Since the whole purpose of this change is graceful CPU fallback, the CUDA availability check itself needs to be guarded.

Fix in Cursor Fix in Web

Comment thread ISSUE_3_INVESTIGATION.md
- Old path (swapped width/height in alpha resize): merge failed.
- New path (correct `(width, height)`): merge succeeded with upscaled alpha shape `(64, 52)`.

This confirms the old code path reproduced the defect conditions and the new path removes them for these representative textures.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Debugging investigation document committed to repository root

Low Severity

ISSUE_3_INVESTIGATION.md is a Codex task debugging artifact containing ephemeral details like specific pixel counts, test script outputs, and reproduction steps. This content belongs in the GitHub issue or PR comments, not as a permanent file in the repository root. It will become stale as code evolves and adds confusion for contributors who may mistake it for essential project documentation.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants