Link to home
Start Free TrialLog in
Avatar of PCav
PCav

asked on

Help with displaying database pictures

Hello I have a VB program that saves and loads pictures (JPEGs) into a database (I can post and E-Mail the code for anyone who wants it) this works great the pictures are go into the database correctly and come out of the database correctly.  Now we want to use the database in a Web based version of the program.  I have some code that I'm using to try and display the pictures

<%
Response.ContentType = "image/JPEG"
Set RS = Server.CreateObject("ADODB.Recordset")
if Request.QueryString("Which") = 1 then
  Which="Pic1"
elseif Request.QueryString("Which") = 2 then
  Which="Pic2"
elseif Request.QueryString("Which") = 3 then
  Which="Pic3"
end if
if Request.QueryString("Table") = 1 then
  Table="Directors"
elseif Request.QueryString("Table") = 2 then
  Table="AirParks"
elseif Request.QueryString("Table") = 3 then
  Table="Properties"
end if
strSQL = "SELECT " & Which & " FROM " & Table & " WHERE id=" & Request.Querystring("id")

RS.Open strSQL, "DSN=AirMLS;uid=" & Session("uid") & ";pwd=" & Session("pwd"), 1, 1
if Which="Pic1" then
  Response.Binarywrite RS.fields("Pic1")
elseif Which="Pic1" then
  Response.Binarywrite RS.fields("Pic2")
elseif Which="Pic1" then
  Response.Binarywrite RS.fields("Pic3")
end if
RS.Close %>

This code is in a seperate file called ShowPicture.asp and I call it as followed
<img src=<%=ShowPicture.asp?ID=12&Which=1&Table=1%> border=1>

I get no errors in either the main pages or if I just do the showpicture as the url, but the picture is not being display.

Can someone please help me.

Avatar of sybe
sybe

Hi, I've seen this before, sorry you still don't have it working.

If Which="Pic1" then
 Response.Binarywrite RS.fields("Pic1")
elseif Which="Pic1" then
 Response.Binarywrite RS.fields("Pic2")
elseif Which="Pic1" then
 Response.Binarywrite RS.fields("Pic3")
end if

These "if" statements do nothing, because they are all "if which=Pic1". I guess it's a typo.

It is hard to see where it goes wrong from here. I would need to see the database. Which database are you using? Access, SQL ?


Avatar of PCav

ASKER

Your right it is a typo.  That has been fixed.  I use Access database.  Do you want me to E-Mail you the database.
Ok, mail me the database to sybev@hotmail.com
PCav can you post me your VB program that loads your pictures into the database ? If you can please post it to Patricia_ani@yahoo.com. Thanks
Most Internet browsers support the displaying of GIF and JPEG images. To display an image, the browser requests the image from a Web server. The server passes the image to the browser as an HTTP transaction with an HTTP header containing an MIME type of IMAGE/GIF or IMAGE/JPEG. You can simulate this behavior with Active Server Pages.

The following example constructs an HTTP header for an image and then uses the binary information from an image field in SQL Server to provide a GIF to the browser.


   FILE: SHOWIMG.ASP
   <%@ LANGUAGE="VBSCRIPT" %>
   <%
   ' Clear out the existing HTTP header information
   Response.Expires = 0
   Response.Buffer = TRUE
   Response.Clear

   ' Change the HTTP header to reflect that an image is being passed.
   Response.ContentType = "image/gif"

   Set cn = Server.CreateObject("ADODB.Connection")
   ' The following open line assumes you have set up a System DataSource
   ' by the name of myDSN.
   cn.Open "DSN=myDSN;UID=sa;PWD=;DATABASE=pubs"
   Set rs = cn.Execute("SELECT logo FROM pub_info WHERE pub_id='0736'")
   Response.BinaryWrite rs("logo")
   Response.End
   %>

This script only displays an image on the screen. If you wish to display an image from an HTML or ASP document you must refer to this script in an image tag. For example, if you wished to display this image with a caption describing it, you might use the following HTML page:

   <HTML>
   <HEAD><TITLE>Display Image</TITLE></HEAD>
   <BODY>
   This page will display the image New Moon Books from a SQL Server 6.5
   image field.<BR>
   <IMG SRC="SHOWIMG.ASP">
   </BODY>
   </HTML>

