Recent

Author Topic: [Solved] Component à la TPicShow (delphi)  (Read 20004 times)

Thaddy

  • Hero Member
  • *****
  • Posts: 16201
  • Censorship about opinions does not belong here.
Re: Component à la TPicShow (delphi)
« Reply #15 on: January 12, 2019, 05:08:15 pm »
<Ignore this>
Sounds like the rather common case of  "TComponentThatWritesMyActualProgramWithoutEffortByMe"
<don't totally ignore it>

Programs are the result of some actual intellectual input. Even generated programs rely on that.
If I smell bad code it usually is bad code and that includes my own code.

Handoko

  • Hero Member
  • *****
  • Posts: 5378
  • My goal: build my own game engine using Lazarus
Re: Component à la TPicShow (delphi)
« Reply #16 on: January 12, 2019, 06:14:28 pm »
bgradbitmap .... seems very very powerful and it is, but the learning-curve is huge. And I find no all needed info to try it on my own.

I think differently. Although, I haven't really use BGRABitmap but I can sure to tell you compare to other graphics libraries BGRABitmap is really easy to learn, the tutorials are very good.

If the learning curve is huge for you, I'm sorry but lets face the truth. Graphics programming is not for you. Graphics programming is not simply calling a function and it works for you. You have to understand the logic behind it, you have to have the basic mathematics skills preferably advanced skill level. Again, sorry of being harsh. But it is actually good for you. Maybe it can motivates you or maybe makes you realize and give up for better.

WimVan

  • Jr. Member
  • **
  • Posts: 85
Re: Component à la TPicShow (delphi)
« Reply #17 on: January 12, 2019, 06:44:21 pm »
Handoko,

You are right. Graphic programming is not my real interest.  I'm a photographer and I'm busy with taking picture ...

Meanwhile, I once wrote a program to repair faulting jpeg's ... and still it does.  And, it was written in pure C without a graphical available gui.
I wrote this all in php for the web.  Here you can see what I mean: https://www.fotospotter.be where I wrote any thing myself ...  And the program admids more than what is visible for a guest, a photo-interested person...
I rewrote anything till now and all is working except, I would like to have fade in fade out so a slideshow is nicer.  No more no less.  SO can someone insult me of not being a real graphical programmer ?  I never pretended this and I will never pretend.
I thought that this site was to help persons... even dummies in certain cases ...

But if this a problem, forget all my requests, .... I'll stop rendering my little app more pleaseable ...
By the way, I once started at DOS 2.0  without a windows-interface, programmed on a COmmodore 24, 64 128, Amiga where I then, did graphical things.
DOS 3 had his entry with Pascal ...
Once I programmed in basic without the existence of linenumbers, ...  SO, I'm not a young person ...

Any way, thanks to every body trying to help others.

Sees

PS. Here you can find what I wrote above

https://groups.google.com/forum/#!topic/alt.comp.freeware/XfnR7aZnzak

 
« Last Edit: January 12, 2019, 06:48:17 pm by WimVan »

Handoko

  • Hero Member
  • *****
  • Posts: 5378
  • My goal: build my own game engine using Lazarus
Re: Component à la TPicShow (delphi)
« Reply #18 on: January 12, 2019, 06:51:21 pm »
I never meant to insult you. I wanted to motivate you. But if you think differently, I'm sorry.

WimVan

  • Jr. Member
  • **
  • Posts: 85
Re: Component à la TPicShow (delphi)
« Reply #19 on: January 12, 2019, 07:59:33 pm »
you do not mean it, but you wrote it anyway.
That's why I was looking for PicShow.  I used it in the years 2004 and it did it just what I try.  But, no development requiered, It was a component.
@Thaddy, Thanks for the title and the message.
I feel lucky.  Apart the fact that there is all needed info, doc and all is clear, there are still so much people with questions and problems with it.
Sorry, yes this sounds negative.
Case closed.

Handoko

  • Hero Member
  • *****
  • Posts: 5378
  • My goal: build my own game engine using Lazarus
