framework2

Форк
0
1526 строк · 39.4 Кб
1
#include "ofGraphicsConstants.h"
2
#include "ofPixels.h"
3
#include "ofColor.h"
4

5
#define GLM_FORCE_CTOR_INIT
6
#include "glm/common.hpp"
7
#include <cstring>
8

9
static ofImageType getImageTypeFromChannels(size_t channels){
10
	switch(channels){
11
	case 1:
12
		return OF_IMAGE_GRAYSCALE;
13
	case 3:
14
		return OF_IMAGE_COLOR;
15
	case 4:
16
		return OF_IMAGE_COLOR_ALPHA;
17
	default:
18
		return OF_IMAGE_UNDEFINED;
19
	}
20
}
21

22
template<typename PixelType>
23
size_t ofPixels_<PixelType>::pixelBitsFromPixelFormat(ofPixelFormat format){
24
	switch(format){
25
		case OF_PIXELS_RGB:
26
		case OF_PIXELS_BGR:
27
			return 3 * sizeof(PixelType) * 8;
28

29
		case OF_PIXELS_RGBA:
30
		case OF_PIXELS_BGRA:
31
			return 4 * sizeof(PixelType) * 8;
32

33
		case OF_PIXELS_GRAY:
34
		case OF_PIXELS_Y:
35
		case OF_PIXELS_U:
36
		case OF_PIXELS_V:
37
			return 1 * sizeof(PixelType) * 8;
38

39
		case OF_PIXELS_NV12:
40
		case OF_PIXELS_NV21:
41
		case OF_PIXELS_YV12:
42
		case OF_PIXELS_I420:
43
			return 12;
44

45
		case OF_PIXELS_UV:
46
		case OF_PIXELS_VU:
47
		case OF_PIXELS_GRAY_ALPHA:
48
			return 2 * sizeof(PixelType) * 8;
49

50
		case OF_PIXELS_YUY2:
51
		case OF_PIXELS_UYVY:
52
		case OF_PIXELS_RGB565:
53
			return 16;
54
			break;
55
		default:
56
			return 0;
57
	}
58

59
}
60

61
template<>
62
std::string ofToString(const ofPixelFormat & p) {
63
	switch (p){
64
		case OF_PIXELS_GRAY:
65
			return "OF_PIXELS_GRAY";
66
		break;
67
		case OF_PIXELS_GRAY_ALPHA:
68
			return "OF_PIXELS_GRAY_ALPHA";
69
		break;
70
		case OF_PIXELS_RGB:
71
			return "OF_PIXELS_RGB";
72
		break;
73
		case OF_PIXELS_BGR:
74
			return "OF_PIXELS_BGR";
75
		break;
76
		case OF_PIXELS_RGBA:
77
			return "OF_PIXELS_RGBA";
78
		break;
79
		case OF_PIXELS_BGRA:
80
			return "OF_PIXELS_BGRA";
81
		break;
82
		case OF_PIXELS_RGB565:
83
			return "OF_PIXELS_RGB565";
84
		break;
85
		case OF_PIXELS_NV12:
86
			return "OF_PIXELS_NV12";
87
		break;
88
		case OF_PIXELS_NV21:
89
			return "OF_PIXELS_NV21";
90
		break;
91
		case OF_PIXELS_YV12:
92
			return "OF_PIXELS_YV12";
93
		break;
94
		case OF_PIXELS_I420:
95
			return "OF_PIXELS_I420";
96
		break;
97
		case OF_PIXELS_YUY2:
98
			return "OF_PIXELS_YUY2";
99
		break;
100
		case OF_PIXELS_UYVY:
101
			return "OF_PIXELS_UYVY";
102
		break;
103
		case OF_PIXELS_Y:
104
			return "OF_PIXELS_Y";
105
		break;
106
		case OF_PIXELS_U:
107
			return "OF_PIXELS_U";
108
		break;
109
		case OF_PIXELS_V:
110
			return "OF_PIXELS_V";
111
		break;
112
		case OF_PIXELS_UV:
113
			return "OF_PIXELS_UV";
114
		break;
115
		case OF_PIXELS_VU:
116
			return "OF_PIXELS_VU";
117
		break;
118
		case OF_PIXELS_NUM_FORMATS:
119
			return "OF_PIXELS_NUM_FORMATS";
120
		break;
121
		case OF_PIXELS_UNKNOWN:
122
			return "OF_PIXELS_UNKNOWN";
123
		break;
124
		case OF_PIXELS_NATIVE:
125
			return "OF_PIXELS_NATIVE";
126
		break;
127
	}
128
	return "OF_PIXELS_UNKNOWN";
129
}
130

131
template<typename PixelType>
132
size_t ofPixels_<PixelType>::bytesFromPixelFormat(size_t w, size_t h, ofPixelFormat format){
133
	return w * h * pixelBitsFromPixelFormat(format) / 8;
134
}
135

136
static size_t channelsFromPixelFormat(ofPixelFormat format){
137
	switch(format){
138
	case OF_PIXELS_RGB:
139
	case OF_PIXELS_BGR:
140
		return 3;
141
		break;
142
	case OF_PIXELS_RGBA:
143
	case OF_PIXELS_BGRA:
144
		return 4;
145
		break;
146
	case OF_PIXELS_GRAY:
147
		return 1;
148
		break;
149
	case OF_PIXELS_GRAY_ALPHA:
150
	case OF_PIXELS_RGB565:
151
		return 2;
152
		break;
153
	case OF_PIXELS_NV12:
154
	case OF_PIXELS_NV21:
155
	case OF_PIXELS_YV12:
156
	case OF_PIXELS_I420:
157
		return 1;
158
		break;
159
	case OF_PIXELS_YUY2:
160
	case OF_PIXELS_UYVY:
161
		return 2;
162
		break;
163
	case OF_PIXELS_Y:
164
	case OF_PIXELS_U:
165
	case OF_PIXELS_V:
166
		return 1;
167
		break;
168
	case OF_PIXELS_UV:
169
	case OF_PIXELS_VU:
170
		return 2;
171
		break;
172
	default:
173
		ofLog(OF_LOG_ERROR,"ofPixels: format doesn't support channels");
174
		return 1;
175
	}
176
}
177

178
static ofPixelFormat ofPixelFormatFromImageType(ofImageType type){
179
	switch(type){
180
	case OF_IMAGE_GRAYSCALE:
181
		return OF_PIXELS_GRAY;
182
		break;
183
	case OF_IMAGE_COLOR:
184
		return OF_PIXELS_RGB;
185
		break;
186
	case OF_IMAGE_COLOR_ALPHA:
187
		return OF_PIXELS_RGBA;
188
		break;
189
	default:
190
		ofLog(OF_LOG_ERROR,"ofPixels: image type not supported");
191
		return OF_PIXELS_UNKNOWN;
192
	}
193
}
194

195
static ofImageType ofImageTypeFromPixelFormat(ofPixelFormat pixelFormat){
196
	switch(pixelFormat){
197
	case OF_PIXELS_GRAY:
198
		return OF_IMAGE_GRAYSCALE;
199
		break;
200
	case OF_PIXELS_BGR:
201
	case OF_PIXELS_RGB:
202
	case OF_PIXELS_RGB565:
203
		return OF_IMAGE_COLOR;
204
		break;
205
	case OF_PIXELS_BGRA:
206
	case OF_PIXELS_RGBA:
207
		return OF_IMAGE_COLOR_ALPHA;
208
		break;
209
	case OF_PIXELS_UNKNOWN:
210
		return OF_IMAGE_UNDEFINED;
211
	default:
212
		ofLog(OF_LOG_ERROR,"ofPixels: image type not supported");
213
		return OF_IMAGE_UNDEFINED;
214
	}
215
}
216

