1 ///////////////////////////////////////////////////////////////////////////////
2 //            Copyright (C) 2004-2010 by The Allacrost Project
3 //                         All Rights Reserved
4 //
5 // This code is licensed under the GNU GPL version 2. It is free software
6 // and you may modify it and/or redistribute it under the terms of this license.
7 // See http://www.gnu.org/copyleft/gpl.html for details.
8 ///////////////////////////////////////////////////////////////////////////////
9 
10 /** ****************************************************************************
11 *** \file    image_base.cpp
12 *** \author  Tyler Olsen, roots@allacrost.org
13 *** \brief   Source file for image base classes
14 *** ***************************************************************************/
15 
16 #include <cstdarg>
17 #include <math.h>
18 
19 #include "image_base.h"
20 #include "video.h"
21 
22 using namespace std;
23 using namespace hoa_utils;
24 
25 namespace hoa_video {
26 
27 namespace private_video {
28 
29 // -----------------------------------------------------------------------------
30 // ImageMemory class
31 // -----------------------------------------------------------------------------
32 
ImageMemory()33 ImageMemory::ImageMemory() :
34 	width(0),
35 	height(0),
36 	pixels(NULL),
37 	rgb_format(false)
38 {}
39 
40 
41 
~ImageMemory()42 ImageMemory::~ImageMemory() {
43 // Winter Knight - I commented this out because it was causing double free
44 // segfaults when ImageMemory objects were copied via copy constructor.
45 	if (pixels != NULL) {
46 		IF_PRINT_WARNING(VIDEO_DEBUG) << "pixels member was not NULL upon object destruction" << endl;
47 //		free(pixels);
48 //		pixels = NULL;
49 	}
50 }
51 
52 
53 
LoadImage(const string & filename)54 bool ImageMemory::LoadImage(const string& filename) {
55 	if (pixels != NULL) {
56 		IF_PRINT_WARNING(VIDEO_DEBUG) << "pixels member was not NULL upon function invocation" << endl;
57 		free(pixels);
58 		pixels = NULL;
59 	}
60 
61 	// Isolate the extension
62 	size_t ext_position = filename.rfind('.');
63 
64 	if (ext_position == string::npos) {
65 		IF_PRINT_WARNING(VIDEO_DEBUG) << "could not decipher file extension for filename: " << filename << endl;
66 		return false;
67 	}
68 
69 	string extension = string(filename, ext_position, filename.length() - ext_position);
70 
71 	// NOTE: We could technically try uppercase forms of the file extension, or also include the .jpeg extension name,
72 	// but Allacrost's file standard states that only the .png and .jpg image file extensions are suppported.
73 	if (extension == ".png")
74 		return _LoadPngImage(filename);
75 	else if (extension == ".jpg")
76 		return _LoadJpgImage(filename);
77 
78 	IF_PRINT_WARNING(VIDEO_DEBUG) << "unsupported file extension: \"" << extension << "\" for filename: " << filename << endl;
79 	return false;
80 }
81 
82 
83 
SaveImage(const string & filename,bool png_image)84 bool ImageMemory::SaveImage(const string& filename, bool png_image) {
85 	if (pixels == NULL) {
86 		IF_PRINT_WARNING(VIDEO_DEBUG) << "pixels member was NULL upon function invocation for file: " << filename << endl;
87 		return false;
88 	}
89 
90 	if (png_image) {
91 		return _SavePngImage(filename);
92 	}
93 	else {
94 		// JPG images don't have alpha information, so we must convert the data to RGB format first
95 		if (rgb_format == false)
96 			RGBAToRGB();
97 		return _SaveJpgImage(filename);
98 	}
99 }
100 
101 
102 
ConvertToGrayscale()103 void ImageMemory::ConvertToGrayscale() {
104 	if (width <= 0 || height <= 0) {
105 		IF_PRINT_WARNING(VIDEO_DEBUG) << "width and/or height members were invalid (<= 0)" << endl;
106 		return;
107 	}
108 
109 	if (pixels == NULL) {
110 		IF_PRINT_WARNING(VIDEO_DEBUG) << "no image data (pixels == NULL)" << endl;
111 		return;
112 	}
113 
114 	uint8 format_bytes = (rgb_format ? 3 : 4);
115 	uint8* end_position = static_cast<uint8*>(pixels) + (width * height * format_bytes);
116 
117 	for (uint8* i = static_cast<uint8*>(pixels); i < end_position; i += format_bytes) {
118 		// Compute the grayscale value for this pixel based on RGB values: 0.30R + 0.59G + 0.11B
119 		uint8 value = static_cast<uint8>((30 * *(i) + 59 * *(i + 1) + 11 * *(i + 2)) * 0.01f);
120 		*i = value;
121 		*(i + 1) = value;
122 		*(i + 2) = value;
123 		// *(i + 3) for RGBA is the alpha value and is left unmodified
124 	}
125 }
126 
127 
RGBAToRGB()128 void ImageMemory::RGBAToRGB() {
129 	if (width <= 0 || height <= 0) {
130 		IF_PRINT_WARNING(VIDEO_DEBUG) << "width and/or height members were invalid (<= 0)" << endl;
131 		return;
132 	}
133 
134 	if (pixels == NULL) {
135 		IF_PRINT_WARNING(VIDEO_DEBUG) << "no image data (pixels == NULL)" << endl;
136 		return;
137 	}
138 
139 	if (rgb_format == true) {
140 		IF_PRINT_WARNING(VIDEO_DEBUG) << "image data was said to already be in RGB format" << endl;
141 		return;
142 	}
143 
144 	uint8* pixel_index = static_cast<uint8*>(pixels);
145 	uint8* pixel_source = pixel_index;
146 
147 	for (int32 i = 0; i < height * width; i++, pixel_index += 4) {
148 		int32 index = 3 * i;
149 		pixel_source[index] = *pixel_index;
150 		pixel_source[index + 1] = *(pixel_index + 1);
151 		pixel_source[index + 2] = *(pixel_index + 2);
152 	}
153 
154 	// Reduce the memory consumed by 1/4 since we no longer need to contain alpha data
155 	pixels = realloc(pixels, width * height * 3);
156 	rgb_format = true;
157 }
158 
159 
160 
CopyFromTexture(TexSheet * texture)161 void ImageMemory::CopyFromTexture(TexSheet* texture) {
162 	if (pixels != NULL)
163 		free(pixels);
164 	pixels = NULL;
165 
166 	// Get the texture as a buffer
167 	height = texture->height;
168 	width = texture->width;
169 	pixels = malloc(height * width * (rgb_format ? 3 : 4));
170 	if (pixels == NULL) {
171 		PRINT_ERROR << "failed to malloc enough memory to copy the texture" << endl;
172 	}
173 
174 	TextureManager->_BindTexture(texture->tex_id);
175 	glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
176 }
177 
178 
179 
CopyFromImage(BaseTexture * img)180 void ImageMemory::CopyFromImage(BaseTexture* img) {
181 	// First copy the image's entire texture sheet to memory
182 	CopyFromTexture(img->texture_sheet);
183 
184 	// Check that the image to copy is smaller than its texture sheet (usually true).
185 	// If so, then copy over only the sub-rectangle area of the image from its texture
186 	if (height > img->height || width > img->width) {
187 		uint8 format_bytes = (rgb_format ? 3 : 4);
188 		uint32 src_bytes = width * format_bytes;
189 		uint32 dst_bytes = img->width * format_bytes;
190 		uint32 src_offset = img->y * width * format_bytes + img->x * format_bytes;
191 		void* img_pixels = malloc(img->width * img->height * format_bytes);
192 		if (img_pixels == NULL) {
193 			PRINT_ERROR << "failed to malloc enough memory to copy the image" << endl;
194 			return;
195 		}
196 
197 		for (int32 i = 0; i < img->height; i++) {
198 			memcpy((uint8*)img_pixels + i * dst_bytes, (uint8*)pixels + i * src_bytes + src_offset, dst_bytes);
199 		}
200 
201 		// Delete the memory used for the texture sheet and replace it with the memory for the image
202 		if (pixels)
203 			free(pixels);
204 
205 		height = img->height;
206 		width = img->width;
207 		pixels = img_pixels;
208 	}
209 }
210 
211 
212 
_LoadPngImage(const string & filename)213 bool ImageMemory::_LoadPngImage(const string& filename) {
214 	// open up the PNG
215 	FILE* fp = fopen(filename.c_str(), "rb");
216 
217 	if (fp == NULL)
218 		return false;
219 
220 	// check the signature to make sure it's a PNG
221 	uint8 test_buffer[8];
222 
223 	fread(test_buffer, 1, 8, fp);
224 	if (png_sig_cmp(test_buffer, 0, 8)) {
225 		fclose(fp);
226 		return false;
227 	}
228 
229 	// load the actual PNG
230 	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);
231 
232 	if (png_ptr == NULL) {
233 		fclose(fp);
234 		return false;
235 	}
236 
237 	// get the info structure
238 	png_infop info_ptr = png_create_info_struct(png_ptr);
239 
240 	if (info_ptr == NULL) {
241 		png_destroy_read_struct(&png_ptr, NULL, (png_infopp)NULL);
242 		fclose(fp);
243 		return false;
244 	}
245 
246 	// error handling
247 	if (setjmp(png_jmpbuf(png_ptr))) {
248 		png_destroy_read_struct(&png_ptr, NULL, (png_infopp)NULL);
249 		fclose(fp);
250 		return false;
251 	}
252 
253 	// read the PNG
254 	png_init_io(png_ptr, fp);
255 	png_set_sig_bytes(png_ptr, 8);
256 	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL);
257 
258 	// and get an array of pointers, one for each row of the PNG
259 	uint8** row_pointers = png_get_rows(png_ptr, info_ptr);
260 
261 	// copy metadata
262 	width = png_get_image_width(png_ptr, info_ptr);
263 	height = png_get_image_height(png_ptr, info_ptr);
264 	pixels = malloc(width * height * 4);
265 
266 	// check that we were able to allocate enough memory for the PNG
267 	if (pixels == NULL) {
268 		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
269 		fclose(fp);
270 		PRINT_ERROR << "failed to malloc sufficient memory for .png file: " << filename << endl;
271 		return false;
272 	}
273 
274 	// convert the damn thing so that it works in our format
275 	// this is mostly just byteswapping and adding extra data - we want everything in four channels
276 	// for the moment, anyway
277 	uint32 bpp = png_get_channels(png_ptr, info_ptr);
278 	uint8* img_pixel = NULL;
279 	uint8* dst_pixel = NULL;
280 
281 	if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) {
282 		// colours come from a palette - for this colour type, we have to look up the colour from the palette
283 		png_colorp palette;
284 		int num_palette;
285 		png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
286 		png_color c;
287 		for (uint32 y = 0; y < height; y++) {
288 			for (uint32 x = 0; x < width; x++) {
289 				img_pixel = row_pointers[y] + (x * bpp);
290 				dst_pixel = ((uint8*)pixels) + ((y * width) + x) * 4;
291 				c = palette[img_pixel[0]];
292 
293 				dst_pixel[0] = c.red;
294 				dst_pixel[1] = c.green;
295 				dst_pixel[2] = c.blue;
296 				dst_pixel[3] = 0xFF;
297 			}
298 		}
299 	}
300 	else if (bpp == 1) {
301 		for (uint32 y = 0; y < height; y++) {
302 			for (uint32 x = 0; x < width; x++) {
303 				img_pixel = row_pointers[y] + (x * bpp);
304 				dst_pixel = ((uint8*)pixels) + ((y * width) + x) * 4;
305 				dst_pixel[0] = img_pixel[0];
306 				dst_pixel[1] = img_pixel[0];
307 				dst_pixel[2] = img_pixel[0];
308 				dst_pixel[3] = 0xFF;
309 			}
310 		}
311 	}
312 	else if (bpp == 3) {
313 		for (uint32 y = 0; y < height; y++) {
314 			for (uint32 x = 0; x < width; x++) {
315 				img_pixel = row_pointers[y] + (x * bpp);
316 				dst_pixel = ((uint8*)pixels) + ((y * width) + x) * 4;
317 				dst_pixel[0] = img_pixel[0];
318 				dst_pixel[1] = img_pixel[1];
319 				dst_pixel[2] = img_pixel[2];
320 				dst_pixel[3] = 0xFF;
321 			}
322 		}
323 	}
324 	else if (bpp == 4) {
325 		for (uint32 y = 0; y < height; y++) {
326 			for (uint32 x = 0; x < width; x++) {
327 				img_pixel = row_pointers[y] + (x * bpp);
328 				dst_pixel = ((uint8*)pixels) + ((y * width) + x) * 4;
329 				dst_pixel[0] = img_pixel[0];
330 				dst_pixel[1] = img_pixel[1];
331 				dst_pixel[2] = img_pixel[2];
332 				dst_pixel[3] = img_pixel[3];
333 			}
334 		}
335 	}
336 	else {
337 		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
338 		fclose(fp);
339 		PRINT_ERROR << "failed to load .png file (bytes per pixel not supported): " << filename << endl;
340 		return false;
341 	}
342 
343 	// clean everything up
344 	png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
345 	fclose(fp);
346 
347 	rgb_format = false;
348 	return true;
349 } // bool ImageMemory::_LoadPngImage(const string& filename)
350 
351 
352 
_LoadJpgImage(const string & filename)353 bool ImageMemory::_LoadJpgImage(const string& filename) {
354 	// open the file
355 	FILE* fp;
356 	uint8** buffer;
357 
358 	if ((fp = fopen(filename.c_str(), "rb")) == NULL)
359 		return false;
360 
361 	// create the error-handing stuff and the main decompression object
362 	jpeg_decompress_struct cinfo;
363 	jpeg_error_mgr jerr;
364 
365 	cinfo.err = jpeg_std_error(&jerr);
366 	jpeg_create_decompress(&cinfo);
367 
368 	// tell it where to read, and read the header
369 	jpeg_stdio_src(&cinfo, fp);
370 	jpeg_read_header(&cinfo, TRUE);
371 
372 	// here we go, here we go, here we go!
373 	jpeg_start_decompress(&cinfo);
374 
375 	// how much space does each row take up?
376 	JDIMENSION row_stride = cinfo.output_width * cinfo.output_components;
377 
378 	// let's get us some MEMORY - but we use the jpeg library to do it so that it comes out of that memory pool
379 	buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
380 
381 	// metadata
382 	width = cinfo.output_width;
383 	height = cinfo.output_height;
384 	pixels = malloc(cinfo.output_width * cinfo.output_height * 3);
385 
386 	// swizzle everything so it's in the format we want
387 	uint32 bpp = cinfo.output_components;
388 	uint8* img_pixel = NULL;
389 	uint8* dst_pixel = NULL;
390 
391 	if (bpp == 3) {
392 		for (uint32 y = 0; y < cinfo.output_height; y++) {
393 			jpeg_read_scanlines(&cinfo, buffer, 1);
394 
395 			for(uint32 x = 0; x < cinfo.output_width; x++) {
396 				img_pixel = buffer[0] + (x * bpp);
397 				dst_pixel = ((uint8 *)pixels) + ((y * cinfo.output_width) + x) * 3;
398 
399 				dst_pixel[0] = img_pixel[0];
400 				dst_pixel[1] = img_pixel[1];
401 				dst_pixel[2] = img_pixel[2];
402 			}
403 		}
404 	}
405 	else if (bpp == 4) {
406 		for (uint32 y = 0; y < cinfo.output_height; y++) {
407 			jpeg_read_scanlines(&cinfo, buffer, 1);
408 
409 			for (uint32 x = 0; x < cinfo.output_width; x++) {
410 				img_pixel = buffer[0] + (x * bpp);
411 				dst_pixel = ((uint8 *)pixels) + ((y * cinfo.output_width) + x) * 3;
412 
413 				dst_pixel[0] = img_pixel[0];
414 				dst_pixel[1] = img_pixel[1];
415 				dst_pixel[2] = img_pixel[2];
416 			}
417 		}
418 	}
419 	else {
420 		jpeg_finish_decompress(&cinfo);
421 		jpeg_destroy_decompress(&cinfo);
422 		fclose(fp);
423 		PRINT_ERROR << "failed to load .jpg file (bytes per pixel not supported): " << filename << endl;
424 		return false;
425 	}
426 
427 	// clean up
428 	jpeg_finish_decompress(&cinfo);
429 	jpeg_destroy_decompress(&cinfo);
430 
431 	fclose(fp);
432 	rgb_format = true;
433 	return true;
434 } // bool ImageMemory::_LoadJpgImage(const string& filename)
435 
436 
437 
_SavePngImage(const std::string & filename) const438 bool ImageMemory::_SavePngImage(const std::string& filename) const {
439 	// open up the file for writing
440 	FILE* fp = fopen(filename.c_str(), "wb");
441 
442 	if (fp == NULL) {
443 		IF_PRINT_WARNING(VIDEO_DEBUG) << "could not open file: " << filename << endl;
444 		return false;
445 	}
446 
447 	// aah, RGB data! We can only handle RGBA at the moment
448 	if (rgb_format == true) {
449 		IF_PRINT_WARNING(VIDEO_DEBUG) << "attempting to save RGB format image data as a RGBA format PNG image" << endl;
450 	}
451 
452 	// grab a write structure
453 	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);
454 
455 	if (!png_ptr) {
456 		IF_PRINT_WARNING(VIDEO_DEBUG) << "png_create_write_struct() failed for file: " << filename << endl;
457 		fclose(fp);
458 		return false;
459 	}
460 
461 	// and a place to store the metadata
462 	png_infop info_ptr = png_create_info_struct(png_ptr);
463 
464 	if (!info_ptr) {
465 		IF_PRINT_WARNING(VIDEO_DEBUG) << "png_create_info_struct() failed for file: " << filename << endl;
466 		png_destroy_write_struct(&png_ptr, NULL);
467 		fclose(fp);
468 		return false;
469 	}
470 
471 	// prepare for error handling!
472 	if (setjmp(png_jmpbuf(png_ptr))) {
473 		IF_PRINT_WARNING(VIDEO_DEBUG) << "setjmp returned non-zero for file: " << filename << endl;
474 		png_destroy_write_struct(&png_ptr, &info_ptr);
475 		fclose(fp);
476 		return false;
477 	}
478 
479 	// tell it where to look
480 	png_init_io(png_ptr, fp);
481 
482 	// write the header
483 	png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
484 		PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
485 
486 	// get the row array from our data
487 	png_byte** row_pointers = new png_byte*[height];
488 	int32 bytes_per_row = width * 4;
489 	for (int32 i = 0; i < height; i++) {
490 		row_pointers[i] = (png_byte*)pixels + bytes_per_row * i;
491 	}
492 
493 	// tell it what the rows are
494 	png_set_rows(png_ptr, info_ptr, row_pointers);
495 	// and write the PNG
496 	png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
497 	png_write_image(png_ptr, row_pointers);
498 	// clean up
499 	png_write_end(png_ptr, info_ptr);
500 	png_destroy_write_struct(&png_ptr, &info_ptr);
501 
502 	// free the memory we ate
503 	delete[] row_pointers;
504 
505 	// peace and love for all
506 	return true;
507 } // bool ImageMemory::_SavePngImage(const std::string& filename) const
508 
509 
510 
_SaveJpgImage(const std::string & filename) const511 bool ImageMemory::_SaveJpgImage(const std::string& filename) const {
512 	FILE* fp = fopen(filename.c_str(), "wb");
513 	if (fp == NULL) {
514 		IF_PRINT_WARNING(VIDEO_DEBUG) << "could not open file: " << filename << endl;
515 		return false;
516 	}
517 
518 	// we don't support RGBA because JPEGs don't support alpha
519 	if (rgb_format == false) {
520 		IF_PRINT_WARNING(VIDEO_DEBUG) << "attempting to save non-RGB format pixel data as a RGB format JPG image" << endl;
521 	}
522 
523 	// compression object and error handling
524 	jpeg_compress_struct cinfo;
525 	jpeg_error_mgr jerr;
526 
527 	cinfo.err = jpeg_std_error(&jerr);
528 	jpeg_create_compress(&cinfo);
529 
530 	// tell libjpeg how we do things in this town
531 	cinfo.in_color_space = JCS_RGB;
532 	cinfo.image_width = width;
533 	cinfo.image_height = height;
534 	cinfo.input_components = 3;
535 
536 	// everything else can be default
537 	jpeg_set_defaults(&cinfo);
538 	// tell it where to look
539 	jpeg_stdio_dest(&cinfo, fp);
540 	// compress it
541 	jpeg_start_compress(&cinfo, TRUE);
542 
543 	JSAMPROW row_pointer; // A pointer to a single row
544 	uint32 row_stride = width * 3; // The physical row width in the buffer (RGB)
545 
546 	// Note that the lines have to be stored from top to bottom
547 	while (cinfo.next_scanline < cinfo.image_height) {
548 		row_pointer = (uint8*)pixels + cinfo.next_scanline * row_stride;
549 	    jpeg_write_scanlines(&cinfo, &row_pointer, 1);
550 	}
551 
552 	// compression is DONE, we are HAPPY
553 	// now finish it and clean up
554 	jpeg_finish_compress(&cinfo);
555 	jpeg_destroy_compress(&cinfo);
556 
557 	fclose(fp);
558 	return true;
559 } // bool ImageMemory::_SaveJpgImage(const std::string& file_name) const
560 
561 // -----------------------------------------------------------------------------
562 // BaseTexture class
563 // -----------------------------------------------------------------------------
564 
BaseTexture()565 BaseTexture::BaseTexture() :
566 	texture_sheet(NULL),
567 	width(0),
568 	height(0),
569 	x(0),
570 	y(0),
571 	u1(0.0f),
572 	v1(0.0f),
573 	u2(0.0f),
574 	v2(0.0f),
575 	smooth(false),
576 	ref_count(0)
577 {}
578 
579 
580 
BaseTexture(int32 width_,int32 height_)581 BaseTexture::BaseTexture(int32 width_, int32 height_) :
582 	texture_sheet(NULL),
583 	width(width_),
584 	height(height_),
585 	x(0),
586 	y(0),
587 	u1(0.0f),
588 	v1(0.0f),
589 	u2(0.0f),
590 	v2(0.0f),
591 	smooth(false),
592 	ref_count(0)
593 {}
594 
595 
596 
BaseTexture(TexSheet * texture_sheet_,int32 width_,int32 height_)597 BaseTexture::BaseTexture(TexSheet* texture_sheet_, int32 width_, int32 height_) :
598 	texture_sheet(texture_sheet_),
599 	width(width_),
600 	height(height_),
601 	x(0),
602 	y(0),
603 	u1(0.0f),
604 	v1(0.0f),
605 	u2(0.0f),
606 	v2(0.0f),
607 	smooth(false),
608 	ref_count(0)
609 {}
610 
611 
612 
~BaseTexture()613 BaseTexture::~BaseTexture() {
614 	if (ref_count > 0) {
615 		IF_PRINT_WARNING(VIDEO_DEBUG) << "destructor invoked when the object had a reference count greater than zero: " << ref_count << endl;
616 	}
617 }
618 
619 
620 
RemoveReference()621 bool BaseTexture::RemoveReference() {
622 	ref_count--;
623 
624 	if (ref_count < 0) {
625 		IF_PRINT_WARNING(VIDEO_DEBUG) << "texture ref_count member is now negative: " << ref_count << endl;
626 		return true;
627 	}
628 	else if (ref_count == 0)
629 		return true;
630 	else
631 		return false;
632 }
633 
634 // -----------------------------------------------------------------------------
635 // ImageTexture class
636 // -----------------------------------------------------------------------------
637 
ImageTexture(const string & filename_,const string & tags_,int32 width_,int32 height_)638 ImageTexture::ImageTexture(const string& filename_, const string& tags_, int32 width_, int32 height_) :
639 	BaseTexture(width_, height_),
640 	filename(filename_),
641 	tags(tags_)
642 {
643 	if (VIDEO_DEBUG) {
644 		if (TextureManager->_IsImageTextureRegistered(filename + tags))
645 			PRINT_WARNING << "constructor invoked when ImageTexture was already referenced for: " << filename << tags << endl;
646 	}
647 
648 	TextureManager->_RegisterImageTexture(this);
649 }
650 
651 
652 
ImageTexture(TexSheet * texture_sheet_,const string & filename_,const string & tags_,int32 width_,int32 height_)653 ImageTexture::ImageTexture(TexSheet* texture_sheet_, const string& filename_, const string& tags_, int32 width_, int32 height_) :
654 	BaseTexture(texture_sheet_, width_, height_),
655 	filename(filename_),
656 	tags(tags_)
657 {
658 	if (VIDEO_DEBUG) {
659 		if (TextureManager->_IsImageTextureRegistered(filename + tags))
660 			PRINT_WARNING << "constructor invoked when ImageTexture was already referenced for: " << filename << tags << endl;
661 	}
662 
663 	TextureManager->_RegisterImageTexture(this);
664 }
665 
666 
667 
~ImageTexture()668 ImageTexture::~ImageTexture() {
669 	// Remove this instance from the texture manager
670 	TextureManager->_UnregisterImageTexture(this);
671 }
672 
673 } // namespace private_video
674 
675 } // namespace hoa_video
676