framework2

Форк
0
1286 строк · 38.4 Кб
1
#include "ofImage.h"
2
#include "ofAppRunner.h"
3
#include "ofPixels.h"
4

5
#include "FreeImage.h"
6

7
#include "ofURLFileLoader.h"
8
#include "uriparser/Uri.h"
9

10
#if defined(TARGET_ANDROID)
11
#include "ofxAndroidUtils.h"
12
#endif
13

14

15
//----------------------------------------------------------
16
// static variable for freeImage initialization:
17
void ofInitFreeImage(bool deinit=false){
18
	// need a new bool to avoid c++ "deinitialization order fiasco":
19
	// http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.15
20
	static bool	* bFreeImageInited = new bool(false);
21
	if(!*bFreeImageInited && !deinit){
22
		FreeImage_Initialise();
23
		*bFreeImageInited = true;
24
	}
25
	if(*bFreeImageInited && deinit){
26
		FreeImage_DeInitialise();
27
		*bFreeImageInited = false;
28
	}
29
}
30

31
template <typename T>
32
FREE_IMAGE_TYPE getFreeImageType(const ofPixels_<T>& pix);
33

34
template <>
35
FREE_IMAGE_TYPE getFreeImageType(const ofPixels& pix) {
36
	return FIT_BITMAP;
37
}
38

39
template <>
40
FREE_IMAGE_TYPE getFreeImageType(const ofShortPixels& pix) {
41
	switch(pix.getNumChannels()) {
42
		case 1: return FIT_UINT16;
43
		case 3: return FIT_RGB16;
44
		case 4: return FIT_RGBA16;
45
		default:
46
			ofLogError("ofImage") << "getFreeImageType(): unknown FreeImage type for number of channels: " << pix.getNumChannels();
47
			return FIT_UNKNOWN;
48
	}
49
}
50
template <>
51
FREE_IMAGE_TYPE getFreeImageType(const ofFloatPixels& pix) {
52
	switch(pix.getNumChannels()) {
53
		case 1: return FIT_FLOAT;
54
		case 3: return FIT_RGBF;
55
		case 4: return FIT_RGBAF;
56
		default:
57
			ofLogError("ofImage") << "getFreeImageType(): unknown FreeImage type for number of channels: " << pix.getNumChannels();
58
			return FIT_UNKNOWN;
59
	}
60
}
61

62
//----------------------------------------------------
63
template<typename PixelType>
64
FIBITMAP* getBmpFromPixels(const ofPixels_<PixelType> &pix){
65
	const PixelType* pixels = pix.getData();
66
	unsigned int width = pix.getWidth();
67
	unsigned int height = pix.getHeight();
68
    unsigned int bpp = pix.getBitsPerPixel();
69

70
	FREE_IMAGE_TYPE freeImageType = getFreeImageType(pix);
71
	FIBITMAP* bmp = FreeImage_AllocateT(freeImageType, width, height, bpp);
72
	unsigned char* bmpBits = FreeImage_GetBits(bmp);
73
	if(bmpBits != nullptr) {
74
		int srcStride = width * pix.getBytesPerPixel();
75
		int dstStride = FreeImage_GetPitch(bmp);
76
		unsigned char* src = (unsigned char*) pixels;
77
		unsigned char* dst = bmpBits;
78
		if(srcStride != dstStride){
79
			for(int i = 0; i < (int)height; i++) {
80
				memcpy(dst, src, srcStride);
81
				src += srcStride;
82
				dst += dstStride;
83
			}
84
		}else{
85
			memcpy(dst,src,dstStride*height);
86
		}
87
	} else {
88
		ofLogError("ofImage") << "getBmpFromPixels(): unable to get FIBITMAP from ofPixels";
89
	}
90

91
	// ofPixels are top left, FIBITMAP is bottom left
92
	FreeImage_FlipVertical(bmp);
93

94
	return bmp;
95
}
96

97
//----------------------------------------------------
98
template<typename PixelType>
99
void putBmpIntoPixels(FIBITMAP * bmp, ofPixels_<PixelType>& pix, bool swapOnLittleEndian = true, bool bUsePassedPixelFormat = false) {
100

101
	// convert to correct type depending on type of input bmp and PixelType
102
	FIBITMAP* bmpConverted = nullptr;
103
	FREE_IMAGE_TYPE imgType = FreeImage_GetImageType(bmp);
104
	if(sizeof(PixelType)==1 &&
105
		(FreeImage_GetColorType(bmp) == FIC_PALETTE || FreeImage_GetBPP(bmp) < 8
106
		||  imgType!=FIT_BITMAP)) {
107
		if(FreeImage_IsTransparent(bmp)) {
108
			bmpConverted = FreeImage_ConvertTo32Bits(bmp);
109
		} else {
110
			bmpConverted = FreeImage_ConvertTo24Bits(bmp);
111
		}
112
		bmp = bmpConverted;
113
	}else if(sizeof(PixelType)==2 && imgType!=FIT_UINT16 && imgType!=FIT_RGB16 && imgType!=FIT_RGBA16){
114
		if(FreeImage_IsTransparent(bmp)) {
115
			bmpConverted = FreeImage_ConvertToType(bmp,FIT_RGBA16);
116
		} else {
117
			bmpConverted = FreeImage_ConvertToType(bmp,FIT_RGB16);
118
		}
119
		bmp = bmpConverted;
120
	}else if(sizeof(PixelType)==4 && imgType!=FIT_FLOAT && imgType!=FIT_RGBF && imgType!=FIT_RGBAF){
121
		if(FreeImage_IsTransparent(bmp)) {
122
			bmpConverted = FreeImage_ConvertToType(bmp,FIT_RGBAF);
123
		} else {
124
			bmpConverted = FreeImage_ConvertToType(bmp,FIT_RGBF);
125
		}
126
		bmp = bmpConverted;
127
	}
128

129
	unsigned int width = FreeImage_GetWidth(bmp);
130
	unsigned int height = FreeImage_GetHeight(bmp);
131
	unsigned int bpp = FreeImage_GetBPP(bmp);
132
	unsigned int channels = (bpp / sizeof(PixelType)) / 8;
133
    unsigned int pitch = FreeImage_GetPitch(bmp);
134
#ifdef TARGET_LITTLE_ENDIAN
135
    bool swapRG = channels && swapOnLittleEndian && (bpp/channels == 8);
136
#else
137
    bool swapRG = false;
138
#endif
139

140

141
	ofPixelFormat pixFormat;
142
    if( bUsePassedPixelFormat ){
143
        pixFormat = pix.getPixelFormat();
144
    }else{
145
        if(channels==1) pixFormat=OF_PIXELS_GRAY;
146
        if(swapRG){
147
            if(channels==3) pixFormat=OF_PIXELS_BGR;
148
            if(channels==4) pixFormat=OF_PIXELS_BGRA;
149
        }else{
150
            if(channels==3) pixFormat=OF_PIXELS_RGB;
151
            if(channels==4) pixFormat=OF_PIXELS_RGBA;
152
        }
153
    }
154
    
155
	// ofPixels are top left, FIBITMAP is bottom left
156
	FreeImage_FlipVertical(bmp);
157

158
	unsigned char* bmpBits = FreeImage_GetBits(bmp);
159
	if(bmpBits != nullptr) {
160
		pix.setFromAlignedPixels((PixelType*) bmpBits, width, height, pixFormat, pitch);
161
	} else {
162
		ofLogError("ofImage") << "putBmpIntoPixels(): unable to set ofPixels from FIBITMAP";
163
	}
164

165
	if(bmpConverted != nullptr) {
166
		FreeImage_Unload(bmpConverted);
167
	}
168

169
    if(swapRG && channels >=3 ) {
170
		pix.swapRgb();
171
    }
172
}
173