217
std::string ofToString(ofPixelFormat pixelFormat){
218
	switch(pixelFormat){
219
		case OF_PIXELS_RGB:
220
			return "RGB";
221
		case OF_PIXELS_BGR:
222
			return "BGR";
223
		case OF_PIXELS_RGBA:
224
			return "RGBA";
225
		case OF_PIXELS_BGRA:
226
			return "BGRA";
227
		case OF_PIXELS_GRAY:
228
			return "GRAY";
229
		case OF_PIXELS_RGB565:
230
			return "RGB565";
231
		case OF_PIXELS_NV12:
232
			return "NV12";
233
		case OF_PIXELS_NV21:
234
			return "NV21";
235
		case OF_PIXELS_YV12:
236
			return "YV12";
237
		case OF_PIXELS_I420:
238
			return "I420";
239
		case OF_PIXELS_YUY2:
240
			return "YUY2";
241
		case OF_PIXELS_UYVY:
242
			return "UYVY";
243
		default:
244
			return "UNKOWN";
245
	}
246
}
247

248
static ofPixelFormat pixelFormatFromNumChannels(size_t channels){
249
	switch(channels){
250
	case 1: return OF_PIXELS_GRAY;
251
	case 2: return OF_PIXELS_GRAY_ALPHA;
252
	case 3: return OF_PIXELS_RGB;
253
	case 4: return OF_PIXELS_RGBA;
254
	default: return OF_PIXELS_UNKNOWN;
255
	}
256
}
257

258
template<typename PixelType>
259
ofPixels_<PixelType>::ofPixels_(){}
260

261

262
template<typename PixelType>
263
ofPixels_<PixelType>::~ofPixels_(){
264
	clear();
265
}
266

267
template<typename PixelType>
268
ofPixels_<PixelType>::ofPixels_(const ofPixels_<PixelType> & mom){
269
	copyFrom( mom );
270
}
271

272
template<typename PixelType>
273
ofPixels_<PixelType>::ofPixels_(ofPixels_<PixelType> && mom)
274
:pixels(mom.pixels)
275
,width(mom.width)
276
,height(mom.height)
277
,pixelsSize(mom.pixelsSize)
278
,bAllocated(mom.bAllocated)
279
,pixelsOwner(mom.pixelsOwner)
280
,pixelFormat(mom.pixelFormat){
281
	mom.pixelsOwner = false;
282
}
283

284

285
template<typename PixelType>
286
void ofPixels_<PixelType>::swap(ofPixels_<PixelType> & pix){
287
	std::swap(pixels,pix.pixels);
288
	std::swap(width, pix.width);
289
	std::swap(height,pix.height);
290
	std::swap(pixelsSize,pix.pixelsSize);
291
	std::swap(bAllocated, pix.bAllocated);
292
	std::swap(pixelsOwner, pix.pixelsOwner);
293
	std::swap(pixelFormat,pix.pixelFormat);
294
}
295

296

297
template<typename PixelType>
298
ofPixels_<PixelType>& ofPixels_<PixelType>::operator=(const ofPixels_<PixelType> & mom){
299
	if(this==&mom) {
300
		return * this;
301
	}
302
	copyFrom( mom );
303
	return *this;
304
}
305

306
template<typename PixelType>
307
ofPixels_<PixelType>& ofPixels_<PixelType>::operator=(ofPixels_<PixelType> && mom){
308
	if(this==&mom) {
309
		return * this;
310
	}
311
	clear();
312
	pixels = mom.pixels;
313
	width = mom.width;
314
	height = mom.height;
315
	pixelsSize = mom.pixelsSize;
316
	bAllocated = mom.bAllocated;
317
	pixelsOwner = mom.pixelsOwner;
318
	pixelFormat = mom.pixelFormat;
319
	mom.pixelsOwner = false;
320
	return *this;
321
}
322

323
template<typename PixelType>
324
void ofPixels_<PixelType>::copyFrom(const ofPixels_<PixelType> & mom){
325
	if(mom.isAllocated()) {
326
		allocate(mom.getWidth(), mom.getHeight(), mom.getPixelFormat());
327
		memcpy(pixels, mom.getData(), getTotalBytes());
328
	}
329
}
330

331
template<typename PixelType>
332
void ofPixels_<PixelType>::set(PixelType val){
333
	iterator _end = end();
334
	for(iterator i=begin();i<_end;++i){
335
		*i = val;
336
	}
337
}
338

339
template<typename PixelType>
340
void ofPixels_<PixelType>::set(size_t channel,PixelType val){
341
	switch(pixelFormat){
342
		case OF_PIXELS_RGB:
343
		case OF_PIXELS_BGR:
344
		case OF_PIXELS_RGBA:
345
		case OF_PIXELS_BGRA:
346
		case OF_PIXELS_GRAY:
347
		case OF_PIXELS_GRAY_ALPHA:
348
		case OF_PIXELS_UV:
349
		case OF_PIXELS_VU:{
350
			for(auto pixel: getPixelsIter()){
351
				pixel[channel] = val;
352
			}
353
		}
354
		break;
355
		case OF_PIXELS_RGB565:
356
		case OF_PIXELS_NV12:
357
		case OF_PIXELS_NV21:
358
		case OF_PIXELS_YV12:
359
		case OF_PIXELS_I420:
360
		case OF_PIXELS_YUY2:
361
		case OF_PIXELS_UYVY:
362
		case OF_PIXELS_Y:
363
		case OF_PIXELS_U:
364
		case OF_PIXELS_V:
365
		case OF_PIXELS_UNKNOWN:
366
		default:
367
			ofLogWarning() << "setting channels not supported for " << ofToString(pixelFormat) << " format";
368
			break;
369
	}
370
}
371

372
template<typename PixelType>
373
void ofPixels_<PixelType>::setFromPixels(const PixelType * newPixels, size_t w, size_t h, size_t channels){
374
	allocate(w, h, channels);
375
	memcpy(pixels, newPixels, getTotalBytes());
376
}
377

378
template<typename PixelType>
379
void ofPixels_<PixelType>::setFromPixels(const PixelType * newPixels, size_t w, size_t h, ofImageType type){
380
	allocate(w,h,type);
381
	setFromPixels(newPixels,w,h,ofPixelFormatFromImageType(type));
382
}
383

384
template<typename PixelType>
385
void ofPixels_<PixelType>::setFromPixels(const PixelType * newPixels, size_t w, size_t h, ofPixelFormat format){
386
	allocate(w,h,format);
387
	memcpy(pixels, newPixels, getTotalBytes());
388
}
389

390

391
template<typename PixelType>
392
void ofPixels_<PixelType>::setFromExternalPixels(PixelType * newPixels, size_t w, size_t h, size_t channels){
393
	setFromExternalPixels(newPixels,w,h,pixelFormatFromNumChannels(channels));
394
}
395

396
template<typename PixelType>
397
void ofPixels_<PixelType>::setFromExternalPixels(PixelType * newPixels, size_t w, size_t h, ofPixelFormat _pixelFormat){
398
	clear();
399
	pixelFormat = _pixelFormat;
400
	width= w;
401
	height = h;
402

403
	pixelsSize = bytesFromPixelFormat(w,h,_pixelFormat) / sizeof(PixelType);
404

405
	pixels = newPixels;
406
	pixelsOwner = false;
407
	bAllocated = true;
408
}
409

410
template<typename PixelType>
411
void ofPixels_<PixelType>::setFromAlignedPixels(const PixelType * newPixels, size_t width, size_t height, size_t channels, size_t stride){
412
	setFromAlignedPixels(newPixels,width,height,pixelFormatFromNumChannels(channels),stride);
413
}
414

