how to get image width with server-side vbscript?

2019-07-15 13:18发布

I have been trying for days to find a way to get the image width of .png files which reside on our server. I am trying to read the first 24 bytes of the file and parse out the width from bytes 17-20. I have found several routines on the web but have not been successful. Strangely enough, it seems I am getting the height from bytes 21-24 decoded from hex to decimal just fine. I have verified the file contents using a hex viewer and the file is good. Here is the main portion of the routine:

Function ReadPNG(fichero)
Dim fso, ts, s, HW, nbytes
    HW = Array("0", "0")
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ts = fso.OpenTextFile(Server.MapPath("\forums\attachments/" & fichero), 1)
    s = Right(ts.Read(24), 8)
    HW(0) = HexToDec(HexAt(s,3) & HexAt(s,4))
    HW(1) = HexToDec(HexAt(s,7) & HexAt(s,8))
    ts.Close
    ReadPNG = HW
End Function

Function HexAt(s, n)
    HexAt = Hex(AscAt(s, n))
End Function

Function HexToDec(ByVal HexVal)

Dim i, num, part
num = 0
For I = 1 to Len(HexVal)
    part = Mid(StrReverse(UCase(HexVal)), I, 1)
    If IsNumeric(part) Then
        num = num + (CInt(part) * 16 ^ (I - 1) )
    Else
        num = num + ( (Asc(part) - 55) * 16^(I - 1) )
    End If
Next

HexToDec = num

End Function

As an example, my file has hex "00 00 01 80" in the width bytes (decimal 384) and hex "00 00 01 32" in the heigth bytes (decimal 306)

I am getting the heigth 306 but thee width is returning "0011" (decimal 17).

I am totally stummped! I do not have to use this routine either.

Thanks, Jim

3条回答
唯我独甜
2楼-- · 2019-07-15 13:25

Here is a generic set of functions I found ages ago for getting information on an image. I'll put the way I've been using it at the end.

':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'
':::                                                             :::'
':::  This routine will attempt to identify any filespec passed  :::'
':::  as a graphic file (regardless of the extension). This will :::'
':::  work with BMP, GIF, JPG and PNG files.                     :::'
':::                                                             :::'
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'
':::          Based on ideas presented by David Crowell          :::'
':::                   (credit where due)                        :::'
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'
'::: blah blah blah blah blah blah blah blah blah blah blah blah :::'
'::: blah blah blah blah blah blah blah blah blah blah blah blah :::'
'::: blah blah     Copyright *c* MM,  Mike Shaffer     blah blah :::'
'::: blah blah      ALL RIGHTS RESERVED WORLDWIDE      blah blah :::'
'::: blah blah  Permission is granted to use this code blah blah :::'
'::: blah blah   in your projects, as long as this     blah blah :::'
'::: blah blah      copyright notice is included       blah blah :::'
'::: blah blah blah blah blah blah blah blah blah blah blah blah :::'
'::: blah blah blah blah blah blah blah blah blah blah blah blah :::'
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'

':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'
':::                                                             :::'
':::  This function gets a specified number of bytes from any    :::'
':::  file, starting at the offset (base 1)                      :::'
':::                                                             :::'
':::  Passed:                                                    :::'
':::       flnm        => Filespec of file to read               :::'
':::       offset      => Offset at which to start reading       :::'
':::       bytes       => How many bytes to read                 :::'
':::                                                             :::'
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'
function GetBytes(flnm, offset, bytes)

 Dim objFSO
 Dim objFTemp
 Dim objTextStream
 Dim lngSize

 on error resume next

 Set objFSO = CreateObject("Scripting.FileSystemObject")

 ' First, we get the filesize'
 Set objFTemp = objFSO.GetFile(flnm)
 lngSize = objFTemp.Size
 set objFTemp = nothing

 fsoForReading = 1
 Set objTextStream = objFSO.OpenTextFile(flnm, fsoForReading)

 if offset > 0 then
    strBuff = objTextStream.Read(offset - 1)
 end if

 if bytes = -1 then        ' Get All!'

    GetBytes = objTextStream.Read(lngSize)  'ReadAll'

 else

    GetBytes = objTextStream.Read(bytes)

 end if

 objTextStream.Close
 set objTextStream = nothing
 set objFSO = nothing

