Welcome Guest! To enable all features, please Login or Register.

Notification

Icon
Error

Options
View
Last Go to last post Unread Go to first unread post
#1 Posted : Monday, August 16, 2010 9:00:26 PM(UTC)

danc  
danc

Groups: Registered
Posts: 7


I have a 1600x1200 image that I retrieve from a capture card at 30fps and return as an hBitmap. I need to be to:

1) Resize smoothly down to 320x240
2) Compress it as a JPEG or JPEG2000
3) Save the compressed data to a byte() buffer
4) Assign the small image to an Image object for display in a PictureBox control
5) This all should happen in under 30ms

I have the current code working but it's slow (10fps) and uses up a lot of memory. I need to make this more efficient and speed it up.

Does anybody have any suggestions on how to speed this up? For example, is there a way to create a RasterImage from an HBitmap without creating a copy? Is there a faster way to smoothly shrink an HBITMAP more directly?

Dim _LastImageData As Byte()
Dim _LastImage As Image

Public Sub ResizeBitmap(hBitmap as System.IntPtr)

' hBitmap is 1600x1200 24-bit image

Dim ltRaster As Leadtools.RasterImage = Nothing
Dim resizeCommand As New Leadtools.ImageProcessing.ResizeCommand
Dim memStream As IO.MemoryStream = New IO.MemoryStream
Dim codecs as New Leadtools.Codecs.RasterCodecs


Try
' The following takes 51 milliseconds
ltRaster = Leadtools.RasterImage.FromHBitmap(hPic, 0)
DeleteObject(hPic)


' Shrink to 320x240. This takes another 28 milliseconds
resizeCommand.Flags = RasterSizeFlags.Resample
resizeCommand.DestinationImage = New RasterImage(RasterMemoryFlags.Conventional, 320, 240, ltRaster.BitsPerPixel, ltRaster.Order, ltRaster.ViewPerspective, ltRaster.GetPalette, IntPtr.Zero, 0)
resizeCommand.Run(ltRaster)

ltRaster.Dispose()

' Save using JPEG. Takes < 1 millisecond
ltRaster = resizeCommand.DestinationImage()
codecs.Options.Jpeg.Save.QualityFactor = 50
codecs.Save(ltRaster, memStream, RasterImageFormat.J2k, 24)

' Extract the byte stream. Takes < 1 milliseconds
memStream.Seek(0, IO.SeekOrigin.Begin)
ReDim _LastImageData(memStream.Length)
memStream.Read(_LastImageData, 0, imageData.Length)

memStream.Close()
memStream.Dispose()

' Save the frame to an Image object for display elsewhere
_LastImage = ltRaster.ConvertToGdiPlusImage()

Catch ex As Exception
Finally
ltRaster.Dispose()
ltRaster = Nothing
End Try

Return imageData
End Sub
 

Try the latest version of LEADTOOLS for free for 60 days by downloading the evaluation: https://www.leadtools.com/downloads

Wanna join the discussion? Login to your LEADTOOLS Support accountor Register a new forum account.

#2 Posted : Tuesday, August 17, 2010 2:45:42 AM(UTC)

Basel  
Guest

Groups: Guests
Posts: 3,028

Was thanked: 2 time(s) in 2 post(s)

When dealing with live video in real time, normal image processing functions may not be suitable unless the video size is small to begin with, or the machine is very powerful.
Instead of obtaining the video frames as HBITMAPs, does the capture device have a DirectShow-compatible video capture driver? If yes, you could use our Multimedia toolkit to display, resize (or zoom) the video frames in real time with little or no loss of frames.
 
#3 Posted : Tuesday, August 17, 2010 12:34:54 PM(UTC)

danc  
danc

Groups: Registered
Posts: 7


Thanks for the prompt reply Basel.

I will take a look at the Multimedia API though much of our code is already done.

Looking at the above code, can you tell if there is any more efficient way of doing what I want to do? It seems that the conversion to a RasterImage is copying data unecessarily and is taking the majority of the time. Can I resize the hbitmap directly?

If I use the multimedia toolkit can you confirm that it has much faster support to shink a 1600x1200 image to 320x240 than the ResizeCommand (which currently takes 28 ms) and does not require the additional copy into a RasterImage (which takes 51 ms)?
 
#4 Posted : Wednesday, August 18, 2010 3:03:32 AM(UTC)

Basel  
Guest

Groups: Guests
Posts: 3,028

Was thanked: 2 time(s) in 2 post(s)

If you use the ltmmCapture control (you will needs DirectShow capture driver), there's no need to resize, you can simply zoom by setting mode to Fit and resize the control itself.

