Building a Versatile Image Class

Rendering to SDL_Renderer

How can we modify the Image class to support rendering to a specific SDL_Renderer instead of an SDL_Surface?

Abstract art representing computer programming

Modifying our Image class to support rendering to an SDL_Renderer instead of an SDL_Surface is a great way to take advantage of hardware acceleration and improve performance.

This change will require significant modifications to our class, as we'll need to use textures instead of surfaces. Here's how we can implement this:

First, let's update our class to use SDL_Texture instead of SDL_Surface:

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

class Image {
public:
  Image(SDL_Renderer* Renderer,
    const std::string& File,
    const SDL_Rect& SourceRect,
    const SDL_Rect& DestRect,
    ScalingMode ScalingMode = ScalingMode::None);

  void Render(SDL_Renderer* Renderer);
// ... other methods ...

  ~Image();

private:
  SDL_Texture* mImageTexture{nullptr};
  SDL_Renderer* mRenderer{nullptr};
// ... other members ...

  void LoadFile(SDL_Renderer* Renderer,
    const std::string& File);
};

Now, let's update our constructor and LoadFile method:

Image::Image(SDL_Renderer* Renderer,
  const std::string& File,
  const SDL_Rect& SourceRect,
  const SDL_Rect& DestRect,
  ScalingMode ScalingMode)
  : mRenderer(Renderer), mScalingMode(ScalingMode) {
  LoadFile(Renderer, File);
  SetSourceRectangle(SourceRect);
  SetDestinationRectangle(DestRect);
}

void Image::LoadFile(SDL_Renderer* Renderer,
  const std::string& File) {
  if (File == mFile) { return; }

  SDL_DestroyTexture(mImageTexture);
  mFile = File;
  mImageTexture = IMG_LoadTexture(Renderer, File.c_str());

  if (!mImageTexture) {
    std::cerr << "Failed to load texture: "
      << IMG_GetError() << '\n';
  }

// Update texture size
  SDL_QueryTexture(mImageTexture, nullptr, nullptr,
    &mTextureWidth, &mTextureHeight);
}

Update the Render method to use SDL_RenderCopy or SDL_RenderCopyEx:

void Image::Render(SDL_Renderer* Renderer) {
  SDL_Rect SrcRect = mAppliedSrcRectangle;
  SDL_Rect DestRect = mAppliedDestRectangle;

  if (mScalingMode == ScalingMode::Cover) {
// ... (Cover logic remains the same)
  }

  SDL_RenderCopyEx(Renderer, mImageTexture,
    &SrcRect, &DestRect,
    mRotationAngle, nullptr, mFlip);
}

We'll need to update our ValidateRectangle method to work with textures:

bool Image::ValidateRectangle(
  const SDL_Rect& Rect,
  const SDL_Texture* Texture,
  const std::string& Context) const {
  if (SDL_RectEmpty(&Rect)) {
    std::cerr << "[ERROR] " << Context
      << ": Rectangle has no area\n";
    return false;
  }
  if (Texture &&
    !RectangleWithinTexture(Rect, Texture)) {
    std::cerr << "[ERROR] " << Context
      << ": Rectangle not within target texture\n";
    return false;
  }
  return true;
}

bool Image::RectangleWithinTexture(
  const SDL_Rect& Rect,
  const SDL_Texture* Texture) const {
  int w, h;
  SDL_QueryTexture(
    const_cast<SDL_Texture*>(Texture),
    nullptr, nullptr, &w, &h);
  return Rect.x >= 0 && Rect.y >= 0 &&
    Rect.x + Rect.w <= w &&
    Rect.y + Rect.h <= h;
}

Update the destructor:

Image::~Image() {
  SDL_DestroyTexture(mImageTexture);
}

With these changes, our Image class now supports rendering to an SDL_Renderer. This allows us to take advantage of hardware acceleration and potentially improve performance.

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

3D art representing computer programming
Part of the course:

Building Minesweeper with C++ and SDL2

Apply what we learned to build an interactive, portfolio-ready capstone project using C++ and the SDL2 library

Free, unlimited access

This course includes:

  • 37 Lessons
  • 100+ Code Samples
  • 92% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

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

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