PrintScreen Plugin v2.0 - Complete Documentation

Table of Contents

  1. Overview
  2. Installation
  3. Configuration
  4. Papyrus Script Integration
  5. API Reference
  6. Image Formats
  7. Logging System
  8. Technical Architecture
  9. Troubleshooting
  10. Performance Optimization

Overview

PrintScreen Plugin v2.0 is a SKSE plugin for Skyrim Special Edition that enables high-quality screenshot capture directly from Papyrus scripts. It uses Windows Desktop Duplication API for efficient screen capture and supports multiple image formats with various compression options.

Key Features

  • Multiple Image Formats: PNG, JPEG, BMP, TIFF, GIF, DDS
  • Animated GIF Support: Capture multi-frame GIFs with customizable duration
  • Advanced Compression: BC1-BC7 compression for DDS, various TIFF compression modes
  • Asynchronous Operation: Non-blocking capture with callback system
  • Parallel Processing: Multi-threaded compression for optimal performance
  • Comprehensive Logging: Detailed logging with configurable levels
  • Thread-Safe: Proper synchronization for stable operation

System Requirements

  • Skyrim Special Edition (1.5.39+)
  • SKSE64 (compatible version)
  • Windows 10/11 with Desktop Duplication API support
  • DirectX 11 compatible graphics card

Installation

  1. Extract Plugin Files:

    Data/SKSE/Plugins/Printscreen.dll

  2. File Structure:

    Skyrim Special Edition/ ├── Data/ │ └── SKSE/ │ └── Plugins/ │ └── Printscreen.dll └── Documents/ └── My Games/ └── Skyrim Special Edition/ └── SKSE/ ├── Printscreen_Log.ini (auto-created) └── printscreen.log (auto-created)

  3. First Run: The plugin will automatically create configuration and log files on first run.

Configuration

Configuration File Location

Documents/My Games/Skyrim Special Edition/SKSE/Plugins/Printscreen_Log.ini

Configuration Options

; Printscreen Plugin Configuration [Logging] ; Log verbosity level (0-5) ; 0 = OFF, 1 = ERROR, 2 = WARN, 3 = INFO, 4 = DEBUG, 5 = TRACE LogLevel=3 ; Enable/disable console output (0/1) ConsoleOutput=1 ; Enable/disable file logging (0/1) FileOutput=1 ; Show timestamps in log entries (0/1) ShowTimestamps=1 ; Maximum log file size in MB MaxLogFileSizeMB=10 [Performance] ; Enable parallel compression for supported formats (0/1) ParallelCompression=1 ; Number of compression threads (0 = auto-detect) CompressionThreads=0 [Capture] ; Log capture progress messages (0/1) LogCaptureProgress=1 ; Log detailed timing information (0/1) LogTimingInfo=0

Log Levels Explained

  • OFF (0): No logging
  • ERROR (1): Critical errors only
  • WARN (2): Warnings and errors
  • INFO (3): General information, warnings, and errors (default)
  • DEBUG (4): Detailed debugging information
  • TRACE (5): Extremely verbose logging

Papyrus Script Integration

Script Header

Scriptname Printscreen_Formula_script extends Quest {Main interface for PrintScreen plugin screenshot functionality} ; Native function declarations bool Function CheckPath(string path) native string Function TakePhoto(string basePath, string imageType, float jpgCompression, string Mode, float GIF_MultiFrame_Duration) native string Function Get_Result() native string Function Cancel() native

Basic Usage Example

; Example: Take a simple PNG screenshot Function TakeScreenshot() string basePath = "C:/Screenshots/Skyrim" string imageType = "png" float jpgCompression = 95.0 ; Not used for PNG string mode = "" ; Not used for PNG float gifDuration = 0.0 ; Not used for single frame ; Check if path is valid if !CheckPath(basePath) Debug.MessageBox("Invalid screenshot path!") return endif ; Start capture string result = TakePhoto(basePath, imageType, jpgCompression, mode, gifDuration) if result == "Started" ; Wait for completion WaitForCapture() else Debug.MessageBox("Failed to start capture: " + result) endif EndFunction Function WaitForCapture() int timeout = 100 ; 10 seconds timeout string result = "" while timeout > 0 result = Get_Result() if result == "CALLBACK_SUCCESS" Debug.MessageBox("Screenshot saved successfully!") return elseif result == "CALLBACK_CANCELLED" Debug.MessageBox("Screenshot cancelled.") return elseif StringUtil.Find(result, "CALLBACK_ERROR:") == 0 string error = StringUtil.Substring(result, 15) Debug.MessageBox("Screenshot failed: " + error) return endif Utility.Wait(0.1) timeout -= 1 endWhile Debug.MessageBox("Screenshot timeout!") EndFunction

