xlColor PixelBufferClass::mixColors(const wxCoord &x, const wxCoord &y, const xlColor &fg, const xlColor &c1, int layer) { static const int n = 0; //increase to change the curve of the crossfade xlColor c0 = fg; HSVValue hsv0; HSVValue hsv1; bool handlesAlpha = MixTypeHandlesAlpha(layers[layer]->mixType); if (!handlesAlpha && layers[layer]->fadeFactor != 1.0) { //need to fade the first here as we're not mixing anything hsv0 = c0.asHSV(); hsv0.value *= layers[layer]->fadeFactor; c0 = hsv0; } float svthresh = layers[layer]->effectMixThreshold; if (layers[layer]->effectMixVaries) { //vary mix threshold gradually during effect interval -DJ layers[layer]->effectMixThreshold = layers[layer]->buffer.GetEffectTimeIntervalPosition(); } if (layers[layer]->effectMixThreshold < 0) { layers[layer]->effectMixThreshold = 0; } xlColor c; double emt, emtNot; switch (layers[layer]->mixType) { case Mix_Normal: c0.alpha = c0.alpha * layers[layer]->fadeFactor * (1.0 - layers[layer]->effectMixThreshold); c = c0.AlphaBlend(c1); break; case Mix_Effect1: case Mix_Effect2: { if (!layers[layer]->effectMixVaries) { emt = layers[layer]->effectMixThreshold; if ((emt > 0.000001) && (emt < 0.99999)) { emtNot = 1-layers[layer]->effectMixThreshold; //make cross-fade linear emt = cos((M_PI/4)*(pow(2*emt-1,2*n+1)+1)); emtNot = cos((M_PI/4)*(pow(2*emtNot-1,2*n+1)+1)); } else { emtNot = layers[layer]->effectMixThreshold; emt = 1 - layers[layer]->effectMixThreshold; } } else { emt = layers[layer]->effectMixThreshold; emtNot = 1-layers[layer]->effectMixThreshold; } xlColor c2(c1); if (layers[layer]->mixType == Mix_Effect2) { c0.Set(c0.Red()*(emtNot),c0.Green()*(emtNot), c0.Blue()*(emtNot)); c2.Set(c1.Red()*(emt),c1.Green()*(emt), c1.Blue()*(emt)); } else { c0.Set(c0.Red()*(emt),c0.Green()*(emt), c0.Blue()*(emt)); c2.Set(c1.Red()*(emtNot),c1.Green()*(emtNot), c1.Blue()*(emtNot)); } c.Set(c0.Red()+c2.Red(), c0.Green()+c2.Green(), c0.Blue()+c2.Blue()); break; } case Mix_Mask1: // first masks second hsv0 = c0.asHSV(); if (hsv0.value <= layers[layer]->effectMixThreshold) { // only if effect 1 is black c=c1; // then show the color of effect 2 } else { c.Set(0, 0, 0); } break; case Mix_Mask2: // second masks first hsv1 = c1.asHSV(); if (hsv1.value <= layers[layer]->effectMixThreshold) { c=c0; } else { c.Set(0, 0, 0); } break; case Mix_Unmask1: // first unmasks second c0.toHSV(hsv0); c1.toHSV(hsv1); if (hsv0.value > layers[layer]->effectMixThreshold) { // if effect 1 is non black hsv1.value = hsv0.value; c = hsv1; } else { c.Set(0, 0, 0); } break; case Mix_Unmask2: // second unmasks first c0.toHSV(hsv0); c1.toHSV(hsv1); if (hsv1.value > layers[layer]->effectMixThreshold) { // if effect 2 is non black hsv0.value = hsv1.value; c = hsv0; } else { c.Set(0, 0, 0); } break; case Mix_Shadow_1on2: // Effect 1 shadows onto effect 2 c0.toHSV(hsv0); c1.toHSV(hsv1); // if (hsv0.value > effectMixThreshold[layer]) { // if effect 1 is non black // to shadow we will shift the hue on the primary layer using the hue and brightness from the // other layer if(hsv0.value>0.0) hsv1.hue = hsv1.hue + (hsv0.value*(hsv1.hue-hsv0.hue))/5.0; // hsv1.value = hsv0.value; //hsv1.saturation = hsv0.saturation; c = hsv1; // } break; case Mix_Shadow_2on1: // Effect 2 shadows onto effect 1 c0.toHSV(hsv0); c1.toHSV(hsv1); //if (hsv1.value > effectMixThreshold[layer]) { // if effect 1 is non black if(hsv1.value>0.0) hsv0.hue = hsv0.hue + (hsv1.value*(hsv0.hue-hsv1.hue))/2.0; //hsv0.value = hsv1.value; //hsv0.saturation = hsv1.saturation; c = hsv0; // } break; case Mix_Layered: c1.toHSV(hsv1); if (hsv1.value <= layers[layer]->effectMixThreshold) { c=c0; } else { c=c1; } break; case Mix_Average: // only average when both colors are non-black if (c0 == xlBLACK) { c=c1; } else if (c1 == xlBLACK) { c=c0; } else { c.Set( (c0.Red()+c1.Red())/2, (c0.Green()+c1.Green())/2, (c0.Blue()+c1.Blue())/2 ); } break; case Mix_BottomTop: c= y < layers[layer]->BufferHt/2 ? c0 : c1; break; case Mix_LeftRight: c= x < layers[layer]->BufferWi/2 ? c0 : c1; break; case Mix_1_reveals_2: c0.toHSV(hsv0); c = hsv0.value > layers[layer]->effectMixThreshold ? c0 : c1; // if effect 1 is non black break; case Mix_2_reveals_1: c1.toHSV(hsv1); c = hsv1.value > layers[layer]->effectMixThreshold ? c1 : c0; // if effect 2 is non black break; } if (layers[layer]->effectMixVaries) { layers[layer]->effectMixThreshold = svthresh; //put it back afterwards in case next row didn't change it } return c; }