Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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;
 Jpg : TGraphic;
 Stream: TStream;
 query : string;
 Field: TBlobField;
Begin
 Stream := nil;
 Jpg := nil;
 query := 'Select JPGFile From Table Where Name=' + QuotedStr(SoftName);
   With ADOQuery do
    Begin
         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;
Finally
  Stream.Free;
  Jpg.Free;

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))
                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}')");                         
                This means the JPEG is broken and at some point cannot be processed any further. Instead of immediately trying to display the picture first save it into a file, then let other software attempt to render a picture out of it - they should fail, too. Have a look at your file in a hex viewer and compare that to a JPEG file that is not broken. That will give you an idea where the problem lies.
– AmigoJack
                May 1, 2022 at 0:35

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.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.