TLIGHT_PRODUCTS / WS281X

PixelBuffer.cpp

Committer:
mutech
Date:
2016-09-06
Revision:
27:bc79f444883b
Child:
28:b452e097da53

File content as of revision 27:bc79f444883b:

/* PixelBuffer.cpp
 * mbed Microcontroller Library
 * Copyright (c) 2016 muetch, t.kuroki
 * Allrights reserved.
 *
 * Rev 0.97 2016-09-07
 */
#include "PixelBuffer.h"

//----------------------------------------------------------------------------
// 指定されたバッファの先頭からblock_size分をbuf_sizeが満杯になるまで繰り返しコピーする
template <class T>
static void repeat_buffer(T *buffer, int buf_size, int block_size = 1)
{
    if (buffer && block_size > 0 && (uint16_t)block_size < buf_size)
    {
        T *dest = buffer + block_size;
        int left = buf_size - block_size;
        while (left > block_size)
        {
            memcpy(dest, buffer, block_size * sizeof(T));
            dest += block_size;
            left -= block_size;
            block_size <<= 1;       // 次回は2倍のサイズの転送
        }
        memcpy(dest, buffer, left * sizeof(T));
    }
} 

//----------------------------------------------------------------------------
RGBPixels::RGBPixels(RGBColor *buffer, int maxPixels)
    : _buf_owner(false)
{
    _dummyPixel = 0;
    setPixelBuffer(buffer, maxPixels);
}

RGBPixels::RGBPixels(int maxPixels)
    : _buf_owner(false)
{
    _dummyPixel = 0;
    setPixelBuffer(nullptr, maxPixels);
}

RGBPixels::~RGBPixels()
{
    if (_buf_owner && _pixels)
        delete[] _pixels;
}

void RGBPixels::setPixelBuffer(RGBColor *buffer, int maxPixels)
{
    if (_buf_owner && _pixels)
        delete[] _pixels;

    _buf_owner = false;
    _pixels = buffer;

    _maxPixels = (maxPixels < 0) ? 0 : (maxPixels > MAX_PIXELS) ? MAX_PIXELS : maxPixels;
    if (!_pixels && _maxPixels > 0)
    {
        _pixels = new RGBColor[_maxPixels];
        _buf_owner = true;   
    }
    _numPixels = _maxPixels;
    clear();
}

int RGBPixels::numPixels(int value)
{
    if (value >= 0)
        _numPixels = (value > _maxPixels) ? _maxPixels : value;
    return _numPixels;
}

// 指定位置のピクセルへ色配列を指定サイズ分をコピーする
void RGBPixels::setPixels(int index, RGBColor *color, int len)
{
    if (_pixels && len > 0 && (uint16_t)index < _numPixels)
    {
        if (index + len > _numPixels)
            len = _numPixels - index;
        memcpy(&_pixels[index], color, len * sizeof(_pixels[0]));
    }
}

void RGBPixels::setPixels(int index, HSVColor *color, int len)
{
    if (_pixels && len > 0 && (uint16_t)index < _numPixels)
    {
        if (index + len > _numPixels)
            len = _numPixels - index;
        RGBColor *dest = &_pixels[index];
        do
        {
            *dest++ = *color++;
        } while (--len);
    }
}

// 指定色を指定位置のピクセルから指定サイズ分書き込む
void RGBPixels::fillPixels(const RGBColor color, int index, int len)
{
    if (_pixels && len > 0 && (uint16_t)index < _numPixels)
    {
        if (index + len > _numPixels)
            len = _numPixels - index;
        _pixels[index] = color;
        repeat_buffer<RGBColor>(_pixels + index, len, 1);
    }
}

void RGBPixels::fillPixels(const HSVColor color, int index, int len)
{
    fillPixels(RGBColor(color), index, len);
}

// 先頭から指定サイズ分のブロックをバッファの最後までコピーする
void RGBPixels::repeatPixels(int block_size)
{
    if (_pixels && block_size > 0 && block_size < _numPixels)
    {
        repeat_buffer<RGBColor>(_pixels, _numPixels, block_size);
    }
}

void RGBPixels::repeatPixels(RGBColor *source, int size)
{
    if (_pixels && source && size > 0)
    {
        if (size > _numPixels)
            size = _numPixels;
        memcpy(_pixels, source, size * sizeof(_pixels[0]));
        repeat_buffer<RGBColor>(_pixels, _numPixels, size);
    }
}

void RGBPixels::repeatPixels(HSVColor *source, int size)
{
    if (_pixels && source && size > 0)
    {
        if (size > _numPixels)
            size = _numPixels;
        for (int i = 0; i < size; ++i)
            _pixels[i] = *source++;
        repeat_buffer<RGBColor>(_pixels, _numPixels, size);
    }
}

