TLIGHT_PRODUCTS / WS281X
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PixelBuffer.cpp Source File

PixelBuffer.cpp

00001 /* PixelBuffer.cpp
00002  * mbed Microcontroller Library
00003  * Copyright (c) 2016 muetch, t.kuroki
00004  * Allrights reserved.
00005  *
00006  * Rev 0.97 2016-09-07
00007  * Rev 0.98 2016-09-08
00008  */
00009 #include "PixelBuffer.h"
00010 
00011 #define USE_MALLOC          1   // 0:new, 1:malloc
00012 
00013 //----------------------------------------------------------------------------
00014 // 指定されたバッファの先頭からblock_size分をbuf_sizeが満杯になるまで繰り返しコピーする
00015 template <class T>
00016 static void repeat_buffer(T *buffer, int buf_size, int block_size = 1)
00017 {
00018     if (buffer && block_size > 0 && (uint16_t)block_size < buf_size)
00019     {
00020         T *dest = buffer + block_size;
00021         int left = buf_size - block_size;
00022         while (left > block_size)
00023         {
00024             memcpy(dest, buffer, block_size * sizeof(T));
00025             dest += block_size;
00026             left -= block_size;
00027             block_size <<= 1;       // 次回は2倍のサイズの転送
00028         }
00029         memcpy(dest, buffer, left * sizeof(T));
00030     }
00031 }
00032 
00033 //----------------------------------------------------------------------------
00034 RGBPixels::RGBPixels(RGBColor *buffer, int maxPixels)
00035     : _owned_buffer(false)
00036 {
00037     _dummy_pixel = 0;
00038     setPixelBuffer(buffer, maxPixels);
00039 }
00040 
00041 RGBPixels::RGBPixels(int maxPixels)
00042     : _owned_buffer(false)
00043 {
00044     _dummy_pixel = 0;
00045     setPixelBuffer(nullptr, maxPixels);
00046 }
00047 
00048 RGBPixels::~RGBPixels()
00049 {
00050     setPixelBuffer(0, 0);
00051 }
00052 
00053 void RGBPixels::setPixelBuffer(RGBColor *buffer, int maxPixels)
00054 {
00055     if (_owned_buffer && _pixels)
00056     {
00057 #if USE_MALLOC
00058         free(_pixels);
00059 #else
00060         delete[] _pixels;
00061 #endif
00062     }
00063     _owned_buffer = false;
00064     _max_pixels = (maxPixels < 0) ? 0 : (maxPixels > MAX_PIXELS) ? MAX_PIXELS : maxPixels;
00065     _pixels = (!_max_pixels) ? NULL : buffer;
00066 
00067     if (!_pixels && _max_pixels > 0)
00068     {
00069 #if USE_MALLOC
00070         _pixels = static_cast<RGBColor*>(malloc(sizeof(RGBColor)*_max_pixels));
00071         if (_pixels)
00072             _owned_buffer = true;
00073         else
00074             _max_pixels = 0;
00075 #else
00076         _pixels = new RGBColor[_max_pixels];
00077         _owned_buffer = true;
00078 #endif
00079     }
00080     _num_pixels = _max_pixels;
00081     clear();
00082 }
00083 
00084 int RGBPixels::numPixels(int value)
00085 {
00086     if (value >= 0)
00087         _num_pixels = (value > _max_pixels) ? _max_pixels : value;
00088     return _num_pixels;
00089 }
00090 
00091 // 指定位置のピクセルへ色配列を指定サイズ分をコピーする
00092 void RGBPixels::setPixels(int index, RGBColor *color, int len)
00093 {
00094     int numPixels = static_cast<int>(_num_pixels);
00095     if (_pixels && len > 0 && index < numPixels && (index + len) > 0)
00096     {
00097         if (index < 0)
00098         {
00099             len   += index;
00100             color -= index;         // <- color += -index;
00101             index  = 0;
00102         }
00103         if (index + len > numPixels)
00104             len = numPixels - index;
00105         memcpy(&_pixels[index], color, len * sizeof(_pixels[0]));
00106     }
00107 }
00108 
00109 void RGBPixels::setPixels(int index, HSVColor *color, int len)
00110 {
00111     int numPixels = static_cast<int>(_num_pixels);
00112     if (_pixels && len > 0 && index < numPixels && (index + len) > 0)
00113     {
00114         if (index < 0)
00115         {
00116             len   += index;
00117             color -= index;
00118             index  = 0;
00119         }
00120         if (index + len > numPixels)
00121             len = numPixels - index;
00122         RGBColor *dest = &_pixels[index];
00123         do
00124         {
00125             *dest++ = *color++;
00126         } while (--len);
00127     }
00128 }
00129 
00130 void RGBPixels::setGammaPixels(int index, RGBColor *color, int len)
00131 {
00132     int numPixels = static_cast<int>(_num_pixels);
00133     if (_pixels && len > 0 && index < numPixels && (index + len) > 0)
00134     {
00135         if (index < 0)
00136         {
00137             len   += index;
00138             color -= index;
00139             index  = 0;
00140         }
00141         if (index + len > numPixels)
00142             len = numPixels - index;
00143         uint8_t *dst = reinterpret_cast<uint8_t *>(&_pixels[index]);
00144         uint8_t *src = reinterpret_cast<uint8_t *>(color);
00145         const uint8_t *gammatab = GetGammaTable();
00146         len *= 3;
00147         do
00148         {
00149             *dst++ = gammatab[*src++];
00150         } while (--len);
00151     }
00152 }
00153 
00154 void RGBPixels::setGammaPixels(int index, HSVColor *color, int len)
00155 {
00156     int numPixels = static_cast<int>(_num_pixels);
00157     if (_pixels && len > 0 && index < numPixels && (index + len) > 0)
00158     {
00159         if (index < 0)
00160         {
00161             len   += index;
00162             color -= index;
00163             index  = 0;
00164         }
00165         if (index + len > numPixels)
00166             len = numPixels - index;
00167         uint8_t *dst = reinterpret_cast<uint8_t *>(&_pixels[index]);
00168         const uint8_t *gammatab = GetGammaTable();
00169         do
00170         {
00171             RGBColor col = *color++;
00172             *dst++ = gammatab[col.r];
00173             *dst++ = gammatab[col.g];
00174             *dst++ = gammatab[col.b];
00175         } while (--len);
00176     }
00177 }
00178 
00179 // 指定色を指定位置のピクセルから指定サイズ分書き込む
00180 void RGBPixels::fillPixels(int index, const RGBColor color, int len)
00181 {
00182     int numPixels = static_cast<int>(_num_pixels);
00183     if (_pixels && len > 0 && index < numPixels && (index + len) > 0)
00184     {
00185         if (index < 0)
00186         {
00187             len   += index;
00188             index  = 0;
00189         }
00190         if (index + len > numPixels)
00191             len = numPixels - index;
00192         _pixels[index] = color;
00193         repeat_buffer<RGBColor>(_pixels + index, len, 1);
00194     }
00195 }
00196 
00197 void RGBPixels::fillPixels(int index, const HSVColor color, int len)
00198 {
00199     fillPixels(index, RGBColor(color), len);
00200 }
00201 
00202 // 先頭から指定サイズ分のブロックをバッファの最後までコピーする
00203 void RGBPixels::repeatPixels(int block_size)
00204 {
00205     if (_pixels && block_size > 0 && block_size < _num_pixels)
00206     {
00207         repeat_buffer<RGBColor>(_pixels, _num_pixels, block_size);
00208     }
00209 }
00210 
00211 void RGBPixels::repeatPixels(RGBColor *source, int size)
00212 {
00213     if (_pixels && source && size > 0)
00214     {
00215         if (size > _num_pixels)
00216             size = _num_pixels;
00217         memcpy(_pixels, source, size * sizeof(_pixels[0]));
00218         repeat_buffer<RGBColor>(_pixels, _num_pixels, size);
00219     }
00220 }
00221 
00222 void RGBPixels::repeatPixels(HSVColor *source, int size)
00223 {
00224     if (_pixels && source && size > 0)
00225     {
00226         if (size > _num_pixels)
00227             size = _num_pixels;
00228         for (int i = 0; i < size; ++i)
00229             _pixels[i] = *source++;
00230         repeat_buffer<RGBColor>(_pixels, _num_pixels, size);
00231     }
00232 }
00233 
00234 RGBPixels& RGBPixels::operator=(const RGBPixels& rhs)
00235 {
00236     if (!rhs._pixels || !rhs._max_pixels)
00237     {
00238         // 右辺が空の場合何もしない
00239         return *this;
00240     }
00241     if (!_pixels || !_max_pixels)
00242     {
00243         // 自分のバッファなしの場合、、新規確保
00244         setPixelBuffer(nullptr, rhs._max_pixels);
00245     }
00246 
00247     if (_pixels && _max_pixels)
00248     {
00249         _num_pixels = rhs._num_pixels;
00250         if (_num_pixels > rhs._max_pixels)
00251             _num_pixels = rhs._max_pixels;
00252         if (_num_pixels > _max_pixels)
00253             _num_pixels = _max_pixels;
00254         memcpy(_pixels, rhs._pixels, sizeof(_pixels[0]) * _num_pixels);
00255     }
00256 
00257     return *this;
00258 }
00259 
00260 //----------------------------------------------------------------------------
00261 void RGBPixels::makeGradation(int index, RGBColor from, RGBColor to, int len)
00262 {
00263     if (!_pixels || len < 1 || index >= _num_pixels || (index + len) <= 0)
00264         return;
00265 
00266     int end = len;
00267     if (index + end > _num_pixels)
00268         end = _num_pixels - index;
00269 
00270     RGBColor color;
00271     RGBColor *dest = _pixels;
00272     if (index > 0)
00273         dest += index;
00274     for (int i = (index < 0) ? -index : 0; i < end; ++i)
00275     {
00276         int j = len - i;
00277         color.red   = ((from.red   * j) + (to.red   * i)) / len;
00278         color.green = ((from.green * j) + (to.green * i)) / len;
00279         color.blue  = ((from.blue  * j) + (to.blue  * i)) / len;
00280         *dest++     = GammaColor(color);
00281     }
00282 }
00283 
00284 void RGBPixels::makeRainbow(int index, HSVColor color, int len, int direction)
00285 {
00286     if (!_pixels || len < 1 || index >= _num_pixels || (index + len) <= 0)
00287         return;
00288 
00289     int end = len;
00290     if (index + end > _num_pixels)
00291         end = _num_pixels - index;
00292 
00293     HSVColor hsv(color);
00294     RGBColor *dest = _pixels;
00295     if (index > 0)
00296         dest += index;
00297     direction = (direction >= 0) ? -3600 : 3600;
00298     for (int i = (index < 0) ? -index : 0; i < end; ++i)
00299     {
00300         hsv.hue = color.hue + direction * i / len;
00301         *dest++ = GammaColor(hsv);
00302     }
00303 }
00304 
00305 //----------------------------------------------------------------------------
00306 //----------------------------------------------------------------------------
00307 HSVPixels::HSVPixels(HSVColor *buffer, int maxPixels)
00308     : _owned_buffer(false)
00309 {
00310     _dummy_pixel = 0;
00311     setPixelBuffer(buffer, maxPixels);
00312 }
00313 
00314 HSVPixels::HSVPixels(int maxPixels)
00315     : _owned_buffer(false)
00316 {
00317     _dummy_pixel = 0;
00318     setPixelBuffer(nullptr, maxPixels);
00319 }
00320 
00321 HSVPixels::~HSVPixels()
00322 {
00323     setPixelBuffer(0, 0);
00324 }
00325 
00326 void HSVPixels::setPixelBuffer(HSVColor *buffer, int maxPixels)
00327 {
00328     if (_owned_buffer && _pixels)
00329     {
00330 #if USE_MALLOC
00331         free(_pixels);
00332 #else
00333         delete[] _pixels;
00334 #endif
00335     }
00336     _owned_buffer = false;
00337     _max_pixels = (maxPixels < 0) ? 0 : (maxPixels > MAX_PIXELS) ? MAX_PIXELS : maxPixels;
00338     _pixels = (!_max_pixels) ? NULL : buffer;
00339 
00340     if (!_pixels && _max_pixels > 0)
00341     {
00342 #if USE_MALLOC
00343         _pixels = static_cast<HSVColor*>(malloc(sizeof(HSVColor)*_max_pixels));
00344         if (_pixels)
00345             _owned_buffer = true;
00346         else
00347             _max_pixels = 0;
00348 #else
00349         _pixels = new HSVColor[_max_pixels];
00350         _owned_buffer = true;
00351 #endif
00352     }
00353     _num_pixels = _max_pixels;
00354     clear();
00355 }
00356 
00357 int HSVPixels::numPixels(int value)
00358 {
00359     if (value >= 0)
00360         _num_pixels = (value > _max_pixels) ? _max_pixels : value;
00361     return _num_pixels;
00362 }
00363 
00364 // 指定位置のピクセルへ色配列を指定サイズ分をコピーする
00365 void HSVPixels::setPixels(int index, HSVColor *color, int len)
00366 {
00367     int numPixels = static_cast<int>(_num_pixels);
00368     if (_pixels && len > 0 && index < numPixels && (index + len) > 0)
00369     {
00370         if (index < 0)
00371         {
00372             len   += index;
00373             color -= index;
00374             index  = 0;
00375         }
00376         if (index + len > numPixels)
00377             len = numPixels - index;
00378         memcpy(&_pixels[index], color, len * sizeof(_pixels[0]));
00379     }
00380 }
00381 
00382 void HSVPixels::setPixels(int index, RGBColor *color, int len)
00383 {
00384     int numPixels = static_cast<int>(_num_pixels);
00385     if (_pixels && len > 0 && index < numPixels && (index + len) > 0)
00386     {
00387         if (index < 0)
00388         {
00389             len   += index;
00390             color -= index;
00391             index  = 0;
00392         }
00393         if (index + len > numPixels)
00394             len = numPixels - index;
00395         HSVColor *dest = &_pixels[index];
00396         do
00397         {
00398             *dest++ = *color++;
00399         } while (--len);
00400     }
00401 }
00402 
00403 // 指定色を指定位置のピクセルから指定サイズ分書き込む
00404 void HSVPixels::fillPixels(int index, const HSVColor color, int len)
00405 {
00406     int numPixels = static_cast<int>(_num_pixels);
00407     if (_pixels && len > 0 && index < numPixels && (index + len) > 0)
00408     {
00409         if (index < 0)
00410         {
00411             len   += index;
00412             index  = 0;
00413         }
00414         if (index + len > numPixels)
00415             len = numPixels - index;
00416         _pixels[index] = color;
00417         repeat_buffer<HSVColor>(_pixels + index, len, 1);
00418     }
00419 }
00420 
00421 void HSVPixels::fillPixels(int index, const RGBColor color, int len)
00422 {
00423     fillPixels(index, HSVColor(color), len);
00424 }
00425 
00426 // 先頭から指定サイズ分のブロックをバッファの最後までコピーする
00427 void HSVPixels::repeatPixels(int block_size)
00428 {
00429     if (_pixels && block_size > 0 && block_size < _num_pixels)
00430     {
00431         repeat_buffer<HSVColor>(_pixels, _num_pixels, block_size);
00432     }
00433 }
00434 
00435 void HSVPixels::repeatPixels(HSVColor *source, int size)
00436 {
00437     if (_pixels && source && size > 0)
00438     {
00439         if (size > _num_pixels)
00440             size = _num_pixels;
00441         memcpy(_pixels, source, size * sizeof(_pixels[0]));
00442         repeat_buffer<HSVColor>(_pixels, _num_pixels, size);
00443     }
00444 }
00445 
00446 void HSVPixels::repeatPixels(RGBColor *source, int size)
00447 {
00448     if (_pixels && source && size > 0)
00449     {
00450         if (size > _num_pixels)
00451             size = _num_pixels;
00452         for (int i = 0; i < size; ++i)
00453             _pixels[i] = *source++;
00454         repeat_buffer<HSVColor>(_pixels, _num_pixels, size);
00455     }
00456 }
00457 
00458 HSVPixels& HSVPixels::operator=(const HSVPixels& rhs)
00459 {
00460     if (!rhs._pixels || !rhs._max_pixels)
00461     {
00462         // 右辺が空の場合何もしない
00463         return *this;
00464     }
00465     if (!_pixels || !_max_pixels)
00466     {
00467         // 自分のバッファなしの場合、、新規確保
00468         setPixelBuffer(nullptr, rhs._max_pixels);
00469     }
00470 
00471     if (_pixels && _max_pixels)
00472     {
00473         _num_pixels = rhs._num_pixels;
00474         if (_num_pixels > rhs._max_pixels)
00475             _num_pixels = rhs._max_pixels;
00476         if (_num_pixels > _max_pixels)
00477             _num_pixels = _max_pixels;
00478         memcpy(_pixels, rhs._pixels, sizeof(_pixels[0]) * _num_pixels);
00479     }
00480 
00481     return *this;
00482 }
00483 
00484 //----------------------------------------------------------------------------
00485 void HSVPixels::makeGradation(int index, HSVColor from, HSVColor to, int len)
00486 {
00487     if (!_pixels || len < 1 || index >= _num_pixels || (index + len) <= 0)
00488         return;
00489 
00490     int end = len;
00491     if (index + end > _num_pixels)
00492         end = _num_pixels - index;
00493 
00494     RGBColor rgb_from(from);
00495     RGBColor rgb_to(to);
00496     RGBColor color;
00497     HSVColor *dest = _pixels;
00498     if (index > 0)
00499         dest += index;
00500     for (int i = (index < 0) ? -index : 0; i < end; ++i)
00501     {
00502         int j = len - i;
00503         color.red   = ((rgb_from.red   * j) + (rgb_to.red   * i)) / len;
00504         color.green = ((rgb_from.green * j) + (rgb_to.green * i)) / len;
00505         color.blue  = ((rgb_from.blue  * j) + (rgb_to.blue  * i)) / len;
00506         *dest++     = GammaColor(color);
00507     }
00508 }
00509 
00510 void HSVPixels::makeRainbow(int index, HSVColor color, int len, int direction)
00511 {
00512     if (!_pixels || len < 1 || index >= _num_pixels || (index + len) <= 0)
00513         return;
00514 
00515     int end = len;
00516     if (index + end > _num_pixels)
00517         end = _num_pixels - index;
00518 
00519     HSVColor hsv(color);
00520     HSVColor *dest = _pixels;
00521     if (index > 0)
00522         dest += index;
00523     direction = (direction >= 0) ? -3600 : 3600;
00524     for (int i = (index < 0) ? -index : 0; i < end; ++i)
00525     {
00526         hsv.hue = color.hue + direction * i / len;
00527        *dest++ = GammaColor(hsv);
00528     }
00529 }
00530 
00531 //----------------------------------------------------------------------------