174
/// internal
175
static int getJpegOptionFromImageLoadSetting(const ofImageLoadSettings &settings) {
176
	int option = 0;
177
	if(settings.accurate)     option |= JPEG_ACCURATE;
178
	if(settings.exifRotate)   option |= JPEG_EXIFROTATE;
179
	if(settings.grayscale)    option |= JPEG_GREYSCALE;
180
	if(settings.separateCMYK) option |= JPEG_CMYK;
181
	return option;
182
}
183

184
template<typename PixelType>
185
static bool loadImage(ofPixels_<PixelType> & pix, const of::filesystem::path& _fileName, const ofImageLoadSettings& settings){
186
	ofInitFreeImage();
187

188
	auto uriStr = _fileName.string();
189
	UriUriA uri;
190
	UriParserStateA state;
191
	state.uri = &uri;
192

193
	if(uriParseUriA(&state, uriStr.c_str())!=URI_SUCCESS){
194
		const int bytesNeeded = 8 + 3 * strlen(uriStr.c_str()) + 1;
195
		std::vector<char> absUri(bytesNeeded);
196
	#ifdef TARGET_WIN32
197
		uriWindowsFilenameToUriStringA(uriStr.c_str(), absUri.data());
198
	#else
199
		uriUnixFilenameToUriStringA(uriStr.c_str(), absUri.data());
200
	#endif
201
		if(uriParseUriA(&state, absUri.data())!=URI_SUCCESS){
202
			ofLogError("ofImage") << "loadImage(): malformed uri when loading image from uri " << _fileName;
203
			uriFreeUriMembersA(&uri);
204
			return false;
205
		}
206
	}
207
	std::string scheme(uri.scheme.first, uri.scheme.afterLast);
208
	uriFreeUriMembersA(&uri);
209

210
	if(scheme == "http" || scheme == "https"){
211
		return ofLoadImage(pix, ofLoadURL(_fileName.string()).data);
212
	}
213

214
	auto fileName = ofToDataPath(_fileName, true);
215
	bool bLoaded = false;
216
	FIBITMAP * bmp = nullptr;
217

218
	FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
219
	fif = FreeImage_GetFileType(fileName.c_str(), 0);
220
	if(fif == FIF_UNKNOWN) {
221
		// or guess via filename
222
		fif = FreeImage_GetFIFFromFilename(fileName.c_str());
223
	}
224
	if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
225
		if(fif == FIF_JPEG) {
226
			int option = getJpegOptionFromImageLoadSetting(settings);
227
			bmp = FreeImage_Load(fif, fileName.c_str(), option | settings.freeImageFlags);
228
		} else {
229
			bmp = FreeImage_Load(fif, fileName.c_str(), 0 | settings.freeImageFlags);
230
		}
231

232
		if (bmp != nullptr){
233
			bLoaded = true;
234
		}
235
	}
236

237
	//-----------------------------
238

239
	if ( bLoaded ){
240
		putBmpIntoPixels(bmp,pix);
241
	}
242

243
	if (bmp != nullptr){
244
		FreeImage_Unload(bmp);
245
	}
246

247
	return bLoaded;
248
}
249

250
template<typename PixelType>
251
static bool loadImage(ofPixels_<PixelType> & pix, const ofBuffer & buffer, const ofImageLoadSettings &settings){
252
	ofInitFreeImage();
253
	bool bLoaded = false;
254
	FIBITMAP* bmp = nullptr;
255
	FIMEMORY* hmem = nullptr;
256

257
	hmem = FreeImage_OpenMemory((unsigned char*) buffer.getData(), buffer.size());
258
	if (hmem == nullptr){
259
		ofLogError("ofImage") << "loadImage(): couldn't load image from ofBuffer, opening FreeImage memory failed";
260
		return false;
261
	}
262

263
	//get the file type!
264
	FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem);
265
	if( fif == -1 ){
266
		ofLogError("ofImage") << "loadImage(): couldn't load image from ofBuffer, unable to guess image format from memory";
267
		FreeImage_CloseMemory(hmem);
268
		return false;
269
	}
270

271

272
	//make the image!!
273
	if(fif == FIF_JPEG) {
274
		int option = getJpegOptionFromImageLoadSetting(settings);
275
		bmp = FreeImage_LoadFromMemory(fif, hmem, option | settings.freeImageFlags);
276
	} else {
277
		bmp = FreeImage_LoadFromMemory(fif, hmem, settings.freeImageFlags);
278
	}
279

280
	if( bmp != nullptr ){
281
		bLoaded = true;
282
	}
283

284
	//-----------------------------
285

286
	if (bLoaded){
287
		putBmpIntoPixels(bmp,pix);
288
	}
289

290
	if (bmp != nullptr){
291
		FreeImage_Unload(bmp);
292
	}
293

294
	if( hmem != nullptr ){
295
		FreeImage_CloseMemory(hmem);
296
	}
297

298
	return bLoaded;
299
}
300

301
//----------------------------------------------------------------
302
bool ofLoadImage(ofPixels & pix, const of::filesystem::path& path, const ofImageLoadSettings &settings) {
303
	return loadImage(pix, path, settings);
304
}
305

306
//----------------------------------------------------------------
307
bool ofLoadImage(ofPixels & pix, const ofBuffer & buffer, const ofImageLoadSettings &settings) {
308
	return loadImage(pix, buffer, settings);
309
}
310

