Introduction
There are many 3rd party TIF Viewers out there, but why pay when this is built into .NET already using System.Drawing.Image
(unless you need to be able to support JPEG compressed TIF files, which GDI doesn't support). Save yourself some time and money and start here.
Background
It's time for me to give back to the community out there. I look many places before I start building an app (why reinvent the wheel) and haven't found one that does exactly this. I'm hoping to save someone some time and money. This article gives you a basis and code example on how to create a multipage TIF Viewer using ASP.NET. The web page will display thumbnails on one side and an enlarged image on the other. Clicking each page will use some JavaScript to update the src
of the large image.
Using the Code
The concept consists of 3 main things:
- An ASP page to call that takes the file path parameter and does the work of configuring thumbnails and big image (Default.aspx in the download)
- A TIF class used to pull pages out of the TIF file
- An ASP page to display the image (ViewImg.aspx in the download)
Default.aspx
This page has only one required parameter, which is FILE
in the query string. FILE
is the absolute path to the file. I've also set up a paging mechanism so that large files load quicker and take less system resources to iterate. There's also an optional STARTPAGE
that can be passed to the query string, which indicates which page to start at (for paging). This pager size is configurable in the code-behind. The code-behind also sets up the JavaScript to change src
attribute of the large image as well as the attributes needed for any TIF rotation or zoom of the big image. The aspx page includes a placeholder that adds an asp:image
object to a placeholder for the thumbnails (querystring
parameters are passed to that src
for thumbnail size). That image has a src
of another page (to be explained later). This same concept is applied for the BIG
image.
int StartPg = 1;
if (Request.QueryString["StartPage"] != null)
StartPg = System.Convert.ToInt16(Request.QueryString["StartPage"]);
int BigImgPg = StartPg;
int EndPg = StartPg + (PagerSize - 1);
if (EndPg > TotalTIFPgs)
EndPg = TotalTIFPgs;
while (StartPg <= EndPg)
{
Label lbl = new Label();
if (StartPg % 4 == 0 && StartPg != 0) lbl.Text = " <br />";
else lbl.Text = " ";
Image Img = new Image();
Img.BorderStyle = (BorderStyle)Enum.Parse(typeof(BorderStyle), "Solid");
Img.BorderWidth = Unit.Parse("1");
Img.Attributes.Add("onClick", "ChangePg(" + StartPg.ToString() + ");");
Img.Attributes.Add("onmouseover", "this.style.cursor='hand';");
Img.ImageUrl = "ViewImg.aspx?FilePath=" + FilePath + "&Pg=" + (StartPg).ToString() +
"&Height=" + DefaultThumbHieght.ToString() + "&Width=" + DefaultThumbWidth;
_plcImgsThumbs.Controls.Add(Img);
_plcImgsThumbs.Controls.Add(lbl);
StartPg++;
}
Image BigImg = new Image();
BigImg.BorderStyle = (BorderStyle)Enum.Parse(typeof(BorderStyle), "Solid");
BigImg.BorderWidth = Unit.Parse("1");
BigImg.ID = "_imgBig";
BigImg.ImageUrl = "ViewImg.aspx?View=1&FilePath=" + FilePath + "&Pg=" +
BigImgPg.ToString() + "&Height=" + DefaultBigHieght.ToString() + "&Width=" +
DefaultBigWidth.ToString();
_plcBigImg.Controls.Add(BigImg);
ViewImg.aspx
This page takes a few parameters (all these parameters are supplied and configured by default.aspx.): FILEPATH
(passed from default.aspx), HEIGHT
(height of the image), WIDTH
(width of the image to display), PG
(the page to display), and ROTATE
(the rotation to apply to the image before displaying it). The page simply uses the TIF class to get an image object and saves it to the outputstream
in a JPG format so that it can be viewed in the browser.
protected void Page_Load(object sender, EventArgs e)
{
System.Drawing.Image TheImg = new App.Files.TIF(
Request.QueryString["FilePath"]).GetTiffImageThumb(
System.Convert.ToInt16(Request.QueryString["Pg"]),
System.Convert.ToInt16(Request.QueryString["Height"]),
System.Convert.ToInt16(Request.QueryString["Width"]));
if (TheImg != null)
{
switch (Request.QueryString["Rotate"])
{
case "90":
TheImg.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone);
break;
case "180":
TheImg.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
break;
case "270":
TheImg.RotateFlip(System.Drawing.RotateFlipType.Rotate270FlipNone);
break;
}
Response.ContentType = "image/jpeg";
TheImg.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
TheImg.Dispose();
}
}
TIF.cs
This class does the work of accessing the TIF file. The main method here, for this project, is GetTIFFImageThumb
, where you supply the page number (the Active Frame from the FrameDimension
) and the size of the thumbnail returned, while accounting for the aspect ratio of the page. It opens the file and loads the page in question to a memorystream
object and returns a system.drawing.image
object from that stream that can be used later (like in the ViewImg.aspx page). I've got a few other methods and objects in the download that may be handy for others (and for my larger project). The only word of caution with respect to your file and the system.drawing.image
object is to always make sure that you properly dispose of the object when finished; otherwise you risk a file in use error when you try to work with it later.
public Image GetTiffImageThumb(int PageNum, int ImgWidth, int ImgHeight)
{
if ((PageNum < 1) | (PageNum > this.PageCount))
{
throw new InvalidOperationException("Page to be retrieved is outside the bounds" +
"of the total TIF file pages. Please choose a page number that exists.");
}
MemoryStream ms = null;
Image SrcImg = null;
Image returnImage = null;
try
{
SrcImg = Image.FromFile(this.m_FilePathName);
ms = new MemoryStream();
FrameDimension FrDim = new FrameDimension(SrcImg.FrameDimensionsList[0]);
SrcImg.SelectActiveFrame(FrDim, PageNum-1);
SrcImg.Save(ms, ImageFormat.Tiff);
SrcImg.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
SrcImg.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
if (SrcImg.Width <= ImgWidth) ImgWidth = SrcImg.Width;
int NewHeight = SrcImg.Height * ImgWidth / SrcImg.Width;
if (NewHeight > ImgHeight)
{
ImgWidth = SrcImg.Width * ImgHeight / SrcImg.Height;
NewHeight = ImgHeight;
}
returnImage = Image.FromStream(ms).GetThumbnailImage(ImgWidth, NewHeight, null,
IntPtr.Zero);
}
catch (Exception ex)
{
throw ex;
}
finally
{
SrcImg.Dispose();
GC.Collect();
GC.WaitForPendingFinalizers();
}
return returnImage;
}
History
- 9th March, 2010: Initial post