StretchDraw slow?

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

StretchDraw slow?

Postby mark_c » Fri Jan 11, 2019 1:26 pm

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 Guru
BCBJ Guru
 
Posts: 153
Joined: Thu Jun 21, 2012 1:13 am

Re: StretchDraw slow

Postby mark_c » Fri Jan 11, 2019 3:24 pm

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?
mark_c
BCBJ Guru
BCBJ Guru
 
Posts: 153
Joined: Thu Jun 21, 2012 1:13 am

Re: StretchDraw slow?

Postby HsiaLin » Fri Jan 11, 2019 5:56 pm

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.
HsiaLin
BCBJ Master
BCBJ Master
 
Posts: 307
Joined: Sun Jul 08, 2007 6:29 pm

Re: StretchDraw slow?

Postby mark_c » Sat Jan 12, 2019 10:28 am

so there is no solution?
Windows explorer is very quick to create and display thumbnails
mark_c
BCBJ Guru
BCBJ Guru
 
Posts: 153
Joined: Thu Jun 21, 2012 1:13 am

Re: StretchDraw slow?

Postby HsiaLin » Sat Jan 12, 2019 10:59 am

I have found no fast solution, maybe Remy can provide some insight.
HsiaLin
BCBJ Master
BCBJ Master
 
Posts: 307
Joined: Sun Jul 08, 2007 6:29 pm

Re: StretchDraw slow?

Postby mark_c » Sat Jan 12, 2019 12:29 pm

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?
mark_c
BCBJ Guru
BCBJ Guru
 
Posts: 153
Joined: Thu Jun 21, 2012 1:13 am

Re: StretchDraw slow

Postby rlebeau » Mon Jan 14, 2019 1:49 pm

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
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1574
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: StretchDraw slow?

Postby mark_c » Mon Jan 14, 2019 2:18 pm

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;

}
mark_c
BCBJ Guru
BCBJ Guru
 
Posts: 153
Joined: Thu Jun 21, 2012 1:13 am

Re: StretchDraw slow?

Postby rlebeau » Mon Jan 14, 2019 9:16 pm

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
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1574
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: StretchDraw slow?

Postby mark_c » Mon Jan 14, 2019 11:58 pm

Thank you Remy
mark_c
BCBJ Guru
BCBJ Guru
 
Posts: 153
Joined: Thu Jun 21, 2012 1:13 am

Re: StretchDraw slow?

Postby HsiaLin » Thu Jan 17, 2019 5:38 pm

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.
HsiaLin
BCBJ Master
BCBJ Master
 
Posts: 307
Joined: Sun Jul 08, 2007 6:29 pm

Re: StretchDraw slow?

Postby rlebeau » Thu Jan 17, 2019 7:25 pm

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
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1574
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA


Return to Technical

Who is online

Users browsing this forum: No registered users and 21 guests

cron