Re: [Solved] Component à la TPicShow (delphi)
« Reply #20 on: January 12, 2019, 10:39:33 pm »
The misunderstanding happened because I forgot about your first post that you're looking for a ready to use slideshow component (TPictShow). I saw your later post that you're trying to do fading using BGRABitmap but you said the learning curve is huge.

No, there is no free slideshow component available for Lazarus. You have to build the slideshow manually using one of the available graphics or game libraries. And BGRABitmap is relatively easy among them:
http://wiki.freepascal.org/Graphics_libraries
http://wiki.freepascal.org/Game_framework

Maybe you don't want it anymore. But hope someone will find it useful:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  9.   ExtDlgs, ExtCtrls, BGRABitmap, BGRABitmapTypes;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     btnImage2: TButton;
  17.     btnImage1: TButton;
  18.     OpenPictureDialog1: TOpenPictureDialog;
  19.     Timer1: TTimer;
  20.     procedure btnImage1Click(Sender: TObject);
  21.     procedure btnImage2Click(Sender: TObject);
  22.     procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
  23.     procedure FormCreate(Sender: TObject);
  24.     procedure FormPaint(Sender: TObject);
  25.     procedure FormResize(Sender: TObject);
  26.     procedure Timer1Timer(Sender: TObject);
  27.   private
  28.     Image1: TBGRABitmap;
  29.     Image2: TBGRABitmap;
  30.     Combined: TBGRABitmap;
  31.     ImageLoaded: Boolean;
  32.   end;
  33.  
  34. const
  35.   TransitionDelayTime = 100;  // should be 5 .. 500
  36.   StillDelayTime      = 200;  // should be 0 .. 1000
  37.  
  38. var
  39.   Form1: TForm1;
  40.  
  41. implementation
  42.  
  43. {$R *.lfm}
  44.  
  45. { TForm1 }
  46.  
  47. procedure TForm1.btnImage1Click(Sender: TObject);
  48. begin
  49.   if not(OpenPictureDialog1.Execute) then Exit;
  50.   Image1            := TBGRABitmap.Create(OpenPictureDialog1.FileName);
  51.   btnImage1.Enabled := False;
  52.   btnImage2.Enabled := True;
  53. end;
  54.  
  55. procedure TForm1.btnImage2Click(Sender: TObject);
  56. begin
  57.   if not(OpenPictureDialog1.Execute) then Exit;
  58.   Image2            := TBGRABitmap.Create(OpenPictureDialog1.FileName);
  59.   Combined          := TBGRABitmap.Create(Width, Height);
  60.   ImageLoaded       := True;
  61.   Timer1.Enabled    := True;
  62.   btnImage1.Visible := False;
  63.   btnImage2.Visible := False;
  64. end;
  65.  
  66. procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
  67. begin
  68.   Timer1.Enabled := False;
  69.   Image1.Free;
  70.   Image2.Free;
  71.   Combined.Free;
  72. end;
  73.  
  74. procedure TForm1.FormCreate(Sender: TObject);
  75. begin
  76.   btnImage2.Enabled := False;
  77.   ImageLoaded       := False;
  78.   Timer1.Enabled    := False;
  79.   Timer1.Interval   := 20;
  80. end;
  81.  
  82. procedure TForm1.FormPaint(Sender: TObject);
  83. const
  84.   Transparency : Integer = 0;
  85.   StillDelay   : Integer = 0;
  86.   Transition   : Integer = 0;
  87.   Direction    : (From1To2, From2To1) = From1To2;
  88. var
  89.   ARect: TRect;
  90. begin
  91.  
  92.   // Don't start before all image are loaded
  93.   if not(ImageLoaded) then Exit;
  94.  
  95.   // Process direction changing
  96.   if Transition >= TransitionDelayTime then
  97.     if StillDelay <= 0 then
  98.     begin
  99.       StillDelay := StillDelayTime;
  100.       Transition := 0;
  101.       Inc(Direction);
  102.       if Direction > High(Direction) then
  103.         Direction := Low(Direction);
  104.     end;
  105.  
  106.   // Process fading and show the result
  107.   ARect        := Rect(0, 0, Width, Height);
  108.   Transparency := Round(Transition / TransitionDelayTime * 255);
  109.   case Direction of
  110.     From1To2:
  111.       begin
  112.         Combined.StretchPutImage(ARect, Image1, dmDrawWithTransparency, 255);
  113.         Combined.StretchPutImage(ARect, Image2, dmDrawWithTransparency, Transparency);
  114.       end;
  115.     From2To1:
  116.       begin
  117.         Combined.StretchPutImage(ARect, Image2, dmDrawWithTransparency, 255);
  118.         Combined.StretchPutImage(ARect, Image1, dmDrawWithTransparency, Transparency);
  119.       end;
  120.   end;
  121.   Combined.Draw(Canvas, 0,0);
  122.  
  123.   // Process delays
  124.   if StillDelay <= 0 then
  125.     Inc(Transition)
  126.   else
  127.     Dec(StillDelay);
  128.  
  129. end;
  130.  
  131. procedure TForm1.FormResize(Sender: TObject);
  132. begin
  133.   if not(ImageLoaded) then Exit;
  134.   Combined.Free;
  135.   Combined := TBGRABitmap.Create(Width, Height);
  136. end;
  137.  
  138. procedure TForm1.Timer1Timer(Sender: TObject);
  139. begin
  140.   FormPaint(Self);
  141. end;
  142.  
  143. end.

  • The code for fading is on the lines 112 .. 121
  • The delay time can be adjusted on line 35 and line 36
  • It supports form resizing, see line 131
  • It does not support proportional image stretching scaling, see Circular post on reply #14 if you want it

