Delphi Retrieve JPG From Long binary data - JPEG error #53

841 views Asked by At

I added many JPEG images into an Access DB as Long binary data. Now I want to retrieve these images into a TImage using Delphi code.

For this work, I wrote the code below, but after running it gives me a JPEG error #53 error. I searched in Google for this error code, and tried some solutions, such as saving as picture to new JPG format, but that does not change anything.

Also, I found different codes for retrieving an image from a database, but all of them gave me the same JPEG error #53 error.

Where is the problem?

procedure RetrieveImage;
var
 Jpg : TGraphic;
 Stream: TStream;
 query : string;
 Field: TBlobField;
Begin
 Stream := nil;
 Jpg := nil;
 query := 'Select JPGFile From Table Where Name=' + QuotedStr(SoftName);
 Try
   With ADOQuery do
    Begin
      Try
         SQL.Clear;
         SQL.Add(query);
         Open;
         Field := TBlobField(FieldbyName('JPGFile'));
         Stream := CreateBlobStream(Field,bmRead);
         Jpg := TJpegImage.Create;
         Jpg.LoadFromStream(Stream);
         MainForm.PictureBox.Picture.Graphic:= Jpg;
      Finally
         Close;
      End;
    End;
Finally
  Stream.Free;
  Jpg.Free;
End;
End;

EDIT:

I used C# code for insert a JPG file into the database (the following code is simplified):

    // Insert Data to Access tables
    private void InsertToTable(string connectionString, string query)
    {
        using (OleDbConnection connection = new OleDbConnection(connectionString))
        {
            try
            {
                connection.Close();
                using (OleDbCommand command = new OleDbCommand(query, connection))
                {
                    connection.Open();
                    using (OleDbDataReader reader = command.ExecuteReader())
                    {
                        reader.Close();
                    }
                    command.Cancel();
                }
                connection.Close();
            }
            finally
            {
                connection.Close();
            }
        }
    }

    // Insert Image into database
    private void SaveToDataBase(string jpegPath)
    {
        //jpegPath example is: (C:\Image\1.jpg)

        string FilePath = Application.StartupPath + directory + dbName;
        string MDBConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + FilePath + "; Jet OLEDB:Engine Type=5";

        // Convert Image to binary
        var image = File.ReadAllBytes(jpegPath);

        InsertToTable(MDBConnStr, $"INSERT INTO Table JPGFile VALUES('{image}')");                         
    }
1

There are 1 answers

0
Remy Lebeau On BEST ANSWER

In your C# code, why are you using ExecuteReader() to execute an INSERT statement? You should be using ExecuteNonQuery() instead.

More importantly, you are not actually inserting the contents of your image byte array into the database, which is why Delphi's TJPEGImage is failing to load the data later. Your SQL query is being created as an interpolated string, but your {image} expression does not insert the raw bytes into the query, like you think it does. And even if it did, that is not the correct way to insert raw bytes into a "Long Binary" field to begin with.

You need to use a parameterized query instead. Add an OleDbParameter to the command.Parameters collection to pass the image data into the database, where you set its DbType property to Binary, its OleDbType property to either Binary,LongVarBinary, or VarBinary, and its Value property to your image byte array. You can then refer to that parameter in your SQL statement.

See Configuring parameters and parameter data types, especially the section on Using parameters with an OleDbCommand or OdbcCommand.

Try something more like this:

// Insert Image into database
private void SaveToDataBase(string jpegPath)
{
    //jpegPath example is: (C:\Image\1.jpg)

    // Convert Image to binary
    var image = File.ReadAllBytes(jpegPath);

    string FilePath = Application.StartupPath + directory + dbName;
    string MDBConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + FilePath + "; Jet OLEDB:Engine Type=5";

    using (OleDbConnection connection = new OleDbConnection(MDBConnStr))
    {
        connection.Open();
        using (OleDbCommand command = new OleDbCommand("INSERT INTO Table JPGFile VALUES(?)", connection))
        {
            command.Parameters.Add("@Image", OleDbType.LongVarBinary).Value = image;
            command.ExecuteNonQuery();
        }
    }
}

Note, however, that binary parameters in OLEDB are limited to 8000 bytes max.