NOTE: The ASP script assumes that the image field (BLOB Data) in the SQL Server table contains a raw GIF image. Internet browsers assume that raw GIF or JPEG data follow the HTTP header. If any extraneous information is contained in the BLOB data, this will be passed by this script, and the image will not display properly. This becomes important when you realize that most methods of placing images into BLOB fields place extra information in the form of headers with the image. Examples of this are Microsoft Access and Microsoft Visual FoxPro. Both of these applications save OLE headers in the BLOB field along with the actual binary data.
This technique can also be applied to other types of binary data, not just graphics. The browser needs to know what type of content is being presented. Do this by specifying the proper mime type in the Response.ContentType variable. For example, if you wanted to view a word document, you would set the ContentType = "application/msword".

The image is in an Access database, so how do I get it to display correctly, because of the OLE heders that you mentioned.
The image is in an Access database, so how do I get it to display correctly, because of the OLE heders that you mentioned.
Here is how to use Visual Basic to retrieve a bitmap stored in an OLE Object field. Because the definition of OLE object storage is not documented, the following code searches the object's OLE header for characters consistent with the start of the graphic. This method may not work in all circumstances.

Be aware that Internet Explorer 3.0 is unable to display true color bitmaps. For this reason, the bitmaps stored in the Access database should be no higher than 256 colors.



Step-by-Step Example to Extract the Photos

Create a new project in Visual Basic and make the project an ActiveX DLL.

Add a reference to ActiveX Data Objects (ADO) by clicking the Project menu and selecting References. Select "Microsoft OLE DB ActiveX Data Objects 1.0 Library" and click OK.

Add a new module to the project by selecting the Project menu and clicking Add Module. Select Module and click Open.

Place the following code in the (general) (declarations) section of MODULE1.BAS:


      ' Enter the following Declare statement as one single line:
      Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
       (lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)


      Type PT
        Width As Integer
        Height As Integer
      End Type

      Type OBJECTHEADER
        Signature As Integer
        HeaderSize As Integer
        ObjectType As Long
        NameLen As Integer
        ClassLen As Integer
        NameOffset As Integer
        ClassOFfset As Integer
        ObjectSize As PT
        OleInfo As String * 256
      End Type


Place the following code in the (general) (declarations) section of CLASS1.CLS:

        Function DisplayBitmap(ByVal OleField As Variant)
        Dim Arr() As Byte
        Dim ObjHeader As OBJECTHEADER
        Dim Buffer As String
        Dim ObjectOffset As Long
        Dim BitmapOffset As Long
        Dim BitmapHeaderOffset As Integer
        Dim ArrBmp() As Byte
        Dim i As Long

        'Resize the array, then fill it with
        'the entire contents of the field
        ReDim Arr(OleField.ActualSize)
        Arr() = OleField.GetChunk(OleField.ActualSize)

        'Copy the first 19 bytes into a variable
        'of the OBJECTHEADER user defined type.
        CopyMemory ObjHeader, Arr(0), 19

        'Determine where the Access Header ends.
        ObjectOffset = ObjHeader.HeaderSize + 1

        'Grab enough bytes after the OLE header to get the bitmap header.
        Buffer = ""
        For i = ObjectOffset To ObjectOffset + 512
            Buffer = Buffer & Chr(Arr(i))
        Next i

        'Make sure the class of the object is a Paint Brush object
        If Mid(Buffer, 12, 6) = "PBrush" Then
            BitmapHeaderOffset = InStr(Buffer, "BM")
            If BitmapHeaderOffset > 0 Then

                'Calculate the beginning of the bitmap
                BitmapOffset = ObjectOffset + BitmapHeaderOffset - 1

                'Move the bitmap into its own array
                ReDim ArrBmp(UBound(Arr) - BitmapOffset)
                CopyMemory ArrBmp(0), Arr(BitmapOffset), UBound(Arr) -
                 BitmapOffset + 1

                'Return the bitmap
                DisplayBitmap = ArrBmp
            End If
        End If
      End Function


Rename the Project by selecting the Project menu, and clicking on "Project1 Properties" and type your new name in the "Project Name" field. This example assumes that you named the project "MyProject" and will refer to that name in future steps.

