Skip to content

Commit

Permalink
Image: improve performance a bit when converting between pixel formats
Browse files Browse the repository at this point in the history
  • Loading branch information
pinkwah committed Jul 29, 2016
1 parent 777d28c commit 5034bbb
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 38 deletions.
77 changes: 49 additions & 28 deletions include/kex/gfx/Pixel
Expand Up @@ -192,32 +192,6 @@ namespace kex {
template <class T, class U>
struct pixel_iterator;

template <class T, class U>
struct pixel_iterator<const T, const U> {
pixel_iterator(const T *ptr):
mPtr(ptr)
{ copy_pixel(*ptr, mTmp); }

const U& operator*() const
{ return mTmp; }

const U* operator->() const
{ return &mTmp; }

pixel_iterator& operator++()
{
copy_pixel(*(++mPtr), mTmp);
return *this;
}

bool operator!=(const pixel_iterator &other) const
{ return mPtr != other.mPtr; }

private:
const T *mPtr;
U mTmp;
};

template <class T>
struct pixel_iterator<T, T> {
pixel_iterator(T *ptr):
Expand All @@ -244,6 +218,48 @@ namespace kex {
return *this;
}

pixel_iterator operator++(int)
{
pixel_iterator copy(*this);
++mPtr;
return copy;
}

pixel_iterator operator+(std::ptrdiff_t idx) const
{
return pixel_iterator(mPtr + idx);
}

pixel_iterator& operator+=(std::ptrdiff_t idx)
{
mPtr += idx;
return *this;
}

pixel_iterator& operator--()
{
--mPtr;
return *this;
}

pixel_iterator operator--(int)
{
pixel_iterator copy(*this);
--mPtr;
return copy;
}

pixel_iterator operator-(std::ptrdiff_t idx) const
{
return pixel_iterator(mPtr - idx);
}

pixel_iterator& operator-=(std::ptrdiff_t idx)
{
mPtr -= idx;
return *this;
}

private:
T *mPtr;
};
Expand Down Expand Up @@ -458,16 +474,21 @@ namespace kex {
uint8_t offset() const
{ return mOffset; }

auto color_ptr(uint8_t index) const noexcept
{
return &mColors[((index + mOffset) & mMask) * mTraits->bytes];
}

template <class T>
auto color(uint8_t index) const noexcept
{
T retval;
copy_pixel(mTraits->format, &mColors[((index + mOffset) & mMask) * mTraits->bytes], retval);
copy_pixel(mTraits->format, color_ptr(index), retval);
return retval;
}

template <class T, class U = T>
auto map()
auto map() const
{
if (static_pixel_traits<std::decay_t<T>>::format != mTraits->format)
throw bad_pixel_format();
Expand Down
7 changes: 3 additions & 4 deletions src/engine/renderer/r_sky.c
Expand Up @@ -666,10 +666,9 @@ void R_InitFire(void) {

paldata = Palette_GetData(Image_GetPalette(fireImage));
for(i = 0; i < 16; i++) {
paldata[i * 4 + 0] = 16 * i;
paldata[i * 4 + 1] = 16 * i;
paldata[i * 4 + 2] = 16 * i;
paldata[i * 4 + 3] = 0xff;
paldata[i * 3 + 0] = 16 * i;
paldata[i * 3 + 1] = 16 * i;
paldata[i * 3 + 2] = 16 * i;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/engine/system/i_png.c
Expand Up @@ -28,6 +28,7 @@
#include <math.h>
#include <kex/compat/gfx.h>
#include <w_wad.h>
#include <SDL_timer.h>

#include "doomdef.h"
#include "doomtype.h"
Expand Down
82 changes: 76 additions & 6 deletions src/kexlib/gfx/Image.cc
Expand Up @@ -69,20 +69,90 @@ namespace {
auto alloc_pixels(const pixel_traits *traits, uint16_t width, uint16_t height)
{ return std::make_unique<uint8_t[]>(calc_length(traits, width, height)); }

template <class SrcT, class DstT>
void tconvert2(const Image &src, Image &dst)
{
auto srcMap = src.map<SrcT>();
auto srcIt = srcMap.cbegin();
auto srcEnd = srcMap.cend();
auto dstIt = dst.map<DstT>().begin();

for (; srcIt != srcEnd; ++srcIt, ++dstIt)
copy_pixel(*srcIt, *dstIt);
};

template <class SrcT, class DstT>
void tconvertpal2(const Image &src, Image &dst)
{
auto srcMap = src.map<Index8>();
auto srcIt = srcMap.cbegin();
auto srcEnd = srcMap.cend();
auto srcPal = src.palette().map<SrcT>().cbegin();
auto dstIt = dst.map<DstT>().begin();

for (; srcIt != srcEnd; ++srcIt, ++dstIt)
copy_pixel(*(srcPal + srcIt->index), *dstIt);
};

template <class DstT>
void tconvertpal(const Image &src, Image &dst)
{
switch (src.palette().format())
{
case pixel_format::rgb:
tconvertpal2<Rgb, DstT>(src, dst);
break;

case pixel_format::bgr:
tconvertpal2<Bgr, DstT>(src, dst);
break;

case pixel_format::rgba:
tconvertpal2<Rgba, DstT>(src, dst);
break;

case pixel_format::bgra:
tconvertpal2<Bgra, DstT>(src, dst);
break;

default:
throw bad_pixel_format();
}
};

/*!
* \brief Templated image conversion. (the first 't' stands for 'template')
* \param src The source image
* \param dst The destination image
*/
template <class T>
template <class DstT>
void tconvert(const Image &src, Image &dst)
{
auto srcIt = src.auto_map<const T>().cbegin();
auto srcEndIt = src.auto_map<const T>().cend();
auto dstIt = dst.map<T>().begin();
switch (src.format())
{
case pixel_format::index8:
tconvertpal<DstT>(src, dst);
break;

case pixel_format::rgb:
tconvert2<Rgb, DstT>(src, dst);
break;

for (; srcIt != srcEndIt; ++srcIt, ++dstIt)
*dstIt = *srcIt;
case pixel_format::bgr:
tconvert2<Bgr, DstT>(src, dst);
break;

case pixel_format::rgba:
tconvert2<Rgba, DstT>(src, dst);
break;

case pixel_format::bgra:
tconvert2<Bgra, DstT>(src, dst);
break;

default:
throw bad_pixel_format();
}
}
}

Expand Down

0 comments on commit 5034bbb

Please sign in to comment.