Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
PixelBuffer.cpp
- Committer:
- mutech
- Date:
- 2016-11-04
- Revision:
- 35:dffa06d09fdc
- Parent:
- 34:5a141ed5d52a
- Child:
- 36:0fe7917a832a
File content as of revision 35:dffa06d09fdc:
/* PixelBuffer.cpp
* mbed Microcontroller Library
* Copyright (c) 2016 muetch, t.kuroki
* Allrights reserved.
*
* Rev 0.97 2016-09-07
* Rev 0.98 2016-09-08
*/
#include "PixelBuffer.h"
#define USE_MALLOC 1 // 0:new, 1:malloc
//----------------------------------------------------------------------------
// 指定されたバッファの先頭から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)
: _owned_buffer(false)
{
_dummyPixel = 0;
setPixelBuffer(buffer, maxPixels);
}
RGBPixels::RGBPixels(int maxPixels)
: _owned_buffer(false)
{
_dummyPixel = 0;
setPixelBuffer(nullptr, maxPixels);
}
RGBPixels::~RGBPixels()
{
setPixelBuffer(0, 0);
}
void RGBPixels::setPixelBuffer(RGBColor *buffer, int maxPixels)
{
if (_owned_buffer && _pixels)
{
#if USE_MALLOC
free(_pixels);
#else
delete[] _pixels;
#endif
}
_owned_buffer = false;
_maxPixels = (maxPixels < 0) ? 0 : (maxPixels > MAX_PIXELS) ? MAX_PIXELS : maxPixels;
_pixels = (!_maxPixels) ? NULL : buffer;
if (!_pixels && _maxPixels > 0)
{
#if USE_MALLOC
_pixels = static_cast<RGBColor*>(malloc(sizeof(RGBColor)*_maxPixels));
if (_pixels)
_owned_buffer = true;
else
_maxPixels = 0;
#else
_pixels = new RGBColor[_maxPixels];
_owned_buffer = true;
#endif
}
_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)
{
int numPixels = static_cast<int>(_numPixels);
if (_pixels && len > 0 && index < numPixels && (index + len) >= 0)
{
if (index < 0)
{
len += index;
color -= index;
index = 0;
}
if (index + len > numPixels)
len = numPixels - index;
memcpy(&_pixels[index], color, len * sizeof(_pixels[0]));
}
}
void RGBPixels::setPixels(int index, HSVColor *color, int len)
{
int numPixels = static_cast<int>(_numPixels);
if (_pixels && len > 0 && index < numPixels && (index + len) >= 0)
{
if (index < 0)
{
len += index;
color -= index;
index = 0;
}
if (index + len > numPixels)
len = numPixels - index;
RGBColor *dest = &_pixels[index];
do
{
*dest++ = *color++;
} while (--len);
}
}
// 指定色を指定位置のピクセルから指定サイズ分書き込む
void RGBPixels::fillPixels(int index, const RGBColor color, 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(int index, const HSVColor color, int len)
{
fillPixels(index, RGBColor(color), 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;
}
//----------------------------------------------------------------------------
void RGBPixels::makeGradation(int index, RGBColor from, RGBColor to, int len)
{
if (!_pixels || len < 1 || index >= _numPixels || (index + len) < 0)
return;
int end = len;
if (index + end > _numPixels)
end = _numPixels - index;
RGBColor color;
RGBColor *dest = _pixels;
if (index > 0)
dest += index;
for (int i = (index < 0) ? -index : 0; i < end; ++i)
{
int j = len - i;
color.red = ((from.red * j) + (to.red * i)) / len;
color.green = ((from.green * j) + (to.green * i)) / len;
color.blue = ((from.blue * j) + (to.blue * i)) / len;
*dest++ = GammaColor(color);
}
}
void RGBPixels::makeRainbow(int index, HSVColor color, int len, int direction)
{
if (!_pixels || len < 1 || index >= _numPixels || (index + len) < 0)
return;
int end = len;
if (index + end > _numPixels)
end = _numPixels - index;
HSVColor hsv(color);
RGBColor *dest = _pixels;
if (index > 0)
dest += index;
direction = (direction >= 0) ? -3600 : 3600;
for (int i = (index < 0) ? -index : 0; i < end; ++i)
{
hsv.hue = color.hue + direction * i / len;
*dest++ = GammaColor(hsv);
}
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
HSVPixels::HSVPixels(HSVColor *buffer, int maxPixels)
: _owned_buffer(false)
{
_dummyPixel = 0;
setPixelBuffer(buffer, maxPixels);
}
HSVPixels::HSVPixels(int maxPixels)
: _owned_buffer(false)
{
_dummyPixel = 0;
setPixelBuffer(nullptr, maxPixels);
}
HSVPixels::~HSVPixels()
{
setPixelBuffer(0, 0);
}
void HSVPixels::setPixelBuffer(HSVColor *buffer, int maxPixels)
{
if (_owned_buffer && _pixels)
{
#if USE_MALLOC
free(_pixels);
#else
delete[] _pixels;
#endif
}
_owned_buffer = false;
_maxPixels = (maxPixels < 0) ? 0 : (maxPixels > MAX_PIXELS) ? MAX_PIXELS : maxPixels;
_pixels = (!_maxPixels) ? NULL : buffer;
if (!_pixels && _maxPixels > 0)
{
#if USE_MALLOC
_pixels = static_cast<HSVColor*>(malloc(sizeof(HSVColor)*_maxPixels));
if (_pixels)
_owned_buffer = true;
else
_maxPixels = 0;
#else
_pixels = new HSVColor[_maxPixels];
_owned_buffer = true;
#endif
}
_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)
{
int numPixels = static_cast<int>(_numPixels);
if (_pixels && len > 0 && index < numPixels && (index + len) >= 0)
{
if (index < 0)
{
len += index;
color -= index;
index = 0;
}
if (index + len > numPixels)
len = numPixels - index;
memcpy(&_pixels[index], color, len * sizeof(_pixels[0]));
}
}
void HSVPixels::setPixels(int index, RGBColor *color, int len)
{
int numPixels = static_cast<int>(_numPixels);
if (_pixels && len > 0 && index < numPixels && (index + len) >= 0)
{
if (index < 0)
{
len += index;
color -= index;
index = 0;
}
if (index + len > numPixels)
len = numPixels - index;
HSVColor *dest = &_pixels[index];
do
{
*dest++ = *color++;
} while (--len);
}
}
// 指定色を指定位置のピクセルから指定サイズ分書き込む
void HSVPixels::fillPixels(int index, const HSVColor color, 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(int index, const RGBColor color, int len)
{
fillPixels(index, HSVColor(color), 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;
}
//----------------------------------------------------------------------------
void HSVPixels::makeGradation(int index, HSVColor from, HSVColor to, int len)
{
if (!_pixels || len < 1 || index >= _numPixels || (index + len) < 0)
return;
int end = len;
if (index + end > _numPixels)
end = _numPixels - index;
RGBColor rgb_from(from);
RGBColor rgb_to(to);
RGBColor color;
HSVColor *dest = _pixels;
if (index > 0)
dest += index;
for (int i = (index < 0) ? -index : 0; i < end; ++i)
{
int j = len - i;
color.red = ((rgb_from.red * j) + (rgb_to.red * i)) / len;
color.green = ((rgb_from.green * j) + (rgb_to.green * i)) / len;
color.blue = ((rgb_from.blue * j) + (rgb_to.blue * i)) / len;
*dest++ = GammaColor(color);
}
}
void HSVPixels::makeRainbow(int index, HSVColor color, int len, int direction)
{
if (!_pixels || len < 1 || index >= _numPixels || (index + len) < 0)
return;
int end = len;
if (index + end > _numPixels)
end = _numPixels - index;
HSVColor hsv(color);
HSVColor *dest = _pixels;
if (index > 0)
dest += index;
direction = (direction >= 0) ? -3600 : 3600;
for (int i = (index < 0) ? -index : 0; i < end; ++i)
{
hsv.hue = color.hue + direction * i / len;
*dest++ = GammaColor(hsv);
}
}
//----------------------------------------------------------------------------