StretchDraw slow?

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

Post Reply
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

StretchDraw slow?

Post by mark_c »

Hello,
I do not know if it has already been discussed and if so I apologize but, to resize some jpeg images I am using the following code but it is very slow: what is the reason?

Thank you

Code: Select all

void __fastcall TForm1::Button1Click(TObject *Sender)
{
        Graphics::TBitmap *bmp1 = new Graphics::TBitmap;
        Graphics::TBitmap *bmp2 = new Graphics::TBitmap;
        TJPEGImage *jpeg = new TJPEGImage;

        jpeg->LoadFromFile("test.jpg");
        bmp1->Width=jpeg->Width;
        bmp1->Height=jpeg->Height;
        bmp1->Assign(jpeg);

        TRect ARect;
        bmp2->Width=120;
        bmp2->Height=120;
        ARect=::Rect(0, 0,  bmp2->Width, bmp2->Height);

        bmp2->Canvas->StretchDraw(ARect,bmp1);

        Image1->Picture->Bitmap->Assign(bmp2);

        delete bmp1;
        delete bmp2;
        delete jpeg;

}
Last edited by mark_c on Fri Jan 11, 2019 3:28 pm, edited 1 time in total.
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Re: StretchDraw slow

Post by mark_c »

sorry, using GetTickCount () I found out that the most greedy function in terms of time is the following assignment:

bmp1-> Assign (jpeg);

so it is not the StretchDraw () function that is responsible for the slowness: is it correct?
HsiaLin
BCBJ Master
BCBJ Master
Posts: 343
Joined: Sun Jul 08, 2007 6:29 pm

Re: StretchDraw slow?

Post by HsiaLin »

I ran into a similar problem recently, the bottleneck was
Image1->Picture->Bitmap->Assign() that creeped along.

Even using TPicture instead of a TBitmap didnt help.
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Re: StretchDraw slow?

Post by mark_c »

so there is no solution?
Windows explorer is very quick to create and display thumbnails
HsiaLin
BCBJ Master
BCBJ Master
Posts: 343
Joined: Sun Jul 08, 2007 6:29 pm

Re: StretchDraw slow?

Post by HsiaLin »

I have found no fast solution, maybe Remy can provide some insight.
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Re: StretchDraw slow?

Post by mark_c »

thank you.

From the documentation I understood that by calling:

Code: Select all

bmp1-> Assign (jpeg);
the jpeg image is copied to a bitmap and, in fact, is seen by a greater consumption of memory.

If we could resize a jpeg without converting it to bitmap first everything would be faster.
I tried some solutions but I can not work directly with the jpeg format.

what is not clear to me is also:
when viewing a jpeg photo on an Image component, it is already in a binary format, because it is necessary to make a translation from jpeg to bitmap before call resize routine?
rlebeau
BCBJ Author
BCBJ Author
Posts: 1759
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: StretchDraw slow

Post by rlebeau »

mark_c wrote:sorry, using GetTickCount () I found out that the most greedy function in terms of time is the following assignment:

bmp1-> Assign (jpeg);

so it is not the StretchDraw () function that is responsible for the slowness: is it correct?
Correct. And it is not even the Assign() itself either, as that will simply end up assigning an internal pointer and increase its reference count. What is actually the slowest piece is the decompression of the JPEG image data into a bitmap format the first time the TJPEGImage::Bitmap property is accessed by Assign().

Also, there is no need to resize the target TBitmap prior to calling Assign() on it. Assign() will handle the resize as needed when copying the bitmap data.

However, you don't actually need to use 2 TBitmap objects at all, 1 TBitmap will suffice, as you can pass the TJPEGImage directly to TCanvas::StretchDraw():

Code: Select all

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    Graphics::TBitmap *bmp = new Graphics::TBitmap;
    try
    {
        TJPEGImage *jpeg = new TJPEGImage;
        try
        {
            jpeg->LoadFromFile("test.jpg");

            TRect ARect = ::Rect(0, 0,  120, 120);
            bmp->Width = ARect.Width;
            bmp->Height = ARect.Height;

            bmp->Canvas->StretchDraw(ARect, jpeg);
        }
        __finally {
            delete jpeg;
        }

        Image1->Picture->Bitmap->Assign(bmp);
    }
    __finally {
        delete bmp;
    }
}
Remy Lebeau (TeamB)
Lebeau Software
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Re: StretchDraw slow?

Post by mark_c »

thanks Remy.
I still ask you if is possible to assign a jpeg instead of a bitmap to the ImageList component?

It would be interesting if it were possible because, saving the status of the ImageList component that contains jpeg instead of bitmap, consumes less disk space.

not possibile

Code: Select all

ImageList1->Add(jpeg, NULL);

possible for the Image component

Code: Select all

void __fastcall TForm1::Button1Click(TObject *Sender)
{
        TJPEGImage *jpeg = new TJPEGImage;

        jpeg->LoadFromFile("test.jpg");

        Image1->Picture->Assign(jpeg);

        WriteComponentResFile("_Image1.dat", Image1);

        delete jpeg;

}
rlebeau
BCBJ Author
BCBJ Author
Posts: 1759
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: StretchDraw slow?

Post by rlebeau »

mark_c wrote:I still ask you if is possible to assign a jpeg instead of a bitmap to the ImageList component?
No, it is not possible. TImageList only works with TBitmap and TIcon. That is an OS limitation more than a VCL limitation. Though, there are some third-party ImageList implementations that work with PNGs, but they ultimately have to convert to Bitmap internally when interacting with the Windows API. I have not heard of anyone making a custom ImageList for JPEGs.
mark_c wrote:It would be interesting if it were possible because, saving the status of the ImageList component that contains jpeg instead of bitmap, consumes less disk space.
Less disk space, perhaps, but not less memory.
Remy Lebeau (TeamB)
Lebeau Software
mark_c
BCBJ Master
BCBJ Master
Posts: 263
Joined: Thu Jun 21, 2012 1:13 am

Re: StretchDraw slow?

Post by mark_c »

Thank you Remy
HsiaLin
BCBJ Master
BCBJ Master
Posts: 343
Joined: Sun Jul 08, 2007 6:29 pm

Re: StretchDraw slow?

Post by HsiaLin »

Mark in your code above you could replace

TJPEGImage *jpeg = new TJPEGImage;
jpeg->LoadFromFile("test.jpg");
Image1->Picture->Assign(jpeg);
WriteComponentResFile("_Image1.dat", Image1);
delete jpeg;

with

Image1->Picture->LoadFromFile(L"test.jpg");
WriteComponentResFile("_Image1.dat", Image1);

it might help somewhat.
rlebeau
BCBJ Author
BCBJ Author
Posts: 1759
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: StretchDraw slow?

Post by rlebeau »

HsiaLin wrote:it might help somewhat.
Somewhat, but not much. Internally, TPicture::LoadFromFile() will still have to create a new TJPEGImage object, call its LoadFromFile() method, and take ownership of it, destroying any existing Graphic object. Same steps as the other code. The only real difference being that TPicture::Assign() makes a copy of the input object, whereas TPicture::LoadFromFile() does not. That is the only thing you really save on. But it is something, at least.
Remy Lebeau (TeamB)
Lebeau Software
Post Reply