图像处理(一)——球面(凹凸)化


原图

凸面化处理结果

凹面化处理结果

/// <summary>
        /// 图像滤镜---球面(凹凸)化
        /// </summary>
        /// <param name="bitmap">待处理图片</param>
        /// <param name="originPoint">球面化的处理原点</param>
        /// <param name="radius">球面化半径</param>
        /// <param name="raised">是否凸面化</param>
        /// <returns></returns>
        private Bitmap GetHandledImage(Bitmap bitmap, Point originPoint, int radius, bool raised)
        {
            var bmp = (Bitmap)bitmap.Clone();
            if (radius <= 0) return bmp;
            try
            {
                var originX = (int)Math.Ceiling(originPoint.X) - 1;
                var originY = (int)Math.Ceiling(originPoint.Y) - 1;
                var width = bmp.Width;
                var height = bmp.Height;
                const int pixelSize = 4;
                
                var bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
                var byColorInfo = new byte[height * bmpData.Stride];
                Marshal.Copy(bmpData.Scan0, byColorInfo, 0, byColorInfo.Length);

                #region Safe

                //var clone = (byte[])byColorInfo.Clone();
                //for (var x = 0; x < width; x++)
                //{
                //    for (var y = 0; y < height; y++)
                //    {
                //        var dx = x - originX;
                //        var dy = y - originY;
                //        var distance = Math.Sqrt(dx * dx + dy * dy);
                //        if (distance <= radius)
                //        {
                //            var theta = Math.Atan2(dy, dx);
                //            var mapR = raised ? (2 * radius / Math.PI) * Math.Asin(distance / radius) : Math.Sin(Math.PI * distance / (2 * radius)) * radius;

                //            dx = originX + (int)(mapR * Math.Cos(theta));
                //            dy = originY + (int)(mapR * Math.Sin(theta));

                //            if (dx < 0 || dx >= width || dy < 0 || dy >= height)
                //            {
                //                byColorInfo[y * bmpData.Stride + x * pixelSize] =
                //                    byColorInfo[y * bmpData.Stride + x * pixelSize + 1] =
                //                        byColorInfo[y * bmpData.Stride + x * pixelSize + 2] =
                //                            byColorInfo[y * bmpData.Stride + x * pixelSize + 3] = 0;
                //            }
                //            else
                //            {
                //                byColorInfo[y * bmpData.Stride + x * pixelSize] = clone[dy * bmpData.Stride + dx * 4];
                //                byColorInfo[y * bmpData.Stride + x * pixelSize + 1] = clone[dy * bmpData.Stride + dx * 4 + 1];
                //                byColorInfo[y * bmpData.Stride + x * pixelSize + 2] = clone[dy * bmpData.Stride + dx * 4 + 2];
                //                byColorInfo[y * bmpData.Stride + x * pixelSize + 3] = clone[dy * bmpData.Stride + dx * 4 + 3];
                //            }
                //        }

                //    }
                //}
                //Marshal.Copy(byColorInfo, 0, bmpData.Scan0, byColorInfo.Length);

                #endregion

                #region Unsafe

                unsafe
                {
                    fixed (byte* source = byColorInfo)
                    {

                        var ptr = (byte*)(bmpData.Scan0);
                        for (var y = 0; y < height; y++)
                        {
                            for (var x = 0; x < width; x++)
                            {
                                var dx = x - originX;
                                var dy = y - originY;
                                var distance = Math.Sqrt(dx * dx + dy * dy);
                                if (distance <= radius)
                                {
                                    var theta = Math.Atan2(dy, dx);
                                    var mapR = raised ? (2 * radius / Math.PI) * Math.Asin(distance / radius): Math.Sin(Math.PI * distance / (2 * radius)) * radius;

                                    dx = originX + (int)(mapR * Math.Cos(theta));
                                    dy = originY + (int)(mapR * Math.Sin(theta));

                                    if (dx < 0 || dx >= width || dy < 0 || dy >= height)
                                    {
                                        ptr[0] = ptr[1] = ptr[2] = ptr[3] = 0;
                                    }
                                    else 
                                    {
                                        ptr[0] = source[dy * bmpData.Stride + dx * pixelSize];
                                        ptr[1] = source[dy * bmpData.Stride + dx * pixelSize + 1];
                                        ptr[2] = source[dy * bmpData.Stride + dx * pixelSize + 2];
                                        ptr[3] = source[dy * bmpData.Stride + dx * pixelSize + 3];

                                    }
                                }

                                ptr += pixelSize;
                            }
                        }
                    }
                }

                #endregion

                bmp.UnlockBits(bmpData);
                return bmp;
            }
            catch (Exception e)
            {
                return (Bitmap)bitmap.Clone();
            }
            
        }

posted @ 2017-03-01 14:04  OneForCheng  阅读(853)  评论(0编辑  收藏  举报