# Overoptimizers anonymous - Hue shifting

This topic is 2334 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

This maybe should go in the general forum, but since it deals with color spaces I'm putting it here and it can be moved if desired.

Anyway.... Can you make it faster/better?

The goal is to write a function that accepts a 32-bit ARGB color and an signed integral number of degrees. The function returns the result of shifting the hue of the color by the number of degrees indicated.

Relevant info: http://en.wikipedia.org/wiki/Hue

Note - the forum is doing nastiness to my indentation, sorry.

 //Just for fun, trying to create the fastest possible //hue_shift function for the 32-bit ARGB color space. //Here's what I have so far: union uCol { struct { BYTE blue; BYTE green; BYTE red; BYTE alpha; }; BYTE channels[4]; UINT uint; }; BYTE region_lut[] = {3, 4, 0xFF, 5, 2, 0xFF, 1, 0}; uCol hue_shift(uCol rgba, int degrees) { int hue, region; BYTE range, minim; /* [ASM BLOCK TRANSLATION INTO C++] int index = 0; if(rgba.red >= rgba.green) {index += 1;} if(rgba.red >= rgba.blue) {index += 2;} if(rgba.green >= rgba.blue) {index += 4;} region = region_lut[index]; */ __asm { pushad //push the registers to the stack xor eax,eax //clear register a movzx ebx,rgba.red //place the red channel in b movzx ecx,rgba.green //green in c movzx edx,rgba.blue //blue in d cmp ebx,ecx //compare b and c jl test02 //if b is less than c goto next test or eax,1 //else set bit 1 in register a test02: cmp ebx,edx //compare b and d jl test03 //if b is less than d goto next test or eax,2 //else set bit 2 in register a test03: cmp ecx,edx //compare c and d jl lookup //if c is less than d goto lookup or eax,4 //else set bit 3 in register a lookup: movzx ebx,region_lut[eax] //place the lookup value in register b mov region,ebx //copy b to the variable 'region' popad //restore the register values } switch(region) { case 0: //RGB range = rgba.red; hue = rgba.green; minim = rgba.blue; break; case 1: //GRB range = rgba.green; hue = rgba.red; minim = rgba.blue; break; case 2: //GBR range = rgba.green; hue = rgba.blue; minim = rgba.red; break; case 3: //BGR range = rgba.blue; hue = rgba.green; minim = rgba.red; break; case 4: //BRG range = rgba.blue; hue = rgba.red; minim = rgba.green; break; case 5: //RBG range = rgba.red; hue = rgba.blue; minim = rgba.green; break; default: break; //error } //There is no saturation, so the color is not changed. if(range == minim) {return rgba;} range -= minim; hue -= minim; if(region & 1) {hue = range - hue;} /* [ASM BLOCK TRANSLATION INTO C++] region += degrees / 60; int new_hue = degrees % 60; new_hue *= range; new_hue /= 60; new_hue += hue; if(new_hue < 0) { new_hue += range; --region; } if(new_hue > range) { new_hue -= range; ++region; } hue = (BYTE)new_hue; region %= 6; if(region < 0) {region += 6;} range += minim; */ __asm { pushad xor edx,edx mov eax,degrees mov ebx,60 cdq idiv ebx //we're dividing 'degrees' by 60 add region,eax //adding the whole number part to 'region' movzx ecx,range imul edx,ecx //multiplying the remainder by 'range' mov eax,edx xor edx,edx cdq idiv ebx //then dividing it by 60 add eax,hue //and adding 'hue' to it //This section corrects the value such that it is gequal zero and //lequal 'range' and finally sets 'hue' to the resulting value. //If the value has to be up-stepped (have 'range' added to it) //then 'region' is decremented. If the value has to be down- //stepped ('range' subtracted) then 'region' is incremented. cmp eax,0 jge geq_zero add eax,ecx dec region jmp leq_rang geq_zero: cmp eax,ecx jle leq_rang sub eax,ecx inc region leq_rang: mov hue,eax //Here we correct 'region' to be within the range 0 to 5. //Then just kick out the result values to memory and finish //the block. mov ebx,6 xor edx,edx mov eax,region cdq idiv ebx cmp edx,0 jge done add edx,6 done: mov region,edx add cl,minim mov range,cl popad } switch(region) { case 0: //RGB rgba.red = range; rgba.green = minim + (BYTE)hue; rgba.blue = minim; break; case 1: //GRB rgba.green = range; rgba.red = range - (BYTE)hue; rgba.blue = minim; break; case 2: //GBR rgba.green = range; rgba.blue = minim + (BYTE)hue; rgba.red = minim; break; case 3: //BGR rgba.blue = range; rgba.green = range - (BYTE)hue; rgba.red = minim; break; case 4: //BRG rgba.blue = range; rgba.red = minim + (BYTE)hue; rgba.green = minim; break; case 5: //RBG rgba.red = range; rgba.blue = range - (BYTE)hue; rgba.green = minim; break; default: break; //error } return rgba; }  Edited by Khatharr

1. 1
2. 2
3. 3
Rutin
25
4. 4
5. 5
khawk
14

• 11
• 11
• 23
• 10
• 9
• ### Forum Statistics

• Total Topics
633649
• Total Posts
3013117
×