Here is the basics of what I have and what I need to know.
So far I have a TreeView navigation section and a ListView that I am attempting to use as an image thumbnail viewer.
I have it successfully pulling the image contents of the directory and displaying them using Image.GetThumbnailImage().
The problem I am having however, is that the ListView has no way to adjust aspect for each item. I am assuming that I would need to overlay the aspect ratio maintained thumbnail on a fixed size image then pull that new image in as the display image.
My question is then, how would I go about doing this? Does anyone have a section of code I could get the idea from or something?
This is the algorithm we use to get a scaled images' size, while preserving its aspect. If we want an image that's inside say a 16x16 box, we'd pass in:
If the image is 30x40, the newsize will come back as 12x16.
/// Get's the largest size which will fit inside newSize,
/// while preserving the aspect ration of currentSize
/// <param name="currentSize">The size whose aspect must
/// be preserved</param>
/// <param name="newSize">The maximum bounds of the result.
/// negative numbers represent unbounded dimension
/// convenient for creating fixed width or fixed height
/// images with a scaling second dimension</param>
/// <returns>the appropriate size</returns>
public static Size GetAspect( Size currentSize, Size newSize )
if( newSize.Width < 0 && newSize.Height < 0 )
// Well, not quite unbounded
float aspect = (float)currentSize.Width / (float)currentSize.Height;
if( ( (float)newSize.Width / aspect > (float)newSize.Height &&
newSize.Height >= 0 ) ||
newSize.Width < 0 )
newSize.Width = (int)Math.Round( (float)newSize.Height * aspect );
newSize.Height = (int)Math.Round( (float)newSize.Width / aspect );
return new Size( NewWidth, NewHeight );
Hope this helps.
PS... The interpolation used in GetThumbnailImage isn't exactly stellar. We draw the image onto a graphics object using InterpolationMode.HighQualityBiCubic.
PPS... I know people have complained about the resizing that we do, but actually it's a CSS problem, the CSS is stretching the image by about 4 pixels and it looks like crap, I'll fix that sometime soon.
actually this is more of what I was looking for, I can handle the aspect ratio but I was wondering how I could impliment it onto a single sized template image to keep images proportioned when added to a ListView (keep in mind this is just my rough hash
out of what I'm working on. I poked around with intellisense untill I figured it out, still need to clean it all up):
PrivateFunction MakePreviewIcon(ByRef myBGImg As Drawing.Image,
ByRef myFGImg As Drawing.Image) As Drawing.Image
Dim sizeFG AsNew Size(myFGImg.Width, myFGImg.Height)
Dim sizeBG AsNew Size(myBGImg.Width, myBGImg.Height)
Dim myGraphic As Drawing.Graphics = Graphics.FromImage(myBGImg)
myGraphic.DrawImage(myFGImg, 0, 0)
Dim myReturnImg As Image = DirectCast(myBGImg.Clone(), Image)
myGraphic.DrawImage(myReturnImg, 0, 0)
Here's some code i use in an asp.net app i wrote:
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim connstr As String = Application("ConnectionString").ToString Dim cnn As New SqlConnection(connstr) Dim cmd As New SqlCommand("select * from t_ezImages where ID=" & Request.QueryString("id"), cnn) cnn.Open() Dim dr As SqlDataReader = cmd.ExecuteReader()
dr.Read() Dim strImageType = dr.GetValue(11)
Dim bindata() As Byte = dr.GetValue(6) Dim Thumbnailbindata() As Byte = resizeImage(bindata)
'******************************************************* Public Function resizeImage(ByVal pic() As Byte) As Byte() ' Const THUMBNAIL_IMAGE_PATH As String = "C:\Thumbnails\Test.jpg" Const maxWidth As Integer = 100 Const maxHeight As Integer = 100 Dim inp As New IntPtr Dim imgHeight, imgWidth As Double
Try Dim image As System.Drawing.Image = System.Drawing.Image.FromStream(New MemoryStream(pic)) Dim bm = New Bitmap(image)
Dim imgHres, imgVres As Single
'Added this for testing - usually 96 dpi for every picture imgHres = bm.horizontalresolution imgVres = bm.verticalresolution
imgHeight = bm.Height imgWidth = bm.Width
If imgWidth > maxWidth Or imgHeight > maxHeight Then 'Determine what dimension is off by more Dim deltaWidth As Double = imgWidth - maxWidth Dim deltaHeight As Double = imgHeight - maxHeight Dim scaleFactor As Double
If deltaHeight > deltaWidth Then 'Scale by the height scaleFactor = maxHeight / imgHeight Else 'Scale by the Width scaleFactor = maxWidth / imgWidth End If
imgWidth *= scaleFactor imgHeight *= scaleFactor End If
Dim w As Integer = Convert.ToInt32(imgWidth) Dim h As Integer = Convert.ToInt32(imgHeight)
Dim imgbmp As System.Drawing.Image = bm.GetThumbnailImage(w, h, Nothing, inp) Dim ms As New MemoryStream imgbmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg) Dim b(ms.Length - 1) As Byte ms.Position = 0 ms.Read(b, 0, ms.Length) Return b
Ahh, I see, so I'm guessing that myBGImg is a white square or something and you're drawing the images in the center of the square to keep their center's all aligned. Sorry, i misread the question, we actually have some routines that will work for that
as well. We use the source and destination features of DrawImage to place images correctly into a box, but that code isn't used anywhere, so i'll leave you to your business, looks like you've made progress.
Why are you drawing the result back into the original background image again at the end there?
Another thing you might want to try is creating a graphics object from an empty (new) image whose size is defined by myBGImg. Then draw the background and the foreground into the new image. This way you won't have to re-initialize your background image every
time. I think the way you're doing it here will pollute the original background.
Yah I've cleaned it up considerably since I forst figured out what I needed to do.
Right now I am pulling in a black-line bordered image for myBGImg.
Here is the code for what I am doing, the myFGImg and myBGImg are being passed in ByVal so it doesn't cause any problems with the source images.
Dim myRectangle As Drawing.RectangleF = myFGImg.GetBounds(GraphicsUnit.Pixel)
Dim myGraphic As Drawing.Graphics = Graphics.FromImage(myBGImg)
Be careful with objects in .NET passing ByVal. Many objects are passed ByRef even with the ByVal declaration since a pointer only is passed. In several examples from MS, they actually populate datasets passed in ByVal in Sub Procedures.....took me a while
to figure out what was going on cause I'd prefer to always use a function if i'm grabbing data if possible.
im student of Bsc in final year and my final year is Thumb Recognition System so i will search campare the algorithm of thumb and i using tool VB.net backand SQL Server so help me
Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.