311
//----------------------------------------------------------------
312
bool ofLoadImage(ofShortPixels & pix, const of::filesystem::path& path, const ofImageLoadSettings &settings) {
313
	return loadImage(pix, path, settings);
314
}
315

316
//----------------------------------------------------------------
317
bool ofLoadImage(ofShortPixels & pix, const ofBuffer & buffer, const ofImageLoadSettings &settings) {
318
	return loadImage(pix, buffer, settings);
319
}
320

321
//----------------------------------------------------------------
322
bool ofLoadImage(ofFloatPixels & pix, const of::filesystem::path& path, const ofImageLoadSettings &settings) {
323
	return loadImage(pix, path, settings);
324
}
325

326
//----------------------------------------------------------------
327
bool ofLoadImage(ofFloatPixels & pix, const ofBuffer & buffer, const ofImageLoadSettings &settings) {
328
	return loadImage(pix, buffer, settings);
329
}
330

331
//----------------------------------------------------------------
332
bool ofLoadImage(ofTexture & tex, const of::filesystem::path& path, const ofImageLoadSettings &settings){
333
	ofPixels pixels;
334
	bool loaded = ofLoadImage(pixels, path, settings);
335
	if(loaded){
336
		tex.allocate(pixels.getWidth(), pixels.getHeight(), ofGetGLInternalFormat(pixels));
337
		tex.loadData(pixels);
338
	}
339
	return loaded;
340
}
341

342
//----------------------------------------------------------------
343
bool ofLoadImage(ofTexture & tex, const ofBuffer & buffer, const ofImageLoadSettings &settings){
344
	ofPixels pixels;
345
	bool loaded = ofLoadImage(pixels, buffer, settings);
346
	if(loaded){
347
		tex.allocate(pixels.getWidth(), pixels.getHeight(), ofGetGLInternalFormat(pixels));
348
		tex.loadData(pixels);
349
	}
350
	return loaded;
351
}
352

353
//----------------------------------------------------------------
354
template<typename PixelType>
355
static bool saveImage(const ofPixels_<PixelType> & _pix, const of::filesystem::path& _fileName, ofImageQualityType qualityLevel) {
356
	ofInitFreeImage();
357
	if (_pix.isAllocated() == false){
358
		ofLogError("ofImage") << "saveImage(): couldn't save \"" << _fileName << "\", pixels are not allocated";
359
		return false;
360
	}
361

362
	ofFilePath::createEnclosingDirectory(_fileName);
363
	auto fileName = ofToDataPath(_fileName);
364
	FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
365
	fif = FreeImage_GetFileType(fileName.c_str(), 0);
366
	if(fif == FIF_UNKNOWN) {
367
		// or guess via filename
368
		fif = FreeImage_GetFIFFromFilename(fileName.c_str());
369
	}
370
	if(fif==FIF_JPEG && (_pix.getNumChannels()==4 || _pix.getBitsPerChannel() > 8)){
371
		ofPixels pix3 = _pix;
372
        if( pix3.getPixelFormat() == OF_PIXELS_BGRA ){
373
            pix3.swapRgb();
374
        }
375
		pix3.setNumChannels(3);
376
		return saveImage(pix3,_fileName,qualityLevel);
377
	}
378

379
	FIBITMAP * bmp = nullptr;
380
	#ifdef TARGET_LITTLE_ENDIAN
381
	if(sizeof(PixelType) == 1 && (_pix.getPixelFormat()==OF_PIXELS_RGB || _pix.getPixelFormat()==OF_PIXELS_RGBA)) {	// Make a local copy.
382
		ofPixels_<PixelType> pix = _pix;
383
		pix.swapRgb();
384
		bmp	= getBmpFromPixels(pix);
385
	}else{
386
	#endif
387

388
		bmp	= getBmpFromPixels(_pix);
389

390

391
	#ifdef TARGET_LITTLE_ENDIAN
392
	}
393
	#endif
394

395
	bool retValue = false;
396
	if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
397
		if(fif == FIF_JPEG) {
398
			int quality = JPEG_QUALITYSUPERB;
399
			switch(qualityLevel) {
400
				case OF_IMAGE_QUALITY_WORST: quality = JPEG_QUALITYBAD; break;
401
				case OF_IMAGE_QUALITY_LOW: quality = JPEG_QUALITYAVERAGE; break;
402
				case OF_IMAGE_QUALITY_MEDIUM: quality = JPEG_QUALITYNORMAL; break;
403
				case OF_IMAGE_QUALITY_HIGH: quality = JPEG_QUALITYGOOD; break;
404
				case OF_IMAGE_QUALITY_BEST: quality = JPEG_QUALITYSUPERB; break;
405
			}
406
			retValue = FreeImage_Save(fif, bmp, fileName.c_str(), quality);
407
		} else {
408
			if(qualityLevel != OF_IMAGE_QUALITY_BEST) {
409
				ofLogWarning("ofImage") << "saveImage(): ofImageCompressionType only applies to JPEGs,"
410
					<< " ignoring value for \" "<< fileName << "\"";
411
			}
412

413
			if (fif == FIF_GIF) {
414
				FIBITMAP* convertedBmp;
415
				if(_pix.getImageType() == OF_IMAGE_COLOR_ALPHA) {
416
					// this just converts the image to grayscale so it can save something
417
					convertedBmp = FreeImage_ConvertTo8Bits(bmp);
418
				} else {
419
					// this will create a 256-color palette from the image
420
					convertedBmp = FreeImage_ColorQuantize(bmp, FIQ_NNQUANT);
421
				}
422
				retValue = FreeImage_Save(fif, convertedBmp, fileName.c_str());
423
				if (convertedBmp != nullptr){
424
					FreeImage_Unload(convertedBmp);
425
				}
426
			} else {
427
				retValue = FreeImage_Save(fif, bmp, fileName.c_str());
428
			}
429
		}
430
	}
431

432
	if (bmp != nullptr){
433
		FreeImage_Unload(bmp);
434
	}
435

436
	return retValue;
437
}
438

439
//----------------------------------------------------------------
440
bool ofSaveImage(const ofPixels & pix, const of::filesystem::path& fileName, ofImageQualityType qualityLevel){
441
	return saveImage(pix,fileName,qualityLevel);
442
}
443

444
//----------------------------------------------------------------
445
bool ofSaveImage(const ofFloatPixels & pix, const of::filesystem::path& fileName, ofImageQualityType qualityLevel) {
446
	return saveImage(pix,fileName,qualityLevel);
447
}
448

