Beispiel #1
0
        public void Crotate(double beta, Point c, int crop_w, int crop_h, int quality, ProgressReporter callback)
        {
            beta *= Math.PI / 180.0;

            float[,] oldr = r_chan;
            float[,] oldg = g_chan;
            float[,] oldb = b_chan;
            float[,] oldhl = hl_chan;
            int oldW = mWidth, oldH = mHeight;

            // Creating new image
            lock (this)
            {
                r_chan = new float[crop_w, crop_h];
                g_chan = new float[crop_w, crop_h];
                b_chan = new float[crop_w, crop_h];
                hl_chan = new float[crop_w, crop_h];
                mWidth = crop_w; mHeight = crop_h;
            }

            // Full progress
            int full_n = 0;
            object full_n_lock = new object();

            // Initializing threads
            int threads_num = 6;
            Thread[] threads = new Thread[threads_num];

            bool user_cancel = false;

            for (int q = 0; q < threads_num; q++)
            {
                threads[q] = new Thread(delegate (object obj)
                {
                    try
                    {
                        int n1 = ((thread_data)obj).i1;
                        int n2 = ((thread_data)obj).i2;

                        for (int n = n1; n < n2; n++)
                        {

                            if (n % REPORT_EVERY_NTH_LINE == 0 && callback != null)
                            {
                                if (!callback((double)full_n / oldH)) throw new UserCancelException();
                            }

                            for (int m = 0; m < oldW; m++)
                            {
                                // Rotated source matrix squares
                                CatEye.Core.Point[] src_tr_pts = new CatEye.Core.Point[]
                                {
                                    Point.Rotate(new CatEye.Core.Point(m,       n      ), -beta, c),
                                    Point.Rotate(new CatEye.Core.Point((m + 1), n      ), -beta, c),
                                    Point.Rotate(new CatEye.Core.Point((m + 1), (n + 1)), -beta, c),
                                    Point.Rotate(new CatEye.Core.Point(m,       (n + 1)), -beta, c)
                                };

                                // Rotated and translated source matrix squares
                                CatEye.Core.Point[] src_tr_pts2 = new CatEye.Core.Point[]
                                {
                                    new Point(src_tr_pts[0].X - c.X + (double)crop_w / 2, src_tr_pts[0].Y - c.Y + (double)crop_h / 2),
                                    new Point(src_tr_pts[1].X - c.X + (double)crop_w / 2, src_tr_pts[1].Y - c.Y + (double)crop_h / 2),
                                    new Point(src_tr_pts[2].X - c.X + (double)crop_w / 2, src_tr_pts[2].Y - c.Y + (double)crop_h / 2),
                                    new Point(src_tr_pts[3].X - c.X + (double)crop_w / 2, src_tr_pts[3].Y - c.Y + (double)crop_h / 2),
                                };

                                ConvexPolygon cp_src_tr = new ConvexPolygon(src_tr_pts2);

                                int xmin = Math.Max((int)cp_src_tr.XMin, 0);
                                int ymin = Math.Max((int)cp_src_tr.YMin, 0);
                                int xmax = Math.Min((int)cp_src_tr.XMax + 1, crop_w);
                                int ymax = Math.Min((int)cp_src_tr.YMax + 1, crop_h);

                                for (int j = ymin; j < ymax; j++)
                                {
                                    for (int i = xmin; i < xmax; i++)
                                    {
                                        double part = cp_src_tr.CalcProjectionToPixel(i, j, quality);

                                        // Adding colors part
                                        lock (this)
                                        {
                                            r_chan[i, j] += (float)(oldr[m, n] * part);
                                            g_chan[i, j] += (float)(oldg[m, n] * part);
                                            b_chan[i, j] += (float)(oldb[m, n] * part);
                                            hl_chan[i, j] += (float)(oldhl[m, n] * part);
                                        }
                                    }
                                }
                            }
                            lock (full_n_lock) full_n ++;
                        }
                    }
                    catch (UserCancelException)
                    {
                        user_cancel = true;
                    }
                });
            }

            // Starting threads
            for (int q = 0; q < threads_num; q++)
            {
                thread_data td = new thread_data();
                td.i1 = (oldH / threads_num) * q;
                if (q < threads_num - 1)
                {
                    td.i2 = (oldH / threads_num) * (q + 1);
                }
                else
                {
                    td.i2 = oldH;
                }

                threads[q].Start(td);
            }

            // Waiting for threads
            for (int q = 0; q < threads_num; q++)
            {
                threads[q].Join();
            }

            if (user_cancel) throw new UserCancelException();
        }
