Skip to content
A framework to perform multiple processing passes on textures in order to upscale them.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

Texture Upscaling Pipeline


A framework to perform multiple processing passes on textures in order to upscale them. This makes it easy to add new passes or iterate development on pre- and post-processing stages.


  • Python 3
  • Pillow
  • OpenCV
  • ESRGAN (my branch with some changes to the commandline usage)
    • CUDA
      • It will fall back to CPU where no CUDA devices are available, however it is almost impractically slow for a large amount of textures
    • Torch
    • TorchVision


  1. Clone the repo
  2. Setup submodules
git clone --recurse-submodules
  1. Install the requirements from requirements.txt
  2. Install CUDA
  3. Install PyTorch and torchvision from the website
  4. Place desired ESRGAN models from the authors page into the directory
  1. Configure settings.json


All images need to be in a format that pillow can read. Preferably this is PNG so it can be lossless.

Configure settings.json with the search path and extensions to search for.

  "searchPath": "D:/gamedata",
  "extensions": [".CACHE.PNG"]

Run the program


When the process has finished successfully all images will be saved alongside the originals with .HIRES.extension


The purpose of this program is to tie together many processing stages that can be performed before and after the upscaling step. The implementation of each stage is defined in a few modules under TextureUpscaler directory, and the order of steps is defined in

Adding a new processing step

The simplest way to add a new step is to add a custom function which works on a single image and can be passed to

run_processing_stage(invert_texture, images, settings)

Any function passed to run_processing_stage should take 4 parameters:

  • inpath: the file to be processed
  • outpath: where the file should be saved once finished
  • workingImage: the WorkingImageData instance for this image which contains all information related to this image, including original path etc
  • settings: a dictionary of all settings from settings.json

When a function completes successfully it should return True so that run_processing_stage updates the paths correctly in the pipeline.

invert_texture is a simple example used for testing the pipeline and makes a good learning example. Below you can see it.

from PIL import Image
import PIL.ImageOps

def invert_texture(inpath, outpath, workingImage, settings):
    """Inverts the colors on the texture specified"""
    print("Inverting texture: " + inpath)
    image =
    inverted_image = None
        inverted_image = PIL.ImageOps.invert(image)
    except IOError:
        return False
    return True
You can’t perform that action at this time.