449
//----------------------------------------------------------------
450
bool ofSaveImage(const ofShortPixels & pix, const of::filesystem::path& fileName, ofImageQualityType qualityLevel) {
451
	return saveImage(pix,fileName,qualityLevel);
452
}
453

454
//----------------------------------------------------------------
455
template<typename PixelType>
456
static bool saveImage(const ofPixels_<PixelType> & _pix, ofBuffer & buffer, ofImageFormat format, ofImageQualityType qualityLevel) {
457
	// thanks to alvaro casinelli for the implementation
458

459
	ofInitFreeImage();
460

461
	if (_pix.isAllocated() == false){
462
		ofLogError("ofImage","saveImage(): couldn't save to ofBuffer, pixels are not allocated");
463
		return false;
464
	}
465

466
	if(format==OF_IMAGE_FORMAT_JPEG && (_pix.getNumChannels()==4 || _pix.getBitsPerChannel() > 8)){
467
		ofPixels pix3 = _pix;
468
        if( pix3.getPixelFormat() == OF_PIXELS_BGRA ){
469
            pix3.swapRgb();
470
        }
471
		pix3.setNumChannels(3);
472
		return saveImage(pix3,buffer,format,qualityLevel);
473
	}
474

475

476
	FIBITMAP * bmp = nullptr;
477
	#ifdef TARGET_LITTLE_ENDIAN
478
	if(sizeof(PixelType) == 1 && (_pix.getPixelFormat()==OF_PIXELS_RGB || _pix.getPixelFormat()==OF_PIXELS_RGBA)) {	// Make a local copy.
479
		ofPixels_<PixelType> pix = _pix;
480
		pix.swapRgb();
481
		bmp	= getBmpFromPixels(pix);
482
	}else{
483
	#endif
484

485
		bmp	= getBmpFromPixels(_pix);
486

487

488
	#ifdef TARGET_LITTLE_ENDIAN
489
	}
490
	#endif
491

492
	if (bmp)  // bitmap successfully created
493
	{
494
		bool returnValue;
495
		// (b) open a memory stream to compress the image onto mem_buffer:
496
		//
497
		FIMEMORY *hmem = FreeImage_OpenMemory();
498
		// (c) encode and save the image to the memory (on dib FIBITMAP image):
499
		//
500
		if(FREE_IMAGE_FORMAT(format) == FIF_JPEG) {
501
			int quality = JPEG_QUALITYSUPERB;
502
			switch(qualityLevel) {
503
				case OF_IMAGE_QUALITY_WORST: quality = JPEG_QUALITYBAD; break;
504
				case OF_IMAGE_QUALITY_LOW: quality = JPEG_QUALITYAVERAGE; break;
505
				case OF_IMAGE_QUALITY_MEDIUM: quality = JPEG_QUALITYNORMAL; break;
506
				case OF_IMAGE_QUALITY_HIGH: quality = JPEG_QUALITYGOOD; break;
507
				case OF_IMAGE_QUALITY_BEST: quality = JPEG_QUALITYSUPERB; break;
508
			}
509
			returnValue = FreeImage_SaveToMemory(FIF_JPEG, bmp, hmem, quality);
510
		}else{
511
			returnValue = FreeImage_SaveToMemory((FREE_IMAGE_FORMAT)format, bmp, hmem);
512
		}
513

514
		/*
515

516
		NOTE: at this point, hmem contains the entire data in memory stored in fif format. the
517
		amount of space used by the memory is equal to file_size:
518
		long file_size = FreeImage_TellMemory(hmem);
519
		but can also be retrieved by FreeImage_AcquireMemory that retrieves both the
520
		length of the buffer, and the buffer memory address.
521
		*/
522
		#ifdef TARGET_WIN32
523
		   DWORD size_in_bytes = 0;
524
		#else
525
		   std::uint32_t size_in_bytes = 0;
526
		#endif
527
		// Save compressed data on mem_buffer
528
		// note: FreeImage_AquireMemory allocates space for aux_mem_buffer):
529
		//
530
		unsigned char *mem_buffer = nullptr;
531
		if (!FreeImage_AcquireMemory(hmem, &mem_buffer, &size_in_bytes)){
532
			ofLogError("ofImage") << "saveImage(): couldn't save to ofBuffer, aquiring compressed image from memory failed";
533
			return false;
534
		}
535

536
		/*
537
		  Now, before closing the memory stream, copy the content of mem_buffer
538
		  to an auxiliary buffer
539
		*/
540

541
		buffer.set((char*)mem_buffer,size_in_bytes);
542

543
		// Finally, close the FIBITMAP object, or we will get a memory leak:
544
		FreeImage_Unload(bmp);
545

546
		// Close the memory stream (otherwise we may get a memory leak).
547
		FreeImage_CloseMemory(hmem);
548
		return returnValue;
549
	}else{
550
		return false;
551
	}
552
}
553

554
//----------------------------------------------------------------
555
bool ofSaveImage(const ofPixels & pix, ofBuffer & buffer, ofImageFormat format, ofImageQualityType qualityLevel) {
556
	return saveImage(pix,buffer,format,qualityLevel);
557
}
558

559
bool ofSaveImage(const ofFloatPixels & pix, ofBuffer & buffer, ofImageFormat format, ofImageQualityType qualityLevel) {
560
	return saveImage(pix,buffer,format,qualityLevel);
561
}
562

563
bool ofSaveImage(const ofShortPixels & pix, ofBuffer & buffer, ofImageFormat format, ofImageQualityType qualityLevel) {
564
	return saveImage(pix,buffer,format,qualityLevel);
565
}
566

567

568
//----------------------------------------------------
569
// freeImage based stuff:
570
void ofCloseFreeImage(){
571
	ofInitFreeImage(true);
572
}
573

574
//-------------------------------------------------------------
575
//  implementation
576

577
//----------------------------------------------------------
578
template<typename PixelType>
579
ofImage_<PixelType>::ofImage_(){
580

581
	width						= 0;
582
	height						= 0;
583
	bpp							= 0;
584
	type						= OF_IMAGE_UNDEFINED;
585
	bUseTexture					= true;		// the default is, yes, use a texture
586

587
	//----------------------- init free image if necessary
588
	ofInitFreeImage();
589
}
590

591
//----------------------------------------------------------
592
template<typename PixelType>
593
ofImage_<PixelType>::ofImage_(const ofPixels_<PixelType> & pix){
594
	width						= 0;
595
	height						= 0;
596
	bpp							= 0;
597
	type						= OF_IMAGE_UNDEFINED;
598
	bUseTexture					= true;		// the default is, yes, use a texture
599

600
	//----------------------- init free image if necessary
601
	ofInitFreeImage();
602

603

604
	setFromPixels(pix);
605
}
606