Make the project Apartment Model Threaded by selecting the "Unattended Execution" check box. Click OK.

Rename the Class in the Property Pane. This example assumes that you named the class "MyClass" and refers to that name in future steps.

Compile the DLL by clicking the File menu and selecting "Make MyProject.dll."

Create an ASP page named "bitmap.asp" that contains the following code:


      <%@ LANGUAGE="VBSCRIPT" %>
      <%
      '   You need to set up a System DSN named 'NWind' that points to
      '   the Northwind.mdb database
      Set DataConn = Server.CreateObject("ADODB.Connection")
      DataConn.Open "DSN=NWind", "admin", ""
      Set cmdTemp = Server.CreateObject("ADODB.Command")
      Set RS = Server.CreateObject("ADODB.Recordset")
      cmdTemp.CommandText = "SELECT Photo FROM Employees
        WHERE EmployeeID = 1"
      cmdTemp.CommandType = 1
      Set cmdTemp.ActiveConnection = DataConn
      RS.Open cmdTemp, , 0, 1
      Response.ContentType = "image/bmp"
      Set Bitmap = Server.CreateObject("MyProject.MyClass")
      Response.BinaryWrite Bitmap.DisplayBitmap(RS("Photo"))
      RS.Close
      %>


Create an HTML page named "BitmapTest.htm" that contains the following code:


      <HTML>
      <HEAD>
      <TITLE>Bitmap Test</TITLE>
      </HEAD>
      <BODY>
      <HR>
      <img src="Bitmap.asp">
      <HR>
      </BODY>
      </HTML>

I don't have access to the server, so I can not create a DLL on the Server.  I need a way to do it from ASP.  Also it's a JPEG file not a Bitmap image.
1) A JPEG file IS a bitmap image.
2) There are no other solutions for your problem then. The only client side solution is to use another database that does not add header information in OLE fields, such as MS SQL Server.
Is it possible to use a Memo field or something, that way no OLE information is written.
You can give it a try, but I don't think so. A Memo file is also a BLOB (Binary Long Object)and Access also adds some weird data to it... In this case it won't work as you coded in the original question, i.e. Response.Binarywrite RS.fields("Pic1").

There is a chance of getting it to work if you open the image in text mode, copy it's contents into a Memo field, and create an ASP page to serve the image bytes. Then a second web page would call it, as <img src="Bitmap.asp">.

Obviously if this works, you won't be able to see the image in any other way.

Good luck, but I still think the proper solution is to use a different database system or ask your server provider to install the dll.
Another thought: have you considered having the images just linked to your database, and naming them using some kind of convetion (such as the table's Primary Key, for example)? This way the all you have to do is to pass the image name to the ASP page. Your database will be lighter and faster, and so will your web application.
Avatar of PCav

ASKER

No Luck I still can't display the Acces pictures.

Use this code:

<%
ID=Request.QueryString("ID")
BlockSize = 4096
Response.ContentType = "image/JPEG"
strQuery = "SELECT * FROM Blob WHERE Blob_ID = " & ID
Set oRD = oConn.Execute(Query)
oRS.MoveFirst
Set Field = oRS("Blob")
FileLength = Field.ActualSize
NumBlocks = FileLength \ BlockSize
LeftOver = FileLength Mod BlockSize
Response.BinaryWrite Field.GetChunk(LeftOver)
For intLoop = 1 to NumBlocks
   Response.BinaryWrite Field.GetChunk(BlockSize)
Next
oRS.Close
Set oRS = nothing
%>

YUou will obviouly need to modify it to fit your database, but you get the idea...

PS. Please send me the database as well... I would like to test it out and see if I cannot modify the code for you... masseym@hotmail.com

Thanks.

Matt
Avatar of PCav

ASKER

It does not work.  It return a broken picture image.

After reading quite extensively, I found that the GetChunk stuff works only in SQL databases not with Access..

I still don't think you'll find another solution other than the ones I've throughly exposed above. They all work fine, if you use SQL Server, or if you use Access you'll need the VB code to create a server object. Alternatively put the images outside the db.

I am willing to give 200 points to anyone who finds a different solution using Access...
ASKER CERTIFIED SOLUTION
Avatar of jzh
jzh

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial