Pixel Density and High-DPI Displays

Image Scaling and DPI

If I'm loading images for my game, do I need different versions for different DPI settings?

Abstract art representing computer programming

The decision to provide multiple image versions depends on your specific needs. Let's explore the options and their implications:

Single Image Approach

The simplest approach is to provide a single high-resolution image and scale it down when needed:

#include <SDL.h>
#include <SDL_image.h>
#include <iostream>

float GetDPIScale(SDL_Window* Window) {/*...*/} class Sprite { SDL_Surface* Image; int BaseWidth; int BaseHeight; public: Sprite(const char* Path) { Image = IMG_Load(Path); BaseWidth = Image->w; BaseHeight = Image->h; } void Draw(SDL_Surface* Target, int x, int y, float Scale ) { SDL_Rect Dest{ x, y, int(BaseWidth * Scale), int(BaseHeight * Scale) }; SDL_BlitScaled(Image, nullptr, Target, &Dest); } ~Sprite() { SDL_FreeSurface(Image); } };

This approach is simple but has drawbacks:

  • Scaling down loses detail in a controlled way
  • Scaling up can look blurry
  • Memory usage is always at maximum resolution

Multiple Resolution Support

For better quality, you can provide multiple resolutions:

class MultiResSprite {
  std::vector<SDL_Surface*> Images;
  std::vector<float> Scales{
    1.0f, 1.5f, 2.0f, 4.0f};
  int BaseWidth;
  int BaseHeight;

public:
  MultiResSprite(
    const std::vector<const char*>& Paths) {
    for (auto Path : Paths) {
      Images.push_back(IMG_Load(Path));
    }
    BaseWidth = Images[0]->w;
    BaseHeight = Images[0]->h;
  }

  void Draw(
    SDL_Surface* Target,
    int x, int y, float Scale
  ) {
    // Find best matching image
    size_t Best{0};
    float BestDiff{std::abs(Scales[0] - Scale)};

    for (size_t i = 1; i < Scales.size(); ++i) {
      float Diff{std::abs(Scales[i] - Scale)};
      if (Diff < BestDiff) {
        Best = i;
        BestDiff = Diff;
      }
    }

    SDL_Rect Dest{
      x, y,
      int(BaseWidth * Scale),
      int(BaseHeight * Scale)
    };
    SDL_BlitScaled(
      Images[Best], nullptr, Target, &Dest);
  }

  ~MultiResSprite() {
    for (auto Image : Images) {
      SDL_FreeSurface(Image);
    }
  }
};

Recommendations

The best approach depends on your game:

  • For pixel art games, use a single resolution and integer scaling
  • For modern games, provide 2-3 resolutions (1x, 2x, 4x)
  • Consider memory constraints on your target platforms
  • Test with different DPI scales to ensure quality
This Question is from the Lesson:

Pixel Density and High-DPI Displays

Learn how to create SDL applications that look great on modern displays across different platforms

Answers to questions are automatically generated and may not have been reviewed.

This Question is from the Lesson:

Pixel Density and High-DPI Displays

Learn how to create SDL applications that look great on modern displays across different platforms

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

This course includes:

  • 128 Lessons
  • 92% Positive Reviews
  • Regularly Updated
  • Help and FAQs
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

View Course
Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2025 - All Rights Reserved