Files
yaze/src/app/gfx/bitmap.cc
2022-09-12 21:17:41 -05:00

127 lines
4.0 KiB
C++

#include "bitmap.h"
#include <SDL.h>
#include <cstdint>
#include <memory>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "app/core/constants.h"
#include "app/gfx/snes_palette.h"
namespace yaze {
namespace app {
namespace gfx {
namespace {
void GrayscalePalette(SDL_Palette *palette) {
for (int i = 0; i < 8; i++) {
palette->colors[i].r = i * 31;
palette->colors[i].g = i * 31;
palette->colors[i].b = i * 31;
}
}
} // namespace
Bitmap::Bitmap(int width, int height, int depth, uchar *data) {
Create(width, height, depth, data);
}
Bitmap::Bitmap(int width, int height, int depth, int data_size) {
Create(width, height, depth, data_size);
}
Bitmap::Bitmap(int width, int height, int depth, uchar *data, int data_size) {
Create(width, height, depth, data, data_size);
}
// Pass raw pixel data directly to the surface
void Bitmap::Create(int width, int height, int depth, uchar *data) {
width_ = width;
height_ = height;
depth_ = depth;
pixel_data_ = data;
surface_ = std::unique_ptr<SDL_Surface, SDL_Surface_Deleter>(
SDL_CreateRGBSurfaceWithFormat(0, width_, height_, depth_,
SDL_PIXELFORMAT_INDEX8),
SDL_Surface_Deleter());
surface_->pixels = pixel_data_;
GrayscalePalette(surface_->format->palette);
}
// Reserves data to later draw to surface via pointer
void Bitmap::Create(int width, int height, int depth, int size) {
width_ = width;
height_ = height;
depth_ = depth;
data_size_ = size;
data_.reserve(size);
pixel_data_ = data_.data();
surface_ = std::unique_ptr<SDL_Surface, SDL_Surface_Deleter>(
SDL_CreateRGBSurfaceWithFormat(0, width, height, depth,
SDL_PIXELFORMAT_INDEX8),
SDL_Surface_Deleter());
surface_->pixels = pixel_data_;
GrayscalePalette(surface_->format->palette);
}
// Pass raw pixel data directly to the surface
void Bitmap::Create(int width, int height, int depth, uchar *data, int size) {
width_ = width;
height_ = height;
depth_ = depth;
pixel_data_ = data;
data_size_ = size;
surface_ = std::unique_ptr<SDL_Surface, SDL_Surface_Deleter>(
SDL_CreateRGBSurfaceWithFormat(0, width_, height_, depth_,
SDL_PIXELFORMAT_INDEX8),
SDL_Surface_Deleter());
surface_->pixels = pixel_data_;
GrayscalePalette(surface_->format->palette);
}
void Bitmap::Create(int width, int height, int depth, Bytes data) {
width_ = width;
height_ = height;
depth_ = depth;
data_ = data;
pixel_data_ = data_.data();
surface_ = std::unique_ptr<SDL_Surface, SDL_Surface_Deleter>(
SDL_CreateRGBSurfaceWithFormat(0, width_, height_, depth_,
SDL_PIXELFORMAT_INDEX8),
SDL_Surface_Deleter());
surface_->pixels = pixel_data_;
GrayscalePalette(surface_->format->palette);
}
// Creates the texture that will be displayed to the screen.
void Bitmap::CreateTexture(std::shared_ptr<SDL_Renderer> renderer) {
texture_ = std::shared_ptr<SDL_Texture>{
SDL_CreateTextureFromSurface(renderer.get(), surface_.get()),
SDL_Texture_Deleter{}};
}
// Convert SNESPalette to SDL_Palette for surface.
void Bitmap::ApplyPalette(const SNESPalette &palette) {
palette_ = palette;
for (int i = 0; i < palette.size_; ++i) {
if (palette.GetColor(i).transparent) {
surface_->format->palette->colors[i].r = 0;
surface_->format->palette->colors[i].g = 0;
surface_->format->palette->colors[i].b = 0;
surface_->format->palette->colors[i].a = 0;
} else {
surface_->format->palette->colors[i].r = palette.GetColor(i).rgb.x;
surface_->format->palette->colors[i].g = palette.GetColor(i).rgb.y;
surface_->format->palette->colors[i].b = palette.GetColor(i).rgb.z;
surface_->format->palette->colors[i].a = palette.GetColor(i).rgb.w;
}
}
}
} // namespace gfx
} // namespace app
} // namespace yaze