/// <summary> /// Creates color map based on chanes made /// </summary> /// <param name="tasks">Task list</param> /// <returns>Tuple of LUT size and color map</returns> public static Tuple <int, Tuple <byte, byte, byte> [, , ]> Export(Stack <ImageTask> tasks) { ColorMixerPipeline pipeline = new ColorMixerPipeline(); Stack <ImageTask> changes = new Stack <ImageTask>(tasks); while (changes.Count > 0) { ImageTask imgTask = changes.Pop(); if ((imgTask.taskType != ImageModification.FlipHorizontally) && (imgTask.taskType != ImageModification.FlipVertically)) { ColorMixer colorMixer = ((ColorTask)imgTask).ColorMixer; pipeline.Add(colorMixer); } } Tuple <byte, byte, byte>[,,] colors = new Tuple <byte, byte, byte> [32, 32, 32]; for (int i = 0; i < 32; ++i) { double b = i / 31.0; for (int j = 0; j < 32; ++j) { double g = j / 31.0; for (int k = 0; k < 32; ++k) { double r = k / 31.0; colors[i, j, k] = pipeline.Run((byte)(r * 255), (byte)(g * 255), (byte)(b * 255)); } } } return(new Tuple <int, Tuple <byte, byte, byte> [, , ]>(32, colors)); }
/// <summary> /// Processes all tasks in main (not waiting) linked list and /// creates restore point to undo queue /// Waits in the while loop while another task should be executed /// or while loop is terminated by main form signal /// </summary> private void Process() { while (form.tasksRunning) { if (head != null) { head.ongoing = true; RestorePoint old = new RestorePoint( form.imageSet.imageMode, head.taskType, form.imageSet.image.Clone(form.imageSet.rectangle, form.imageSet.image.PixelFormat), form.imageSet.thumb.Clone(form.imageSet.thumbRectangle, form.imageSet.thumb.PixelFormat), form.imageSet.saturation, form.imageSet.brightness, form.imageSet.clarity ); undoQueue.Add(old); redoQueue.Flush(); head.Process(); head = head.next; if (head != null) { head.previous = null; } form.RedrawImageSet(); } else { Thread.Sleep(100); } } }
/// <summary> /// Initialize image task type, image color filter (as image view mode), image set and /// other variables with defaults /// </summary> /// <param name="mod">One of provided image modifications</param> /// <param name="imageSet">Pointer to image set from engine</param> public ImageTask(ImageModification mod, ImageSet imageSet) { taskType = mod; ongoing = false; previous = null; next = null; iSet = imageSet; iMode = iSet.imageMode; }
/// <summary> /// Initialize task control variables to defaults and /// starts parallel thread for image processing /// </summary> /// <param name="form">Pointer to main app form</param> public TaskControl(MainForm form) { this.form = form; head = null; tail = null; headWaiting = null; tailWaiting = null; undoQueue = new Queue(); redoQueue = new Queue(); tasks = new Stack <ImageTask>(); removed = new Stack <ImageTask>(); Thread t = new Thread(Process); t.IsBackground = true; t.Start(); }
/// <summary> /// Puts every task from waiting linked list to main linked list /// </summary> public void CheckAndProcess() { if (head == null) { head = headWaiting; tail = tailWaiting; headWaiting = null; tailWaiting = null; } else if (head.ongoing) { Thread.Sleep(100); CheckAndProcess(); } else { if (headWaiting != null) { tail.next = headWaiting; headWaiting.previous = tail; tail = tailWaiting; } } }
/// <summary> /// Adds image task to the tasks and linked list for image processing /// </summary> /// <param name="task">Task which should edit image set</param> public void Add(ImageTask task) { tasks.Push(task); if ((head == null) || (!head.ongoing)) { if (head == null) { head = task; tail = task; } else { if (tail.taskType == task.taskType) { if (tail.previous == null) { head = task; tail = task; } else { tail.previous.next = task; task.previous = tail.previous; tail = task; } } else { tail.next = task; task.previous = tail; tail = task; } } } else { if (headWaiting == null) { headWaiting = task; tailWaiting = task; } else { if (tailWaiting.taskType == task.taskType) { if (tailWaiting.previous == null) { headWaiting = task; tailWaiting = task; } else { tailWaiting.previous.next = task; task.previous = tailWaiting.previous; tailWaiting = task; } } else { tailWaiting.next = task; task.previous = tailWaiting; tailWaiting = task; } } } }