You can assign memory to a RasterImage without converting or copying. You can use the following constructor with RasterMemoryFlags.User:
RasterImage Constructor(RasterMemoryFlags,Int32,Int32,Int32,RasterByteOrder,RasterViewPerspective,RasterColor[],Byte[],Int32)

 
#5 Posted : Wednesday, August 18, 2010 2:33:49 PM(UTC)

danc  
danc

Groups: Registered
Posts: 7


Thanks for the reply.

As far as ItmmCapture, I do need both the original size (1600x1200) and the smaller size. I create two separate, compressed data stream that I use elsewhere in the program. Not sure that zoom will allow me to do this?

Also, I tried using the RasterImage constructor but I get the following error:

System.AccessViolationException was caught
Message="Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
Source="Leadtools"
StackTrace:
at L_MemoryCopy(Void* , Void* , UInt32 ) at LT_Namespace.L_CopyMemory(Byte* dest, Byte* src, UInt32 count) at L_ResizeBitmap(_BITMAPHANDLE* , _BITMAPHANDLE* , UInt32 ) at Leadtools.ImageProcessing.ResizeCommand.RunCommand(RasterImage image, IntPtr bitmap, RasterImageChangedFlags& changedFlags) at Leadtools.ImageProcessing.RasterCommand.Run(RasterImage image) at SoVideoConf2.VideoConference.GrabDxFrame() in C:\Documents and Settings\User\Desktop\ALL NEW\My Projects\SoVideoConf2\SoVideoConf2\VideoConference.vb:line 724
InnerException:


Here is the code that is capturing the image (simplified and error handling removed). Can you tell me if I am doing something wrong here?


== Capture code (Managed C++) ==

System::IntPtr hBitmap

void *Hbuffer;
Hbuffer = NULL;

// Get a pointer to the video header.
VIDEOINFOHEADER *pVideoHeader = (VIDEOINFOHEADER*)DX.MediaType.pbFormat;

// The video header contains the bitmap information.
// Copy it into a BITMAPINFO structure.
BITMAPINFO BitmapInfo;
ZeroMemory(&BitmapInfo, sizeof(BitmapInfo));
CopyMemory(&BitmapInfo.bmiHeader, &(pVideoHeader->bmiHeader), sizeof(BITMAPINFOHEADER));

// Create a DIB from the bitmap header, and get a pointer to the buffer.
HBITMAP hBitmap = CreateDIBSection(0, &BitmapInfo, DIB_RGB_COLORS, &Hbuffer, NULL, 0);

// Copy the image into the buffer.
long Size = (DX.cbBuffer);
DX.pSampleGrabber->GetCurrentBuffer(&Size, (long *)Hbuffer);

long Width = pVideoHeader->bmiHeader.biWidth;
long Height = pVideoHeader->bmiHeader.biHeight;

== Try to use it (VB.NET) ==

Dim ltRaster As Leadtools.RasterImage = Nothing
ltRaster = New Leadtools.RasterImage(Leadtools.RasterMemoryFlags.User, Width, Height, 24, RasterByteOrder.Rgb, RasterViewPerspective.BottomLeft, Nothing, hBitmap, Size)

Dim resizeCommand As New Leadtools.ImageProcessing.ResizeCommand
resizeCommand.Flags = RasterSizeFlags.Resample
resizeCommand.DestinationImage = New RasterImage(RasterMemoryFlags.Conventional, 320, 240, ltRaster.BitsPerPixel, ltRaster.Order, ltRaster.ViewPerspective, ltRaster.GetPalette, IntPtr.Zero, 0)
resizeCommand.Run(ltRaster)

-- Run throws the exception
 
#6 Posted : Thursday, August 19, 2010 3:22:35 AM(UTC)

Basel  
Guest

Groups: Guests
Posts: 3,028

Was thanked: 2 time(s) in 2 post(s)

About obtaining 2 copies of the frame, if you need the data from them both and not only display the zoomed copy, it can't be done this way. You could still use ltmmCapture, but you will also need some of our DirectShow processing filters such as the Video Resize filter and the Video Callback filter.

About creating the bitmap, did you try to pass the bitmap bytes to our constructor without creating a DIB first? If you still can't get it to work, try to create a small project that only delivers some sample data to the function and I can try to modify it to construct a LEAD image from it. You can post it here or send it to support@leadtools.com and mention this forum post. If you send files, please put them in a ZIP or a RAR file.

 
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Powered by YAF.NET | YAF.NET © 2003-2020, Yet Another Forum.NET
This page was generated in 0.222 seconds.