edit:
The declaration of the constant "Transparency" on line 84 should be put on the line 89 as a variable.
« Last Edit: January 12, 2019, 10:57:07 pm by Handoko »

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: [Solved] Component à la TPicShow (delphi)
« Reply #21 on: January 13, 2019, 03:05:38 am »
In fact there is a slideshow under development
https://gilles-vasseur.developpez.com/tutoriels/transitions/bgra1/
though I think there is no download link

I don’t believe it helps to be harsh with people. If we don’t want to spend time on it we can simply say it. If we force ourselves to help it is bad for us and the other person. And we end up being passive aggressive or judgemental.

It is sometimes difficult to ask for help because we show our vulnerability. So I would enjoy it to be a safe space here.
Conscience is the debugger of the mind

WimVan

  • Jr. Member
  • **
  • Posts: 85
Re: [Solved] Component à la TPicShow (delphi)
« Reply #22 on: January 13, 2019, 10:09:46 am »
It is sometimes difficult to ask for help because we show our vulnerability. So I would enjoy it to be a safe space here.
I mis a thumb-up-icon ....

Bart

  • Hero Member
  • *****
  • Posts: 5469
    • Bart en Mariska's Webstek
Re: [Solved] Component à la TPicShow (delphi)
« Reply #23 on: January 13, 2019, 10:59:32 am »
It is sometimes difficult to ask for help because we show our vulnerability. So I would enjoy it to be a safe space here.

Yes, a safe place this shall remain.

Not asking for help is obviously worse.
We try to help as good as we can.
For me, this assumes that whoever asks for help also must put in the effort (note: this is not a reflection upon TS).
You might however be subjected to various degrees of humor  (especially when askig for help with homework assignments) O:-)

Bart

Handoko

  • Hero Member
  • *****
  • Posts: 5378
  • My goal: build my own game engine using Lazarus
Re: [Solved] Component à la TPicShow (delphi)
« Reply #24 on: January 13, 2019, 05:31:51 pm »
How To Do Proportional Scaling

Now I improved the source code to do proportional scaling. Doing proportional scaling is not hard but it is very difficult to explain it, especially with my limitation of English.

