// Assume Form1 is a Windwos.Forms form in your application // The OCR engine we are using private IOcrEngine _ocrEngine; // The document we are using private IOcrDocument _ocrDocument; // Our raster image viewer instance private RasterImageViewer _viewer; public Form1() { InitializeComponent(); // Unlock the support needed for LEADTOOLS Plus OCR engine RasterSupport.Unlock(RasterSupportType.Document, "Replace with your own key here"); RasterSupport.Unlock(RasterSupportType.OcrPlus, "Replace with your own key here"); RasterSupport.Unlock(RasterSupportType.OcrPlusPdfLeadOutput, "Replace with your own key here"); // Initialize the raster image viewer // Turn on use DPI, center the image, add border padding and frame shadow to show that our calculations will be // independent on all of those extra options _viewer = new RasterImageViewer(); _viewer.Dock = DockStyle.Fill; _viewer.BackColor = SystemColors.AppWorkspace; _viewer.UseDpi = true; _viewer.BorderPadding.All = 8; _viewer.FrameSize = new SizeF(1, 1); _viewer.FrameShadowSize = new SizeF(2, 2); _viewer.SizeMode = RasterPaintSizeMode.Normal; _viewer.HorizontalAlignMode = RasterPaintAlignMode.Center; _viewer.VerticalAlignMode = RasterPaintAlignMode.Center; _viewer.AutoDisposeImages = true; _viewer.InteractiveMode = RasterViewerInteractiveMode.None; // Turn on scale to gray painting in the viewer RasterPaintProperties props = _viewer.PaintProperties; props.PaintDisplayMode |= RasterPaintDisplayModeFlags.ScaleToGray; _viewer.PaintProperties = props; // Subscribe to the viewer events we need _viewer.KeyDown += new KeyEventHandler(_viewer_KeyDown); _viewer.MouseDown += new MouseEventHandler(_viewer_MouseDown); _viewer.PostImagePaint += new PaintEventHandler(_viewer_PostImagePaint); Controls.Add(_viewer); _viewer.BringToFront(); // Create and startup the OCR engine _ocrEngine = OcrEngineManager.CreateEngine(OcrEngineType.Plus, false); _ocrEngine.Startup(null, null, null, null); // Create the OCR document _ocrDocument = _ocrEngine.DocumentManager.CreateDocument(); // Load an image into the OCR document string tifFileName = LeadtoolsExamples.Common.ImagesPath.Path + "Ocr1.tif"; IOcrPage ocrPage = _ocrDocument.Pages.AddPage(tifFileName, null); // Do auto zone ocrPage.AutoZone(null); // AutoZone does not specify a name for the zones, so loop through all the zones and set their names // to a unique value. We will use the name in the paint code later IOcrZoneCollection ocrZones = ocrPage.Zones; for(int i = 0; i < ocrZones.Count; i++) { OcrZone ocrZone = ocrZones[i]; // Construct the name from the ID ocrZone.Name = string.Format("Zone {0}", ocrZone.Id); ocrZones[i] = ocrZone; } // Show the same image in the viewer _viewer.Image = ocrPage.GetRasterImage(); // Note, the image we got from GetRasterImage is a copy of the image in the engine // Since we set teh AutoDisposeImages of the viewer to "true", the image will be disposed // when the viewer is disposed at application termination Text = "+ to zoom in, - to zoom out, enter to return to 100%. Select the zones with the mouse"; } protected override void OnFormClosed(FormClosedEventArgs e) { // Dispose the document _ocrDocument.Dispose(); // Shutdown the OCR engine _ocrEngine.Shutdown(); _ocrEngine.Dispose(); base.OnFormClosed(e); } private void _viewer_KeyDown(object sender, KeyEventArgs e) { const double zoomRatio = 1.2; double scaleFactor = _viewer.ScaleFactor; switch(e.KeyCode) { case Keys.Add: case Keys.Oemplus: // Zoon in scaleFactor *= zoomRatio; e.Handled = true; break; case Keys.Subtract: case Keys.OemMinus: // Zone out scaleFactor /= zoomRatio; e.Handled = true; break; case Keys.Enter: scaleFactor = 1; e.Handled = true; break; } const double minimumScaleFactor = 0.05; const double maximumScaleFactor = 11; scaleFactor = Math.Max(minimumScaleFactor, Math.Min(maximumScaleFactor, scaleFactor)); // Check if scale factor has changed if(scaleFactor != _viewer.ScaleFactor) { _viewer.BeginUpdate(); // Yes, zoom keeping the center of the image // Get what you see in physical coordinates Rectangle rc = Rectangle.Intersect(_viewer.PhysicalViewRectangle, _viewer.ClientRectangle); // Get the center of what you see in physical coordinates PointF center = new PointF(rc.Left + rc.Width / 2, rc.Top + rc.Height / 2); Transformer t = new Transformer(_viewer.Transform); // Get the center of what you see in logical coordinates center = t.PointToLogical(center); _viewer.ScaleFactor = scaleFactor; // Bring the original center into the view center t = new Transformer(_viewer.Transform); // Get the center of what you saw before the zoom in physical coordinates center = t.PointToPhysical(center); // Bring the old center into the center of the view _viewer.CenterAtPoint(Point.Round(center)); _viewer.EndUpdate(); } } private void _viewer_MouseDown(object sender, MouseEventArgs e) { // Perform hit-testing on the zones if(_ocrEngine != null && _ocrEngine.IsStarted && _ocrDocument != null && _ocrDocument.Pages.Count > 0 && e.Button == MouseButtons.Left) { // Get the transform of the viewer // Use the transform that takes the DPI into consideration since we turned that on using(Matrix matrix = _viewer.GetTransformWithDpi()) { Transformer t = new Transformer(matrix); // Convert the mouse click coordinates from physical (viewer) to logical (image) PointF point = new PointF(e.X, e.Y); point = t.PointToLogical(point); // Hit test the zones // An alternitave to calling HitTestZone is to loop through all the zones // and get the value of .Bounds in pixels, then check if the point is inside // the boundaries. IOcrPage ocrPage = _ocrDocument.Pages[0]; int zoneIndex = ocrPage.HitTestZone(new LogicalPoint(point)); if(zoneIndex != -1) { // We hit a zone, loop through all the zones, unselect all but the hit tested zone for(int index = 0; index < ocrPage.Zones.Count; index++) { // Since OcrZone is a structure, we cannot simply do // ocrZone.Zones[index].Selected = value // We have to get a copy of the structure, modify it and set it back OcrZone ocrZone = ocrPage.Zones[index]; if(index != zoneIndex) ocrZone.Selected = false; else ocrZone.Selected = true; ocrPage.Zones[index] = ocrZone; } // Re-paint the viewer to show the new zones _viewer.Invalidate(); } } } } private void _viewer_PostImagePaint(object sender, PaintEventArgs e) { // Draw the zones on the viewer in their correct location if(_ocrEngine != null && _ocrEngine.IsStarted && _ocrDocument != null && _ocrDocument.Pages.Count > 0) { // Get the transform of the viewer // Use the transform that takes the DPI into consideration since we turned that on using(Matrix matrix = _viewer.GetTransformWithDpi()) { Transformer t = new Transformer(matrix); IOcrPage ocrPage = _ocrDocument.Pages[0]; Pen normalPen = new Pen(Color.Blue, 1); Pen selectedPen = new Pen(Color.Red, 2); selectedPen.DashStyle = DashStyle.Dash; foreach(OcrZone ocrZone in ocrPage.Zones) { // Get the zone bounds in pixels // You can also use ocrPage.GetZoneBoundsInPixels here RectangleF zoneBounds = ocrZone.Bounds.ToRectangleF(ocrPage.DpiX, ocrPage.DpiY); // This rectangle is in image (logical) coordinates with top-left view perspective // Convert to the physical coordinates of the viewer zoneBounds = t.RectangleToPhysical(zoneBounds); // Now draw this zone on the viewer surface if(ocrZone.Selected) e.Graphics.DrawRectangle(selectedPen, zoneBounds.X, zoneBounds.Y, zoneBounds.Width - 1, zoneBounds.Height - 1); else e.Graphics.DrawRectangle(normalPen, zoneBounds.X, zoneBounds.Y, zoneBounds.Width - 1, zoneBounds.Height - 1); // Draw the zone name on the left hand corner of the zone // Note, in a real application you might want to have an option to show/hide the zone names (labels) SizeF labelSize = e.Graphics.MeasureString(ocrZone.Name, Font); RectangleF labelRectangle = new RectangleF(zoneBounds.X, zoneBounds.Y - labelSize.Height, labelSize.Width, labelSize.Height); e.Graphics.FillRectangle(Brushes.Yellow, labelRectangle); e.Graphics.DrawString(ocrZone.Name, Font, Brushes.Black, labelRectangle.X, labelRectangle.Y); } } } } |