end function


':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'
':::                                                             :::'
':::  Functions to convert two bytes to a numeric value (long)   :::'
':::  (both little-endian and big-endian)                        :::'
':::                                                             :::'
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'
function lngConvert(strTemp)
 lngConvert = clng(asc(left(strTemp, 1)) + ((asc(right(strTemp, 1)) * 256)))
end function

function lngConvert2(strTemp)
 lngConvert2 = clng(asc(right(strTemp, 1)) + ((asc(left(strTemp, 1)) * 256)))
end function


':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'
':::                                                             :::'
':::  This function does most of the real work. It will attempt  :::'
':::  to read any file, regardless of the extension, and will    :::'
':::  identify if it is a graphical image.                       :::'
':::                                                             :::'
':::  Passed:                                                    :::'
':::       flnm        => Filespec of file to read               :::'
':::       width       => width of image                         :::'
':::       height      => height of image                        :::'
':::       depth       => color depth (in number of colors)      :::'
':::       strImageType=> type of image (e.g. GIF, BMP, etc.)    :::'
':::                                                             :::'
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'
function gfxSpex(flnm, width, height, depth, strImageType)

 dim strPNG 
 dim strGIF
 dim strBMP
 dim strType
 strType = ""
 strImageType = "(unknown)"

 gfxSpex = False

 strPNG = chr(137) & chr(80) & chr(78)
 strGIF = "GIF"
 strBMP = chr(66) & chr(77)

 strType = GetBytes(flnm, 0, 3)

 if strType = strGIF then                ' is GIF'

    strImageType = "GIF"
    Width = lngConvert(GetBytes(flnm, 7, 2))
    Height = lngConvert(GetBytes(flnm, 9, 2))
    Depth = 2 ^ ((asc(GetBytes(flnm, 11, 1)) and 7) + 1)
    gfxSpex = True

 elseif left(strType, 2) = strBMP then        ' is BMP'

    strImageType = "BMP"
    Width = lngConvert(GetBytes(flnm, 19, 2))
    Height = lngConvert(GetBytes(flnm, 23, 2))
    Depth = 2 ^ (asc(GetBytes(flnm, 29, 1)))
    gfxSpex = True

 elseif strType = strPNG then            ' Is PNG'

    strImageType = "PNG"
    Width = lngConvert2(GetBytes(flnm, 19, 2))
    Height = lngConvert2(GetBytes(flnm, 23, 2))
    Depth = getBytes(flnm, 25, 2)

    select case asc(right(Depth,1))
       case 0
          Depth = 2 ^ (asc(left(Depth, 1)))
          gfxSpex = True
       case 2
          Depth = 2 ^ (asc(left(Depth, 1)) * 3)
          gfxSpex = True
       case 3
          Depth = 2 ^ (asc(left(Depth, 1)))  '8'
          gfxSpex = True
       case 4
          Depth = 2 ^ (asc(left(Depth, 1)) * 2)
          gfxSpex = True
       case 6
          Depth = 2 ^ (asc(left(Depth, 1)) * 4)
          gfxSpex = True
       case else
          Depth = -1
    end select


 else

    strBuff = GetBytes(flnm, 0, -1)        ' Get all bytes from file'
    lngSize = len(strBuff)
    flgFound = 0

    strTarget = chr(255) & chr(216) & chr(255)
    flgFound = instr(strBuff, strTarget)

    if flgFound = 0 then
       exit function
    end if

    strImageType = "JPG"
    lngPos = flgFound + 2
    ExitLoop = false

    do while ExitLoop = False and lngPos < lngSize

       do while asc(mid(strBuff, lngPos, 1)) = 255 and lngPos < lngSize
          lngPos = lngPos + 1
       loop

       if asc(mid(strBuff, lngPos, 1)) < 192 or asc(mid(strBuff, lngPos, 1)) > 195 then
          lngMarkerSize = lngConvert2(mid(strBuff, lngPos + 1, 2))
          lngPos = lngPos + lngMarkerSize  + 1
       else
          ExitLoop = True
       end if

   loop

   if ExitLoop = False then

      Width = -1
      Height = -1
      Depth = -1

   else

      Height = lngConvert2(mid(strBuff, lngPos + 4, 2))
      Width = lngConvert2(mid(strBuff, lngPos + 6, 2))
      Depth = 2 ^ (asc(mid(strBuff, lngPos + 8, 1)) * 8)
      gfxSpex = True

   end if

 end if