RGBPixels& RGBPixels::operator=(const RGBPixels& rhs)
{
    if (!rhs._pixels || !rhs._maxPixels)
    {
        // 右辺が空の場合何もしない
        return *this;
    }
    if (!_pixels || !_maxPixels)
    {
        // 自分のバッファなしの場合、、新規確保
        setPixelBuffer(nullptr, rhs._maxPixels);
    }

    if (_pixels && _maxPixels)
    {
        _numPixels = rhs._numPixels;
        if (_numPixels > rhs._maxPixels)
            _numPixels = rhs._maxPixels;
        if (_numPixels > _maxPixels)
            _numPixels = _maxPixels;
        memcpy(_pixels, rhs._pixels, sizeof(_pixels[0]) * _numPixels);
    }

    return *this;
}

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
HSVPixels::HSVPixels(HSVColor *buffer, int maxPixels)
    : _buf_owner(false)
{
    _dummyPixel = 0;
    setPixelBuffer(buffer, maxPixels);
}

HSVPixels::HSVPixels(int maxPixels)
    : _buf_owner(false)
{
    _dummyPixel = 0;
    setPixelBuffer(nullptr, maxPixels);
}

HSVPixels::~HSVPixels()
{
    if (_buf_owner && _pixels)
        delete[] _pixels;
}

void HSVPixels::setPixelBuffer(HSVColor *buffer, int maxPixels)
{
    if (_buf_owner && _pixels)
        delete[] _pixels;

    _buf_owner = false;
    _pixels = buffer;

    _maxPixels = (maxPixels < 0) ? 0 : (maxPixels > MAX_PIXELS) ? MAX_PIXELS : maxPixels;
    if (!_pixels && _maxPixels > 0)
    {
        _pixels = new HSVColor[_maxPixels];
        _buf_owner = true;   
    }
    _numPixels = _maxPixels;
    clear();
}

int HSVPixels::numPixels(int value)
{
    if (value >= 0)
        _numPixels = (value > _maxPixels) ? _maxPixels : value;
    return _numPixels;
}

// 指定位置のピクセルへ色配列を指定サイズ分をコピーする
void HSVPixels::setPixels(int index, HSVColor *color, int len)
{
    if (_pixels && len > 0 && (uint16_t)index < _numPixels)
    {
        if (index + len > _numPixels)
            len = _numPixels - index;
        memcpy(&_pixels[index], color, len * sizeof(_pixels[0]));
    }
}

void HSVPixels::setPixels(int index, RGBColor *color, int len)
{
    if (_pixels && len > 0 && (uint16_t)index < _numPixels)
    {
        if (index + len > _numPixels)
            len = _numPixels - index;
        HSVColor *dest = &_pixels[index];
        do
        {
            *dest++ = *color++;
        } while (--len);
    }
}

// 指定色を指定位置のピクセルから指定サイズ分書き込む
void HSVPixels::fillPixels(const HSVColor color, int index, int len)
{
    if (_pixels && len > 0 && (uint16_t)index < _numPixels)
    {
        if (index + len > _numPixels)
            len = _numPixels - index;
        _pixels[index] = color;
        repeat_buffer<HSVColor>(_pixels + index, len, 1);
    }
}

void HSVPixels::fillPixels(const RGBColor color, int index, int len)
{
    fillPixels(HSVColor(color), index, len);
}

// 先頭から指定サイズ分のブロックをバッファの最後までコピーする
void HSVPixels::repeatPixels(int block_size)
{
    if (_pixels && block_size > 0 && block_size < _numPixels)
    {
        repeat_buffer<HSVColor>(_pixels, _numPixels, block_size);
    }
}

void HSVPixels::repeatPixels(HSVColor *source, int size)
{
    if (_pixels && source && size > 0)
    {
        if (size > _numPixels)
            size = _numPixels;
        memcpy(_pixels, source, size * sizeof(_pixels[0]));
        repeat_buffer<HSVColor>(_pixels, _numPixels, size);
    }
}

void HSVPixels::repeatPixels(RGBColor *source, int size)
{
    if (_pixels && source && size > 0)
    {
        if (size > _numPixels)
            size = _numPixels;
        for (int i = 0; i < size; ++i)
            _pixels[i] = *source++;
        repeat_buffer<HSVColor>(_pixels, _numPixels, size);
    }
}

HSVPixels& HSVPixels::operator=(const HSVPixels& rhs)
{
    if (!rhs._pixels || !rhs._maxPixels)
    {
        // 右辺が空の場合何もしない
        return *this;
    }
    if (!_pixels || !_maxPixels)
    {
        // 自分のバッファなしの場合、、新規確保
        setPixelBuffer(nullptr, rhs._maxPixels);
    }

    if (_pixels && _maxPixels)
    {
        _numPixels = rhs._numPixels;
        if (_numPixels > rhs._maxPixels)
            _numPixels = rhs._maxPixels;
        if (_numPixels > _maxPixels)
            _numPixels = _maxPixels;
        memcpy(_pixels, rhs._pixels, sizeof(_pixels[0]) * _numPixels);
    }

    return *this;
}

//----------------------------------------------------------------------------