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
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 //----------------------------------------------------------------------------
Generated on Thu Jul 14 2022 04:31:44 by