607
template<typename PixelType>
608
ofImage_<PixelType>::ofImage_(const of::filesystem::path & fileName, const ofImageLoadSettings &settings){
609
	width						= 0;
610
	height						= 0;
611
	bpp							= 0;
612
	type						= OF_IMAGE_UNDEFINED;
613
	bUseTexture					= true;		// the default is, yes, use a texture
614

615
	//----------------------- init free image if necessary
616
	ofInitFreeImage();
617

618

619
	load(fileName, settings);
620
}
621

622
//----------------------------------------------------------
623
template<typename PixelType>
624
ofImage_<PixelType>& ofImage_<PixelType>::operator=(const ofImage_<PixelType>& mom) {
625
	if(&mom==this) return *this;
626
	clone(mom);
627

628
	#if defined(TARGET_ANDROID)
629
	ofAddListener(ofxAndroidEvents().unloadGL,this,&ofImage_<PixelType>::unloadTexture);
630
	ofAddListener(ofxAndroidEvents().reloadGL,this,&ofImage_<PixelType>::update);
631
	#endif
632
	return *this;
633
}
634

635
//----------------------------------------------------------
636
template<typename PixelType>
637
ofImage_<PixelType>::ofImage_(const ofImage_<PixelType>& mom) {
638
	clear();
639
	clone(mom);
640

641
	#if defined(TARGET_ANDROID)
642
	ofAddListener(ofxAndroidEvents().unloadGL,this,&ofImage_<PixelType>::unloadTexture);
643
	ofAddListener(ofxAndroidEvents().reloadGL,this,&ofImage_<PixelType>::update);
644
	#endif
645
}
646

647
//----------------------------------------------------------
648
template<typename PixelType>
649
ofImage_<PixelType>::ofImage_(ofImage_<PixelType>&& mom){
650
    pixels      = std::move(mom.pixels);
651
    tex         = std::move(mom.tex);
652

653
    bUseTexture = mom.bUseTexture;
654
    width       = mom.width;
655
    height      = mom.height;
656
    bpp         = mom.bpp;
657
    type        = mom.type;
658

659
    mom.clear(); //clear remaining flags and sizes from the mom
660

661
    #if defined(TARGET_ANDROID)
662
    ofAddListener(ofxAndroidEvents().unloadGL,this,&ofImage_<PixelType>::unloadTexture);
663
    ofAddListener(ofxAndroidEvents().reloadGL,this,&ofImage_<PixelType>::update);
664
    #endif
665
}
666

667
//----------------------------------------------------------
668
template<typename PixelType>
669
ofImage_<PixelType>& ofImage_<PixelType>::operator=(ofImage_<PixelType>&& mom){
670
    if(&mom==this) return *this;
671

672
    pixels      = std::move(mom.pixels);
673
    tex         = std::move(mom.tex);
674

675
    bUseTexture = mom.bUseTexture;
676
    width       = mom.width;
677
    height      = mom.height;
678
    bpp         = mom.bpp;
679
    type        = mom.type;
680

681
    mom.clear(); //clear remaining flags and sizes from the mom
682

683
    #if defined(TARGET_ANDROID)
684
    ofAddListener(ofxAndroidEvents().unloadGL,this,&ofImage_<PixelType>::unloadTexture);
685
    ofAddListener(ofxAndroidEvents().reloadGL,this,&ofImage_<PixelType>::update);
686
    #endif
687

688
    return *this;
689
}
690

691
//----------------------------------------------------------
692
template<typename PixelType>
693
ofImage_<PixelType>::~ofImage_(){
694
	clear();
695
}
696

697
//----------------------------------------------------------
698
template<typename PixelType>
699
bool ofImage_<PixelType>::loadImage(const ofFile & file){
700
	return load(file);
701
}
702

703
//----------------------------------------------------------
704
template<typename PixelType>
705
bool ofImage_<PixelType>::load(const of::filesystem::path& fileName, const ofImageLoadSettings &settings){
706
	#if defined(TARGET_ANDROID)
707
	ofAddListener(ofxAndroidEvents().unloadGL,this,&ofImage_<PixelType>::unloadTexture);
708
	ofAddListener(ofxAndroidEvents().reloadGL,this,&ofImage_<PixelType>::update);
709
	#endif
710
	bool bLoadedOk = ofLoadImage(pixels, fileName, settings);
711
	if (!bLoadedOk) {
712
		ofLogError("ofImage") << "loadImage(): couldn't load image from \"" << fileName << "\"";
713
		clear();
714
		return false;
715
	}
716
	update();
717
	return bLoadedOk;
718
}
719

720
//----------------------------------------------------------
721
template<typename PixelType>
722
bool ofImage_<PixelType>::loadImage(const std::string& fileName){
723
	return load(fileName);
724
}
725

726
//----------------------------------------------------------
727
template<typename PixelType>
728
bool ofImage_<PixelType>::load(const ofBuffer & buffer, const ofImageLoadSettings &settings){
729
	#if defined(TARGET_ANDROID)
730
	ofAddListener(ofxAndroidEvents().unloadGL,this,&ofImage_<PixelType>::unloadTexture);
731
	ofAddListener(ofxAndroidEvents().reloadGL,this,&ofImage_<PixelType>::update);
732
	#endif
733
	bool bLoadedOk = ofLoadImage(pixels, buffer, settings);
734
	if (!bLoadedOk) {
735
		ofLogError("ofImage") << "loadImage(): couldn't load image from ofBuffer";
736
		clear();
737
		return false;
738
	}
739
	update();
740
	return bLoadedOk;
741
}
742

743
//----------------------------------------------------------
744
template<typename PixelType>
745
bool ofImage_<PixelType>::loadImage(const ofBuffer & buffer){
746
	return load(buffer);
747
}
748

749
//----------------------------------------------------------
750
template<typename PixelType>
751
bool ofImage_<PixelType>::save(const of::filesystem::path& fileName, ofImageQualityType qualityLevel) const {
752
	return ofSaveImage(pixels, fileName, qualityLevel);
753
}
754

755
//----------------------------------------------------------
756
template<typename PixelType>
757
bool ofImage_<PixelType>::save(ofBuffer & buffer, ofImageFormat imageFormat, ofImageQualityType qualityLevel) const {
758
	return ofSaveImage(pixels, buffer, imageFormat, qualityLevel);
759
}
760