415
template<typename PixelType>
416
void ofPixels_<PixelType>::setFromAlignedPixels(const PixelType * newPixels, size_t width, size_t height, ofPixelFormat _pixelFormat, size_t stride) {
417
	size_t channels = channelsFromPixelFormat(_pixelFormat);
418
	if(channels==0) return;
419

420
	if(width*channels==stride){
421
		setFromPixels(newPixels,width,height,_pixelFormat);
422
		return;
423
	}
424
	allocate(width, height, _pixelFormat);
425
	size_t dstStride = width * pixelBitsFromPixelFormat(_pixelFormat)/8;
426
	const unsigned char* src = (unsigned char*) newPixels;
427
	unsigned char* dst =  (unsigned char*) pixels;
428
	for(size_t i = 0; i < height; i++) {
429
		memcpy(dst, src, dstStride);
430
		src += stride;
431
		dst += dstStride;
432
	}
433
}
434

435
template<typename PixelType>
436
void ofPixels_<PixelType>::setFromAlignedPixels(const PixelType * newPixels, size_t width, size_t height, ofPixelFormat _pixelFormat, std::vector<size_t> strides) {
437
	size_t channels = channelsFromPixelFormat(_pixelFormat);
438
	if(channels==0) return;
439

440
	switch(_pixelFormat){
441
	case OF_PIXELS_I420: {
442
		if(strides.size() != 3){
443
		ofLogError("ofPixels") << "number of planes for I420 should be 3";
444
		break;
445
		}
446

447
		if(width==strides[0] && width/2==strides[1] && width/2==strides[2]){
448
		setFromPixels(newPixels,width,height,_pixelFormat);
449
		return;
450
		}
451

452
		allocate(width, height, _pixelFormat);
453

454
		const unsigned char* src = (unsigned char*) newPixels;
455
		unsigned char* dst =  (unsigned char*) pixels;
456
		// Y Plane
457
		for(size_t i = 0; i < height; i++) {
458
		memcpy(dst, src, width);
459
		src += strides[0];
460
		dst += width;
461
		}
462
		// U Plane
463
		for(size_t i = 0; i < height /2; i++){
464
		memcpy(dst,src,width/2);
465
		src += strides[1];
466
		dst += width/2;
467
		}
468
		// V Plane
469
		for(size_t i = 0; i < height /2; i++){
470
		memcpy(dst,src,width/2);
471
		src += strides[2];
472
		dst += width/2;
473
		}
474
		break;
475
	}
476
	case OF_PIXELS_RGB:
477
	case OF_PIXELS_RGBA:
478
	case OF_PIXELS_GRAY:
479
	case OF_PIXELS_GRAY_ALPHA:
480
		setFromAlignedPixels(newPixels,width,height,_pixelFormat,strides[0]);
481
		return;
482
	default:
483
		ofLogError("ofPixels") << "setFromAlignedPixels with planes strides: pixel format not supported yet";
484
		break;
485
	}
486
	return;
487
}
488

489
template<typename PixelType>
490
PixelType * ofPixels_<PixelType>::getPixels(){
491
	return pixels;
492
}
493

494
template<typename PixelType>
495
const PixelType * ofPixels_<PixelType>::getPixels() const{
496
	return pixels;
497
}
498

499
template<typename PixelType>
500
PixelType * ofPixels_<PixelType>::getData(){
501
	return pixels;
502
}
503

504
template<typename PixelType>
505
const PixelType * ofPixels_<PixelType>::getData() const{
506
	return pixels;
507
}
508

509
template<typename PixelType>
510
void ofPixels_<PixelType>::allocate(size_t w, size_t h, size_t _channels){
511
	allocate(w,h,pixelFormatFromNumChannels(_channels));
512
}
513

514
template<typename PixelType>
515
void ofPixels_<PixelType>::allocate(size_t w, size_t h, ofPixelFormat format){
516
	if (w == 0 || h == 0 || format == OF_PIXELS_UNKNOWN) {
517
		return;
518
	}
519

520
	size_t newSize = bytesFromPixelFormat(w,h,format);
521
	size_t oldSize = getTotalBytes();
522
	//we check if we are already allocated at the right size
523
	if(bAllocated && newSize==oldSize){
524
		pixelFormat = format;
525
		width = w;
526
		height = h;
527
		return; //we don't need to allocate
528
	}
529

530
	//we do need to allocate, clear the data
531
	clear();
532

533
	pixelFormat	= format;
534
	width 		= w;
535
	height 		= h;
536

537
	pixelsSize = newSize / sizeof(PixelType);
538

539
	pixels = new PixelType[pixelsSize];
540
	bAllocated = true;
541
	pixelsOwner = true;
542
}
543

544
template<typename PixelType>
545
void ofPixels_<PixelType>::allocate(size_t w, size_t h, ofImageType type){
546
	allocate(w,h,ofPixelFormatFromImageType(type));
547
}
548

549
template<typename PixelType>
550
void ofPixels_<PixelType>::swapRgb(){
551
	switch(pixelFormat){
552
	case OF_PIXELS_RGB:
553
	case OF_PIXELS_BGR:
554
	case OF_PIXELS_RGBA:
555
	case OF_PIXELS_BGRA:{
556
		for(auto pixel: getPixelsIter()){
557
			std::swap(pixel[0],pixel[2]);
558
		}
559
	}
560
	break;
561
	default:
562
		ofLogWarning("ofPixels") << "rgb swap not supported for this pixel format";
563
		break;
564
	}
565
	switch(pixelFormat){
566
	case OF_PIXELS_RGB:
567
		pixelFormat = OF_PIXELS_BGR;
568
		break;
569
	case OF_PIXELS_BGR:
570
		pixelFormat = OF_PIXELS_RGB;
571
		break;
572
	case OF_PIXELS_RGBA:
573
		pixelFormat = OF_PIXELS_BGRA;
574
		break;
575
	case OF_PIXELS_BGRA:
576
		pixelFormat = OF_PIXELS_RGBA;
577
		break;
578
	default:
579
		break;
580
	}
581
}
582

583
template<typename PixelType>
584
void ofPixels_<PixelType>::clear(){
585
	if(pixels){
586
		if(pixelsOwner) delete[] pixels;
587
		pixels = nullptr;
588
	}
589

590
	width			= 0;
591
	height			= 0;
592
	pixelFormat		= OF_PIXELS_UNKNOWN;
593
	pixelsSize		= 0;
594
	bAllocated		= false;
595
}
596

597
template<typename PixelType>
598
size_t ofPixels_<PixelType>::getPixelIndex(size_t x, size_t y) const {
599
	if( !bAllocated ){
600
		return 0;
601
	}else{
602
		size_t pixelStride;
603
		switch(pixelFormat){
604
			case OF_PIXELS_RGB:
605
			case OF_PIXELS_BGR:
606
				pixelStride = 3;
607
				return ( x + y * width ) * pixelStride;
608
				break;
609
			case OF_PIXELS_RGBA:
610
			case OF_PIXELS_BGRA:
611
				pixelStride = 4;
612
				return ( x + y * width ) * pixelStride;
613
				break;
614
			case OF_PIXELS_GRAY:
615
			case OF_PIXELS_Y:
616
			case OF_PIXELS_U:
617
			case OF_PIXELS_V:
618
				pixelStride = 1;
619
				return ( x + y * width ) * pixelStride;
620
				break;
621
			case OF_PIXELS_GRAY_ALPHA:
622
			case OF_PIXELS_UV:
623
			case OF_PIXELS_VU:
624
			case OF_PIXELS_YUY2:
625
			case OF_PIXELS_UYVY:
626
				pixelStride = 2;
627
				return ( x + y * width ) * pixelStride;
628
				break;
629
			case OF_PIXELS_RGB565:
630
				pixelStride = 2;
631
				return ( x + y * width ) * pixelStride;
632
				break;
633
			case OF_PIXELS_NV12:
634
			case OF_PIXELS_YV12:
635
			case OF_PIXELS_I420:
636
			case OF_PIXELS_UNKNOWN:
637
			default:
638
				ofLogWarning() << "getting pixel index not supported for " << ofToString(pixelFormat) << " format";
639
				return 0;
640
				break;
641
		}
642
	}
643
}
644