First, look the code below. There are many optimizations can be done (for better performance), but I tried to wrote it in the more readable way:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  9.   ExtDlgs, ExtCtrls, BGRABitmap, BGRABitmapTypes;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     btnImage2: TButton;
  17.     btnImage1: TButton;
  18.     OpenPictureDialog1: TOpenPictureDialog;
  19.     Timer1: TTimer;
  20.     procedure btnImage1Click(Sender: TObject);
  21.     procedure btnImage2Click(Sender: TObject);
  22.     procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
  23.     procedure FormCreate(Sender: TObject);
  24.     procedure FormPaint(Sender: TObject);
  25.     procedure FormResize(Sender: TObject);
  26.     procedure Timer1Timer(Sender: TObject);
  27.   private
  28.     Image1: TBGRABitmap;
  29.     Image2: TBGRABitmap;
  30.     Combined: TBGRABitmap;
  31.     ImageLoaded: Boolean;
  32.   end;
  33.  
  34. const
  35.   TransitionDelayTime = 100;  // should be 5 .. 500
  36.   StillDelayTime      = 200;  // should be 0 .. 1000
  37.  
  38. var
  39.   Form1: TForm1;
  40.  
  41. implementation
  42.  
  43. {$R *.lfm}
  44.  
  45. { TForm1 }
  46.  
  47. procedure TForm1.btnImage1Click(Sender: TObject);
  48. begin
  49.   if not(OpenPictureDialog1.Execute) then Exit;
  50.   Image1            := TBGRABitmap.Create(OpenPictureDialog1.FileName);
  51.   btnImage1.Enabled := False;
  52.   btnImage2.Enabled := True;
  53. end;
  54.  
  55. procedure TForm1.btnImage2Click(Sender: TObject);
  56. begin
  57.   if not(OpenPictureDialog1.Execute) then Exit;
  58.   Image2            := TBGRABitmap.Create(OpenPictureDialog1.FileName);
  59.   Combined          := TBGRABitmap.Create(Width, Height);
  60.   ImageLoaded       := True;
  61.   Timer1.Enabled    := True;
  62.   btnImage1.Visible := False;
  63.   btnImage2.Visible := False;
  64. end;
  65.  
  66. procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
  67. begin
  68.   Timer1.Enabled := False;
  69.   Image1.Free;
  70.   Image2.Free;
  71.   Combined.Free;
  72. end;
  73.  
  74. procedure TForm1.FormCreate(Sender: TObject);
  75. begin
  76.   btnImage2.Enabled := False;
  77.   ImageLoaded       := False;
  78.   Timer1.Enabled    := False;
  79.   Timer1.Interval   := 20;
  80. end;
  81.  
  82. procedure TForm1.FormPaint(Sender: TObject);
  83. const
  84.   StillDelay   : Integer = 0;
  85.   Transition   : Integer = 0;
  86.   Direction    : (From1To2, From2To1) = From1To2;
  87. var
  88.   Transparency    : Integer;
  89.   AspectForm      : Single;
  90.   AspectImage1    : Single;
  91.   AspectImage2    : Single;
  92.   Image1NewWidth  : Integer;
  93.   Image1NewHeight : Integer;
  94.   Image2NewWidth  : Integer;
  95.   Image2NewHeight : Integer;
  96.   RectImage1      : TRect;
  97.   RectImage2      : TRect;
  98. begin
  99.  
  100.   // Don't start before all image are loaded
  101.   if not(ImageLoaded) then Exit;
  102.  
  103.   // Process direction changing
  104.   if Transition >= TransitionDelayTime then
  105.     if StillDelay <= 0 then
  106.     begin
  107.       StillDelay := StillDelayTime;
  108.       Transition := 0;
  109.       Inc(Direction);
  110.       if Direction > High(Direction) then
  111.         Direction := Low(Direction);
  112.     end;
  113.  
  114.   // Calculations for proportional scaling
  115.   AspectForm   := Width / Height;
  116.   AspectImage1 := Image1.Width / Image1.Height;
  117.   AspectImage2 := Image2.Width / Image2.Height;
  118.   if AspectForm > AspectImage1 then // use same height
  119.   begin
  120.     Image1NewHeight := Height;
  121.     Image1NewWidth  := Round(Image1NewHeight * AspectImage1);
  122.   end
  123.   else begin                        // use same width
  124.     Image1NewWidth  := Width;
  125.     Image1NewHeight := Round(Image1NewWidth / AspectImage1);
  126.   end;
  127.   if AspectForm > AspectImage2 then // use same height
  128.   begin
  129.     Image2NewHeight := Height;
  130.     Image2NewWidth  := Round(Image2NewHeight * AspectImage2);
  131.   end
  132.   else begin                        // use same width
  133.     Image2NewWidth  := Width;
  134.     Image2NewHeight := Round(Image2NewWidth / AspectImage2);
  135.   end;
  136.   RectImage1.Left   := (Width-Image1NewWidth) div 2;   // Make the image center
  137.   RectImage1.Top    := (Height-Image1NewHeight) div 2; // Make the image center
  138.   RectImage1.Width  := Image1NewWidth;
  139.   RectImage1.Height := Image1NewHeight;
  140.   RectImage2.Left   := (Width-Image2NewWidth) div 2;   // Make the image center
  141.   RectImage2.Top    := (Height-Image2NewHeight) div 2; // Make the image center
  142.   RectImage2.Width  := Image2NewWidth;
  143.   RectImage2.Height := Image2NewHeight;
  144.  
  145.   // Process fading and show the result
  146.   Transparency := Round(Transition / TransitionDelayTime * 255);
  147.   case Direction of
  148.     From1To2:
  149.       begin
  150.         Combined.StretchPutImage(RectImage1, Image1, dmDrawWithTransparency, 255);
  151.         Combined.StretchPutImage(RectImage2, Image2, dmDrawWithTransparency, Transparency);
  152.       end;
  153.     From2To1:
  154.       begin
  155.         Combined.StretchPutImage(RectImage2, Image2, dmDrawWithTransparency, 255);
  156.         Combined.StretchPutImage(RectImage1, Image1, dmDrawWithTransparency, Transparency);
  157.       end;
  158.   end;
  159.   Combined.Draw(Canvas, 0,0);
  160.  
  161.   // Process delays
  162.   if StillDelay <= 0 then
  163.     Inc(Transition)
  164.   else
  165.     Dec(StillDelay);
  166.  
  167. end;
  168.  
  169. procedure TForm1.FormResize(Sender: TObject);
  170. begin
  171.   if not(ImageLoaded) then Exit;
  172.   Combined.Free;
  173.   Combined := TBGRABitmap.Create(Width, Height);
  174. end;
  175.  
  176. procedure TForm1.Timer1Timer(Sender: TObject);
  177. begin
  178.   FormPaint(Self);
  179. end;
  180.  
  181. end.

