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-09-07
- Revision:
- 28:b452e097da53
- Parent:
- 27:bc79f444883b
- Child:
- 29:a362df191524
File content as of revision 28:b452e097da53:
/* 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"
//----------------------------------------------------------------------------
// 指定されたバッファの先頭から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(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(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;
}
//----------------------------------------------------------------------------
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)
: _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;
}
//----------------------------------------------------------------------------
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);
}
}
//----------------------------------------------------------------------------