645
template<typename PixelType>
646
ofColor_<PixelType> ofPixels_<PixelType>::getColor(size_t index) const {
647
	return (Pixel(pixels + index, getNumChannels(), pixelFormat)).getColor();
648
}
649

650
template<typename PixelType>
651
ofColor_<PixelType> ofPixels_<PixelType>::getColor(size_t x, size_t y) const {
652
	return getColor(getPixelIndex(x, y));
653
}
654

655
template<typename PixelType>
656
void ofPixels_<PixelType>::setColor(size_t index, const ofColor_<PixelType>& color) {
657

658
	switch(pixelFormat){
659
		case OF_PIXELS_RGB:
660
			pixels[index] = color.r;
661
			pixels[index+1] = color.g;
662
			pixels[index+2] = color.b;
663
			break;
664
		case OF_PIXELS_BGR:
665
			pixels[index] = color.b;
666
			pixels[index+1] = color.g;
667
			pixels[index+2] = color.r;
668
			break;
669
		case OF_PIXELS_RGBA:
670
			pixels[index] = color.r;
671
			pixels[index+1] = color.g;
672
			pixels[index+2] = color.b;
673
			pixels[index+3] = color.a;
674
			break;
675
		case OF_PIXELS_BGRA:
676
			pixels[index] = color.b;
677
			pixels[index+1] = color.g;
678
			pixels[index+2] = color.r;
679
			pixels[index+3] = color.a;
680
			break;
681
		case OF_PIXELS_GRAY:
682
			pixels[index] = color.getBrightness();
683
			break;
684
		case OF_PIXELS_GRAY_ALPHA:
685
			pixels[index] = color.getBrightness();
686
			pixels[index+1] = color.a;
687
			break;
688
		case OF_PIXELS_RGB565:
689
		case OF_PIXELS_NV12:
690
		case OF_PIXELS_NV21:
691
		case OF_PIXELS_YV12:
692
		case OF_PIXELS_I420:
693
		case OF_PIXELS_YUY2:
694
		case OF_PIXELS_UYVY:
695
		case OF_PIXELS_Y:
696
		case OF_PIXELS_U:
697
		case OF_PIXELS_V:
698
		case OF_PIXELS_UV:
699
		case OF_PIXELS_VU:
700
		case OF_PIXELS_UNKNOWN:
701
		default:
702
			ofLogWarning("ofPixels") << "setting color not supported yet for " << ofToString(pixelFormat) << " format";
703
			break;
704
	}
705
}
706

707
template<typename PixelType>
708
void ofPixels_<PixelType>::setColor(size_t x, size_t y, const ofColor_<PixelType>& color) {
709
	setColor(getPixelIndex(x, y), color);
710
}
711

712
template<typename PixelType>
713
void ofPixels_<PixelType>::setColor(const ofColor_<PixelType>& color) {
714
	switch(pixelFormat){
715
		case OF_PIXELS_RGB:{
716
			for(auto pixel: getPixelsIter()){
717
				pixel[0] = color.r;
718
				pixel[1] = color.g;
719
				pixel[2] = color.b;
720
			}
721
		}
722
		break;
723
		case OF_PIXELS_BGR:{
724
			for(auto pixel: getPixelsIter()){
725
				pixel[0] = color.b;
726
				pixel[1] = color.g;
727
				pixel[2] = color.r;
728
			}
729
		}
730
		break;
731
		case OF_PIXELS_RGBA:{
732
			for(auto pixel: getPixelsIter()){
733
				pixel[0] = color.r;
734
				pixel[1] = color.g;
735
				pixel[2] = color.b;
736
				pixel[3] = color.a;
737
			}
738
		}
739
		break;
740
		case OF_PIXELS_BGRA:{
741
			for(auto pixel: getPixelsIter()){
742
				pixel[0] = color.b;
743
				pixel[1] = color.g;
744
				pixel[2] = color.r;
745
				pixel[3] = color.a;
746
			}
747
		}
748
		break;
749
		case OF_PIXELS_GRAY:{
750
			PixelType b = color.getBrightness();
751
			for(iterator i=begin();i!=end();++i){
752
				*i = b;
753
			}
754
		}
755
		break;
756
		case OF_PIXELS_GRAY_ALPHA:{
757
			PixelType b = color.getBrightness();
758
			for(auto pixel: getPixelsIter()){
759
				pixel[0] = b;
760
				pixel[1] = color.a;
761
			}
762
		}
763
		break;
764
		case OF_PIXELS_RGB565:
765
		case OF_PIXELS_NV12:
766
		case OF_PIXELS_NV21:
767
		case OF_PIXELS_YV12:
768
		case OF_PIXELS_I420:
769
		case OF_PIXELS_YUY2:
770
		case OF_PIXELS_UYVY:
771
		case OF_PIXELS_Y:
772
		case OF_PIXELS_U:
773
		case OF_PIXELS_V:
774
		case OF_PIXELS_UV:
775
		case OF_PIXELS_VU:
776
		case OF_PIXELS_UNKNOWN:
777
		default:
778
			ofLogWarning("ofPixels") << "setting color not supported yet for " << ofToString(pixelFormat) << " format";
779
		break;
780
	}
781
}
782

783
template<typename PixelType>
784
PixelType & ofPixels_<PixelType>::operator[](size_t pos){
785
	return pixels[pos];
786
}
787

788
template<typename PixelType>
789
const PixelType & ofPixels_<PixelType>::operator[](size_t pos) const{
790
	return pixels[pos];
791
}
792

793
template<typename PixelType>
794
bool ofPixels_<PixelType>::isAllocated() const{
795
	return bAllocated;
796
}
797

798
template<typename PixelType>
799
size_t ofPixels_<PixelType>::getWidth() const{
800
	return width;
801
}
802

803
template<typename PixelType>
804
size_t ofPixels_<PixelType>::getHeight() const{
805
	return height;
806
}
807

808
template<typename PixelType>
809
size_t ofPixels_<PixelType>::getBytesPerPixel() const{
810
	return pixelBitsFromPixelFormat(pixelFormat)/8;
811
}
812

813
template<typename PixelType>
814
size_t ofPixels_<PixelType>::getBitsPerPixel() const{
815
	return pixelBitsFromPixelFormat(pixelFormat);
816
}
817

818
template<typename PixelType>
819
size_t ofPixels_<PixelType>::getBytesPerChannel() const{
820
	return sizeof(PixelType);
821
}
822

823
template<typename PixelType>
824
size_t ofPixels_<PixelType>::getBitsPerChannel() const{
825
	return getBytesPerChannel() * 8;
826
}
827

828
template<typename PixelType>
829
size_t ofPixels_<PixelType>::getBytesStride() const{
830
	return pixelBitsFromPixelFormat(pixelFormat) * width / 8;
831
}
832

833
template<typename PixelType>
834
size_t ofPixels_<PixelType>::getNumChannels() const{
835
	return channelsFromPixelFormat(pixelFormat);
836
}
837

838
template<typename PixelType>
839

840
size_t ofPixels_<PixelType>::getTotalBytes() const{
841
	return bytesFromPixelFormat(width,height,pixelFormat);
842
}
843

