store a jpeg in an AnsiString buffer

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

store a jpeg in an AnsiString buffer

Postby mark_c » Wed Oct 16, 2019 11:50 am

Hello,
in this small example, I don't understand why AnsiString has problems with the null character and the string is truncated?

I want to store a jpeg image in an AnsiString buffer for an experiment but it doesn't work.

thanks

Code: Select all
    AnsiString MyBuffer;
    char buf[]="\xff\xd8\xff\xe0\0\xff\xd7\xff";
    MyBuffer+=buf;
mark_c
BCBJ Guru
BCBJ Guru
 
Posts: 170
Joined: Thu Jun 21, 2012 1:13 am

Re: store a jpeg in an AnsiString buffer

Postby rlebeau » Wed Oct 16, 2019 5:54 pm

mark_c wrote:in this small example, I don't understand why AnsiString has problems with the null character and the string is truncated?


The data is truncated because you are invoking operator+= using a char[] array as input.

When referred to by its name alone, a char[] array *decays* into a char* pointer to its first element. The operator takes an AnsiString as input, not a char* pointer. However, AnsiString has a constructor that takes a char* as input, and treats it as a null-terminated string, stopping on the first null char it encounters in memory. Which in your case is at buf[4].

To do what you are attempting, explicitly construct a temp AnsiString containing the full array data, and then pass that temp as the input value for the operator. AnsiString has another constructor that takes both a char* pointer and a size as input, copying the char data as-is up to the specified size, eg:

Code: Select all
AnsiString MyBuffer;
const char buf[] = "\xff\xd8\xff\xe0\x00\xff\xd7\xff";
MyBuffer += AnsiString(buf, 8);


Then, the code can be simplified by omitting the operator altogether:

Code: Select all
const char buf[] = "\xff\xd8\xff\xe0\x00\xff\xd7\xff";
AnsiString MyBuffer(buf, 8);


mark_c wrote:I want to store a jpeg image in an AnsiString buffer for an experiment


What kind of experiment? You really should not be storing binary data in an AnsiString to begin with. Too many ways the data could get corrupted if the AnsiString is misused. There are better containers designed for binary data, such as TBytes and std::vector.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1610
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: store a jpeg in an AnsiString buffer

Postby mark_c » Thu Oct 17, 2019 3:11 am

thanks Remy,
actually it's a raw experiment. I took a jpeg image (1920x1080 pixels 24 bit) and linked it a number of times, to understand:

type test.jpg >> __test.jpg
type test.jpg >> __test.jpg
type test.jpg >> __test.jpg
this for at least 100 times.

After this, I now try to recover the individual jpeg images and view them on the fly to understand where there may be bottlenecks in the code.
With this version of the code I don't go beyond viewing 15 frames per second, but I believe we can do better.

p.s.
in the meantime I discovered hot water, that is, most of the time is due to jpeg decompression. Perhaps the decompression operation should be performed by the gpu?

Code: Select all
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

#include <stdio.h>
#include <Jpeg.hpp>

AnsiString MyJpegBuffer, MyBuffer;
int fps;

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
        DoubleBuffered = true;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
        #define MAXSIZE 4096
        FILE *fp;
        char buf[MAXSIZE];
        AnsiString MyBuffer;
        fps=0;

        Timer1->Enabled=true;

        fp=fopen("__test.jpg","rb");
        if(!fp) return;

        while(!feof(fp))
        {
                fread(buf, 1, MAXSIZE, fp);
                MyBuffer+=AnsiString(buf,MAXSIZE);

                int QueueJpeg = MyBuffer.Pos("\xFF\xD9");

                if(QueueJpeg > 0)
                {
                        MyJpegBuffer = MyBuffer.SubString(1, QueueJpeg+1);

                        MyBuffer.Delete(1,QueueJpeg+1);

                        char *JpegPtr=MyJpegBuffer.c_str();


                        try
                        {
                                TStream *picture;
                                picture = new TMemoryStream;
                                TJPEGImage *myjpg;
                                myjpg = new TJPEGImage;
                           picture->Write(JpegPtr, MyJpegBuffer.Length());
                           picture->Position=NULL;
                           myjpg->LoadFromStream(picture);

                                Image1->Canvas->Draw(0,0,myjpg);
                                Image1->Update();

                                delete myjpg;
                                delete picture;

                        } catch(...) { }

                                fps++;
                                Application->ProcessMessages();
                }
        }

        fclose(fp);

        ShowMessage(IntToStr(fps));
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
        Label1->Caption = fps;
        fps=0;
}
//---------------------------------------------------------------------------
mark_c
BCBJ Guru
BCBJ Guru
 
Posts: 170
Joined: Thu Jun 21, 2012 1:13 am


Return to Technical

Who is online

Users browsing this forum: No registered users and 24 guests

cron