761
//----------------------------------------------------------
762
template<typename PixelType>
763
void ofImage_<PixelType>::saveImage(const std::string& fileName, ofImageQualityType qualityLevel) const {
764
	save(fileName, qualityLevel);
765
}
766

767
//----------------------------------------------------------
768
template<typename PixelType>
769
void ofImage_<PixelType>::saveImage(ofBuffer & buffer, ofImageQualityType qualityLevel) const {
770
    save(buffer, OF_IMAGE_FORMAT_PNG, qualityLevel);
771
}
772

773
//----------------------------------------------------------
774
template<typename PixelType>
775
void ofImage_<PixelType>::saveImage(const ofFile & file, ofImageQualityType compressionLevel) const {
776
	save(file,compressionLevel);
777
}
778

779
// we could cap these values - but it might be more useful
780
// to be able to set anchor points outside the image
781

782
//----------------------------------------------------------
783
template<typename PixelType>
784
void ofImage_<PixelType>::setAnchorPercent(float xPct, float yPct){
785
    if (bUseTexture)tex.setAnchorPercent(xPct, yPct);
786
}
787

788
//----------------------------------------------------------
789
template<typename PixelType>
790
void ofImage_<PixelType>::setAnchorPoint(float x, float y){
791
    if (bUseTexture)tex.setAnchorPoint(x, y);
792
}
793

794
//----------------------------------------------------------
795
template<typename PixelType>
796
void ofImage_<PixelType>::resetAnchor(){
797
   	if (bUseTexture)tex.resetAnchor();
798
}
799

800
//------------------------------------
801
template<typename PixelType>
802
void ofImage_<PixelType>::draw(float x, float y) const{
803
	draw(x,y,0,getWidth(),getHeight());
804
}
805

806
//------------------------------------
807
template<typename PixelType>
808
void ofImage_<PixelType>::draw(float x, float y, float z) const{
809
	draw(x,y,z,getWidth(),getHeight());
810
}
811

812

813
//------------------------------------
814
template<typename PixelType>
815
void ofImage_<PixelType>::draw(const glm::vec3 & pos) const{
816
	draw(pos.x,pos.y,pos.z,getWidth(),getHeight());
817
}
818

819
//------------------------------------
820
template<typename PixelType>
821
void ofImage_<PixelType>::draw(float x, float y, float w, float h) const{
822
	draw(x,y,0,w,h);
823
}
824

825
//------------------------------------
826
template<typename PixelType>
827
void ofImage_<PixelType>::draw(float x, float y, float z, float w, float h) const{
828
	drawSubsection(x,y,z,w,h,0,0,getWidth(),getHeight());
829
}
830

831

832
//------------------------------------
833
template<typename PixelType>
834
void ofImage_<PixelType>::draw(const glm::vec3 & pos, float w, float h) const{
835
	draw(pos.x,pos.y,pos.z,w,h);
836
}
837

838
//------------------------------------
839
template<typename PixelType>
840
void ofImage_<PixelType>::drawSubsection(float x, float y, float w, float h, float sx, float sy) const{
841
	drawSubsection(x,y,0,w,h,sx,sy,w,h);
842
}
843

844
//------------------------------------
845
template<typename PixelType>
846
void ofImage_<PixelType>::drawSubsection(float x, float y, float w, float h, float sx, float sy, float _sw, float _sh) const{
847
	drawSubsection(x,y,0,w,h,sx,sy,_sw,_sh);
848
}
849

850
//------------------------------------
851
template<typename PixelType>
852
void ofImage_<PixelType>::drawSubsection(float x, float y, float z, float w, float h, float sx, float sy) const{
853
	drawSubsection(x,y,z,w,h,sx,sy,w,h);
854
}
855

856
//------------------------------------
857
template<typename PixelType>
858
void ofImage_<PixelType>::drawSubsection(float x, float y, float z, float w, float h, float sx, float sy, float sw, float sh) const{
859
	ofGetCurrentRenderer()->draw(*this,x,y,z,w,h,sx,sy,sw,sh);
860
}
861

862
//------------------------------------
863
template<typename PixelType>
864
void ofImage_<PixelType>::allocate(int w, int h, ofImageType newType){
865

866
	if (width == w && height == h && newType == type){
867
		return;
868
	}
869
#if defined(TARGET_ANDROID)
870
	ofAddListener(ofxAndroidEvents().unloadGL,this,&ofImage_<PixelType>::unloadTexture);
871
	ofAddListener(ofxAndroidEvents().reloadGL,this,&ofImage_<PixelType>::update);
872
#endif
873
	pixels.allocate(w, h, newType);
874

875
	// take care of texture allocation --
876
	if (pixels.isAllocated() && bUseTexture){
877
		tex.allocate(pixels);
878
	}
879

880
	width	= pixels.getWidth();
881
	height	= pixels.getHeight();
882
	bpp		= pixels.getBitsPerPixel();
883
	type	= pixels.getImageType();
884
}
885

886

887
//------------------------------------
888
template<typename PixelType>
889
bool ofImage_<PixelType>::bAllocated(){
890
    return pixels.isAllocated();
891
}
892

893
//------------------------------------
894
template<typename PixelType>
895
void ofImage_<PixelType>::clear(){
896
#if defined(TARGET_ANDROID)
897
	ofRemoveListener(ofxAndroidEvents().unloadGL,this,&ofImage_<PixelType>::unloadTexture);
898
	ofRemoveListener(ofxAndroidEvents().reloadGL,this,&ofImage_<PixelType>::update);
899
#endif
900
	pixels.clear();
901
	if(bUseTexture)	tex.clear();
902

903
	width					= 0;
904
	height					= 0;
905
	bpp						= 0;
906
	type 					= OF_IMAGE_UNDEFINED;
907
	bUseTexture 			= true;		// the default is, yes, use a texture
908
}
909

910
//------------------------------------
911
template<typename PixelType>
912
ofPixels_<PixelType> &  ofImage_<PixelType>::getPixels(){
913
	return pixels;
914
}
915

916
//------------------------------------
917
template<typename PixelType>
918
const ofPixels_<PixelType> & ofImage_<PixelType>::getPixels() const{
919
	return pixels;
920
}
921

922
//----------------------------------------------------------
923
template<typename PixelType>
924
ofPixels_<PixelType> & ofImage_<PixelType>::getPixelsRef(){
925
	return pixels;
926
}
927

928
//----------------------------------------------------------
929
template<typename PixelType>
930
const ofPixels_<PixelType> & ofImage_<PixelType>::getPixelsRef() const {
931
	return pixels;
932
}
933