844
template<typename PixelType>
845
size_t ofPixels_<PixelType>::getNumPlanes() const{
846
	switch(pixelFormat){
847
		case OF_PIXELS_RGB:
848
		case OF_PIXELS_BGR:
849
		case OF_PIXELS_RGB565:
850
		case OF_PIXELS_RGBA:
851
		case OF_PIXELS_BGRA:
852
		case OF_PIXELS_GRAY:
853
		case OF_PIXELS_GRAY_ALPHA:
854
		case OF_PIXELS_YUY2:
855
		case OF_PIXELS_UYVY:
856
		case OF_PIXELS_Y:
857
		case OF_PIXELS_U:
858
		case OF_PIXELS_V:
859
		case OF_PIXELS_UV:
860
		case OF_PIXELS_VU:
861
			return 1;
862
		case OF_PIXELS_NV12:
863
		case OF_PIXELS_NV21:
864
			return 2;
865
		case OF_PIXELS_YV12:
866
		case OF_PIXELS_I420:
867
			return 3;
868
		case OF_PIXELS_NUM_FORMATS:
869
		case OF_PIXELS_NATIVE:
870
		case OF_PIXELS_UNKNOWN:
871
			return 0;
872
	}
873
	return 0;
874
}
875

876
template<typename PixelType>
877
ofPixels_<PixelType> ofPixels_<PixelType>::getPlane(size_t planeIdx){
878
	planeIdx = glm::clamp(planeIdx, size_t(0), getNumPlanes());
879
	ofPixels_<PixelType> plane;
880
	switch(pixelFormat){
881
		case OF_PIXELS_RGB:
882
		case OF_PIXELS_BGR:
883
		case OF_PIXELS_RGB565:
884
		case OF_PIXELS_RGBA:
885
		case OF_PIXELS_BGRA:
886
		case OF_PIXELS_GRAY:
887
		case OF_PIXELS_GRAY_ALPHA:
888
		case OF_PIXELS_YUY2:
889
		case OF_PIXELS_UYVY:
890
		case OF_PIXELS_Y:
891
		case OF_PIXELS_U:
892
		case OF_PIXELS_V:
893
		case OF_PIXELS_UV:
894
		case OF_PIXELS_VU:
895
			plane.setFromExternalPixels(pixels,width,height,pixelFormat);
896
			break;
897
		case OF_PIXELS_NV12:
898
			switch(planeIdx){
899
			case 0:
900
				plane.setFromExternalPixels(pixels,width,height,OF_PIXELS_Y);
901
				break;
902
			case 1:
903
				plane.setFromExternalPixels(pixels+width*height,width/2,height/2,OF_PIXELS_UV);
904
				break;
905
			}
906
			break;
907
		case OF_PIXELS_NV21:
908
			switch(planeIdx){
909
			case 0:
910
				plane.setFromExternalPixels(pixels,width,height,OF_PIXELS_Y);
911
				break;
912
			case 1:
913
				plane.setFromExternalPixels(pixels+width*height,width/2,height/2,OF_PIXELS_VU);
914
				break;
915
			}
916
			break;
917
		case OF_PIXELS_YV12:
918
			switch(planeIdx){
919
			case 0:
920
				plane.setFromExternalPixels(pixels,width,height,OF_PIXELS_Y);
921
				break;
922
			case 1:
923
				plane.setFromExternalPixels(pixels+width*height,width/2,height/2,OF_PIXELS_V);
924
				break;
925
			case 2:
926
				plane.setFromExternalPixels(pixels + (width*height+width/2*height/2), width/2, height/2, OF_PIXELS_U);
927
				break;
928
			}
929
			break;
930
		case OF_PIXELS_I420:
931
			switch(planeIdx){
932
			case 0:
933
				plane.setFromExternalPixels(pixels,width,height,OF_PIXELS_Y);
934
				break;
935
			case 1:
936
				plane.setFromExternalPixels(pixels+width*height,width/2,height/2,OF_PIXELS_U);
937
				break;
938
			case 2:
939
				plane.setFromExternalPixels(pixels + (width*height+width/2*height/2), width/2, height/2, OF_PIXELS_V);
940
				break;
941
			}
942
			break;
943
		case OF_PIXELS_NUM_FORMATS:
944
		case OF_PIXELS_NATIVE:
945
		case OF_PIXELS_UNKNOWN:
946
			break;
947
	}
948
	return plane;
949
}
950

951
template<typename PixelType>
952
ofImageType ofPixels_<PixelType>::getImageType() const{
953
	return ofImageTypeFromPixelFormat(pixelFormat);
954
}
955

956
template<typename PixelType>
957
void ofPixels_<PixelType>::setImageType(ofImageType imageType){
958
	if(!isAllocated() || imageType==getImageType()) return;
959
	ofPixels_<PixelType> dst;
960
	dst.allocate(width,height,imageType);
961
	PixelType * dstPtr = &dst[0];
962
	PixelType * srcPtr = &pixels[0];
963
	size_t dstNumChannels = dst.getNumChannels();
964
	size_t srcNumChannels = getNumChannels();
965
	size_t diffNumChannels = 0;
966
	if(dstNumChannels<srcNumChannels){
967
		diffNumChannels = srcNumChannels-dstNumChannels;
968
	}
969
	for(size_t i=0;i<width*height;i++){
970
		const PixelType & gray = *srcPtr;
971
		for(size_t j=0;j<dstNumChannels;j++){
972
			if(j<srcNumChannels){
973
				*dstPtr++ =  *srcPtr++;
974
			}else if(j<3){
975
				*dstPtr++ = gray;
976
			}else{
977
				*dstPtr++ = ofColor_<PixelType>::limit();
978
			}
979
		}
980
		srcPtr+=diffNumChannels;
981
	}
982
	swap(dst);
983
}
984

985
template<typename PixelType>
986
ofPixelFormat ofPixels_<PixelType>::getPixelFormat() const{
987
	return pixelFormat;
988
}
989

990
template<typename PixelType>
991
void ofPixels_<PixelType>::setNumChannels(size_t numChannels){
992
	if(!isAllocated() || numChannels==getNumChannels()) return;
993
	setImageType(getImageTypeFromChannels(numChannels));
994
}
995

996
template<typename PixelType>
997
size_t ofPixels_<PixelType>::size() const{
998
	return pixelsSize;
999
}
1000

1001
template<typename PixelType>
1002
ofPixels_<PixelType> ofPixels_<PixelType>::getChannel(size_t channel) const{
1003
	ofPixels_<PixelType> channelPixels;
1004
	size_t channels = channelsFromPixelFormat(pixelFormat);
1005
	if(channels==0) return channelPixels;
1006

1007
	channelPixels.allocate(width,height,1);
1008
	channel = glm::clamp(channel, size_t(0), channels-1);
1009
	iterator channelPixel = channelPixels.begin();
1010
	for(auto p: getConstPixelsIter()){
1011
		*channelPixel++ = p[channel];
1012
	}
1013
	return channelPixels;
1014
}
1015

1016
template<typename PixelType>
1017
void ofPixels_<PixelType>::setChannel(size_t channel, const ofPixels_<PixelType> channelPixels){
1018
	size_t channels = channelsFromPixelFormat(pixelFormat);
1019
	if(channels==0) return;
1020

1021
	channel = glm::clamp(channel, size_t(0), channels-1);
1022
	const_iterator channelPixel = channelPixels.begin();
1023
	for(auto p: getPixelsIter()){
1024
		p[channel] = *channelPixel++;
1025
	}
1026

1027
}
1028