Advanced Example: Animated GIF

Function CaptureAnimatedGIF() string basePath = "C:/Screenshots/Skyrim" string imageType = "gif_multiframe" float jpgCompression = 0.0 ; Not used for GIF string mode = "" ; Not used for GIF float gifDuration = 5.0 ; 5 second GIF string result = TakePhoto(basePath, imageType, jpgCompression, mode, gifDuration) if result == "Started" Debug.Notification("Recording 5 second GIF...") WaitForCapture() endif EndFunction

API Reference

CheckPath

bool Function CheckPath(string path) native

Validates a file path for screenshot storage.

Parameters:

  • path - Directory path to validate

Returns:

  • true if path is valid and writable
  • false if path is invalid or not writable

Notes:

  • Creates directory if it doesn't exist
  • Tests write permissions
  • Path must be absolute (e.g., "C:/Screenshots")

TakePhoto

string Function TakePhoto(string basePath, string imageType, float jpgCompression, string Mode, float GIF_MultiFrame_Duration) native

Initiates screenshot capture.

Parameters:

  • basePath - Directory where screenshot will be saved
  • imageType - Image format (see Image Formats)
  • jpgCompression - JPEG quality (0-100, only for JPEG)
  • Mode - Compression mode for TIFF/DDS (see format-specific options)
  • GIF_MultiFrame_Duration - Duration in seconds for animated GIFs (1-30)

Returns:

  • "Started" - Capture initiated successfully
  • "Already running" - Another capture is in progress
  • Error message if validation fails

Generated Filename Format:

SS_YYYYMMDD_HHMMSS_mmm.ext

Example: SS_20250716_143052_123.png

Get_Result

string Function Get_Result() native

Polls capture status.

Returns:

  • "Running" - Capture still in progress
  • "CALLBACK_SUCCESS" - Capture completed successfully
  • "CALLBACK_CANCELLED" - Capture was cancelled
  • "CALLBACK_ERROR:message" - Capture failed with error
  • Current status string

Cancel

string Function Cancel() native

Requests cancellation of ongoing capture.

Returns:

  • "Cancel requested" - Cancellation initiated
  • "Not running" - No capture to cancel

Image Formats

PNG (Portable Network Graphics)

  • Type: "png"
  • Compression: Lossless
  • Best for: High-quality screenshots with transparency
  • File size: Medium to large

JPEG (Joint Photographic Experts Group)

  • Type: "jpg" or "jpeg"
  • Compression: Lossy
  • Quality parameter: 0-100 (default: 95)
  • Best for: Photographic content, smaller file sizes
  • File size: Small to medium

BMP (Bitmap)

  • Type: "bmp"
  • Compression: None
  • Best for: Fast capture, no compression overhead
  • File size: Very large

TIFF (Tagged Image File Format)

  • Type: "tif" or "tiff"
  • Compression modes:
    • "none" - No compression
    • "lzw" - Lossless LZW compression
    • "zip" - Lossless ZIP compression
    • "rle" - Run-length encoding
    • "ccitt1d" - CCITT Group 3 1D
    • "ccitt4" - CCITT Group 4
  • Best for: Professional archival
  • File size: Variable

GIF (Graphics Interchange Format)

  • Single frame: "gif"
  • Animated: "gif_multiframe"
  • Frame rate: 10 FPS (fixed)
  • Duration: 1-30 seconds (animated only)
  • Best for: Simple animations, limited colors
  • File size: Small to medium

DDS (DirectDraw Surface)

  • Type: "dds"
  • Compression modes:
    • "bc1" - BC1/DXT1 (RGB, optional 1-bit alpha)
    • "bc2" - BC2/DXT3 (RGB + 4-bit alpha)
    • "bc3" - BC3/DXT5 (RGB + interpolated alpha)
    • "bc4" - BC4 (single channel)
    • "bc5" - BC5 (two channels, normal maps)
    • "bc6h" - BC6H (HDR RGB)
    • "bc7_fast" - BC7 fast mode
    • "bc7_normal" - BC7 balanced mode
    • "bc7_slow" - BC7 best quality
  • Best for: Game textures, GPU-friendly format
  • File size: Very small (highly compressed)

