ASP缩略图解决方案






4.88/5 (39投票s)
用于生成缩略图和缩略图视图的ASP页面和免费COM对象。
引言
几个月前,我写了一篇关于一个C#类生成缩略图以及一个可重用的ASP.NET用户控件显示缩略图视图的文章。一些人要求我将我的解决方案移植到经典ASP。我抽出了一些时间来完成,现在我展示了结果。ASP解决方案在功能上等同于ASP.NET(事实上,许多代码片段已经从C#翻译成VBScript)。只缺少一些高级选项(评论显示和编辑、斜面缩略图、缩略图缓存、缩略图保存),因为它们在经典ASP中难以实现。缩略图视图的解决方案是可重用且易于使用的。您只需进行虚拟包含并在表单中调用服务器函数即可。为了以JPEG格式生成缩略图数据,我创建了一个ATL-COM对象,它是Davide Pizzolato的CxImage
类的包装器。CxImage
是一个C++类,用于加载、保存、显示、转换BMP、JPEG、GIF、PNG、TIFF、MNG、ICO、PCX、TGA、WMF、WBMP、JBG和J2K图像。COM包装器对象也可用于其他任务。例如,您可以创建一个网页,让用户对他们的图像应用图像处理算法。
在本文中,我将介绍如何使用缩略图工具以及代码的重要部分。
如何创建单个缩略图和缩略图视图
缩略图解决方案的ASP部分由文件ThumbGenerate.asp和ListThumbs.inc组成。下载zip并解压文件后,将包含ThumbAsp文件夹设置为虚拟目录,并将浏览器指向TestListThumbs.asp页面。这是一个测试页面,其一个实例如上图所示。在虚拟路径文本框中输入包含图像的IIS虚拟目录的路径,然后按“提交”按钮。您应该会看到该目录中图像的缩略图。也尝试其他选项,并查看缩略图上的变化。
ThumbGenerate.asp是一个VBScript代码文件,可用于<img>
标签中,以动态生成JPEG格式的缩略图。下面显示了ASP文件的典型用法。<a>
链接指向一个图像,<img>
标签通过其src
属性值指定了同一图像的动态生成的缩略图。
<a href='https://codeproject.org.cn/santorini/SANTO007.jpg'>
<img src='https://codeproject.org.cn/ThumbAsp/ThumbGenerate.asp?
VFilePath=/santorini/SANTO007.jpg&
Width=200&Height=200&Quality=75'
border=0 alt='Name: SANTO007.jpg'/></a>
ASP文件的参数以查询字符串的形式给出。它们是以下内容:
VFilePath
:原始图像的虚拟路径。唯一强制参数。如果指定的文件不存在或不是图像,则会从NoThumb.gif文件生成一个“无缩略图”默认图像。Width
、Height
:所需的缩略图大小。如果未给出,则从appSettings
读取;如果未在appSettings
中指定,则默认为150x150。Quality
:JPEG质量参数。范围从1(最低质量)到99(最高质量)。默认为75。AllowStretch
:设置为“True
”以允许缩略图拉伸以适应上述大小。如果未给出,则默认为False
。ShellThumbnails
:如果未指定或设置为“False
”,则使用CxImageATL.dll(ProgID='CxImageATL.CxImage'
)中实现的CxImage
包装器对象生成缩略图。如果设置为“True
”,则使用ThumbExtract.dll(ProgID='ThumbExtract.FileThumbExtract'
)中实现的COM对象生成缩略图。后者利用负责在您单击文件或在资源管理器中选择缩略图视图时生成缩略图的shell接口(IExtractImage
)。这允许您为各种文件类型(例如,PowerPoint演示文稿)创建缩略图视图,如下图所示。
请参阅我的文章为您的MFC文档类型创建缩略图提取器对象,了解如何通过实现IExtractImage
接口来开发一个可以提取任何文件类型的缩略图的COM对象。在同一篇文章中,您可以找到ThumbExtract.dll的代码。
ListThumbs.inc是一个创建缩略图视图的ASP文件。要在ASP页面中使用它,您必须按如下方式包含该文件:
<!-- #include virtual ="/ThumbAsp/ListThumbs.inc" -->
在您想要显示缩略图视图的位置,您需要调用具有以下语法的ListThumbs
函数:
ListThumbs(VPath,Columns,Filter,AllowPaging,PageSize,Width,Height,_
Quality, AllowStretch,ShowFilenames,ShellThumbnails)
ListThumbs
函数的参数具有以下含义:
VPath
:您想要显示其内容作为缩略图的虚拟目录。Columns
:视图的列数。Filter
:用于选择您想要显示缩略图的文件的过滤器(例如,*.jpg;*.gif)。AllowPaging
,PageSize
:设置AllowPaging=True
以显示每页包含PageSize
个缩略图的页面。要使分页工作,您必须在ASP文档的第一个表单中调用该函数。Width
,Height
,AllowStretch
,Quality
,ShellThumbnails
:参见上述说明。ShowFilenames
:设置ShowFilenames=True
以在每个缩略图下方显示相应的文件名。
ListThumbs.inc和ThumbGenerate.asp必须包含在同一个虚拟目录中。当然,您还必须注册COM对象。
源代码解释
如上所述,CxImageATL
对象是CxImage
图像类的包装器。该类具有加载和保存所有流行图像格式以及各种图像处理和操作函数。对于缩略图生成,使用了Resample
函数。我添加了一个名为ImageForASP
的新函数,它使用任何支持的图像格式将图像作为Variant字节数组返回。返回的Variant ImageData
可以通过调用Response.BinaryWrite ImageData
来从ASP页面显示图像。ImageType
参数默认为2
(JPEG),Quality
参数默认为75
,并且仅用于JPEG格式。
// method to display image in ASP pages
STDMETHODIMP CCxImage::ImageForASP(long ImageType, long Quality,
VARIANT *ImageData)
{
SAFEARRAY *psaData; BYTE *pData,*pBuffer; long size;
SAFEARRAYBOUND rgsabound[1];
m_image.SetJpegQuality((BYTE)Quality);
CxMemFile memfile; memfile.Open();
bool bOk = m_image.Encode(&memfile, ImageType);
if(!bOk) return E_FAIL; // NO-IMAGE
pBuffer=memfile.GetBuffer();
size=memfile.Size();
// create safe array and copy image data
rgsabound[0].lLbound = 0; rgsabound[0].cElements = size;
psaData = SafeArrayCreate(VT_UI1, 1, rgsabound);
SafeArrayAccessData(psaData, (void **)&pData);
memcpy(pData,pBuffer,size);
SafeArrayUnaccessData(psaData);
free(pBuffer);
// put data in variant
ImageData->vt = (VT_ARRAY | VT_UI1);
ImageData->parray = psaData;
return S_OK;
}
ThumbExtract.dll有一个名为ThumbJpgData
的等效函数,它以JPEG格式返回缩略图图像数据(再次使用了CxImage
文件)。下面是ThumbGenerate.asp文件的代码。唯一棘手的部分是如何保留原始图像的宽高比。另请注意,原始图像的位深度必须增加到24位,因为JPEG不支持索引图像。
<%
Set fso = Server.CreateObject("Scripting.FileSystemObject")
Response.ContentType = "image/jpeg"
' ---- parameter parsing ----'
Dim VFilePath,FilePath,Width,Height,Quality,bShellThumbnails,
bStretch,bCreate
VFilePath = Request("VFilePath")
If Len(VFilePath)=0 Then VFilePath="NoThumb.gif"
FilePath = Server.MapPath(VFilePath)
If Not fso.FileExists(FilePath) Then
FilePath = Server.MapPath("NoThumb.gif")
End If
If Len(Request("Width"))>0 Then
Width = Int(Request("Width"))
Else Width = 200
End If
If Len(Request("Height"))>0 Then
Height = Int(Request("Height"))
Else Height = 200
End If
If Len(Request("Quality"))>0 Then
Quality = Int(Request("Quality"))
Else Quality = 75
End If
If Len(Request("ShellThumbnails"))>0 Then
bShellThumbnails = (Request("ShellThumbnails")="True")
Else bShellThumbnails = False
End If
If Len(Request("AllowStretch"))>0 Then
bStretch = (Request("AllowStretch")="True")
Else bStretch = False
End If
Dim BinData
If bShellThumbnails Then
' Create COM Shell Thumbnail object
Set objThumb = Server.CreateObject("ThumbExtract.FileThumbExtract")
Call objThumb.SetPath(FilePath)
Call objThumb.SetThumbnailSize(Width,Height)
Call objThumb.ExtractThumbnail
BinData = objThumb.ThumbJpgData(Quality)
Else
' Create COM CxImage wrapper object
Set objCxImage = Server.CreateObject("CxImageATL.CxImage")
Call objCxImage.Load(FilePath,GetFileType(FilePath))
Call objCxImage.IncreaseBpp(24)
' determine thumbnail size and resample original image data
If Not bStretch Then ' retain aspect ratio
widthOrig = CDbl(objCxImage.GetWidth())
heightOrig = CDbl(objCxImage.GetHeight())
fx = widthOrig/Width
fy = heightOrig/Height 'subsample factors
' must fit in thumbnail size
If fx>fy Then f=fx Else f=fy ' Max(fx,fy)
If f<1 Then f=1
widthTh = Int(widthOrig/f)
heightTh = Int(heightOrig/f)
Else
widthTh = Width
heightTh = Height
End If
Call objCxImage.Resample(widthTh,heightTh,2)
BinData = objCxImage.ImageForASP(2,Quality)
End If
' output in Response '
Response.BinaryWrite BinData
Function GetFileType(sFile)
dot = InStrRev(sFile, ".")
filetype=2
If dot > 0 Then sExt = LCase(Mid(sFile, dot + 1, 3))
If sExt = "bmp" Then filetype = 0
If sExt = "gif" Then filetype = 1
If sExt = "jpg" Then filetype = 2
If sExt = "png" Then filetype = 3
If sExt = "ico" Then filetype = 4
If sExt = "tif" Then filetype = 5
If sExt = "tga" Then filetype = 6
If sExt = "pcx" Then filetype = 7
GetFileType=filetype
End Function
%>
接下来列出ListThumbs.inc文件的源代码。它本质上是我之前介绍的ASP.NET缩略图用户控件从C#到VBScript的翻译。ASP.NET DataList
控件产生的输出可以通过用代码构造HTML表格轻松实现。Columns
参数决定了行(<tr>
)标签的放置位置。然而,DataList
控件的编辑功能很难用ASP代码实现。因此,此版本中我没有实现缩略图评论的编辑和呈现。
<%
Function ListThumbs(VPath,Columns,Filter,AllowPaging,PageSize,Width,Height,Quality,
AllowStretch,ShowFilenames,ShellThumbnails)
Set fso = CreateObject("Scripting.FileSystemObject")
Set ScriptName = Request.ServerVariables("SCRIPT_NAME")
ScriptPath = Left(ScriptName,InstrRev(ScriptName,"/"))
If Right(VPath,1)<>"/" Then VPath=VPath & "/"
path = Server.MapPath(VPath): If Right(path,1)<>"\" Then path=path & "\"
' analyze filter string
If Len(Filter)=0 Then Filter = "*.gif;*.jpg;*.bmp"
arSuffixes = Split(Filter,";")
For i=0 To UBound(arSuffixes)
pos=Instr(1,arSuffixes(i),".")
If pos>0 Then arSuffixes(i) = Mid(arSuffixes(i),pos) ' e.g. ".gif"
Next
Dim CurPage,TotalPages
' -- write client script and hidden field for current page and path
If AllowPaging Then Call WriteGotoPageScript
If Len(Request.Form("hdnCurPage"))>0 Then
CurPage = CInt(Request.Form("hdnCurPage"))
Else CurPage=1
End If
Response.Write "<input type='hidden' name='hdnCurPage' value='" &_
CurPage & "' />" & vbCrLf
' restart page numbering if different page
If Request.Form("hdnPrevPath")<> VPath Then CurPage = 1
Response.Write "<input type='hidden' name='hdnPrevPath' value='" &_
VPath & "' />" & vbCrLf
Dim arrFilesAll(),ubn
If fso.FolderExists(path) Then
Set oFolder = fso.GetFolder(path)
For Each oFile in oFolder.Files
bFileInFilter=False
For i=0 To UBound(arSuffixes)
If IsFileOfType(oFile.Name,arSuffixes(i)) Then bFileInFilter=True
Next
If bFileInFilter Then
ReDim Preserve arrFilesAll(ubn)
arrFilesAll(ubn) = oFile.Name
ubn=ubn+1
End If ' if in filter
Next
End If
If AllowPaging Then
TotalPages = CInt(ubn/PageSize)
If ubn Mod PageSize>0 Then TotalPages = TotalPages + 1
if TotalPages=0 Then TotalPages=1
' make sure current page is in the [1,totalPages] range
if CurPage>TotalPages Then
CurPage=TotalPages
else
if CurPage<1 Then CurPage=1
end if
' range of files to read
StartIndex = (CurPage-1)*PageSize
EndIndex = CurPage*PageSize
If ubn < EndIndex Then EndIndex = ubn
Else
StartIndex = 0: EndIndex = ubn
End If
' write thumbnail hrefs
If fso.FolderExists(path) Then
Response.Write "<TABLE ALIGN='CENTER'>" & vbCrLf
For index=StartIndex To EndIndex-1
FileName = arrFilesAll(index)
' Response.write path & FileName
Set oFile=fso.GetFile(path & FileName) : FileSize=oFile.Size
nCol = nCol+1
VFilePath = VPath & FileName
sHREF = "<a href='" & VFilePath & "'>" & _
"<img src='" & ScriptPath & "ThumbGenerate.asp?VFilePath=" & _
Server.URLEncode(VFilePath) & "&Width=" &_
Width & "&Height=" & Height &_
"&Quality=" & Quality & _
"&ShellThumbnails=" & ShellThumbnails &_
"&AllowStretch=" & AllowStretch & _
"' border=0 alt='Name: " & FileName &_
" Size: " & CInt(FileSize/1024) &_
" Kb'/> </a>"
If nCol = 1 Then Response.Write "<TR>"
Response.Write "<TD align='Center' " & _
"style='background-color:White;border-width:1px;" &_
"border-style:Solid;font-size:8pt;'>" & vbCrLf
Response.Write sHREF & vbCrLf
If ShowFilenames Then Response.Write "<br/>" & FileName
Response.Write "</TD>" & vbCrLf
If nCol = Columns Then
Response.Write "</TR>" & vbCrLf
nCol = 0
End If
Next
Response.Write NumImagesDisplayed(EndIndex-StartIndex,AllowPaging,ubn,_
CurPage,TotalPages)
If AllowPaging Then
Response.Write CreateNavBar(VPath,CurPage,TotalPages,Columns)
End If
Response.Write "</TABLE>" & vbCrLf
Else
Response.Write "Directory Does Not Exist<P>" & vbCrLf
End If
End Function
Function NumImagesDisplayed(NumDisplayed,AllowPaging,TotalFiles,CurPage,TotalPages)
s = "<tr><td align='Center' colspan='" & Columns &_
"' style='background-color:#FFFFC0;font-size:8pt;'>"
s = s & NumDisplayed
if AllowPaging Then s = s & " of " & TotalFiles
' s = s & " images"
if AllowPaging Then
s = s & " (Page " & CurPage & " of " & TotalPages & ")"
end if
s = s & "</td></tr>"
NumImagesDisplayed = s
End Function
Function CreateNavBar(VPath,CurPage,TotalPages,Columns)
if TotalPages = 1 Then Exit Function
s = "<tr><td align='Center' colspan='" & Columns &_
"' style='font-size:8pt;'>"
if CurPage>1 Then
'GoToPage client script updates hidden field with target page
'and then causes a postback
s = s & "<A href=""javascript:GoToPage('" & VPath &_
"'," & CurPage-1 & _
");""><< Prev</A> "
End If
for i=1 To TotalPages
if i=CurPage Then
s = s & "<b>" & i & "</b>"
else
s = s & "<A href=""javascript:GoToPage('" & VPath &_
"'," & i & ");"">" & _
i & "</A>"
end if
s = s & " "
If i Mod 10=0 Then s = s & "<br/>"
Next
If CurPage<TotalPages Then
s = s & " <A href=""javascript:GoToPage('" &_
VPath & "'," & CurPage+1 & _
");"">Next >></A> "
End If
s = s & "</td></tr>"
CreateNavBar = s
End Function
Function IsFileOfType(afile,infile_type)
IsFileOfType = (UCase(Right(afile,Len(infile_type)))=UCase(infile_type))
End Function
Sub WriteGotoPageScript
Response.Write "<script language=""javascript"">" & vbCrLf & _
"//<!--" & vbCrLf & "function GoToPage(vpath,n) { " & vbCrLf & _
"document.forms(0).hdnCurPage.value=n;" & vbCrLf & _
"document.forms(0).submit(); " & vbCrLf & _
"}" & vbCrLf & "//-->" & vbCrLf & "</" & "script>" & vbCrLf
End Sub
%>
“注入”到HTML表单中的GoToPage
客户端JavaScript函数实现了页面导航。当用户按下任何页面链接时,此函数在客户端执行。它将hdnCurPage
隐藏字段的值设置为等于参数n
(即页码),然后提交表单。回发后,页码会在页面加载时从隐藏字段中检索。
结论
我还没有在网上找到任何完全免费的ASP缩略图解决方案,所以我希望您会觉得这篇文章和代码有用。如果可以的话,我建议您使用ASP.NET解决方案,因为它更快且有更多选项。似乎.NET的图像处理类具有优化的代码。也许如果您有一台快速PC,您不会注意到差异,但在我的奔腾II上,这很明显。
历史
- 2002年12月8日:首次发布。
- 2009年10月31日:文章更新。