//Make this an extension method so there's not an AForge dependence wherever EMB is used public static void ChangeHue(this EmbEntry entry, double hue, double _saturation, double lightness) { float brightness = (float)lightness / 5f; float saturation = (float)_saturation; Bitmap bitmap = (Bitmap)entry.DdsImage; // Apply filters var hueFilter = new AForge.Imaging.Filters.HueAdjustment((int)hue); var hslFilter = new AForge.Imaging.Filters.HSLLinear(); //Apply filters hueFilter.ApplyInPlace(bitmap); if (lightness > 0 || saturation > 0) { //Taken from: https://csharp.hotexamples.com/examples/AForge.Imaging.Filters/HSLLinear/-/php-hsllinear-class-examples.html // create luminance filter if (brightness > 0) { hslFilter.InLuminance = new Range(0.0f, 1.0f - brightness); //TODO - isn't it better not to truncate, but compress? hslFilter.OutLuminance = new Range(brightness, 1.0f); } else { hslFilter.InLuminance = new Range(-brightness, 1.0f); hslFilter.OutLuminance = new Range(0.0f, 1.0f + brightness); } // create saturation filter if (saturation > 0) { hslFilter.InSaturation = new Range(0.0f, 1.0f - saturation); //Ditto? hslFilter.OutSaturation = new Range(saturation, 1.0f); } else { hslFilter.InSaturation = new Range(-saturation, 1.0f); hslFilter.OutSaturation = new Range(0.0f, 1.0f + saturation); } if (hslFilter.FormatTranslations.ContainsKey(bitmap.PixelFormat)) { hslFilter.ApplyInPlace(bitmap); } } //Convert back to WPF Bitmap entry.DdsImage = (WriteableBitmap)bitmap; entry.wasEdited = true; }
//Make this an extension method so there's not an AForge dependence wherever EMB is used public static void ChangeHue(this EmbEntry entry, double hue, double _saturation, double lightness, List <IUndoRedo> undos = null, bool hueSet = false, int variance = 0) { float brightness = (float)lightness / 5f; float saturation = (float)_saturation; WriteableBitmap oldBitmap = entry.DdsImage; Bitmap bitmap = (Bitmap)entry.DdsImage; if (hueSet) { if (variance != 0) { hue += Random.Range(-variance, variance); } var hueFilter = new AForge.Imaging.Filters.HueModifier((int)hue); hueFilter.ApplyInPlace(bitmap); } else { //Hue Adjustment (shifting) // Apply filters var hueFilter = new AForge.Imaging.Filters.HueAdjustment((int)hue); var hslFilter = new AForge.Imaging.Filters.HSLLinear(); //Apply filters hueFilter.ApplyInPlace(bitmap); if (lightness > 0 || saturation > 0) { //Taken from: https://csharp.hotexamples.com/examples/AForge.Imaging.Filters/HSLLinear/-/php-hsllinear-class-examples.html // create luminance filter if (brightness > 0) { hslFilter.InLuminance = new Range(0.0f, 1.0f - brightness); //TODO - isn't it better not to truncate, but compress? hslFilter.OutLuminance = new Range(brightness, 1.0f); } else { hslFilter.InLuminance = new Range(-brightness, 1.0f); hslFilter.OutLuminance = new Range(0.0f, 1.0f + brightness); } // create saturation filter if (saturation > 0) { hslFilter.InSaturation = new Range(0.0f, 1.0f - saturation); //Ditto? hslFilter.OutSaturation = new Range(saturation, 1.0f); } else { hslFilter.InSaturation = new Range(-saturation, 1.0f); hslFilter.OutSaturation = new Range(0.0f, 1.0f + saturation); } if (hslFilter.FormatTranslations.ContainsKey(bitmap.PixelFormat)) { hslFilter.ApplyInPlace(bitmap); } } } //Convert back to WPF Bitmap entry.DdsImage = (WriteableBitmap)bitmap; entry.wasEdited = true; if (undos != null) { undos.Add(new UndoableProperty <EmbEntry>(nameof(EmbEntry.DdsImage), entry, oldBitmap, entry.DdsImage)); } }
private async Task ProcessImage() { //If we are already waiting on another process request, then stop here. if (isImageProcessing) { return; } isImageProcessing = true; //If enough time has not passed since the last process then we must enter a waiting state if (stopwatch.ElapsedMilliseconds < previewDelay) { //For loop is safer than while. for (int wait = 0; wait < previewDelay; wait += previewDelayWait) { if (stopwatch.ElapsedMilliseconds >= previewDelay) { break; } await Task.Delay(previewDelayWait); } //while(stopwatch.ElapsedMilliseconds < previewDelay) //{ // await Task.Delay(10); //} } //Create System.Drawing.Bitmap Bitmap bitmap = (Bitmap)OriginalTextureBackup; // Apply filters var hueFilter = new AForge.Imaging.Filters.HueAdjustment(HueValue); var satFilter = new AForge.Imaging.Filters.SaturationCorrection((float)SaturationValue); var hslFilter = new AForge.Imaging.Filters.HSLLinear(); float brightness = (float)LightnessValue; if (brightness > 0) { hslFilter.InLuminance = new Range(0.0f, 1.0f - brightness); //TODO - isn't it better not to truncate, but compress? hslFilter.OutLuminance = new Range(brightness, 1.0f); } else { hslFilter.InLuminance = new Range(-brightness, 1.0f); hslFilter.OutLuminance = new Range(0.0f, 1.0f + brightness); } // create saturation filter float saturation = (float)SaturationValue; if (saturation > 0) { hslFilter.InSaturation = new Range(0.0f, 1.0f - saturation); //Ditto? hslFilter.OutSaturation = new Range(saturation, 1.0f); } else { hslFilter.InSaturation = new Range(-saturation, 1.0f); hslFilter.OutSaturation = new Range(0.0f, 1.0f + saturation); } bitmap = hueFilter.Apply(bitmap); hslFilter.ApplyInPlace(bitmap); //Convert back to WPF Bitmap CurrentTexture.DdsImage = (WriteableBitmap)bitmap; //Restart the timer isImageProcessing = false; stopwatch.Restart(); }