Beispiel #2
0
        private static bool SolvePoissonNeiman(float[,] I0, float[,] rho, int steps_max, float stop_dpd, SolutionReporter callback)
        {
            int w = rho.GetLength(0), h = rho.GetLength(1);
            float[,] I = new float[w + 2, h + 2];
            float[,] Inew = new float[w + 2, h + 2];

            // Setting initial values
            for (int i = 0; i < w + 2; i++)
            for (int j = 0; j < h + 2; j++)
            {
                int i1 = i;
                if (i == 0) i1 = 1;
                if (i == w + 1) i1 = w;
                int j1 = j;
                if (j == 0) j1 = 1;
                if (j == h + 1) j1 = h;

                I[i, j] = I0[i1 - 1, j1 - 1];
                Inew[i, j] = I0[i1 - 1, j1 - 1];
            }

            float delta = 0; float delta_prev = 10000;
            object delta_lock = new object();
            for (int step = 0; step < steps_max; step ++)
            {
                // *** Horizontal iterations ***
                int threads_num = 6;
                Thread[] threads = new Thread[threads_num];

                for (int q = 0; q < threads_num; q++)
                {
                    threads[q] = new Thread(delegate (object obj)
                    {
                        int i1 = ((thread_data)obj).i1;
                        int i2 = ((thread_data)obj).i2;

                        float my_delta = 0;

                        for (int i = i1; i < i2; i++)
                        {
                            // Run, Thomas, run!
                            float[] alpha = new float[h + 3];
                            float[] beta = new float[h + 3];

                            alpha[1] = 0.25f; beta[1] = 0.25f * (I[i + 1, 0] + Inew[i - 1, 0]);
                            for (int j = 1; j < h + 2; j++)
                            {
                                alpha[j + 1] = 1.0f / (4 - alpha[j]);
                                float Fj;
                                if (j < h + 1)
                                    Fj = I[i + 1, j] + Inew[i - 1, j] - 2 * rho[i - 1, j - 1];
                                else
                                    Fj = I[i + 1, j] + Inew[i - 1, j];

                                beta[j + 1] = (Fj + beta[j]) / (4f - alpha[j]);
                            }

                            Inew[i, h + 1] = beta[h + 2];

                            for (int j = h; j >= 0; j--)
                            {
                                double iold = I[i, j];
                                Inew[i, j] = alpha[j + 1] * Inew[i, j + 1] + beta[j + 1];
                                my_delta += (float)Math.Abs(Inew[i, j] - iold);
                            }
                        }

                        lock (delta_lock)
                        {
                            delta += my_delta;
                        }

                    });
                }

                // Starting horizontal threads
                for (int q = 0; q < threads_num; q++)
                {
                    thread_data td = new thread_data();
                    td.i1 = (w / threads_num) * q + 1;
                    if (q < threads_num - 1)
                    {
                        td.i2 = (w / threads_num) * (q + 1) + 1;
                    }
                    else
                    {
                        td.i2 = w + 1;
                    }

                    threads[q].Start(td);
                }

                // Waiting for horizontal threads
                for (int q = 0; q < threads_num; q++)
                {
                    threads[q].Join();
                }

                // Restoring Neiman boundary conditions after horizontal iterations
                for (int i = 0; i < w + 2; i++)
                {
                    Inew[i, 0] = Inew[i, 1];
                    Inew[i, h + 1] = Inew[i, h];
                }
                for (int j = 0; j < h + 2; j++)
                {
                    Inew[0, j] = Inew[1, j];
                    Inew[w + 1, j] = Inew[w, j];
                }

                // Controlling the constant after horizontal iterations
                float m = 0;
                for (int i = 0; i < w + 2; i++)
                for (int j = 0; j < h + 2; j++)
                {
                    m += Inew[i, j];
                }
                m /= (w+2) * (h+2);

                for (int i = 0; i < w + 2; i++)
                for (int j = 0; j < h + 2; j++)
                {
                    I[i, j] = Inew[i, j] - m;
                }

                // *** Vertical iterations ***
                threads = new Thread[threads_num];

                for (int q = 0; q < threads_num; q++)
                {
                    threads[q] = new Thread(delegate (object obj)
                    {
                        int j1 = ((thread_data)obj).i1;
                        int j2 = ((thread_data)obj).i2;

                        float my_delta = 0;

                        for (int j = j1; j < j2; j++)
                        {
                            // Run, Thomas, run!
                            float[] alpha = new float[w + 3];
                            float[] beta = new float[w + 3];

                            alpha[1] = 0.25f; beta[1] = 0.25f * (I[0, j + 1] + Inew[0, j - 1]);
                            for (int i = 1; i < w + 2; i++)
                            {
                                alpha[i + 1] = 1.0f / (4 - alpha[i]);
                                float Fi;
                                if (i < w + 1)
                                    Fi = I[i, j + 1] + Inew[i, j - 1] - 2 * rho[i - 1, j - 1];
                                else
                                    Fi = I[i, j + 1] + Inew[i, j - 1];

                                beta[i + 1] = (Fi + beta[i]) / (4f - alpha[i]);
                            }

                            Inew[w + 1, j] = beta[w + 2];

                            for (int i = w; i >= 0; i--)
                            {
                                double iold = I[i, j];
                                Inew[i, j] = alpha[i + 1] * Inew[i + 1, j] + beta[i + 1];
                                my_delta += (float)Math.Abs(Inew[i, j] - iold);
                            }
                        }

                        lock (delta_lock)
                        {
                            delta += my_delta;
                        }

                    });
                }

                // Starting vertical threads
                for (int q = 0; q < threads_num; q++)
                {
                    thread_data td = new thread_data();
                    td.i1 = (h / threads_num) * q + 1;
                    if (q < threads_num - 1)
                    {
                        td.i2 = (h / threads_num) * (q + 1) + 1;
                    }
                    else
                    {
                        td.i2 = h + 1;
                    }

                    threads[q].Start(td);
                }

                // Waiting for vertical threads
                for (int q = 0; q < threads_num; q++)
                {
                    threads[q].Join();
                }

                // Restoring Neiman boundary conditions after vertical iterations
                for (int i = 0; i < w + 2; i++)
                {
                    Inew[i, 0] = Inew[i, 1];
                    Inew[i, h + 1] = Inew[i, h];
                }
                for (int j = 0; j < h + 2; j++)
                {
                    Inew[0, j] = Inew[1, j];
                    Inew[w + 1, j] = Inew[w, j];
                }

                // Controlling the constant after vertical iterations
                m = 0;
                for (int i = 0; i < w + 2; i++)
                for (int j = 0; j < h + 2; j++)
                {
                    m += Inew[i, j];
                }
                m /= (w+2) * (h+2);

                for (int i = 0; i < w + 2; i++)
                for (int j = 0; j < h + 2; j++)
                {
                    I[i, j] = Inew[i, j] - m;
                }

                for (int i = 1; i < w + 1; i++)
                for (int j = 1; j < h + 1; j++)
                {
                    I0[i - 1, j - 1] = I[i, j];
                }

                delta /= (float)Math.Sqrt(w * h);
                float dpd = Math.Abs((delta - delta_prev) / delta);

                // This formula is found experimentally
                float progress = (float)Math.Min(Math.Pow(stop_dpd / (dpd + 0.000001), 0.78), 0.999);

                if (callback != null)
                {
                    callback(progress, I0);
                }

                if (dpd < stop_dpd)
                {
                    return true;
                }
                delta_prev = delta;
                delta = 0;
            }

            return false;
        }