The code for doing proportional scaling starts from line #114 .. # 143.

You need to supply the image's x, y, w, h when showing it. That's why I added RectImage1 and RectImage2. See the example on line #150 and #151.

The x and y values of RectImages are not (0, 0). Because (0, 0) mean top left corner. So we have to calculate the center position. The calculation are performed on the line #136, #137, #140, #141.

To be able to calculate the center position, we have to calculate the image's width and height first. And this is the most tricky part. This is the pseudo code:

  if AspectOfContainer > AspectOfObject then
  begin

      // object use the height of container
      ObjectNewHeight := container's Height;
      // and we calculate the object's width
      ObjectNewWidth  := Round(ObjectNewHeight * AspectOfObject);
  end
  else begin
                       
      // object use the width of container
      ObjectNewWidth  := container's Width;
      // and we calculate the object's height
      ObjectNewHeight := Round(ObjectNewWidth / AspectOfObject);
  end;


Note:
The code for calculating object's new width and new height is on the line #118 .. #135.
To be able to calculate the object's new width or height we need the Aspect value of the object.

You can use wikipedia to learn more about aspect.

In graphics programming you can use aspect to calculate the new size of object by using these formulas:

Object_New_Width = Object_New_Height x Aspect_Of_The_Object
and
Object_New_Height = Object_New_Width / Aspect_Of_The_Object

