A Robust Image Gallery for ASP.NET, Part 2
By Robert Van Dyk
In Part 1 we examined how to build up an array of JPEG files and subdirectories in a given directory. In this part we'll look at how to generate the required HTML to display thumbnails of the images.
Emitting the HTML for a JPEG Image
Before we generate the HTML to be emitted to display the thumbnail for a particular image, we first need to determine the scale factor we will use for the image in order to create its thumbnail. I wasn't planning on showing this, except for the fact that I believe it to be an improvement on the original code from the True Image Resizing article. With the old code, the image was scaled down to the first size-calculated fit that conformed to the min and max parameters set. With the rewritten code, we only accept the best scale down that can be applied to the size of the image. I had to do this, because I wanted to accommodate both images that were long and short and images that were tall and fat equally as well - something I found the old code didn't do well. In the code that follows,
currentImage
is a System.Drawing.Image
object and
.Height
and .Width
are full-scale dimensions.
|
Here there are two constants - maxHeight
and maxWidth
, which specify the
maximum height and width, respectively, for a thumbnail. In the code you can toggle the values
for these constants, but for the live demo I have them set to 93 and 125 for the height and width.
The first set of If/Else
statements checks to see if the image needs to be scaled at
all. If it does, it uses the ratio of deviation between the actual sizes and the maximum acceptable
sizes to guess the best scale factor. The second group of If
statements checks to
see that this is the best scale factor, and if not, selects the better one.
The next step is to figure out the name of the file, and its size. We do this through a couple of methods that are provided through the .NET Framework.
|
Here, I declare a String called filename
that is set to the filename of the file without
any of the path information or extension. Then, I check to see that it is 20 characters or shorter,
which effectively constrains the filename to one line of real estate in the 125 pixel wide table
element. fs
here is an instance of a FileStream
object (which is not shown
here, but is in the complete code available at the end of this article). The Length
property
of the FileStream
object returns the file's size in bytes.
This byte size is then divided by 1,024 to convert that number to kilobytes.
The final action is to produce the HTML string that will be emitted to the user's browser to display the thumbnail. This string will include a link to open a new image in a JavaScript window whose size is determined by (a) the size of the full- scale image and (b) the size/resolution that your user has his monitor set at.
An <img>
tag is used to actually display the image. Like in the
True Image Resizing article, there exists a separate ASP.NET
Web page to display the scaled down image. In the previous article this page was called
ShowThumbnail.aspx
; I decided to rename it to thu.aspx
. The only
modification is that thu.aspx
has a QueryString variable named path
that is needed in order to be able to support the recursive subdirectory system.
This article does not examine Thu.aspx
, it can be used as-is from the download section
at the end of this article.
In addition to displaying the image with an <img>
tag, we need to also display some
file information, including the image's dimensions and file size. The entire HTML to be emitted for
a particular image is done so in the final two lines of AddImage()
function:
|
Since the file that will actually return our thumbnail is
The following code exists in the
The
The
Here we are processing the
Let me first explain
The next two variables I use are
Also, I recommend that you display
Also, remember, there is a line near the top of
Happy Programming.
thu.aspx?img=filename&w=width&h=height&path=path we need to parse all spaces out of
this URL and replace them with the
%20
that Web browsers understand. A more robust
approach would be to use Server.UrlEncode()
here instead.
Handling Subdirectories
We want to link to subdirectories so that people can organize their images, otherwise this whole
gallery thing isn't very scaleable. To indicate that something is a subdirectory, I create a
standard folder looking image that will be displayed for all these items. With a couple of calls to
the Path
class methods we can determine directory name and how many images and
subdirectories it contains.
AddDirectoryLink()
function, and is called when displaying
a subdirectory in the image gallery.
try
Dim filesIn = Directory.GetFiles(s, "*.jpg")
Dim dirsIn = Directory.GetDirectories(s)
return "<a href=""thumb.aspx?page=1&subpage=" & _
inSubpageSlash.replace(" ","%20") & _
Path.GetFileName(s.replace(" ","%20")) & """>" & _
"<img width=125 height=93 src=""Folder.jpg"" " & _
"border='0'></a>" & _
"<br><div align=center>" & _
"<span style=""font size:'8pt'; " & _
"font-family:'Verdana';"">" & _
Path.GetFileName(s) & "<br>" & _
dirsIn.Length & " directories<br>" & filesIn.Length & _
" images<br></span></div>"
catch
Response.Write(s)
end try
filesIn
and dirsIn
arrays are used strictly for their .Length
property to determine the number of files and subdirectories that the displayed directory contains inside
of it. Note that the link that is created has a fairly complicated QueryString variable named subpage
,
while everything else is pretty easy to follow. In fact, everything else should fall into place because
it is done very similarly to the way the files are done.
subpage
QueryString variable stores the number of subdirectories we've stepped through.
In a way, the subpage
variable is kind of like an array where each element is separated
by a \
mark. InSubpageSlash
represents the previous subpage value and
Path.GetFileName(s)
represents the new directory that is being added to the array. As
long as Web browsers do not have a bound on the number of characters they can process in a URL
then you can add as many subdirectories as you want to the image gallery (though, I
would personally stick to three or four levels, to make it easier on your users.) The trickiest
part of the programming comes when I manipulated the subpage
variable. Take a look at
the code segment below from the HandleDirectoryInput()
subroutine:
Dim inSubpage = Request.QueryString("subpage")
Dim inSubpageSlash = ""
If inSubpage <> ""
inSubpage = inSubpage.replace("%20", " ")
inSubpageSlash = inSubpage + "\"
PathVar += inSubpageSlash
top.text = "<font face='Verdana' size='1'>" & _
"<a href=thumb.aspx?page=1>home</a>"
Dim used = ""
Dim unused = inSubpage.replace(" ", "_")
While unused.IndexOf("\") > 0
used = inSubpage.subString(0,used.length + _
unused.IndexOf("\")).replace(" ", "_")
unused = inSubpage.subString(used.length+1, _
inSubpage.length-used.length-1).replace(" ", "_")
top.text += " \ <a href=thumb.aspx?page=1&subpage=" & _
used.replace("_","%20") & ">" & _
used.subString(used.lastIndexOf("\")+1,_
used.length-used.lastIndexOf("\")-1) & "</a>"
used += "\"
End While
top.text += " \ " & unused & "</font>"
Else
top.text = "<font face='Verdana' size='1'>home</font>"
End If
subpage
QueryString value and generating the upper part of
the table that indicates the current sub-directory. If there is no subpage
specified,
we know that the user is in the root directory, and therefore can just print out home
.
Otherwise, we have some processing to do.
inSubpageSlash
. Basically, this is here because inSubpage
does not contain a \
character at the end of it, and in order for thu.aspx
to work you need to pass it a path that does end with a \
. Also, having this variable
made things easier to develop when I created the script. It wouldn't be too hard to go work
inSubpageSlash
out of the code, but sloppy as I am, it is staying put.
used
and unused
. Basically, initially
everything is unused
so inSubpage
is copied over to that. Then, for every
directory that is called out in unused
, we need to copy a link to that directory, with a
working link including everything up to that point. If the inSubpage
variable was
pictures\summer\vacation\beach
then we need to generate a string that prints the word
pictures
and links to pictures
, followed by summer
with a
link to pictures\summer
, and so on. It continues like that until you get to
beach
with the link pictures\summer\vacation\beach
. Using a fairly high
level of string manipulation that relies on the convention that directories are separated by a
\
I am able to execute this in a while loop, so that infinite subdirectories are
possible.
Conclusion
Now it is time for you breath a sigh of relief because I am giving away the full version of the
code I just explained to you how to write. There are a couple of parts that were left out, though
nothing that should be too hard to understand (and if you don't get it, I am willing to help, just drop
me an email).
thumbs.aspx
in an IFRAME
like:
[View a Live Demo!]
<center>
<IFRAME src="thumb.aspx?page=1" width="700" height="330"
scrolling="auto" frameborder="0">
[Your user agent does not support frames or is currently
configured not to display frames. However, you may visit
<A href="foo.html">the related document.</A>]
</IFRAME>
</center>
thumbs.aspx
that is used to
specify the location of the root directory you have your images in that you need to modify.
And finally, I would also encourage anyone who does decide to use my code to shoot me an e-mail at
vandyr@rpi.edu and tell me how you like (or don't like) it.
Attachments