934
//----------------------------------------------------------
935
template<typename PixelType>
936
ofImage_<PixelType>::operator ofPixels_<PixelType>&(){
937
	return pixels;
938
}
939

940
//------------------------------------
941
template<typename PixelType>
942
ofTexture & ofImage_<PixelType>::getTexture(){
943
	return tex;
944
}
945

946
//------------------------------------
947
template<typename PixelType>
948
const ofTexture & ofImage_<PixelType>::getTexture() const{
949
	return tex;
950
}
951

952
//------------------------------------
953
// for getting a reference to the texture
954
template<typename PixelType>
955
ofTexture & ofImage_<PixelType>::getTextureReference(){
956
	return getTexture();
957
}
958

959
//------------------------------------
960
template<typename PixelType>
961
const ofTexture & ofImage_<PixelType>::getTextureReference() const{
962
	return getTexture();
963
}
964

965
//----------------------------------------------------------
966
template<typename PixelType>
967
void ofImage_<PixelType>::bind(int textureLocation) const{
968
	if (bUseTexture && tex.isAllocated())
969
		tex.bind(textureLocation);
970
}
971

972
//----------------------------------------------------------
973
template<typename PixelType>
974
void ofImage_<PixelType>::unbind(int textureLocation) const{
975
	if (bUseTexture && tex.isAllocated())
976
		tex.unbind(textureLocation);
977
}
978

979
//------------------------------------
980
template<typename PixelType>
981
ofColor_<PixelType> ofImage_<PixelType>::getColor(int x, int y) const {
982
	return pixels.getColor(x, y);
983
}
984

985
//------------------------------------
986
template<typename PixelType>
987
ofColor_<PixelType> ofImage_<PixelType>::getColor(int index) const {
988
	return pixels.getColor(index);
989
}
990

991
//------------------------------------
992
template<typename PixelType>
993
void ofImage_<PixelType>::setColor(int x, int y, const ofColor_<PixelType>& color) {
994
	pixels.setColor(x, y, color);
995
}
996

997
//------------------------------------
998
template<typename PixelType>
999
void ofImage_<PixelType>::setColor(int index, const ofColor_<PixelType>& color) {
1000
	pixels.setColor(index, color);
1001
}
1002

1003
//------------------------------------
1004
template<typename PixelType>
1005
void ofImage_<PixelType>::setColor(const ofColor_<PixelType>& color) {
1006
	pixels.setColor(color);
1007
}
1008

1009
//------------------------------------
1010
template<typename PixelType>
1011
void  ofImage_<PixelType>::setFromPixels(const PixelType * newPixels, int w, int h, ofImageType newType, bool bOrderIsRGB){
1012

1013
	allocate(w, h, newType);
1014
	pixels.setFromPixels(newPixels,w,h,newType);
1015

1016
	if (!bOrderIsRGB && sizeof(PixelType) == 1){
1017
		pixels.swapRgb();
1018
	}
1019

1020
	update();
1021
}
1022

1023
//------------------------------------
1024
template<typename PixelType>
1025
void ofImage_<PixelType>::setFromPixels(const ofPixels_<PixelType> & pixels){
1026
	setFromPixels(pixels.getData(),pixels.getWidth(),pixels.getHeight(),pixels.getImageType());
1027
}
1028

1029
//------------------------------------
1030
template<typename PixelType>
1031
ofImage_<PixelType> & ofImage_<PixelType>::operator=(ofPixels_<PixelType> & pixels){
1032
	setFromPixels(pixels);
1033
	return *this;
1034
}
1035

1036
//------------------------------------
1037
template<typename PixelType>
1038
void ofImage_<PixelType>::update(){
1039
	width = pixels.getWidth();
1040
	height = pixels.getHeight();
1041
	bpp = pixels.getBitsPerPixel();
1042
	type = pixels.getImageType();
1043
	if (pixels.isAllocated() && bUseTexture){
1044
		int glInternalFormat = ofGetGLInternalFormat(pixels);
1045
		if(!tex.isAllocated() || tex.getWidth() != width || tex.getHeight() != height || tex.getTextureData().glInternalFormat != glInternalFormat){
1046
			tex.allocate(pixels);
1047
		}else{
1048
			tex.loadData(pixels);
1049
		}
1050
	}
1051
}
1052

1053
//------------------------------------
1054
template<typename PixelType>
1055
void ofImage_<PixelType>::setUseTexture(bool bUse){
1056
	bUseTexture = bUse;
1057
}
1058

1059
//------------------------------------
1060
template<typename PixelType>
1061
bool ofImage_<PixelType>::isUsingTexture() const{
1062
	return bUseTexture;
1063
}
1064

1065
//------------------------------------
1066
template<>
1067
void ofImage_<unsigned char>::grabScreen(int x, int y, int w, int h){
1068
	std::shared_ptr<ofBaseGLRenderer> renderer = ofGetGLRenderer();
1069
	if(renderer){
1070
		renderer->saveScreen(x,y,w,h,pixels);
1071
		update();
1072
	}
1073
}
1074

1075
//------------------------------------
1076
template<typename PixelType>
1077
void ofGrabScreen(ofPixels_<PixelType> & pixels, int x, int y, int w, int h){
1078
	ofPixels p;
1079
	std::shared_ptr<ofBaseGLRenderer> renderer = ofGetGLRenderer();
1080
	if(renderer){
1081
		renderer->saveScreen(x,y,w,h,p);
1082
		pixels = p;
1083
	}
1084
}
1085

1086
//------------------------------------
1087
template<>
1088
void ofGrabScreen(ofPixels & p, int x, int y, int w, int h){
1089
	std::shared_ptr<ofBaseGLRenderer> renderer = ofGetGLRenderer();
1090
	if(renderer){
1091
		renderer->saveScreen(x,y,w,h,p);
1092
	}
1093
}
1094

1095
//------------------------------------
1096
template<typename PixelType>
1097
void ofImage_<PixelType>::grabScreen(int x, int y, int w, int h){
1098
	ofGrabScreen(pixels,x,y,w,h);
1099
	update();
1100
}
1101

1102
//------------------------------------
1103
template<typename PixelType>
1104
void ofImage_<PixelType>::setImageType(ofImageType newType){
1105
	changeTypeOfPixels(pixels, newType);
1106
	update();
1107
}
1108

1109
//------------------------------------
1110
template<typename PixelType>
1111
ofImageType ofImage_<PixelType>::getImageType() const{
1112
	return type;
1113
}
1114

1115
//------------------------------------
1116
template<typename PixelType>
1117
void ofImage_<PixelType>::resize(int newWidth, int newHeight){
1118
	if(newWidth == width && newHeight == height) return;
1119

1120
	resizePixels(pixels, newWidth, newHeight);
1121
	update();
1122
}
1123

