CamTimer.WebcamWithPreview.DistortedDraw C# (CSharp) Method

DistortedDraw() static private method

static private DistortedDraw ( byte sourceBuffer, Bitmap displacementMap, Bitmap destBitmap ) : void
sourceBuffer byte
displacementMap System.Drawing.Bitmap
destBitmap System.Drawing.Bitmap
return void
        internal static unsafe void DistortedDraw(byte* sourceBuffer, Bitmap displacementMap, Bitmap destBitmap)
        {
            int sourceWidth = destBitmap.Width, sourceHeight = destBitmap.Height;
            BitmapData previewData = destBitmap.LockBits(new Rectangle(0, 0, sourceWidth, sourceHeight), ImageLockMode.WriteOnly, destBitmap.PixelFormat);
            int sourceDataStride = previewData.Stride;
            int sourceBPP = destBitmap.PixelFormat.ToString().Contains("16") ? 2 : destBitmap.PixelFormat.ToString().Contains("24") ? 3 : destBitmap.PixelFormat.ToString().Contains("32") ? 4 : 0;

            if (displacementMap == null) {
                unsafe {
                    byte* previewScan0 = (byte*)previewData.Scan0;
                    byte* sourceScan0 = (byte*)sourceBuffer;
                    for (int y = 0, yofs = 0, invyofs = (sourceHeight - 1 - y) * sourceDataStride; y < sourceHeight; y++, yofs += sourceDataStride, invyofs -= sourceDataStride) {
                        for (int x = 0; x < sourceDataStride; x += 4) {
                            *(int*)(previewScan0 + yofs + x) = *(int*)(sourceScan0 + invyofs + x);
                        }
                    }
                }
            } else {
                BitmapData mapData = displacementMap.LockBits(new Rectangle(0, 0, displacementMap.Width, displacementMap.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
                int mapDataStride = mapData.Stride;
                int mapDeltaY = (768 << 16) / sourceHeight;
                int mapDeltaX = (1024 << 16) / sourceWidth;

                unsafe {
                    byte* sourceDataScan0 = (byte*)sourceBuffer;
                    byte* destDataScan0 = (byte*)previewData.Scan0;
                    byte* mapDataScan0 = (byte*)mapData.Scan0;
                    int value, mapOffset, mapOffsetY, sourceOffset;

                    for (int y = 0, mapY = 0, destOffsetY = 0; y < sourceHeight; y++, destOffsetY += sourceDataStride, mapY += mapDeltaY) {
                        mapOffsetY = (mapY >> 16) * mapDataStride;
                        for (int x = 0, mapX = 0, destOffset = destOffsetY; x < sourceWidth; x++, destOffset += sourceBPP, mapX += mapDeltaX) {
                            // read 24bit value from displacement map
                            mapOffset = mapOffsetY + ((mapX >> 16 << 2) + (mapX >> 16 << 1) >> 1); //(mapX >> 16) * 3;
                            value = *(ushort*)(mapDataScan0 + mapOffset) + (*(mapDataScan0 + mapOffset + 2) << 16);

                            // calculate offset relative to this image (x = map.x/1024*x*sourceBPP, y = map.y/768*sourceDataStride)
                            sourceOffset =
                                (((767 - ((value & 0xFFF000) >> 12)) << 16) / 768 * sourceHeight >> 16) * sourceDataStride +
                                ((((value & 0xFFF)) << 16) / 1024 * sourceWidth >> 16) * sourceBPP;

                            if (sourceBPP == 3) {
                                *(ushort*)(destDataScan0 + destOffset) = *(ushort*)(sourceDataScan0 + sourceOffset);
                                *(destDataScan0 + destOffset + 2) = *(sourceDataScan0 + sourceOffset + 2);
                            } else if (sourceBPP == 2) {
                                *(ushort*)(destDataScan0 + destOffset) = *(ushort*)(sourceDataScan0 + sourceOffset);
                            } else if (sourceBPP == 4) {
                                *(int*)(destDataScan0 + destOffset) = *(int*)(sourceDataScan0 + sourceOffset);
                            }
                        }
                    }
                }

                displacementMap.UnlockBits(mapData);
            }
            destBitmap.UnlockBits(previewData);
        }

Usage Example

Example #1
0
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            #region create thumbnail option
            for (int x = 0; x < args.Length; x++)
            {
                if ((args[x].Trim().Equals("/displace", StringComparison.OrdinalIgnoreCase)) || (args[x].Trim().Equals("-displace", StringComparison.OrdinalIgnoreCase)))
                {
                    OpenFileDialog openDialog = new OpenFileDialog();
                    openDialog.Title            = "Select displacement map";
                    openDialog.Filter           = "All files (*.*)|*.*";
                    openDialog.FilterIndex      = 1;
                    openDialog.CheckFileExists  = true;
                    openDialog.DereferenceLinks = true;
                    openDialog.ShowReadOnly     = false;
                    openDialog.FileName         = string.Empty;
                    if (openDialog.ShowDialog() == DialogResult.OK)
                    {
                        // load displacement map
                        string mapName = openDialog.FileName;
                        Bitmap mapBitmap;
                        try {
                            mapBitmap = new Bitmap(mapName);
                        } catch (Exception) {
                            MessageBox.Show("Error loading displacement map. Application ended.", Application.ProductName, MessageBoxButtons.OK);
                            return;
                        }
                        if ((mapBitmap.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb) || (mapBitmap.Size.Width != 1024) || (mapBitmap.Size.Height != 768))
                        {
                            MessageBox.Show("The displacement map must be 1024x768 and 24bpp. Application ended.", Application.ProductName, MessageBoxButtons.OK);
                            return;
                        }

                        openDialog.Title    = "Select image to displace";
                        openDialog.FileName = string.Empty;
                        if (openDialog.ShowDialog() == DialogResult.OK)
                        {
                            // load source bitmap
                            string sourceName = openDialog.FileName;
                            Bitmap sourceBitmap;
                            try {
                                sourceBitmap = new Bitmap(sourceName);
                            } catch (Exception) {
                                MessageBox.Show("Error loading image. Application ended.", Application.ProductName, MessageBoxButtons.OK);
                                return;
                            }
                            if ((sourceBitmap.PixelFormat != System.Drawing.Imaging.PixelFormat.Format16bppRgb565) && (sourceBitmap.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb) && (sourceBitmap.PixelFormat != System.Drawing.Imaging.PixelFormat.Format32bppRgb))
                            {
                                MessageBox.Show("This image to displace must be 16bpp(565), 24bpp(888) or 32bpp. Application ended.", Application.ProductName, MessageBoxButtons.OK);
                                return;
                            }

                            // create distorted bitmap
                            Bitmap destBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height, sourceBitmap.PixelFormat);
                            Bitmap destThumb  = new Bitmap((int)(320 * 0.5), (int)(240 * 0.5), sourceBitmap.PixelFormat);
                            unsafe {
                                BitmapData sourceData  = sourceBitmap.LockBits(new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, sourceBitmap.PixelFormat);
                                byte *     sourceScan0 = (byte *)sourceData.Scan0;
                                WebcamWithPreview.DistortedDraw((byte *)sourceScan0, mapBitmap, destBitmap);
                                sourceBitmap.UnlockBits(sourceData);
                            }
                            using (Graphics g = Graphics.FromImage(destThumb)) {
                                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                                g.InterpolationMode  = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                                g.PixelOffsetMode    = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                                g.SmoothingMode      = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                                g.DrawImage(destBitmap, g.VisibleClipBounds);
                            }

                            // write distorted jpeg
                            EncoderParameters eargs = new EncoderParameters();
                            eargs.Param = new EncoderParameter[] { new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 95L) };

                            ImageCodecInfo[] arrCodecs = ImageCodecInfo.GetImageEncoders();
                            foreach (ImageCodecInfo i in arrCodecs)
                            {
                                if (i.FormatID.Equals(ImageFormat.Jpeg.Guid))
                                {
                                    destThumb.Save(Path.Combine(Path.GetDirectoryName(mapName), Path.GetFileNameWithoutExtension(mapName)) + "-thumb.jpg", i, eargs);
                                    break;
                                }
                            }

                            MessageBox.Show("Displaced bitmap created successfully! Application ended.", Application.ProductName, MessageBoxButtons.OK);
                        }
                    }
                    return;
                }
            }
            #endregion

            // one instance limit
            IntPtr mutexPtr = NativeMethods.CreateMutexA(IntPtr.Zero, false, "FJRCamTimerMutex");
            if (mutexPtr != IntPtr.Zero)
            {
                if (Marshal.GetLastWin32Error() == NativeMethods.ERROR_ALREADY_EXISTS)
                {
                    NativeMethods.ReleaseMutex(mutexPtr);
                    MessageBox.Show(Language.FormatString(Language.LanguageString.App_AlreadyRunning), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }

            Kernel kernel = new Kernel(args);
            Application.Run();
            kernel = null;

            if (mutexPtr != IntPtr.Zero)
            {
                NativeMethods.ReleaseMutex(mutexPtr);
            }
        }