Permalink
Browse files

Copy pixel arrays instead of iterating.

More speed, more!
  • Loading branch information...
SupSuper committed Sep 27, 2018
1 parent 490d964 commit 61ba9615cdacad46c64e4f2dc0705f8498329274
Showing with 82 additions and 24 deletions.
  1. +56 −21 src/Engine/Surface.cpp
  2. +26 −3 src/Engine/Surface.h
@@ -20,6 +20,7 @@
#include "ShaderDraw.h"
#include <vector>
#include <fstream>
#include <algorithm>
#include <SDL_gfxPrimitives.h>
#include <SDL_image.h>
#include <SDL_endian.h>
@@ -211,6 +212,56 @@ Surface::~Surface()
SDL_FreeSurface(_surface);
}
/**
* Performs a fast copy of a pixel array, accounting for pitch.
* @param src Source array.
*/
template <typename T>
void Surface::rawCopy(const std::vector<T> &src)
{
// Copy whole thing
if (_surface->pitch == _surface->w)
{
std::copy(src.begin(), src.end(), (T*)_surface->pixels);
}
// Copy row by row
else
{
for (int y = 0; y < _surface->h; ++y)
{
size_t begin = y * _surface->w;
size_t end = std::min(begin + _surface->w, src.size());
if (begin >= src.size())
break;
std::copy(src.begin() + begin, src.begin() + end, (T*)getRaw(0, y));
}
}
}
/**
* Loads a raw array of pixels into the surface. The pixels must be
* in the same BPP as the surface.
* @param bytes Pixel array.
*/
void Surface::loadRaw(const std::vector<unsigned char> &bytes)
{
lock();
rawCopy(bytes);
unlock();
}
/**
* Loads a raw array of pixels into the surface. The pixels must be
* in the same BPP as the surface.
* @param bytes Pixel array.
*/
void Surface::loadRaw(const std::vector<char> &bytes)
{
lock();
rawCopy(bytes);
unlock();
}
/**
* Loads the contents of an X-Com SCR image file into
* the surface. SCR files are simply uncompressed images
@@ -228,19 +279,7 @@ void Surface::loadScr(const std::string &filename)
}
std::vector<char> buffer((std::istreambuf_iterator<char>(imgFile)), (std::istreambuf_iterator<char>()));
// Lock the surface
lock();
int x = 0, y = 0;
for (std::vector<char>::iterator i = buffer.begin(); i != buffer.end(); ++i)
{
setPixelIterative(&x, &y, *i);
}
// Unlock the surface
unlock();
loadRaw(buffer);
}
/**
@@ -280,11 +319,7 @@ void Surface::loadImage(const std::string &filename)
_surface = SDL_CreateRGBSurfaceFrom(_alignedBuffer, width, height, bpp, GetPitch(bpp, width), 0, 0, 0, 0);
if (_surface)
{
int x = 0, y = 0;
for (std::vector<unsigned char>::const_iterator i = image.begin(); i != image.end(); ++i)
{
setPixelIterative(&x, &y, *i);
}
loadRaw(image);
setPalette((SDL_Color*)color->palette, 0, color->palettesize);
int transparent = 0;
for (int c = 0; c < _surface->format->palette->ncolors; ++c)
@@ -406,8 +441,9 @@ void Surface::loadBdy(const std::string &filename)
currentRow = y;
for (int i = 0; i < pixelCnt; ++i)
{
if (currentRow == y) // avoid overscan into next row
setPixelIterative(&x, &y, dataByte);
setPixelIterative(&x, &y, dataByte);
if (currentRow != y) // avoid overscan into next row
break;
}
}
else
@@ -429,7 +465,6 @@ void Surface::loadBdy(const std::string &filename)
imgFile.close();
}
/**
* Clears the entire contents of the surface, resulting
* in a blank image of the specified color. (0 for transparent)
@@ -19,6 +19,7 @@
*/
#include <SDL.h>
#include <string>
#include <vector>
#include "GraphSubset.h"
namespace OpenXcom
@@ -44,6 +45,10 @@ class Surface
void *_alignedBuffer;
std::string _tooltip;
/// Copies raw pixels.
template <typename T>
void rawCopy(const std::vector<T> &bytes);
/// Resizes the surface.
void resize(int width, int height);
public:
/// Creates a new surface with the specified size and position.
@@ -52,6 +57,10 @@ class Surface
Surface(const Surface& other);
/// Cleans up the surface.
virtual ~Surface();
/// Loads a raw pixel array.
void loadRaw(const std::vector<unsigned char> &bytes);
/// Loads a raw pixel array.
void loadRaw(const std::vector<char> &bytes);
/// Loads an X-Com SCR graphic.
void loadScr(const std::string &filename);
/// Loads an X-Com SPK graphic.
@@ -143,12 +152,12 @@ class Surface
{
return;
}
((Uint8 *)_surface->pixels)[y * _surface->pitch + x * _surface->format->BytesPerPixel] = pixel;
*getRaw(x, y) = pixel;
}
/**
* Changes the color of a pixel in the surface and returns the
* next pixel position. Useful when changing a lot of pixels in
* a row, eg. loading images.
* a row, eg. manipulating images.
* @param x Pointer to the X position of the pixel. Changed to the next X position in the sequence.
* @param y Pointer to the Y position of the pixel. Changed to the next Y position in the sequence.
* @param pixel New color for the pixel.
@@ -175,7 +184,21 @@ class Surface
{
return 0;
}
return ((Uint8 *)_surface->pixels)[y * _surface->pitch + x * _surface->format->BytesPerPixel];
return *getRaw(x, y);
}
/**
* Returns the pointer to a specified pixel in the surface.
* @param x X position of the pixel.
* @param y Y position of the pixel.
* @return Pointer to the pixel.
*/
Uint8 *getRaw(int x, int y) const
{
if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())
{
return 0;
}
return (Uint8 *)_surface->pixels + (y * _surface->pitch + x * _surface->format->BytesPerPixel);
}
/**
* Returns the internal SDL_Surface for SDL calls.

0 comments on commit 61ba961

Please sign in to comment.