PDA

View Full Version : Save the "As-zoomed" image as shown in the Live display (not the full unzoomed image)



kmmatney
October 1, 2013, 05:25:30
In my application, the LiveDisplay window is always automatically resized to show the full camera window as the form is resized. The LiveDisplayLeft and LiveDislpayTop properties are also set automatically as the camera is zoomed to keep the image centered and the zoomed image filling up the whole live display window. This all works well - however when I am zoomed in, if I save a bitmap it saves the whole image buffer, and not the zoomed in portion that is actually shown in the live display window. is there a way to save the exact contents as-shown in the live display window - not the entire camera image?

I guess I could do it by saving a new bitmap with the same offsets and size of my zoomed image, but it would be a lot easier if I didn't have to do that.

Stefan Geissler
October 1, 2013, 08:36:45
Hello


I guess I could do it by saving a new bitmap with the same offsets and size of my zoomed image, but it would be a lot easier if I didn't have to do that.

You are right. You create a System.Drawing.Bitmap of the wanted image size and draw the icImagingControl.ActiveImageBuffer.Bitmap into this using the left, height, width and top value of the "Display" starting properties. Unfortunately I have no sample code for this. Do you need sample code? If so, C# or VB?

kmmatney
October 2, 2013, 21:41:27
Thanks for the quick reply! I'm using VB.Net. I am already doing quite a bit of bitmap manipulation with the image, so I should heopfully be able to figure it out, but sample code would be useful. The code I have for keeping the live display in synch with the zoom and the size of the Image control is pretty simple:

Image control is named "ICC"

With ICC
.LiveDisplayLeft = 0.5 * (.Width - .LiveDisplayWidth)
.LiveDisplayTop = 0.5 * (.Height - .LiveDisplayHeight)
End With


So I'm guessing I would create a bitmap of size .LiveDisplayWdith and .LiveDisplayHeight and then paint into it using the livedisplay coordinates.

Stefan Geissler
October 4, 2013, 11:31:46
Hi

here we go:



IcImagingControl1.MemorySnapImage()
Dim SaveBitmap As Bitmap = New Bitmap(IcImagingControl1.Width, IcImagingControl1.Height)
Dim CurrentGraphics As Graphics

CurrentGraphics = Graphics.FromImage(SaveBitmap)

CurrentGraphics.DrawImage(IcImagingControl1.ImageA ctiveBuffer.Bitmap,
IcImagingControl1.LiveDisplayLeft, IcImagingControl1.LiveDisplayTop,
IcImagingControl1.Width, IcImagingControl1.Height)


SaveBitmap.Save("test.png", Imaging.ImageFormat.Png)


It is simply drawing with the correct top, left, with and height from IC Imaging Control into a previously created bitmap. However, I needed to read the MSDN before, learning about the Graphics.

kmmatney
October 8, 2013, 22:04:12
The above code didn't work in my application. The problem is that to keep the zoomed image "centered" in the display window, you need to adjust the .LiveDisplayLeft and .LiveDisplyTop properties with this code:

Zoom_Factor = Zoom that we set - tied to a scroll control

ICC.LiveDisplayZoomFactor = Zoom_factor * (ICC.Width / ICC.ImageWidth)

With ICC
.LiveDisplayLeft = 0.5 * (.Width - .LiveDisplayWidth)
.LiveDisplayTop = 0.5 * (.Height - .LiveDisplayHeight)
End With

As you zoom in, the LiveDisplayWidth and LiveDisplayHeight properties get bigger, and you soon get negative values for .LiveDisplayLeft and .LiveDisplayTop. The graphics object doesn't seem to know how to deal with this, and you only get a partial (or no) image.

I was able to get it to work, but I first had to save the full resolution bitmap (2592 x 1944 in my case) and then reload the bitmap, from the disk and then extract the portion needed to get the zoomed region.

The code is:




ICC.MemorySaveImage(filename)

