Exemple #1
0
        /// <summary>
        /// Adds padding to a bitmap, optionally cropping it at the same time.
        /// </summary>
        /// <param name="s"></param>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="right"></param>
        /// <param name="bottom"></param>
        /// <param name="bgcolor"></param>
        /// <param name="crop"></param>
        public WicBitmapPadder(IWICBitmapSource s, int left, int top, int right, int bottom, byte[] bgcolor, WICRect crop)
        {
            this.s       = s;
            this.left    = left;
            this.right   = right;
            this.bottom  = bottom;
            this.top     = top;
            this.bgcolor = bgcolor;
            this.crop    = crop;

            Guid pf;

            s.GetPixelFormat(out pf);
            if (bgcolor.Length != ConversionUtils.BytesPerPixel(pf))
            {
                throw new ArgumentException("bgcolor length must match the format bytes per pixel");
            }
        }
Exemple #2
0
        public static byte[] ConvertColor(Color color, Guid pixelFormat)
        {
            if (pixelFormat == Consts.GUID_WICPixelFormat24bppBGR)
            {
                return new byte[] { color.B, color.G, color.R }
            }
            ;
            if (pixelFormat == Consts.GUID_WICPixelFormat24bppRGB)
            {
                return new byte[] { color.R, color.G, color.B }
            }
            ;

            if (pixelFormat == Consts.GUID_WICPixelFormat32bppBGR || pixelFormat == Consts.GUID_WICPixelFormat32bppBGRA ||
                pixelFormat == Consts.GUID_WICPixelFormat32bppPBGRA)
            {
                return new byte[] { color.B, color.G, color.R, color.A }
            }
            ;

            if (pixelFormat == Consts.GUID_WICPixelFormat32bppPRGBA || pixelFormat == Consts.GUID_WICPixelFormat32bppRGBA)
            {
                return new byte[] { color.R, color.G, color.B, color.A }
            }
            ;

            if (pixelFormat == Consts.GUID_WICPixelFormat8bppGray)
            {
                return new byte[] { (byte)Math.Min(0, Math.Max(255, (float)color.B * 0.081f + (float)color.G * 0.419f + (float)color.R * 0.5f)) }
            }
            ;


            byte[] data = new byte[ConversionUtils.BytesPerPixel(pixelFormat)];


            return(data);
        }
    }
}
Exemple #3
0
        public void CopyPixels(WICRect prc, uint destStride, uint destBufferSize, [Out]
                               [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] destBuffer)
        {
            //Get normal size of source rect
            uint sw, sh;

            s.GetSize(out sw, out sh);

            //Get normal (uncropped size) of this bitmap. Includes source cropping
            uint fullWidth, fullHeight;

            this.GetSize(out fullWidth, out fullHeight);

            //Copy or generate source crop rectangle.
            WICRect crop = this.crop == null ? new WICRect {
                X = 0, Y = 0, Width = (int)sw, Height = (int)sh
            }: new WICRect {
                X = this.crop.X, Y = this.crop.Y, Width = this.crop.Width, Height = this.crop.Height
            };

            //Copy padding values so we can modify them based on the dest crop area.
            int left   = this.left;
            int top    = this.top;
            int right  = this.right;
            int bottom = this.bottom;


            int w = prc != null ? prc.Width : (int)fullWidth;
            int h = prc != null ? prc.Height : (int)fullHeight;

            //Adjust padding based on what they're asking to crop off
            if (prc != null)
            {
                left   -= prc.X;
                top    -= prc.Y;
                right  -= (int)(fullWidth - prc.X - prc.Width);
                bottom -= (int)(fullHeight - prc.Y - prc.Height);
            }

            //Now, adjust negative padding to crop from the source bitmap. We should end up with only positive padding.
            if (left < 0)
            {
                crop.X += left * -1; crop.Width += left; left = 0;
            }
            if (top < 0)
            {
                crop.Y += top * -1; crop.Height += top;  top = 0;
            }
            if (right < 0)
            {
                crop.Width += right; right = 0;
            }
            if (bottom < 0)
            {
                crop.Height += bottom; bottom = 0;
            }

            //Now, if we don't have to add any padding (say the caller ended up cropping it all off), just pass the request on.
            if (left == 0 && top == 0 && right == 0 && bottom == 0)
            {
                s.CopyPixels(crop, destStride, destBufferSize, destBuffer);
                return;
            }
            //Ah, looks like we still have to do padding.


            //Get pixel format
            Guid format;

            s.GetPixelFormat(out format);

            //Calculate buffer and stride for source data
            uint bpp         = (uint)ConversionUtils.BytesPerPixel(format);               //Round up to nearest byte.
            uint srcStride   = (((bpp * (uint)Math.Max(0, crop.Width)) + 4 - 1) / 4) * 4; //Round up to nearest 4-byte alignment
            uint sbufferSize = srcStride * (uint)Math.Max(0, crop.Height);

            //Allocate for source data
            byte[] sbuffer = new byte[sbufferSize];

            //Decode and store the source data
            if (sbufferSize > 0)
            {
                s.CopyPixels(crop, srcStride, sbufferSize, sbuffer);
            }


            //Ok, now it's time to start work.
            //Manually build a padding stride for left, top/bottom, and right, then use Array.Copy to do it more efficiently.

            //Favor doing complete row - don't let left/right overlap with top/bottom.
            if (left > 0 && h > (top + bottom))
            {
                //Cache manually built array for speed
                if (cachedLeftPadding == null)
                {
                    cachedLeftPadding = new byte[left * bpp];
                    for (int i = 0; i < left; i++)
                    {
                        Array.Copy(bgcolor, 0, cachedLeftPadding, i * bpp, bpp);
                    }
                }
                //Then copy it down
                for (int j = 0; j < h - top - bottom; j++)
                {
                    Array.Copy(cachedLeftPadding, 0, destBuffer, (destStride * (j + top)), left * bpp);
                }
            }
            if (right > 0 && h > (top + bottom))
            {
                //Cache manually built array for speed
                if (cachedRightPadding == null)
                {
                    cachedRightPadding = new byte[right * bpp];
                    for (int i = 0; i < right; i++)
                    {
                        Array.Copy(bgcolor, 0, cachedRightPadding, i * bpp, bpp);
                    }
                }
                //Then copy it down
                for (int j = 0; j < h - top - bottom; j++)
                {
                    Array.Copy(cachedRightPadding, 0, destBuffer, (destStride * (j + top)) + (left + crop.Width) * bpp, right * bpp);
                }
            }

            if (top > 0 || bottom > 0)
            {
                //Cache manually built array for speed
                if (cachedRowPadding == null)
                {
                    cachedRowPadding = new byte[(crop.Width + left + right) * bpp];
                    for (int i = 0; i < crop.Width + left + right; i++)
                    {
                        Array.Copy(bgcolor, 0, cachedRowPadding, i * bpp, bpp);
                    }
                }

                //Copy it down for both top and bottom
                if (top > 0)
                {
                    for (int j = 0; j < Math.Min(h, top); j++)
                    {
                        Array.Copy(cachedRowPadding, 0, destBuffer, (destStride * j), (crop.Width + left + right) * bpp);
                    }
                }
                if (bottom > 0)
                {
                    for (int j = 0; j < Math.Min(h, bottom); j++) //If the manual row was at the bottom, don't copy it again.
                    {
                        Array.Copy(cachedRowPadding, 0, destBuffer, (destStride * (j + top + Math.Max(0, crop.Height))), (crop.Width + left + right) * bpp);
                    }
                }
            }

            //Now, copy the image data. If we didn't use left or right padding we can copy the whole thing at once.
            if (sbufferSize > 0)
            {
                if (srcStride == destStride)
                {
                    Array.Copy(sbuffer, 0, destBuffer, top * destStride, sbuffer.Length);
                }
                else
                {
                    //Otherwise, one row at a time
                    for (int j = 0; j < crop.Height; j++)
                    {
                        Array.Copy(sbuffer, j * srcStride, destBuffer, (left * bpp) + (top + j) * destStride, crop.Width * bpp);
                    }
                }
            }


            //We're done!
        }