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?
Thanks
-
-
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:
Size newSize = GetAspect( image.Size, new Size( 16, 16 ) );
If the image is 30x40, the newsize will come back as 12x16./// <summary> /// Get's the largest size which will fit inside newSize, /// while preserving the aspect ration of currentSize /// </summary> /// <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 return currentSize; } 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 ); } else { 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.
-Bryn
-
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):
Private Function MakePreviewIcon(ByRef myBGImg As Drawing.Image, ByRef myFGImg As Drawing.Image) As Drawing.Image
Dim sizeFG As New Size(myFGImg.Width, myFGImg.Height)
Dim sizeBG As New Size(myBGImg.Width, myBGImg.Height)
Dim myRectangle As New Drawing.Rectangle( _
Math.Round(CDbl((sizeBG.Width - sizeFG.Width) / 2), 0), _
Math.Round(CDbl((sizeBG.Height - sizeFG.Height) / 2), 0), _
sizeFG.Width, sizeFG.Height)
Dim myGraphic As Drawing.Graphics = Graphics.FromImage(myBGImg)
myGraphic.SetClip(myRectangle)
myGraphic.DrawImage(myFGImg, 0, 0)
Dim myReturnImg As Image = DirectCast(myBGImg.Clone(), Image)
myGraphic.DrawImage(myReturnImg, 0, 0)
Return myReturnImg
End Function
-
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)
Response.BinaryWrite(Thumbnailbindata)
End Sub
'*******************************************************
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 DoubleTry
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.verticalresolutionimgHeight = 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 DoubleIf deltaHeight > deltaWidth Then
'Scale by the height
scaleFactor = maxHeight / imgHeight
Else
'Scale by the Width
scaleFactor = maxWidth / imgWidth
End IfimgWidth *= scaleFactor
imgHeight *= scaleFactor
End IfDim 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
'bitmap.Save(THUMBNAIL_IMAGE_PATH, Imaging.ImageFormat.Jpeg)Catch ex As Exception
End Try
End Function 'resizeImage -
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)
myRectangle.Y = Math.Round((myBGImg.Height - myRectangle.Height) / 2)
myRectangle.X = Math.Round((myBGImg.Width - myRectangle.Width) / 2)
Dim myGraphic As Drawing.Graphics = Graphics.FromImage(myBGImg)
myGraphic.SetClip(myRectangle)
myGraphic.DrawImage(myFGImg, myRectangle)
Return myBGImg.Clone()
-
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.
-
hi
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
Thread Closed
This thread is kinda stale and has been closed but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.