1029
//From ofPixelsUtils
1030
//----------------------------------------------------------------------
1031
template<typename PixelType>
1032
void ofPixels_<PixelType>::crop(size_t x, size_t y, size_t _width, size_t _height){
1033
	if (bAllocated){
1034
		ofPixels_<PixelType> crop;
1035
		cropTo(crop,x,y,_width,_height);
1036
		swap(crop);
1037
	}
1038
}
1039

1040
//----------------------------------------------------------------------
1041
template<typename PixelType>
1042
void ofPixels_<PixelType>::cropTo(ofPixels_<PixelType> &toPix, size_t x, size_t y, size_t _width, size_t _height) const{
1043
	if (bAllocated){
1044

1045
		if(&toPix == this){
1046
			toPix.crop(x,y,_width,_height);
1047
			return;
1048
		}
1049

1050
		_width = glm::clamp(_width, size_t(1), getWidth());
1051
		_height = glm::clamp(_height, size_t(1), getHeight());
1052

1053
		if ((toPix.width != _width) || (toPix.height != _height) || (toPix.pixelFormat != pixelFormat)){
1054
			toPix.allocate(_width, _height, pixelFormat);
1055
		}
1056

1057
		// this prevents having to do a check for bounds in the for loop;
1058
		size_t minX = std::max(x, static_cast<size_t>(0));
1059
		size_t maxX = std::min(x + _width, width);
1060
		size_t minY = std::max(y, static_cast<size_t>(0));
1061
		size_t maxY = std::min(y + _height, height);
1062

1063
		auto newPixel = toPix.getPixelsIter().begin();
1064
		for(auto line: getConstLines(minY, maxY - minY)){
1065
			for(auto pixel: line.getPixels(minX, maxX - minX)){
1066
				newPixel++ = pixel;
1067
			}
1068
		}
1069
	}
1070
}
1071

1072
//----------------------------------------------------------------------
1073
template<typename PixelType>
1074
void ofPixels_<PixelType>::rotate90To(ofPixels_<PixelType> & dst, int nClockwiseRotations) const{
1075
	size_t channels = channelsFromPixelFormat(pixelFormat);
1076

1077
	if (bAllocated == false || channels==0){
1078
		return;
1079
	}
1080

1081
	if(&dst == this){
1082
		dst.rotate90(nClockwiseRotations);
1083
		return;
1084
	}
1085

1086
	// first, figure out which type of rotation we have
1087
	int rotation = nClockwiseRotations;
1088
	while (rotation < 0){
1089
		rotation+=4;
1090
	}
1091
	rotation %= 4;
1092

1093
	// if it's 0, just make a copy.  if it's 2, do it by a mirror operation.
1094
	if (rotation == 0) {
1095
		dst = *this;
1096
		return;
1097
		// do nothing!
1098
	} else if (rotation == 2) {
1099
		mirrorTo(dst, true, true);
1100
		return;
1101
	}
1102

1103
	// otherwise, we will need to do some new allocaiton.
1104
	dst.allocate(height,width,getImageType());
1105

1106
	size_t strideSrc = width * channels;
1107
	size_t strideDst = dst.width * channels;
1108

1109
	if(rotation == 1){
1110
		PixelType * srcPixels = pixels;
1111
		PixelType * startPixels = dst.getData() + strideDst;
1112
		for (size_t i = 0; i < height; ++i){
1113
			startPixels -= channels;
1114
			PixelType * dstPixels = startPixels;
1115
			for (size_t j = 0; j < width; ++j){
1116
				for (size_t k = 0; k < channels; ++k){
1117
					dstPixels[k] = srcPixels[k];
1118
				}
1119
				srcPixels += channels;
1120
				dstPixels += strideDst;
1121
			}
1122
		}
1123
	} else if(rotation == 3){
1124
		PixelType * dstPixels = dst.pixels;
1125
		PixelType * startPixels = pixels + strideSrc;
1126
		for (size_t i = 0; i < dst.height; ++i){
1127
			startPixels -= channels;
1128
			PixelType * srcPixels = startPixels;
1129
			for (size_t j = 0; j < dst.width; ++j){
1130
				for (size_t k = 0; k < channels; ++k){
1131
					dstPixels[k] = srcPixels[k];
1132
				}
1133
				srcPixels += strideSrc;
1134
				dstPixels += channels;
1135
			}
1136
		}
1137
	}
1138
}
1139

1140
//----------------------------------------------------------------------
1141
template<typename PixelType>
1142
void ofPixels_<PixelType>::rotate90(int nClockwiseRotations){
1143
	size_t channels = channelsFromPixelFormat(pixelFormat);
1144

1145
	if (bAllocated == false || channels==0){
1146
		return;
1147
	}
1148

1149
	// first, figure out which type of rotation we have
1150
	int rotation = nClockwiseRotations;
1151
	while (rotation < 0){
1152
		rotation+=4;
1153
	}
1154
	rotation %= 4;
1155

1156
	// if it's 0, do nothing.  if it's 2, do it by a mirror operation.
1157
	if (rotation == 0) {
1158
		return;
1159
		// do nothing!
1160
	} else if (rotation == 2) {
1161
		mirror(true, true);
1162
		return;
1163
	}
1164

1165
	ofPixels_<PixelType> newPixels;
1166
	rotate90To(newPixels,nClockwiseRotations);
1167
	std::swap(newPixels.pixels,pixels);
1168
	width = newPixels.width;
1169
	height = newPixels.height;
1170
	pixelsSize = newPixels.size();
1171

1172
}
1173

1174
//----------------------------------------------------------------------
1175
template<typename PixelType>
1176
void ofPixels_<PixelType>::mirror(bool vertically, bool horizontal){
1177
	size_t channels = channelsFromPixelFormat(pixelFormat);
1178

1179
	if ((!vertically && !horizontal) || channels==0){
1180
		return;
1181
	}
1182

1183
	size_t bytesPerPixel = channels;
1184
	PixelType * oldPixels = pixels;
1185
	PixelType tempVal;
1186

1187
	if (! (vertically && horizontal)){
1188
		size_t wToDo = horizontal ? width/2 : width;
1189
		size_t hToDo = vertically ? height/2 : height;
1190

1191
		for (size_t i = 0; i < wToDo; i++){
1192
			for (size_t j = 0; j < hToDo; j++){
1193

1194
				size_t  pixelb = (vertically ? (height - j - 1) : j) * width + (horizontal ? (width - i - 1) : i);
1195
				size_t  pixela = j*width + i;
1196
				for (size_t k = 0; k < bytesPerPixel; k++){
1197

1198
					tempVal = oldPixels[pixela*bytesPerPixel + k];
1199
					oldPixels[pixela*bytesPerPixel + k] = oldPixels[pixelb*bytesPerPixel + k];
1200
					oldPixels[pixelb*bytesPerPixel + k] = tempVal;
1201

1202
				}
1203
			}
1204
		}
1205
	} else {
1206
		// I couldn't think of a good way to do this in place.  I'm sure there is.
1207
		mirror(true, false);
1208
		mirror(false, true);
1209
	}
1210

1211
}
1212