end function

I've been using it to generate a randomized XML file for an image library. The script only gets run when I finish uploading a new image to the library.

Here's the usage: (or at least how I used it)

'collect the image information into an array'
Dim blnGfxSpex, width, height, colors, strType
intCount = 0
For Each objFile In objFS.GetFolder(".\images").Files
    If LCase(Right(objFile.Name, 4)) = ".jpg" and intCount <= intNumOfFiles Then
        blnGfxSpex = gfxSpex((".\images\" & objFile.Name), width, height, colors, strType)

        arrImages(intCount) = "<image>" & vbNewLine & _
                                "<filename>" & objFile.Name & "</filename>" & vbNewLine & _
                                "<caption></caption>" & vbNewLine & _
                                "<width>" & width & "</width>" & vbNewLine & _
                                "<height>" & height & "</height>" & vbNewLine & _
                                "</image>" & vbNewLine
        intCount = intCount + 1
    End If
Next

As you can see, I'm initializing the variables for width, height, etc. and the function sets them as appropriate. I know it's not kosher to use global variables like that, but it works.

Performance isn't as bad as you would think. In this particular case I am filtering the image library to just JPGs, but that is due to a limitation in the image library the XML is for, not due to a limitation in the functions.

查看更多
相关推荐>>
3楼-- · 2019-07-15 13:43

Here is a post I saw awhile ago, looks like it could possibly simplify things a bit. I have not tested, so let me know your results.

<%
dim iWidth, iheight
sub ImgDimension(img)
dim myImg, fs
Set fs= CreateObject("Scripting.FileSystemObject")
if not fs.fileExists(img) then exit sub
set myImg = loadpicture(img)
iWidth = round(myImg.width / 26.4583)
iheight = round(myImg.height / 26.4583)
set myImg = nothing
end sub

ImgDimension(Server.MapPath("server image file"))
%> 

See here for post: http://www.haneng.com/asp-forum/ASP---Get-Image-Size_12971.html

UPDATE: Seeing that this method will not work in 64bit. Here is a link to another alternative method: http://www.4guysfromrolla.com/webtech/050300-1.shtml

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-07-15 13:46

I use this simple function to return width, height and file size (eg. 640x480 - 200KBytes):

   Function ImgDim(img)
    Dim objFSO, objGF, objLP, imgWdt, imgHgt, imgSiz
    img = Server.MapPath("/pictures/"& img) 'path to picture
    Set objFSO= CreateObject("Scripting.FileSystemObject")
    If objFSO.fileExists(img) Then
     Set objGF = objFSO.GetFile(img)
      imgSiz = objGF.Size
     Set objGF = Nothing
     Set objLP = loadpicture(img)
      imgWdt = round(objLP.width / 26.4583)
      imgHgt = round(objLP.height / 26.4583)
     Set objLP = Nothing
     Set fs = Nothing
     ImgDim = imgWdt &"x"& imgHgt &" - "& imgSiz/1024 &"KBytes"
    End If
   End Function

works beautifully, hope it helps.

查看更多
登录 后发表回答