See the pseudocode to learn how to use these formulas.
We have to add Round function because BGRABitmap needs integer values for those inputs.

And the last thing is the how to calculate the aspects. In our case we need 3 aspects:
- Aspect of the container -> the form itself
- Aspect of the object1 -> Image1
- Aspect of the object2 -> Image2
See line #115 .. #117.

The explanation above is in a reverse-way. In short, this is how you do proportional scaling (in the 'correct' non reverse-way):
  • First calculate the aspect of the container and aspect of the object
  • Calculate the object new width if (AspectOfContainer > AspectOfObject)
  • Calculate the object new height if (AspectOfContainer <= AspectOfObject)
  • Calculate the center position of the object
  • Now you have the x, y, w, h

Graphics programming is fun ... as long as you have the passion to do it.
Have fun!

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: [Solved] Component à la TPicShow (delphi)
« Reply #25 on: January 13, 2019, 06:39:21 pm »
Looks great Handoko.

Some remarks:
- the size of the drawable part is ClientWidth x ClientHeight, not Width x Height (you can also read the value of Combined.Width and Combined.Height so that the drawing is consistent with the virtual screen size)
- calling FromPaint directly works on Windows and Linux but not on MacOS. Instead you can call Invalidate. This may cause some blinking depending on the system, so you need to prevent the erase background event or set the DoubleBuffered property to True.
Conscience is the debugger of the mind

Handoko

  • Hero Member
  • *****
  • Posts: 5378
  • My goal: build my own game engine using Lazarus
Re: [Solved] Component à la TPicShow (delphi)
« Reply #26 on: January 13, 2019, 06:47:39 pm »
In the source code I provided above, because the container is the form itself so the client width and client height is the form's width and height. It can be simplified by using width and height only, because the Self is the form. But I agree if someone copy/pasted the code, without the 'client' it has higher chances of failure.