1124

1125
//------------------------------------
1126
template<typename PixelType>
1127
void ofImage_<PixelType>::crop(int x, int y, int w, int h){
1128
	w = glm::clamp(w,1,int(getWidth()));
1129
	h = glm::clamp(h,1,int(getHeight()));
1130

1131
	pixels.crop(x,y,w,h);
1132
	update();
1133
}
1134

1135
//------------------------------------
1136
template<typename PixelType>
1137
void ofImage_<PixelType>::cropFrom(const ofImage_<PixelType> & otherImage, int x, int y, int w, int h){
1138
	w = glm::clamp(w,1,int(otherImage.getWidth()));
1139
	h = glm::clamp(h,1,int(otherImage.getHeight()));
1140

1141
	otherImage.pixels.cropTo(pixels, x, y, w, h);
1142
	update();
1143
}
1144

1145
//------------------------------------
1146
template<typename PixelType>
1147
void ofImage_<PixelType>::rotate90(int nRotations){
1148
	pixels.rotate90(nRotations);
1149
	update();
1150
}
1151

1152
//------------------------------------
1153
template<typename PixelType>
1154
void ofImage_<PixelType>::mirror(bool vertical, bool horizontal){
1155
	pixels.mirror(vertical, horizontal);
1156
	update();
1157
}
1158

1159

1160

1161

1162

1163

1164
//----------------------------------------------------------------------------------------------------
1165
//----------------------------------------------------------------------------------------------------
1166
//----------------------------------------------------------------------------------------------------
1167
// freeImage based code & utilities:
1168

1169

1170
//----------------------------------------------------
1171
template<typename PixelType>
1172
void ofImage_<PixelType>::resizePixels(ofPixels_<PixelType> &pix, int newWidth, int newHeight){
1173

1174
	FIBITMAP * bmp					= getBmpFromPixels(pix);
1175
	FIBITMAP * convertedBmp			= nullptr;
1176

1177
	convertedBmp = FreeImage_Rescale(bmp, newWidth, newHeight, FILTER_BICUBIC);
1178
    putBmpIntoPixels(convertedBmp, pix, false, true);
1179

1180
	if (bmp != nullptr)				FreeImage_Unload(bmp);
1181
	if (convertedBmp != nullptr)		FreeImage_Unload(convertedBmp);
1182
}
1183

1184
//----------------------------------------------------
1185
template<typename PixelType>
1186
void ofImage_<PixelType>::changeTypeOfPixels(ofPixels_<PixelType> &pix, ofImageType newType){
1187
	int oldType = pix.getImageType();
1188

1189
	if (oldType == newType) {
1190
		return; // no need to reallocate
1191
	}
1192

1193
	FIBITMAP * bmp = getBmpFromPixels(pix);
1194
	FIBITMAP * convertedBmp = nullptr;
1195

1196
    ofPixelFormat oldPixFormat = pix.getPixelFormat();
1197

1198
	switch (newType){
1199
		case OF_IMAGE_GRAYSCALE:
1200
			convertedBmp = FreeImage_ConvertToGreyscale(bmp);
1201
			break;
1202
		case OF_IMAGE_COLOR:
1203
			convertedBmp = FreeImage_ConvertTo24Bits(bmp);
1204
			break;
1205
		case OF_IMAGE_COLOR_ALPHA:
1206
			convertedBmp = FreeImage_ConvertTo32Bits(bmp);
1207
			break;
1208
		default:
1209
			ofLogError("ofImage") << "changeTypeOfPixels(): unknown image type: "
1210
				<< ofToString(newType);
1211
			break;
1212
	}
1213

1214
    putBmpIntoPixels(convertedBmp, pix, false);
1215
    
1216
    // if we started with BGRA or BGR pixels make sure we end up with similar
1217
    if( pix.getNumChannels() >= 3 && ( oldPixFormat == OF_PIXELS_BGR || oldPixFormat == OF_PIXELS_BGRA ) ){
1218
        ofPixelFormat fixedFormat = pix.getPixelFormat();
1219
        if( fixedFormat == OF_PIXELS_RGBA ){
1220
            fixedFormat = OF_PIXELS_BGRA;
1221
        }else if( fixedFormat == OF_PIXELS_RGB ){
1222
            fixedFormat = OF_PIXELS_BGR;
1223
        }
1224
        pix.setFromPixels(pix.getData(),pix.getWidth(),pix.getHeight(), fixedFormat);
1225
    }
1226

1227
	if (bmp != nullptr) {
1228
		FreeImage_Unload(bmp);
1229
	}
1230
	if (convertedBmp != nullptr) {
1231
		FreeImage_Unload(convertedBmp);
1232
	}
1233
}
1234

1235

1236
//----------------------------------------------------------
1237
template<typename PixelType>
1238
void ofImage_<PixelType>::unloadTexture(){
1239
	tex.clear();
1240
}
1241

1242
//----------------------------------------------------------
1243
template<typename PixelType>
1244
float ofImage_<PixelType>::getHeight() const{
1245
	return height;
1246
}
1247

1248
//----------------------------------------------------------
1249
template<typename PixelType>
1250
float ofImage_<PixelType>::getWidth() const{
1251
	return width;
1252
}
1253

1254
//----------------------------------------------------------
1255
// Sosolimited: texture compression
1256
// call this function before you call loadImage()
1257
template<typename PixelType>
1258
void ofImage_<PixelType>::setCompression(ofTexCompression compression)
1259
{
1260
	if(bUseTexture){
1261
		tex.setCompression( compression );
1262
	}
1263
}
1264

1265
template class ofImage_<unsigned char>;
1266
template class ofImage_<float>;
1267
template class ofImage_<unsigned short>;
1268

1269
template<>
1270
std::string ofToString(const ofImageType & imgType){
1271
	switch(imgType) {
1272
		case OF_IMAGE_GRAYSCALE:
1273
			return "OF_IMAGE_GRAYSCALE";
1274
		break;
1275
		case OF_IMAGE_COLOR:
1276
			return "OF_IMAGE_COLOR";
1277
		break;
1278
		case  OF_IMAGE_COLOR_ALPHA:
1279
			return "OF_IMAGE_COLOR_ALPHA";
1280
		break;
1281
		case OF_IMAGE_UNDEFINED:
1282
			return "OF_IMAGE_UNDEFINED";
1283
		break;
1284
	}
1285
	return "OF_IMAGE_UNDEFINED";
1286
}
1287

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

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

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

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