Output Dynamically Resized Image from Data Stream...
I am converting from classic ASP to .NET via VB.NET and sorta stuck on outputting streamed images from a dynamically resizing routine courtesy of [4guysfromrolla]. I would definitely appreciate any expert input in my times of transition. Graci.
Use an aspx page for the image links. Have the aspx page do any processing needed on the image and pass out the content. Semi-relevant example to follow in my next post.
EDIT: After now having followed the link you provided, I have to ask... What exactly are you having problems with? Specific questions lead to more specific answers...
Last edited by CardboardHammer; 05-03-2004 at 10:26 AM.
Complete codebehind for a page that I use to generate piechart graphics.
Code:
Imports System.Drawing
Imports System.Drawing.Imaging
Public Class PieChart
Inherits System.Web.UI.Page
#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
End Sub
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Output error image on bad data... everything else, revert to defaults on error
Dim arrValues As Array
Dim arrVals() As Single
Dim sSum As Single
Dim arrColors() As Color
Dim numColors As Int32
Dim strFormat As String
Dim lSize As Int32
Dim sCurrentDegree As Single
Dim iLoop As Int32
Dim iEndLoop As Int32
Dim objBkgrColor As Color
objBkgrColor = Color.White 'Default
Dim coll As Collections.Specialized.NameValueCollection
coll = Request.QueryString
arrValues = coll.GetValues("f")
If Not arrValues Is Nothing Then
Try
strFormat = Convert.ToString(arrValues.GetValue(0))
Catch 'Ignore any error
End Try
End If
arrValues = coll.GetValues("s")
If Not arrValues Is Nothing Then
Try
lSize = Convert.ToInt32(arrValues.GetValue(0))
If lSize <= 0 Then
'Default size
lSize = 200
ElseIf lSize > 800 Then
'Maximum size
lSize = 800
End If
Catch 'Use Default size
lSize = 200
End Try
Else
'Use Default size
lSize = 200
End If
arrValues = coll.GetValues("a")
If Not arrValues Is Nothing Then
Try
sCurrentDegree = Convert.ToSingle(arrValues.GetValue(0))
Catch 'Ignore any error
End Try
End If
arrValues = coll.GetValues("c")
If Not arrValues Is Nothing Then
iEndLoop = arrValues.GetUpperBound(0)
Try
Dim arrTempColors(iEndLoop) As Color
For iLoop = 0 To iEndLoop
arrTempColors(iLoop) = Color.FromArgb(Convert.ToInt32(arrValues.GetValue(iLoop)))
Next
arrColors = arrTempColors
Catch 'IRevert to default colors on error
'Get default colors
Procedures.GetDefaultColors(arrColors)
End Try
Else
'Get default colors
Procedures.GetDefaultColors(arrColors)
End If
numColors = arrColors.GetLength(0)
arrValues = coll.GetValues("b")
If Not arrValues Is Nothing Then
Try
objBkgrColor = Color.FromArgb(Convert.ToInt32(arrValues.GetValue(0)))
Catch 'Ignore any error
End Try
End If
Dim sTemp As Single
arrValues = coll.GetValues("d")
If Not arrValues Is Nothing Then
Try
iEndLoop = arrValues.GetUpperBound(0)
Dim arrValsTemp(iEndLoop) As Single
For iLoop = 0 To iEndLoop
sTemp = Convert.ToSingle(arrValues.GetValue(iLoop))
If sTemp < 0 Then
iEndLoop = -1
End If
arrValsTemp(iLoop) = sTemp
sSum += arrValsTemp(iLoop)
Next
arrVals = arrValsTemp
Catch 'ignore all errors...?
iEndLoop = -1
End Try
Else
iEndLoop = -1
End If
arrValues = coll.GetValues("r")
If Not arrValues Is Nothing Then
Try
If Convert.ToString(arrValues.GetValue(0)) = "-" Then
sSum *= -1 'counterclockwise rotation
End If
Catch 'Ignore any error
End Try
End If
' Create a Bitmap instance and a Graphics instance
Dim objBitmap As Bitmap
objBitmap = New Bitmap(lSize, lSize, PixelFormat.Format32bppArgb)
Dim objGraphics As Graphics
objGraphics = Graphics.FromImage(objBitmap)
'Put a white background in
objGraphics.FillRectangle(New SolidBrush(objBkgrColor), 0, 0, lSize, lSize)
For iLoop = 0 To iEndLoop
'use twice, calculate once
sTemp = 360 * arrVals(iLoop) / sSum
'Draw the slice
objGraphics.FillPie(New SolidBrush(arrColors(iLoop Mod numColors)), 0, 0, lSize, lSize, sCurrentDegree, sTemp)
' increment the currentDegree
sCurrentDegree += sTemp
Next
' Save the image to the OutputStream
If strFormat = "jpeg" Then
Response.ClearContent()
Response.ContentType = "image/jpeg"
objBitmap.Save(Response.OutputStream, ImageFormat.Jpeg)
Response.Flush()
Else
Response.ClearContent()
Response.ContentType = "image/gif"
objBitmap.Save(Response.OutputStream, ImageFormat.Gif)
Response.Flush()
End If
' clean up...
objGraphics.Dispose()
objBitmap.Dispose()
End Sub
End Class
I understand the logic of the algorithm to dynamically resize the image up to the point of outputting the information back to the client. How do I know exactly what is being thrown back from the data stream once the image has been resized? The reason why this is so important for me is that I have to fit this algorithm in a For Each Next Loop that would take an image in a given folder, thumbnailize it, then output <td> <img src... onClick()...> </td>. The onClick() is for opening a new window with the full-sized image originally in javascript but if anyone knows how to completely turn this into a server solution, THAT WOULD BE AWESOME. I'm guessing the starting point would be to use an ASP Image Control then place the appropriate event handler to trigger opening of the new window... then adding on to the complexity... this new window should be dynamic in accordance with user's resolution and centered. Is this possible with a complete ASP.NET solution? Then again I've tried Response.Write ASP Controls and that doesn't seem to work because of code stack issues... insights?
The src attribute for the image tag is the URL of page that does the resizing along with a querystring containing parameters for the image being shrunk, the size being shrunk to, image format, etc. If you want 10 thumbnails on a page, you're going to have 10 image tags and then 10 requests for the resizing page from the browser when the browser processes the image tags. You don't resize all 10 images at the same time as you're generating the rest of the page and then send everything the client in one shot; that's just not the way it works.
"what is being thrown back from the data stream once the image has been resized" is the equivalent (as far as the client browser is concerned) of what the client would get if you resized the image manually and then setting the src attribute of the image tag to the URL of the resized image.
Before saving image data to Response.OutputStream, you can use Response.ClearContent() to get rid of any crap that may have already been tossed in, then set the content type appropriately, and then save.
Right on... but instead of having separate image tags it can be done with a For Next Loop? If so how would this work in example? I'm quite the visual learner so looking examples is my best way of learning.
You could combine all the thumbnails into one image, but then you'd need to treat that image as an imagemap (or whatever the heck it's called) in order to open the correct full-size image when handling the onclick event.
To handle the images, you'd shrink each one of them to thumbnail size and paste them into the correct place in the image to be output. It could be done in a loop: shrink an image in the list/array of images and paste into place in the final image in each iteration of the loop.
I've never done an image map, so you'll need to find another resource for dealing with that.
Bookmarks