1213
//----------------------------------------------------------------------
1214
template<typename PixelType>
1215
void ofPixels_<PixelType>::mirrorTo(ofPixels_<PixelType> & dst, bool vertically, bool horizontal) const{
1216
	if(&dst == this){
1217
		dst.mirror(vertically,horizontal);
1218
		return;
1219
	}
1220

1221
	if (!vertically && !horizontal){
1222
		dst = *this;
1223
		return;
1224
	}
1225

1226
	size_t bytesPerPixel = getNumChannels();
1227
	dst.allocate(width, height, getPixelFormat());
1228

1229
	if(vertically && !horizontal){
1230
		auto dstLines = dst.getLines();
1231
		auto lineSrc = getConstLines().begin();
1232
		auto line = --dstLines.end();
1233
		auto stride = line.getStride();
1234

1235
		for(; line>=dstLines.begin(); --line, ++lineSrc){
1236
			memcpy(line.begin(), lineSrc.begin(), stride);
1237
		}
1238
	}else if (!vertically && horizontal){
1239
		size_t wToDo = width/2;
1240
		size_t hToDo = height;
1241
		for (size_t i = 0; i < wToDo; i++){
1242
			for (size_t j = 0; j < hToDo; j++){
1243
				size_t pixelb = j*width + (width - 1 - i);
1244
				size_t pixela = j*width + i;
1245
				for (size_t k = 0; k < bytesPerPixel; k++){
1246
					dst[pixela*bytesPerPixel + k] = pixels[pixelb*bytesPerPixel + k];
1247
					dst[pixelb*bytesPerPixel + k] = pixels[pixela*bytesPerPixel + k];
1248

1249
				}
1250
			}
1251
		}
1252
	} else {
1253
		// I couldn't think of a good way to do this in place.  I'm sure there is.
1254
		mirrorTo(dst,true, false);
1255
		dst.mirror(false, true);
1256
	}
1257

1258
}
1259

1260
//----------------------------------------------------------------------
1261
template<typename PixelType>
1262
bool ofPixels_<PixelType>::resize(size_t dstWidth, size_t dstHeight, ofInterpolationMethod interpMethod){
1263

1264
	if ((dstWidth == 0) || (dstHeight == 0) || !(isAllocated())) return false;
1265

1266
	ofPixels_<PixelType> dstPixels;
1267
	dstPixels.allocate(dstWidth, dstHeight, getPixelFormat());
1268

1269
	if(!resizeTo(dstPixels,interpMethod)) return false;
1270

1271
	delete [] pixels;
1272
	pixels = dstPixels.getData();
1273
	width  = dstWidth;
1274
	height = dstHeight;
1275
	pixelsSize = dstPixels.size();
1276
	dstPixels.pixelsOwner = false;
1277
	return true;
1278
}
1279

1280
//----------------------------------------------------------------------
1281
template<typename PixelType>
1282
float ofPixels_<PixelType>::bicubicInterpolate (const float *patch, float x,float y, float x2,float y2, float x3,float y3) {
1283
	// adapted from http://www.paulinternet.nl/?page=bicubic
1284
	// Note that this code can produce values outside of 0...255, due to cubic overshoot.
1285
	// The ofClamp() prevents this from happening.
1286

1287
	float p00 = patch[ 0];
1288
	float p10 = patch[ 4];
1289
	float p20 = patch[ 8];
1290
	float p30 = patch[12];
1291

1292
	float p01 = patch[ 1];
1293
	float p11 = patch[ 5];
1294
	float p21 = patch[ 9];
1295
	float p31 = patch[13];
1296

1297
	float p02 = patch[ 2];
1298
	float p12 = patch[ 6];
1299
	float p22 = patch[10];
1300
	float p32 = patch[14];
1301

1302
	float p03 = patch[ 3];
1303
	float p13 = patch[ 7];
1304
	float p23 = patch[11];
1305
	float p33 = patch[15];
1306

1307
	float a00 =    p11;
1308
	float a01 =   -p10 +   p12;
1309
	float a02 =  2.0f*p10 - 2.0f*p11 +   p12 -   p13;
1310
	float a03 =   -p10 +   p11 -   p12 +   p13;
1311
	float a10 =   -p01 +   p21;
1312
	float a11 =    p00 -   p02 -   p20 +   p22;
1313
	float a12 = -2.0f*p00 + 2.0f*p01 -   p02 +   p03 + 2.0f*p20 - 2.0f*p21 +   p22 -   p23;
1314
	float a13 =    p00 -   p01 +   p02 -   p03 -   p20 +   p21 -   p22 +   p23;
1315
	float a20 =  2.0f*p01 - 2.0f*p11 +   p21 -   p31;
1316
	float a21 = -2.0f*p00 + 2.0f*p02 + 2.0f*p10 - 2.0f*p12 -   p20 +   p22 +   p30 -   p32;
1317
	float a22 =  4*p00 - 4*p01 + 2.0f*p02 - 2.0f*p03 - 4*p10 + 4*p11 - 2.0f*p12 + 2.0f*p13 + 2.0f*p20 - 2.0f*p21 + p22 - p23 - 2.0f*p30 + 2.0f*p31 - p32 + p33;
1318
	float a23 = -2.0f*p00 + 2.0f*p01 - 2.0f*p02 + 2.0f*p03 + 2.0f*p10 - 2.0f*p11 + 2.0f*p12 - 2.0f*p13 -   p20 +   p21 - p22 + p23 +   p30 -   p31 + p32 - p33;
1319
	float a30 =   -p01 +   p11 -   p21 +   p31;
1320
	float a31 =    p00 -   p02 -   p10 +   p12 +   p20 -   p22 -   p30 +   p32;
1321
	float a32 = -2.0f*p00 + 2.0f*p01 -   p02 +   p03 + 2.0f*p10 - 2.0f*p11 +   p12 -   p13 - 2.0f*p20 + 2.0f*p21 - p22 + p23 + 2.0f*p30 - 2.0f*p31 + p32 - p33;
1322
	float a33 =    p00 -   p01 +   p02 -   p03 -   p10 +   p11 -   p12 +   p13 +   p20 -   p21 + p22 - p23 -   p30 +   p31 - p32 + p33;
1323

1324
	float out =
1325
	a00      + a01 * y      + a02 * y2      + a03 * y3 +
1326
	a10 * x  + a11 * x  * y + a12 * x  * y2 + a13 * x  * y3 +
1327
	a20 * x2 + a21 * x2 * y + a22 * x2 * y2 + a23 * x2 * y3 +
1328
	a30 * x3 + a31 * x3 * y + a32 * x3 * y2 + a33 * x3 * y3;
1329

1330
	return std::min(static_cast<size_t>(255), std::max(static_cast<size_t>(out), static_cast<size_t>(0)));
1331
}
1332