Dim BSource As Bitmap
Dim BFinal As Bitmap
Dim ROI As Rectangle

' load the bitmap without locking the file
BSource = SafeImageFromFile(filename)

' calculate the region of the image we need to extract the "zoomed" part of the image
With ROI
.X = CInt((ICC.ImageWidth - ICC.ImageWidth / ZoomFactor()) * 0.5)
.Y = CInt((ICC.ImageHeight - ICC.ImageHeight / ZoomFactor()) * 0.5)
.Width = CInt(ICC.ImageWidth / ZoomFactor())
.Height = CInt(ICC.ImageHeight / ZoomFactor())
End With

' Copy the region we want to a new bitmap
BFinal = CopyBitmapRegion(BSource, ROI)
BSource.Dispose()

' give some time for all file locks to end
Thread.Sleep(50)
Application.DoEvents()

' save over the original full-size image
BFinal.Save(filename, Imaging.ImageFormat.Bmp)
BFinal.Dispose()



and the routine to get the region of interest from the original bitmap is:




Public Function CopyBitmapRegion(srcBitmap As Bitmap, Section As Rectangle) As Bitmap

' Create the new bitmap and associated graphics object
Dim bmp As New Bitmap(Section.Width, Section.Height)
Dim g As Graphics = Graphics.FromImage(bmp)

' Draw the specified section of the source bitmap to the new one
g.DrawImage(srcBitmap, 0, 0, Section, GraphicsUnit.Pixel)

' Clean up
g.Dispose()

' Return the bitmap
Return bmp

End Function 'CopyBitmapRegion


I can probably figure out a way to do it in memory, without writing out the full res file first, but this is the basic algorithm needed to save a centered zoomed image.

Stefan Geissler
October 10, 2013, 10:08:37
Hi

I figured it out. This is my zoom factor:

Private f As Integer = 5

First of all, lets implement the centering zooming:


With IcImagingControl1
Dim w As Integer = .ImageWidth / f
Dim h As Integer = .ImageHeight / f

Dim x0 As Integer = (.ImageWidth - w) / 2
Dim y0 As Integer = (.ImageHeight - h) / 2

Dim x1 As Integer = x0 + w
Dim y1 As Integer = y0 + h



.LiveDisplayHeight = .ImageHeight * f
.LiveDisplayWidth = .ImageWidth * f

.LiveDisplayLeft = -((.ImageWidth - w) / 2) * f
.LiveDisplayTop = -((.ImageHeight - h) / 2) * f
End Widh


Now lets save the visible zoomed image:


Private Sub btnSaveImage_Click(sender As Object, e As EventArgs) Handles btnSaveImage.Click
IcImagingControl1.MemorySnapImage()
Dim SaveBitmap As Bitmap = New Bitmap(IcImagingControl1.Width, IcImagingControl1.Height)
Dim CurrentGraphics As Graphics
Dim TargetRect As Rectangle
Dim CropRegion As New Rectangle

With IcImagingControl1

TargetRect.X = 0
TargetRect.Y = 0
TargetRect.Width = IcImagingControl1.Width
TargetRect.Height = IcImagingControl1.Height

CropRegion.Width = .ImageWidth / f
CropRegion.Height = .ImageHeight / f

CropRegion.X = (.ImageWidth - CropRegion.Width) / 2
CropRegion.Y = (.ImageHeight - CropRegion.Height) / 2

End With


CurrentGraphics = Graphics.FromImage(SaveBitmap)

CurrentGraphics.DrawImage(IcImagingControl1.ImageA ctiveBuffer.Bitmap,
TargetRect, CropRegion,
GraphicsUnit.Pixel)

SaveBitmap.Save("test.png", Imaging.ImageFormat.Png)
End Sub


Hopefully this solves your issue faster, than saving the bitmap first on hard disc.

kmmatney
October 11, 2013, 22:53:27
Yes - That works great - thanks!