I don't have a Mac. :-[
But, I will remember to use Invalidate (instead of Form's Paint) and use Double Buffer.

Thank you for the suggestions.

edit:
Suggestion for BGRABitmap, please consider to add proportional scaling feature.
« Last Edit: January 13, 2019, 06:49:38 pm by Handoko »

WimVan

  • Jr. Member
  • **
  • Posts: 85
Re: [Solved] Component à la TPicShow (delphi)
« Reply #27 on: January 13, 2019, 09:44:14 pm »
Handoko,
Runs well, except, if you have a a landscaped image and a portrait-image,  when the fade in image is the portrait, you still see parts of the first image ...
I too tried something.  I used bgrabitmap and crossfade;  It runs well, except, I have no proportial scaling.
For crossfade you need two images with the same width, height.  Portrait and landscape isn't
So I was thinking to create an image (runtime) which covers the whole canvas-area after I draw an image on it respecting proportial scaling and centering it.  Of course, this may not been seen while showing the slideshow.  It should have been done in memory.  If I find this out, I'll can finalise my version.
Still interested if you can fade in the new image while fade out the second one.  This is what crossfade does.

Code: Pascal  [Select][+][-]
  1. unit slide_1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  9.   ExtCtrls, math, types, BGRABitmap, BGRABitmapTypes;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     knop: TButton;
  17.     procedure FormWindowStateChange(Sender: TObject);
  18.     procedure knopClick(Sender: TObject);
  19.     procedure FormCreate(Sender: TObject);
  20.     procedure FormPaint(Sender: TObject);
  21.   private
  22.     image: TBGRABitmap;
  23.     image_from : TBGRABitmap;
  24.     image_to   : TBGRABitmap;
  25.  
  26.   public
  27.  
  28.   end;
  29.  
  30. var
  31.   Form1: TForm1;
  32.   nfoto : integer;
  33.  
  34. implementation
  35.  
  36. {$R *.lfm}
  37.  
  38. { TForm1 }
  39.  
  40. procedure TForm1.knopClick(Sender: TObject);
  41. var
  42.   nknop : integer;
  43.   str_foto_from, str_foto_to : string;
  44. begin
  45.   if nfoto = 0 then
  46.   begin
  47.     str_foto_from := 'img_044000d.jpg';
  48.     str_foto_to   := 'img_045014d.jpg';
  49.   end;
  50.   if nfoto = 1 then
  51.   begin
  52.     str_foto_from := 'img_045014d.jpg';
  53.     str_foto_to   := 'img_044333d.jpg';
  54.   end;
  55.   if nfoto = 2 then
  56.   begin
  57.     str_foto_from := 'img_044333d.jpg';
  58.     str_foto_to   := 'img_042000d.jpg';
  59.   end;
  60.   image_from.LoadFromFile( str_foto_from);
  61. // change image-size to a fullsized form
  62.   BGRAReplace(image_from, image_from.Resample(Form1.Width, Form1.Height, rmSimpleStretch));
  63.  
  64.   image_to.LoadFromFile( str_foto_to );
  65.   // change image-size to a fullsized form
  66.   BGRAReplace(image_to, image_to.Resample(Form1.Width, Form1.Height, rmSimpleStretch));
  67.  
  68.   nfoto := nfoto + 1;
  69.   if nfoto = 3 then nfoto := 0;
  70.  
  71. // fading using crossqfade by incresing transparency-value (from 1 to 255 by step of 5
  72.   for nknop := 1 to 51 do
  73.   begin
  74.     knop.Tag := nknop;
  75.     form1.Tag := 1;
  76. // call form-paint-event
  77.     form1.Repaint;
  78.   end;
  79. end;
  80.  
  81. procedure TForm1.FormWindowStateChange(Sender: TObject);
  82. begin
  83.   image.SetSize(ClientWidth,ClientHeight);
  84.   image.Fill(BGRABlack);
  85. end;
  86.  
  87.  
  88. procedure TForm1.FormCreate(Sender: TObject);
  89. begin
  90.   image_from := TBGRABitmap.Create;
  91.   image_to   := TBGRABitmap.Create;
  92.   image      := TBGRABitmap.Create;
  93.   image.SetSize(ClientWidth,ClientHeight);
  94.   image.Fill(BGRABlack);
  95.   nfoto := 0;
  96. end;
  97.  
  98. procedure TForm1.FormPaint(Sender: TObject);
  99. var r
  100.   destRect: TRect;
  101. begin
  102.   if form1.Tag = 1 then
  103.   begin
  104. // create an image from two images with transparency  FormPaint is put in a loop while increasing the transparancy of image 2(image_to), decreasing image 1 (image_from)
  105.     image.CrossFade(Rect(0,0,image.Width, image.Height), image_from, image_to, round(knop.tag * 5), dmSet);
  106.       sleep( 20 );
  107.       image.   Draw(Canvas, 0,0);
  108.     Form1.Tag := 2; // ready to next
  109.   end;
  110. end;
  111.  
  112. end.
  113.  

used images are added.  Image img_044333d.jpg is portrait and as I told, proportial scaling is still not set
Due to limitation of attachments-size I added bad looking images (size 200 pixel-150 pixel)


gillou58

  • New member
  • *
  • Posts: 9
Re: [Solved] Component à la TPicShow (delphi)
« Reply #28 on: January 14, 2019, 09:28:25 am »
Hi,
As circular suggested, perhaps you will be interested in a component I wrote a few months ago for teaching purpose. For the moment explanations are only in French. I will try to work on it ASAP if someone is interested in this kind of work.

You have to install the excellent BRABitmap library first.

The TGVTransition Component is in the gvsoft package. You have to install it too.
There is a demo in the sample directory. If you can't read French, compile this program just click on the Test button and try to change the options values.

There are https://www.developpez.net/forums/d1869926/autres-langages/pascal/lazarus/creer-transitions-d-image-image-lazarus-bgrabitmap-7-composant-complet/seven tutorials (all in French :( ) to explain how I wrote this component.

[EDIT] Demo is here : https://www.dropbox.com/s/jpmsd5gpt4rwzhy/demo.7z?dl=0

Gilles
« Last Edit: January 14, 2019, 09:31:26 am by gillou58 »

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: [Solved] Component à la TPicShow (delphi)
« Reply #29 on: January 14, 2019, 12:59:30 pm »
In the source code I provided above, because the container is the form itself so the client width and client height is the form's width and height. It can be simplified by using width and height only, because the Self is the form. But I agree if someone copy/pasted the code, without the 'client' it has higher chances of failure.
Nope, the Form Width is a few pixels bigger than the Form ClientWidth as it contains the form border.

Quote
Suggestion for BGRABitmap, please consider to add proportional scaling feature.
Sure. I've added StretchPutImageProportionally on dev branch.  :)
Hence the code becomes:
Code: Delphi  [Select][+][-]
  1. procedure TForm1.FormPaint(Sender: TObject);
  2. const
  3.   StillDelay   : Integer = 0;
  4.   Transition   : Integer = 0;
  5.   Direction    : (From1To2, From2To1) = From1To2;
  6. var
  7.   Transparency    : Integer;
  8.   r: TRect;
  9. begin
  10.  
  11.   // Don't start before all image are loaded
  12.   if not(ImageLoaded) then Exit;
  13.  
  14.   // Process direction changing
  15.   if Transition >= TransitionDelayTime then
  16.     if StillDelay <= 0 then
  17.     begin
  18.       StillDelay := StillDelayTime;
  19.       Transition := 0;
  20.       Inc(Direction);
  21.       if Direction > High(Direction) then
  22.         Direction := Low(Direction);
  23.     end;
  24.  
  25.   // Process fading and show the result
  26.   Transparency := Round(Transition / TransitionDelayTime * 255);
  27.   Combined.Fill(BGRABlack);
  28.   r := Rect(0,0,Combined.Width,Combined.Height);
  29.   case Direction of
  30.     From1To2:
  31.       begin
  32.         Combined.StretchPutImageProportionally(r, taCenter,tlCenter, Image1, dmDrawWithTransparency, 255);
  33.         Combined.StretchPutImageProportionally(r, taCenter,tlCenter, Image2, dmDrawWithTransparency, Transparency);
  34.       end;
  35.     From2To1:
  36.       begin
  37.         Combined.StretchPutImageProportionally(r, taCenter,tlCenter, Image2, dmDrawWithTransparency, 255);
  38.         Combined.StretchPutImageProportionally(r, taCenter,tlCenter, Image1, dmDrawWithTransparency, Transparency);
  39.       end;
  40.   end;
  41.   Combined.Draw(Canvas, 0,0);
  42.  
  43.   // Process delays
  44.   if StillDelay <= 0 then
  45.     Inc(Transition)
  46.   else
  47.     Dec(StillDelay);
  48.  
  49. end;

@gillou58:
Thanks for the link. My mistake there was a download link:
https://pascal.developpez.com/telecharger/detail/id/6236/TGVTransition-composant-visuel-pour-l-affichage-de-transitions-d-image-a-image

@WimVan:
I see your point. Indeed when images do not have the same aspect ratio, the previous image does not disappear as the fading occurs. You can generate your stretched images like that:
Code: Delphi  [Select][+][-]
  1.   function CreateStretched(AImage: TBGRABitmap): TBGRABitmap;
  2.   var
  3.     ratio: single;
  4.   begin
  5.     result := TBGRABitmap.Create(Combined.Width,Combined.Height, BGRABlack);
  6.     ratio := min(Combined.Width/AImage.Width,Combined.Height/AImage.Height);
  7.     r := rect(0,0,round(AImage.Width*ratio),round(AImage.Height*ratio));
  8.     r.Offset((Combined.Width-r.Width) div 2, (Combined.Height-r.Height) div 2);
  9.     result.StretchPutImage(r, AImage, dmDrawWithTransparency);
  10.   end;

I noticed CrossFade was slow so I just optimized it a bit on dev branch.
« Last Edit: January 14, 2019, 01:11:29 pm by circular »
Conscience is the debugger of the mind

 

TinyPortal © 2005-2018