1333
//----------------------------------------------------------------------
1334
template<typename PixelType>
1335
bool ofPixels_<PixelType>::resizeTo(ofPixels_<PixelType>& dst, ofInterpolationMethod interpMethod) const{
1336
	if(&dst == this){
1337
		return true;
1338
	}
1339

1340
	if (!(isAllocated()) || !(dst.isAllocated()) || getBytesPerPixel() != dst.getBytesPerPixel()) return false;
1341

1342
	size_t srcWidth      = getWidth();
1343
	size_t srcHeight     = getHeight();
1344
	size_t dstWidth	  = dst.getWidth();
1345
	size_t dstHeight	  = dst.getHeight();
1346
	size_t bytesPerPixel = getBytesPerPixel();
1347

1348

1349
	PixelType * dstPixels = dst.getData();
1350

1351
	switch (interpMethod){
1352

1353
			//----------------------------------------
1354
		case OF_INTERPOLATE_NEAREST_NEIGHBOR:{
1355
			size_t dstIndex = 0;
1356
			float srcxFactor = (float)srcWidth/dstWidth;
1357
			float srcyFactor = (float)srcHeight/dstHeight;
1358
			float srcy = 0.5;
1359
			for (size_t dsty=0; dsty<dstHeight; dsty++){
1360
				float srcx = 0.5;
1361
				size_t srcIndex = static_cast<size_t>(srcy) * srcWidth;
1362
				for (size_t dstx=0; dstx<dstWidth; dstx++){
1363
					size_t pixelIndex = static_cast<size_t>(srcIndex + srcx) * bytesPerPixel;
1364
					for (size_t k=0; k<bytesPerPixel; k++){
1365
						dstPixels[dstIndex] = pixels[pixelIndex];
1366
						dstIndex++;
1367
						pixelIndex++;
1368
					}
1369
					srcx+=srcxFactor;
1370
				}
1371
				srcy+=srcyFactor;
1372
			}
1373
		}break;
1374

1375
			//----------------------------------------
1376
		case OF_INTERPOLATE_BILINEAR:
1377
			// not implemented yet
1378
			ofLogError("ofPixels") << "resizeTo(): bilinear resize not implemented, not resizing";
1379
			break;
1380

1381
			//----------------------------------------
1382
		case OF_INTERPOLATE_BICUBIC:
1383
			float px1, py1;
1384
			float px2, py2;
1385
			float px3, py3;
1386

1387
			float srcColor = 0;
1388
			float interpCol;
1389
			size_t patchRow;
1390
			size_t patchIndex;
1391
			float patch[16];
1392

1393
			size_t srcRowBytes = srcWidth*bytesPerPixel;
1394
			size_t loIndex = (srcRowBytes)+1;
1395
			size_t hiIndex = (srcWidth*srcHeight*bytesPerPixel)-(srcRowBytes)-1;
1396

1397
			for (size_t dsty=0; dsty<dstHeight; dsty++){
1398
				for (size_t dstx=0; dstx<dstWidth; dstx++){
1399

1400
					size_t   dstIndex0 = (dsty*dstWidth + dstx) * bytesPerPixel;
1401
					float srcxf = srcWidth  * (float)dstx/(float)dstWidth;
1402
					float srcyf = srcHeight * (float)dsty/(float)dstHeight;
1403
					size_t   srcx = static_cast<size_t>(std::min(srcWidth-1, static_cast<size_t>(srcxf)));
1404
					size_t   srcy = static_cast<size_t>(std::min(srcHeight-1, static_cast<size_t>(srcyf)));
1405
					size_t   srcIndex0 = (srcy*srcWidth + srcx) * bytesPerPixel;
1406

1407
					px1 = srcxf - srcx;
1408
					py1 = srcyf - srcy;
1409
					px2 = px1 * px1;
1410
					px3 = px2 * px1;
1411
					py2 = py1 * py1;
1412
					py3 = py2 * py1;
1413

1414
					for (size_t k=0; k<bytesPerPixel; k++){
1415
						size_t   dstIndex = dstIndex0+k;
1416
						size_t   srcIndex = srcIndex0+k;
1417

1418
						for (size_t dy=0; dy<4; dy++) {
1419
							patchRow = srcIndex + ((dy-1)*srcRowBytes);
1420
							for (size_t dx=0; dx<4; dx++) {
1421
								patchIndex = patchRow + (dx-1)*bytesPerPixel;
1422
								if ((patchIndex >= loIndex) && (patchIndex < hiIndex)) {
1423
									srcColor = pixels[patchIndex];
1424
								}
1425
								patch[dx*4 + dy] = srcColor;
1426
							}
1427
						}
1428

1429
						interpCol = (PixelType)bicubicInterpolate(patch, px1,py1, px2,py2, px3,py3);
1430
						dstPixels[dstIndex] = interpCol;
1431
					}
1432

1433
				}
1434
			}
1435
			break;
1436
	}
1437

1438
	return true;
1439
}
1440

1441
//----------------------------------------------------------------------
1442
template<typename PixelType>
1443
bool ofPixels_<PixelType>::pasteInto(ofPixels_<PixelType> &dst, size_t xTo, size_t yTo) const{
1444
	if (!(isAllocated()) || !(dst.isAllocated()) || getBytesPerPixel() != dst.getBytesPerPixel() || xTo + getWidth()>dst.getWidth() || yTo + getHeight()>dst.getHeight()) return false;
1445

1446
	size_t bytesToCopyPerRow = (xTo + getWidth()<=dst.getWidth() ? getWidth() : dst.getWidth()-xTo) * getBytesPerPixel();
1447
	size_t columnsToCopy = yTo + getHeight() <= dst.getHeight() ? getHeight() : dst.getHeight()-yTo;
1448
	PixelType * dstPix = dst.getData() + ((xTo + yTo*dst.getWidth())*dst.getBytesPerPixel());
1449
	const PixelType * srcPix = getData();
1450
	size_t srcStride = getWidth()*getBytesPerPixel();
1451
	size_t dstStride = dst.getWidth()*dst.getBytesPerPixel();
1452

1453
	for(size_t y=0;y<columnsToCopy; y++){
1454
		memcpy(dstPix,srcPix,bytesToCopyPerRow);
1455
		dstPix += dstStride;
1456
		srcPix += srcStride;
1457
	}
1458

1459
	return true;
1460
}
1461

1462

1463
template<typename A, typename B>
1464
inline A clampedAdd(const A& a, const B& b) {
1465
	return glm::clamp((float) a + (float) b, 0.f, ofColor_<A>::limit());
1466
}
1467

1468

1469
//----------------------------------------------------------------------
1470
template<typename PixelType>
1471
bool ofPixels_<PixelType>::blendInto(ofPixels_<PixelType> &dst, size_t xTo, size_t yTo) const{
1472
	if (!(isAllocated()) || !(dst.isAllocated()) || getBytesPerPixel() != dst.getBytesPerPixel() || xTo + getWidth()>dst.getWidth() || yTo + getHeight()>dst.getHeight() || getNumChannels()==0) return false;
1473

1474
	std::function<void(const ConstPixel&,Pixel&)> blendFunc;
1475
	switch(getNumChannels()){
1476
	case 1:
1477
		blendFunc = [](const ConstPixel&src, Pixel&dst){
1478
			dst[0] = clampedAdd(src[0], dst[0]);
1479
		};
1480
		break;
1481
	case 2:
1482
		blendFunc = [](const ConstPixel&src, Pixel&dst){
1483
			dst[0] = clampedAdd(src[0], dst[0] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[1]));
1484
			dst[1] = clampedAdd(src[1], dst[1] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[1]));
1485
		};
1486
		break;
1487
	case 3:
1488
		blendFunc = [](const ConstPixel&src, Pixel&dst){
1489
			dst[0] = clampedAdd(src[0], dst[0]);
1490
			dst[1] = clampedAdd(src[1], dst[1]);
1491
			dst[2] = clampedAdd(src[2], dst[2]);
1492
		};
1493
		break;
1494
	case 4:
1495
		blendFunc = [](const ConstPixel&src, Pixel&dst){
1496
			dst[0] = clampedAdd(src[0], dst[0] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[3]));
1497
			dst[1] = clampedAdd(src[1], dst[1] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[3]));
1498
			dst[2] = clampedAdd(src[2], dst[2] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[3]));
1499
			dst[3] = clampedAdd(src[3], dst[3] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[3]));
1500
		};
1501
		break;
1502
	}
1503
	auto dstLine = dst.getLine(yTo);
1504
	for(auto line: getConstLines()){
1505
		auto dstPixel = dstLine.getPixels().begin() + xTo;
1506
		for(auto p: line.getPixels()){
1507
			blendFunc(p,dstPixel);
1508
			dstPixel++;
1509
		}
1510
		dstLine++;
1511
	}
1512

1513
	return true;
1514
}
1515

1516

1517
template class ofPixels_<char>;
1518
template class ofPixels_<unsigned char>;
1519
template class ofPixels_<short>;
1520
template class ofPixels_<unsigned short>;
1521
template class ofPixels_<int>;
1522
template class ofPixels_<unsigned int>;
1523
template class ofPixels_<long>;
1524
template class ofPixels_<unsigned long>;
1525
template class ofPixels_<float>;
1526
template class ofPixels_<double>;
1527

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.