| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  image_quantize.cpp                                                   */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                    http://www.godotengine.org                         */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2017-01-01 22:01:57 +01:00
										 |  |  | /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							| 
									
										
										
										
											2017-04-08 00:45:00 +02:00
										 |  |  | /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | #include "image.h"
 | 
					
						
							|  |  |  | #include "print_string.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | #include "os/os.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #include "set.h"
 | 
					
						
							|  |  |  | #include "sort.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //#define QUANTIZE_SPEED_OVER_QUALITY
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Image::MCBlock::MCBlock() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | Image::MCBlock::MCBlock(BColorPos *p_colors, int p_color_count) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	colors = p_colors; | 
					
						
							|  |  |  | 	color_count = p_color_count; | 
					
						
							|  |  |  | 	min_color.color = BColor(255, 255, 255, 255); | 
					
						
							|  |  |  | 	max_color.color = BColor(0, 0, 0, 0); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	shrink(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int Image::MCBlock::get_longest_axis_index() const { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	int max_dist = -1; | 
					
						
							|  |  |  | 	int max_index = 0; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	for (int i = 0; i < 4; i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		int d = max_color.color.col[i] - min_color.color.col[i]; | 
					
						
							|  |  |  | 		if (d > max_dist) { | 
					
						
							|  |  |  | 			max_index = i; | 
					
						
							|  |  |  | 			max_dist = d; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return max_index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | int Image::MCBlock::get_longest_axis_length() const { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	int max_dist = -1; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	for (int i = 0; i < 4; i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		int d = max_color.color.col[i] - min_color.color.col[i]; | 
					
						
							|  |  |  | 		if (d > max_dist) { | 
					
						
							|  |  |  | 			max_dist = d; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return max_dist; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | bool Image::MCBlock::operator<(const MCBlock &p_block) const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	int alen = get_longest_axis_length(); | 
					
						
							|  |  |  | 	int blen = p_block.get_longest_axis_length(); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (alen == blen) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return colors < p_block.colors; | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 		return alen < blen; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Image::MCBlock::shrink() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	min_color = colors[0]; | 
					
						
							|  |  |  | 	max_color = colors[0]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	for (int i = 1; i < color_count; i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		for (int j = 0; j < 4; j++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			min_color.color.col[j] = MIN(min_color.color.col[j], colors[i].color.col[j]); | 
					
						
							|  |  |  | 			max_color.color.col[j] = MAX(max_color.color.col[j], colors[i].color.col[j]); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Image::quantize() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	bool has_alpha = detect_alpha() != ALPHA_NONE; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	bool quantize_fast = OS::get_singleton()->has_environment("QUANTIZE_FAST"); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	convert(FORMAT_RGBA); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	ERR_FAIL_COND(format != FORMAT_RGBA); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	DVector<uint8_t> indexed_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		int color_count = data.size() / 4; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		ERR_FAIL_COND(color_count == 0); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Set<MCBlock> block_queue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		DVector<BColorPos> data_colors; | 
					
						
							|  |  |  | 		data_colors.resize(color_count); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		DVector<BColorPos>::Write dcw = data_colors.write(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		DVector<uint8_t>::Read dr = data.read(); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		const BColor *drptr = (const BColor *)&dr[0]; | 
					
						
							|  |  |  | 		BColorPos *bcptr = &dcw[0]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			for (int i = 0; i < color_count; i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				//uint32_t data_ofs=i<<2;
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				bcptr[i].color = drptr[i]; //BColor(drptr[data_ofs+0],drptr[data_ofs+1],drptr[data_ofs+2],drptr[data_ofs+3]);
 | 
					
						
							|  |  |  | 				bcptr[i].index = i; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		//printf("color count: %i\n",color_count);
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		for(int i=0;i<color_count;i++) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			BColor bc = ((BColor*)&wb[0])[i]; | 
					
						
							|  |  |  | 			printf("%i - %i,%i,%i,%i\n",i,bc.r,bc.g,bc.b,bc.a); | 
					
						
							|  |  |  | 		}*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		MCBlock initial_block((BColorPos *)&dcw[0], color_count); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		block_queue.insert(initial_block); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		while (block_queue.size() < 256 && block_queue.back()->get().color_count > 1) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			MCBlock longest = block_queue.back()->get(); | 
					
						
							|  |  |  | 			//printf("longest: %i (%i)\n",longest.get_longest_axis_index(),longest.get_longest_axis_length());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			block_queue.erase(block_queue.back()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			BColorPos *first = longest.colors; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			BColorPos *median = longest.colors + (longest.color_count + 1) / 2; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			BColorPos *end = longest.colors + longest.color_count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 			int lai =longest.get_longest_axis_index(); | 
					
						
							|  |  |  | 			switch(lai) { | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 				case 0: { SortArray<BColorPos,BColorPos::SortR> sort; sort.sort(first,end-first); } break; | 
					
						
							|  |  |  | 				case 1: { SortArray<BColorPos,BColorPos::SortG> sort; sort.sort(first,end-first); } break; | 
					
						
							|  |  |  | 				case 2: { SortArray<BColorPos,BColorPos::SortB> sort; sort.sort(first,end-first); } break; | 
					
						
							|  |  |  | 				case 3: { SortArray<BColorPos,BColorPos::SortA> sort; sort.sort(first,end-first); } break; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 				case 0: { SortArray<BColorPos,BColorPos::SortR> sort; sort.nth_element(0,end-first,median-first,first); } break; | 
					
						
							|  |  |  | 				case 1: { SortArray<BColorPos,BColorPos::SortG> sort; sort.nth_element(0,end-first,median-first,first); } break; | 
					
						
							|  |  |  | 				case 2: { SortArray<BColorPos,BColorPos::SortB> sort; sort.nth_element(0,end-first,median-first,first); } break; | 
					
						
							|  |  |  | 				case 3: { SortArray<BColorPos,BColorPos::SortA> sort; sort.nth_element(0,end-first,median-first,first); } break; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			//avoid same color from being split in 2
 | 
					
						
							|  |  |  | 			//search forward and flip
 | 
					
						
							|  |  |  | 			BColorPos *median_end=median; | 
					
						
							|  |  |  | 			BColorPos *p=median_end+1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			while(p!=end) { | 
					
						
							|  |  |  | 				if (median_end->color==p->color) { | 
					
						
							|  |  |  | 					SWAP(*(median_end+1),*p); | 
					
						
							|  |  |  | 					median_end++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				p++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			//search backward and flip
 | 
					
						
							|  |  |  | 			BColorPos *median_begin=median; | 
					
						
							|  |  |  | 			p=median_begin-1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			while(p!=(first-1)) { | 
					
						
							|  |  |  | 				if (median_begin->color==p->color) { | 
					
						
							|  |  |  | 					SWAP(*(median_begin-1),*p); | 
					
						
							|  |  |  | 					median_begin--; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				p--; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (first < median_begin) { | 
					
						
							|  |  |  | 				median=median_begin; | 
					
						
							|  |  |  | 			} else if (median_end < end-1) { | 
					
						
							|  |  |  | 				median=median_end+1; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				break; //shouldn't have arrived here, since it means all pixels are equal, but wathever
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			MCBlock left(first,median-first); | 
					
						
							|  |  |  | 			MCBlock right(median,end-median); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			block_queue.insert(left); | 
					
						
							|  |  |  | 			block_queue.insert(right); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			switch (longest.get_longest_axis_index()) { | 
					
						
							|  |  |  | 				case 0: { | 
					
						
							|  |  |  | 					SortArray<BColorPos, BColorPos::SortR> sort; | 
					
						
							|  |  |  | 					sort.nth_element(0, end - first, median - first, first); | 
					
						
							|  |  |  | 				} break; | 
					
						
							|  |  |  | 				case 1: { | 
					
						
							|  |  |  | 					SortArray<BColorPos, BColorPos::SortG> sort; | 
					
						
							|  |  |  | 					sort.nth_element(0, end - first, median - first, first); | 
					
						
							|  |  |  | 				} break; | 
					
						
							|  |  |  | 				case 2: { | 
					
						
							|  |  |  | 					SortArray<BColorPos, BColorPos::SortB> sort; | 
					
						
							|  |  |  | 					sort.nth_element(0, end - first, median - first, first); | 
					
						
							|  |  |  | 				} break; | 
					
						
							|  |  |  | 				case 3: { | 
					
						
							|  |  |  | 					SortArray<BColorPos, BColorPos::SortA> sort; | 
					
						
							|  |  |  | 					sort.nth_element(0, end - first, median - first, first); | 
					
						
							|  |  |  | 				} break; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			MCBlock left(first, median - first); | 
					
						
							|  |  |  | 			MCBlock right(median, end - median); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			block_queue.insert(left); | 
					
						
							|  |  |  | 			block_queue.insert(right); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		while (block_queue.size() > 256) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			block_queue.erase(block_queue.front()); // erase least significant
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		int res_colors = 0; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		int comp_size = (has_alpha ? 4 : 3); | 
					
						
							|  |  |  | 		indexed_data.resize(color_count + 256 * comp_size); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		DVector<uint8_t>::Write iw = indexed_data.write(); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		uint8_t *iwptr = &iw[0]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		BColor pallete[256]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		//	print_line("applying quantization - res colors "+itos(block_queue.size()));
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		while (block_queue.size()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			const MCBlock &b = block_queue.back()->get(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			uint64_t sum[4] = { 0, 0, 0, 0 }; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			for (int i = 0; i < b.color_count; i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				sum[0] += b.colors[i].color.col[0]; | 
					
						
							|  |  |  | 				sum[1] += b.colors[i].color.col[1]; | 
					
						
							|  |  |  | 				sum[2] += b.colors[i].color.col[2]; | 
					
						
							|  |  |  | 				sum[3] += b.colors[i].color.col[3]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			BColor c(sum[0] / b.color_count, sum[1] / b.color_count, sum[2] / b.color_count, sum[3] / b.color_count); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			//printf(" %i: %i,%i,%i,%i out of %i\n",res_colors,c.r,c.g,c.b,c.a,b.color_count);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			for (int i = 0; i < comp_size; i++) { | 
					
						
							|  |  |  | 				iwptr[color_count + res_colors * comp_size + i] = c.col[i]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (quantize_fast) { | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				for (int i = 0; i < b.color_count; i++) { | 
					
						
							|  |  |  | 					iwptr[b.colors[i].index] = res_colors; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				pallete[res_colors] = c; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			res_colors++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			block_queue.erase(block_queue.back()); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!quantize_fast) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			for (int i = 0; i < color_count; i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				const BColor &c = drptr[i]; | 
					
						
							|  |  |  | 				uint8_t best_dist_idx = 0; | 
					
						
							|  |  |  | 				uint32_t dist = 0xFFFFFFFF; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				for (int j = 0; j < res_colors; j++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 					const BColor &pc = pallete[j]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					uint32_t d = 0; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 					{ | 
					
						
							|  |  |  | 						int16_t v = (int16_t)c.r - (int16_t)pc.r; | 
					
						
							|  |  |  | 						d += v * v; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						int16_t v = (int16_t)c.g - (int16_t)pc.g; | 
					
						
							|  |  |  | 						d += v * v; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						int16_t v = (int16_t)c.b - (int16_t)pc.b; | 
					
						
							|  |  |  | 						d += v * v; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						int16_t v = (int16_t)c.a - (int16_t)pc.a; | 
					
						
							|  |  |  | 						d += v * v; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 					if (d <= dist) { | 
					
						
							|  |  |  | 						best_dist_idx = j; | 
					
						
							|  |  |  | 						dist = d; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				iwptr[i] = best_dist_idx; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		//iw = DVector<uint8_t>::Write();
 | 
					
						
							|  |  |  | 		//dr = DVector<uint8_t>::Read();
 | 
					
						
							|  |  |  | 		//wb = DVector<uint8_t>::Write();
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	print_line(itos(indexed_data.size())); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	data = indexed_data; | 
					
						
							|  |  |  | 	format = has_alpha ? FORMAT_INDEXED_ALPHA : FORMAT_INDEXED; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | } //do none
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Image::quantize() {} //do none
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 |