Logging System

Log File Location

Documents/My Games/Skyrim Special Edition/SKSE/printscreen.log

Log Entry Format

[YYYY-MM-DD HH:MM:SS] [LEVEL] Message

Example Log Entries

[2025-07-16 14:30:52] [INFO] === PrintScreen Plugin Logger Initialized === [2025-07-16 14:30:52] [INFO] Log file: C:/Users/.../Documents/My Games/Skyrim Special Edition/SKSE/printscreen.log [2025-07-16 14:30:52] [DEBUG] Validating path: 'C:/Screenshots/Skyrim' [2025-07-16 14:30:52] [INFO] === PAPYRUS TAKEPHOTO CALLED === [2025-07-16 14:30:52] [INFO] Starting capture thread... [2025-07-16 14:30:53] [INFO] Frame captured successfully [2025-07-16 14:30:53] [INFO] Image saved successfully: C:/Screenshots/Skyrim/SS_20250716_143052_123.png (2453760 bytes)

Performance Logging

When LogTimingInfo=1:

[2025-07-16 14:30:53] [TIMING] DDS compression completed successfully in 125ms [2025-07-16 14:30:53] [TIMING] Compression ratio: 4.82:1 (8294400 -> 1720320 bytes)

Technical Architecture

Threading Model

  • Main Thread: Papyrus function calls, state management
  • Worker Thread: Asynchronous capture operations
  • Compression Threads: Parallel DDS/TIFF compression (auto-scaled to CPU cores)

Memory Management

  • DirectX scratch images for frame storage
  • Automatic cleanup on scope exit
  • Efficient buffer reuse for multi-frame captures

Error Handling

  • Comprehensive HRESULT checking
  • Exception safety with try-catch blocks
  • Graceful degradation (e.g., fallback to uncompressed on compression failure)

Desktop Duplication API Flow

  1. Create D3D11 device and context
  2. Get DXGI adapter and output
  3. Create output duplication interface
  4. Acquire frame with timeout handling
  5. Copy to staging texture for CPU access
  6. Convert to DirectXTex image format
  7. Apply compression/encoding
  8. Save to file

Troubleshooting

Common Issues

"Failed to setup desktop duplication"

  • Cause: Graphics driver issues or unsupported hardware
  • Solution: Update graphics drivers, ensure DirectX 11 support

"Invalid base path"

  • Cause: Path doesn't exist or no write permissions
  • Solution: Use CheckPath() first, ensure path is absolute

"Already running"

  • Cause: Previous capture still in progress
  • Solution: Wait for completion or call Cancel()

Large File Sizes

  • Solution: Use DDS format with BC compression or JPEG with lower quality

Slow Capture Performance

  • Solution:
    • Enable parallel compression in config
    • Use faster compression modes (bc1, bc7_fast)
    • Reduce GIF duration

Debug Steps

  1. Set LogLevel=5 for maximum verbosity
  2. Check log file for detailed error messages
  3. Verify path permissions with CheckPath()
  4. Test with simple PNG format first
  5. Monitor system resources during capture

Performance Optimization

Recommended Settings by Use Case

Fast Capture (Real-time)

[Performance] ParallelCompression=1 CompressionThreads=0 ; Use in Papyrus: imageType = "bmp" ; or "bc1" for compressed

High Quality Archive

[Performance] ParallelCompression=1 ; Use in Papyrus: imageType = "png" ; or "bc7_slow" for DDS

Small File Size

; Use in Papyrus: imageType = "jpg" jpgCompression = 85.0 ; or "bc3" for DDS

Performance Tips

  1. Pre-validate paths during initialization, not during capture
  2. Use appropriate formats - BMP for speed, DDS for size
  3. Limit GIF duration - Longer GIFs consume more memory
  4. Monitor thread count - Too many threads can cause contention
  5. Disable unnecessary logging in production (LogLevel=1)

Compression Performance (Typical 1920x1080)

  • BMP: <50ms (no compression)
  • PNG: 200-400ms
  • JPEG: 100-200ms
  • BC1: 150-250ms (parallel)
  • BC7 Fast: 300-500ms (parallel)
  • BC7 Slow: 1000-3000ms (parallel)

Version: 2.0.0
Author: William G Lea
License: See LICENSE file
Support: Check Nexus Mods page for updates and community support