Ejemplo n.º 1
0
        private bool PtinConvexPolygon(AafPnt[] p, AafPnt pt)
        {
            int dir = 0;
            int j;

            //Basically what we are doing is seeing if pt is on the same side of each face of the polygon through cross multiplication
            for (int i = 0; i < 4; i++)
            {
                j = ja[i];
                double cross = (p[i].x - pt.x) * (p[j].y - pt.y) - (p[j].x - pt.x) * (p[i].y - pt.y);

                if (cross == 0)
                {
                    continue;
                }

                if (cross > 0)
                {
                    if (dir == -1)
                    {
                        return(false);
                    }

                    dir = 1;
                }
                else
                {
                    if (dir == 1)
                    {
                        return(false);
                    }

                    dir = -1;
                }
            }
            return(true);
        }
Ejemplo n.º 2
0
        private void DoTransform(Bitmap src, Bitmap dst, Aaf_callback callbackfunc)
        {
            //Get source bitmap's information
            if (src == null)
            {
                return;
            }

            //Create the source dib array and the dstdib array
            aaf_dblrgbquad[] dbldstdib = new aaf_dblrgbquad[outwidth * outheight];
            for (int i = 0; i < dbldstdib.Length; i++)
            {
                dbldstdib[i] = new aaf_dblrgbquad();
            }

            //Create polygon arrays
            AafPnt[] p       = new AafPnt[4];
            AafPnt[] poffset = new AafPnt[4];

            //Loop through the source's pixels
            //遍历原图(实质上是pixelgrid)各个点
            for (int x = 0; x < src.Width; x++)
            {
                for (int y = 0; y < src.Height; y++)
                {
                    //取当前点 下一点 右一点 斜右下角点 四点才组成一个四边形
                    //这个四边形是原图像的一个像素点
                    //Construct the source pixel's rotated polygon from pixelgrid
                    p[0] = pixelgrid[x + y * (src.Width + 1)];
                    p[1] = pixelgrid[(x + 1) + y * (src.Width + 1)];
                    p[2] = pixelgrid[(x + 1) + (y + 1) * (src.Width + 1)];
                    p[3] = pixelgrid[x + (y + 1) * (src.Width + 1)];

                    //Find the scan area on the destination's pixels
                    int mindx = int.MaxValue;
                    int mindy = int.MaxValue;
                    int maxdx = int.MinValue;
                    int maxdy = int.MinValue;
                    for (int i = 0; i < 4; i++)
                    {
                        if (rounddown(p[i].x) < mindx)
                        {
                            mindx = rounddown(p[i].x);
                        }
                        if (roundup(p[i].x) > maxdx)
                        {
                            maxdx = roundup(p[i].x);
                        }
                        if (rounddown(p[i].y) < mindy)
                        {
                            mindy = rounddown(p[i].y);
                        }
                        if (roundup(p[i].y) > maxdy)
                        {
                            maxdy = roundup(p[i].y);
                        }
                    }

                    int SrcIndex = x + y * src.Width;
                    //遍历四边形包含了目标图几个像素点
                    //按照相交面积占整个像素的的百分比,把颜色按照该比例存放一个目标像素点颜色的数组中
                    //这里计算出来的颜色只是初步颜色,还没到最终结果
                    //loop through the scan area to find where source(x, y) overlaps with the destination pixels
                    for (int xx = mindx - 1; xx <= maxdx; xx++)
                    {
                        if (xx < 0 || xx >= dst.Width)
                        {
                            continue;
                        }
                        for (int yy = mindy - 1; yy <= maxdy; yy++)
                        {
                            if (yy < 0 || yy >= dst.Height)
                            {
                                continue;
                            }

                            //offset p and by (xx,yy) and put that into poffset
                            for (int i = 0; i < 4; i++)
                            {
                                poffset[i].x = p[i].x - xx;
                                poffset[i].y = p[i].y - yy;
                            }

                            //FIND THE OVERLAP *a whole lot of code pays off here*
                            //这里则是计算出覆盖了面积占当前像素的百分比
                            double dbloverlap = PixOverlap(poffset);
                            //按照百分比来为目标像素点累加颜色
                            //因为一个目标像素点有可能有几个原来像素的覆盖了
                            if (dbloverlap > 0)
                            {
                                int   dstindex = xx + yy * outwidth;
                                int   srcWidth = src.Width;
                                Color srcColor;
                                if (SrcIndex == 0)
                                {
                                    srcColor = src.GetPixel(0, 0);
                                }
                                else
                                {
                                    srcColor = src.GetPixel(SrcIndex % src.Width, SrcIndex / src.Width);
                                }
                                //Add the rgb and alpha values in proportion to the overlap area
                                dbldstdib[dstindex].Red   += (double)((srcColor.R) * dbloverlap);
                                dbldstdib[dstindex].Blue  += (double)(srcColor.B) * dbloverlap;
                                dbldstdib[dstindex].Green += (double)(srcColor.G) * dbloverlap;
                                dbldstdib[dstindex].Alpha += dbloverlap;
                            }
                        }
                    }
                }
                if (callbackfunc != null)
                {
                    //Send the callback message
                    double percentdone = (double)(x + 1) / (double)(src.Width);
                    if (callbackfunc(percentdone))
                    {
                        dbldstdib = null;
                        p         = null;
                        poffset   = null;
                        return;
                    }
                }
            }

            //Free memory no longer needed


            //Create final destination bits
            RGBQUDA[] dstdib = new RGBQUDA[dst.Width * dst.Height];
            for (int i = 0; i < dstdib.Length; i++)
            {
                dstdib[i] = new RGBQUDA()
                {
                    R = 0, G = 0, B = 0, A = 1
                }
            }
            ;

            //这里是实际上真正像素点的颜色,并且填到了目标图片中去
            //Write to dstdib with the information stored in dbldstdib
            for (int x = 0; x < outwidth; x++)
            {
                if (x + outstartx >= dst.Width)
                {
                    continue;
                }
                for (int y = 0; y < outheight; y++)
                {
                    if (y + outstarty >= dst.Height)
                    {
                        continue;
                    }
                    int offindex = x + y * outwidth;
                    int dstindex = x + outstartx + (y + outstarty) * dst.Width;

                    int dstIndexX = dstindex / dst.Width;
                    int dstIndexY = dstindex % dst.Width;
                    if (dbldstdib[offindex].Alpha > 1)
                    {
                        //handles wrap around for non-convex transformations
                        dstdib[dstindex].R = byterange(dbldstdib[offindex].Red / dbldstdib[offindex].Alpha);
                        dstdib[dstindex].G = byterange(dbldstdib[offindex].Green / dbldstdib[offindex].Alpha);
                        dstdib[dstindex].B = byterange(dbldstdib[offindex].Blue / dbldstdib[offindex].Alpha);
                        dstdib[dstindex].A = byterange(dbldstdib[offindex].Alpha / dbldstdib[offindex].Alpha);
                    }
                    else
                    {
                        //Color dstColor = dst.GetPixel(dstIndexX, dstIndexY);
                        dstdib[dstindex].R = byterange(dbldstdib[offindex].Red + (1 - dbldstdib[offindex].Alpha) * (double)dstdib[dstindex].R);
                        dstdib[dstindex].G = byterange(dbldstdib[offindex].Green + (1 - dbldstdib[offindex].Alpha) * (double)dstdib[dstindex].G);
                        dstdib[dstindex].B = byterange(dbldstdib[offindex].Blue + (1 - dbldstdib[offindex].Alpha) * (double)dstdib[dstindex].B);
                        dstdib[dstindex].A = byterange(dbldstdib[offindex].Alpha + (1 - dbldstdib[offindex].Alpha) * (double)dstdib[dstindex].A);
                    }
                    dst.SetPixel(dstIndexY, dstIndexX, Color.FromArgb((int)(1.0 * dbldstdib[dstindex].Alpha * 255), dstdib[dstindex].R, dstdib[dstindex].G, dstdib[dstindex].B));


                    //dst.SetPixel(dstIndexY, dstIndexX, Color.FromArgb((int)dbldstdib[offindex].Red, (int)dbldstdib[offindex].Green, (int)dbldstdib[offindex].Blue, (int)dbldstdib[offindex].Alpha));
                }
            }

            //:D
            return;
        }

        double PixOverlap(AafPnt[] p)
        {
            polyoverlapsize = 0;
            polysortedsize  = 0;

            double minx, maxx, miny, maxy;
            int    j;

            double z;

            for (int i = 0; i < 4; i++)
            {
                //Search for source points within the destination quadrolateral
                if (p[i].x >= 0 && p[i].x <= 1 && p[i].y >= 0 && p[i].y <= 1)
                {
                    polyoverlap[polyoverlapsize++] = p[i];
                }

                //Search for destination points within the source quadrolateral
                if (PtinConvexPolygon(p, corners[i]))
                {
                    polyoverlap[polyoverlapsize++] = corners[i];
                }

                //Search for line intersections
                j    = ja[i];
                minx = aaf_min(p[i].x, p[j].x);
                miny = aaf_min(p[i].y, p[j].y);
                maxx = aaf_max(p[i].x, p[j].x);
                maxy = aaf_max(p[i].y, p[j].y);

                if (minx < 0.0 && 0.0 < maxx)
                {//Cross left
                    z = p[i].y - p[i].x * (p[i].y - p[j].y) / (p[i].x - p[j].x);
                    if (z >= 0.0 && z <= 1.0)
                    {
                        polyoverlap[polyoverlapsize].x   = 0.0;
                        polyoverlap[polyoverlapsize++].y = z;
                    }
                }
                if (minx < 1.0 && 1.0 < maxx)
                {//Cross right
                    z = p[i].y + (1 - p[i].x) * (p[i].y - p[j].y) / (p[i].x - p[j].x);
                    if (z >= 0.0 && z <= 1.0)
                    {
                        polyoverlap[polyoverlapsize].x   = 1.0;
                        polyoverlap[polyoverlapsize++].y = z;
                    }
                }
                if (miny < 0.0 && 0.0 < maxy)
                {//Cross bottom
                    z = p[i].x - p[i].y * (p[i].x - p[j].x) / (p[i].y - p[j].y);
                    if (z >= 0.0 && z <= 1.0)
                    {
                        polyoverlap[polyoverlapsize].x   = z;
                        polyoverlap[polyoverlapsize++].y = 0.0;
                    }
                }
                if (miny < 1.0 && 1.0 < maxy)
                {//Cross top
                    z = p[i].x + (1 - p[i].y) * (p[i].x - p[j].x) / (p[i].y - p[j].y);
                    if (z >= 0.0 && z <= 1.0)
                    {
                        polyoverlap[polyoverlapsize].x   = z;
                        polyoverlap[polyoverlapsize++].y = 1.0;
                    }
                }
            }

            //Sort the points and return the area
            SortPoints();
            return(Area());
        }