unit UJVu;
{##############################################################################)
            JVu, mein zweites öffentlich gemachtes Delphiprogramm.
       Aber das erste, von dem ich auch mal etwas Sourcecode preisgebe.
             Erstellt und Compiliert mit Delphi 5.0 Professional

               Copyright: Horst Rudolph > www.horst-rudolph.de

--------------------------------------------------------------------------------
  Programm-Historie
--------------------------------------------------------------------------------
  Aktuelle Version: 1.0, vom 06.04.2006
    (für meine Tochter Johanna, die vorgestern 18 Jahre alt wurde.)
    Programmdokumentation: erst mal spärlich
    Hilfstexte: nur kurze Hilfstexte im Programm

(##############################################################################}
interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Grids, Outline, DirOutln, ExtCtrls, ToolWin, ComCtrls, UInput,
  ActnList, ImgList, Buttons, Gauges, ExtDlgs, Menus, Clipbrd, USpline,
  jpeg,UJVuBasics;

type
  Point = record x,y:integer; end;

  TFormJVu = class(TForm)
    ScrollBox1: TScrollBox;    ScrollBox2: TScrollBox;
    Shape1: TShape;    Shape2: TShape;    Shape3: TShape;    Shape4: TShape;    Shape5: TShape;
    Shape6: TShape;    Shape7: TShape;    Shape8: TShape;    Shape9: TShape;    Shape10: TShape;
    Shape11: TShape;
    Panel1: TPanel;    Panel2: TPanel;    Panel3: TPanel;    Panel4: TPanel;    Panel5: TPanel;
    Panel6: TPanel;    Panel7: TPanel;    Panel8: TPanel;    Panel9: TPanel;    Panel10: TPanel;
    Panel11: TPanel;   Panel12: TPanel;   Panel13: TPanel;   Panel14: TPanel;   Panel15: TPanel;
    Panel16: TPanel;   Panel17: TPanel;   Panel18: TPanel;   Panel19: TPanel;   Panel20: TPanel;
    Panel21: TPanel;   Panel22: TPanel;   Panel23: TPanel;   Panel24: TPanel;   Panel25: TPanel;
    Panel26: TPanel;
    Label1: TLabel;    Label2: TLabel;    Label3: TLabel;    Label4: TLabel;    Label5: TLabel;
    Label6: TLabel;    Label7: TLabel;    Label8: TLabel;
    sbRoteAugen: TSpeedButton;
    sbEmboss: TSpeedButton;
    SpeedButton9: TSpeedButton;
    SpeedButton10: TSpeedButton;
    SpeedButton11: TSpeedButton;
    sb12: TSpeedButton;
    sbWeichZeichnen: TSpeedButton;
    sbKonturen: TSpeedButton;
    SpeedButton15: TSpeedButton;
    SpeedButton16: TSpeedButton;
    SpeedButton17: TSpeedButton;
    sbSchaerfen: TSpeedButton;
    sbGraustufen: TSpeedButton;
    sbInvert: TSpeedButton;
    sbHelligkeit: TSpeedButton;
    sbKontrast: TSpeedButton;
    sbFarbePlusMinusR: TSpeedButton;
    sbHelligkeitPlus: TSpeedButton;
    sbRotateR90: TSpeedButton;
    sbRotateL90: TSpeedButton;
    sbRotate180: TSpeedButton;
    sbDrehen: TSpeedButton;
    SpeedButton29: TSpeedButton;
    SpeedButton30: TSpeedButton;
    sbRueckgaengig: TSpeedButton;
    sbZoomMinus: TSpeedButton;
    sb1Zu1: TSpeedButton;
    sbZoomAnpassen: TSpeedButton;
    sbZuschneiden: TSpeedButton;
    sbZoomPlus: TSpeedButton;
    sbSpeichernUnter: TSpeedButton;
    sbNeuLaden: TSpeedButton;
    sbSpeichernB: TSpeedButton;
    sbLaden: TSpeedButton;
    sbVomClipboard: TSpeedButton;
    sbInsClipboard: TSpeedButton;
    sbSpiegelnH: TSpeedButton;
    sbSpiegelnV: TSpeedButton;
    sbSpiegelbild: TSpeedButton;
    sbRaute: TSpeedButton;
    SpeedButton45: TSpeedButton;
    SpeedButton46: TSpeedButton;
    SpeedButton47: TSpeedButton;
    sbGroesse: TSpeedButton;
    sbSpeichern: TSpeedButton;
    sbDateiOptionen: TSpeedButton;
    sbAusschnittKopieren: TSpeedButton;
    sbPlusHintergrund: TSpeedButton;
    sbPlusRahmen: TSpeedButton;
    SpeedButton55: TSpeedButton;
    SpeedButton56: TSpeedButton;
    SpeedButton57: TSpeedButton;
    sbMonochrom: TSpeedButton;
    SavePictureDialog1: TSavePictureDialog;
    sbFarbePlusMinusG: TSpeedButton;
    sbFarbePlusMinusB: TSpeedButton;
    sbFarbePlusMinusW: TSpeedButton;
    sbNeuesBild: TSpeedButton;
    Image1: TImage;
    BtnAbbruch: TButton;
    Image2: TImage;
    OpenPictureDialog1: TOpenPictureDialog;
    Gauge1: TGauge;
    Edit1: TEdit;
    Image3: TImage;
    procedure FormShow(Sender: TObject);
    procedure ScrollBox1Resize(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Shape1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure Shape1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure Shape1MouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
    procedure Panel20Click(Sender: TObject);
    procedure sbSpeichernUnterMouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
    procedure sbGraustufenClick(Sender: TObject);
    procedure sbSpiegelnHClick(Sender: TObject);
    procedure sbRueckgaengigClick(Sender: TObject);
    procedure sbSpiegelnVClick(Sender: TObject);
    procedure sbRotate180Click(Sender: TObject);
    procedure sb1Zu1Click(Sender: TObject);
    procedure sbZoomAnpassenClick(Sender: TObject);
    procedure sbZoomPlusClick(Sender: TObject);
    procedure Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure Image1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure sbInvertClick(Sender: TObject);
    procedure sbZuschneidenClick(Sender: TObject);
    procedure BtnAbbruchClick(Sender: TObject);
    procedure sbRotateR90Click(Sender: TObject);
    procedure sbSpeichernClick(Sender: TObject);
    procedure sbDateiOptionenClick(Sender: TObject);
    procedure sbWeichZeichnenClick(Sender: TObject);
    procedure sbHelligkeitClick(Sender: TObject);
    procedure sbMonochromClick(Sender: TObject);
    procedure sbGroesseClick(Sender: TObject);
    procedure sbSchaerfenClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure sbSpeichernUnterClick(Sender: TObject);
    procedure sbSpeichernBClick(Sender: TObject);
    procedure sbHelligkeitPlusClick(Sender: TObject);
    procedure Shape11MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure sbKonturenClick(Sender: TObject);
    procedure sbKontrastClick(Sender: TObject);
    procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure SBEmbossClick(Sender: TObject);
    procedure sbSpiegelbildClick(Sender: TObject);
    procedure sbInsClipboardClick(Sender: TObject);
    procedure sbFarbePlusMinusRMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure sbLadenClick(Sender: TObject);
    procedure sbNeuesBildClick(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
    procedure sbPlusHintergrundClick(Sender: TObject);
    procedure sbPlusRahmenClick(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure sbDrehenClick(Sender: TObject);
    procedure sbRauteClick(Sender: TObject);
  private
    { Private-Deklarationen }
    Bmp1,Bmp2,Bmp3:TBitmap;
    Zoom,DateiSize,
    mb,mx,my,ms: integer;
  public
    { Public-Deklarationen }
    procedure DisplayHint(Sender: TObject);
    procedure ShowMark(Showit: boolean);
    procedure SetShapesFrom10;
    procedure SetShapes1011;
  end;

var
  bgstring: string;
  FormJVu: TFormJVu;

implementation

{$R *.DFM}

//##### Formular #####

procedure TFormJVu.FormCreate(Sender: TObject);
begin
  FormJVu.Caption:=paramstr(1);
  FormJVuBasics:=TFormJVuBasics.Create(Self);
  FormSpline:=TFormSpline.Create(Self);
  FormInput:=TFormInput.Create(Self);
  with FormJVuBasics.Memo1 do FormJVu.SetBounds(strtoint(Lines[0]),strtoint(Lines[1]),strtoint(Lines[2]),strtoint(Lines[3]));
  Bmp1:=TBitmap.Create;
  Bmp1.PixelFormat:=pf24bit;
  Bmp2:=TBitmap.Create;
  Bmp3:=TBitmap.Create;
  Zoom:=0;
  DateiSize:=0;
  GlobalGauge:=Gauge1;
  Application.OnHint:=DisplayHint;
  Scrollbox1.Brush.Bitmap:=Image2.Picture.Bitmap;
  bgstring:='';
end;

procedure TFormJVu.FormActivate(Sender: TObject);
begin
  if ParamCount > 1 then begin
    if ParamStr(2) = 'RotateR90' then begin
      sbRotateR90Click(sbRotateR90);
      sbSpeichernClick(Sender);
      FormJVu.Close;
    end;
    if ParamStr(2) = 'RotateL90' then begin
      sbRotateR90Click(sbRotateL90);
      sbSpeichernClick(Sender);
      FormJVu.Close;
    end;
    if ParamStr(2) = 'hg' then begin //überarbeiten
{
      bgstring:=extractfilepath(ParamStr(1))+'bg.jpg';
      sbPlusHintergrundClick(Sender);
      sbSpeichernClick(Sender);
}
      FormJVu.Close;
    end;
  end;
  bgstring:='';
end;

procedure TFormJVu.FormShow(Sender: TObject);
begin
  if Caption = '' then begin
    GlobalBmp.Assign(Image3.Picture.Bitmap);
    Caption:=extractfilepath(ParamStr(0))+'HRBG.bmp';
  end else BildLaden(Caption);
  Edit1.Text:=GlobalComment;
  DateiSize:=GlobalSize div 1024;
  Bmp1.Assign(GlobalBmp);
  Bmp1.PixelFormat:=pf24bit;
  BmpRueck.Assign(Bmp1);
  ScrollBox1.HorzScrollBar.Position:=0;
  ScrollBox1.VertScrollBar.Position:=0;
  ShowMark(false);
  mb:=0;
  ScrollBox1Resize(Sender);
  sbSpeichern.Enabled:=false;
end;

procedure TFormJVu.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  BtnAbbruchClick(Sender);
  FormJVuBasics.SaveJniPas(FormJVu.BoundsRect);
end;

procedure TFormJVu.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key = VK_F3 then sbSpeichernClick(Sender);
  if Key = VK_ESCAPE then Close;
  if Key = ord('C') then if ssCtrl in Shift then sbInsClipboardClick(sbInsClipboard);
  if Key = ord('V') then if ssCtrl in Shift then sbZuschneidenClick(sbVomClipboard);
  if Key = ord('Z') then if ssCtrl in Shift then sbRueckgaengigClick(Sender);
end;

procedure TFormJVu.DisplayHint(Sender: TObject);
begin
  Label7.Caption:=GetLongHint(Application.Hint);
end;

procedure TFormJVu.Edit1Change(Sender: TObject);
begin
  sbSpeichern.Enabled:=true;
end;

procedure TFormJVu.ScrollBox1Resize(Sender: TObject);
var sx,sy:integer;
begin
  if Bmp1 = nil then exit;
  if Bmp1.Width <= 0 then exit;
  sx:=ScrollBox1.HorzScrollBar.Position;
  sy:=ScrollBox1.VertScrollBar.Position;
  Image1.Visible:=false;
  ScrollBox1.HorzScrollBar.Position:=0;
  ScrollBox1.VertScrollBar.Position:=0;
  if Zoom = 0 then begin
    Image1.Width:=ScrollBox1.ClientWidth;
    Image1.Height:=trunc(Image1.Width*Bmp1.Height/Bmp1.Width);
    if Image1.Height > ScrollBox1.ClientHeight then begin
      Image1.Height:=ScrollBox1.ClientHeight;
      Image1.Width:=trunc(Image1.Height*Bmp1.Width/Bmp1.Height);
    end;
    Label2.Caption:='Zoom: '+inttostr(trunc(Image1.Width/Bmp1.Width*100))+'%';
  end;
  if Zoom > 0 then begin
    Image1.Width:=trunc(Bmp1.Width*Zoom/100);
    Image1.Height:=trunc(Bmp1.Height*Zoom/100);
    Label2.Caption:='Zoom: '+inttostr(Zoom)+'%';
  end;
  if Image1.Width >= ScrollBox1.ClientWidth then Image1.Left:=0 else
    Image1.Left:=(ScrollBox1.ClientWidth-Image1.Width) div 2;
  if Image1.Height >= ScrollBox1.ClientHeight then Image1.Top:=0 else
    Image1.Top:=(ScrollBox1.ClientHeight-Image1.Height) div 2;
  ScrollBox1.HorzScrollBar.Position:=sx;
  ScrollBox1.VertScrollBar.Position:=sy;
  Image1.Visible:=true;

  Image1.Picture.Bitmap.Width:=Image1.Width;
  Image1.Picture.Bitmap.Height:=Image1.Height;
  Image1.Canvas.StretchDraw(Image1.Clientrect,Bmp1);
  Label1.Caption:='Größe: '+inttostr(Bmp1.Width)+'*'+inttostr(Bmp1.Height);
  Label3.Caption:='Dateigröße: '+inttostr(DateiSize)+' kB';
  if Shape11.Visible then begin
    SetShapes1011;
    SetShapesFrom10;
  end;
end;

//##### Shapes und Abbruch für die Markierung #####

procedure TFormJVu.ShowMark(Showit: boolean);
begin
  Shape1.Visible:=Showit;  Shape2.Visible:=Showit;
  Shape3.Visible:=Showit;  Shape4.Visible:=Showit;
  Shape5.Visible:=Showit;  Shape6.Visible:=Showit;
  Shape7.Visible:=Showit;  Shape8.Visible:=Showit;
  Shape9.Visible:=Showit;  Shape11.Visible:=Showit;
end;

procedure TFormJVu.SetShapesFrom10;
begin
  Shape1.Left:=Shape10.Left;
  Shape1.Top:=Shape10.Top;
  Shape1.Width:=Shape10.Width;
  Shape1.Height:=Shape10.Height;
  Shape2.Left:=Shape10.Left; Shape2.Top:=Shape10.Top;
  Shape3.Left:=Shape10.Left+Shape10.Width-9; Shape3.Top:=Shape10.Top;
  Shape4.Left:=Shape10.Left+Shape10.Width-9; Shape4.Top:=Shape10.Top+Shape10.Height-9;
  Shape5.Left:=Shape10.Left; Shape5.Top:=Shape10.Top+Shape10.Height-9;
  Shape6.Left:=Shape10.Left+(Shape10.Width div 2)-4; Shape6.Top:=Shape10.Top;
  Shape7.Left:=Shape10.Left+Shape10.Width-9; Shape7.Top:=Shape10.Top+(Shape10.Height div 2)-4;
  Shape8.Left:=Shape10.Left+(Shape10.Width div 2)-4; Shape8.Top:=Shape10.Top+Shape10.Height-9;
  Shape9.Left:=Shape10.Left; Shape9.Top:=Shape10.Top+(Shape10.Height div 2)-4;
end;

procedure TFormJVu.SetShapes1011;
var x1,y1,x2,y2,d: integer;
begin
  d:=16;
  Shape11.Left:=Image1.Left;
  Shape11.Top:=Image1.Top;
  Shape11.Width:=Image1.Width;
  Shape11.Height:=Image1.Height;

  x1:=Image1.Left;   if x1 < 0 then x1:=0;
  y1:=Image1.Top;    if y1 < 0 then y1:=0;
  if (Shape10.Left < x1) or (Shape10.Left > x2-d) then Shape10.Left:=x1;
  if (Shape10.Top  < y1) or (Shape10.Top  > y2-d) then Shape10.Top:=y1;
  x1:=Shape10.Left;
  y1:=Shape10.Top;

  x2:=Image1.Width-x1;  if x2 > Scrollbox1.Width-x1 then x2:=Scrollbox1.Width-x1;
  y2:=Image1.Height-y1; if y2 > Scrollbox1.Height-y1 then y2:=Scrollbox1.Height-y1;

  if Shape10.Width > x2 then Shape10.Width:=x2;
  if Shape10.Height > y2 then Shape10.Height:=y2;

  if Shape10.Width < d then Shape10.Width:=d;
  if Shape10.Height < d then Shape10.Height:=d;
  Label7.Caption:=inttostr(Shape10.Width)+' x '+inttostr(Shape10.Height);
end;

procedure TFormJVu.Shape1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbLeft then mb:=1;
  if Button = mbRight then mb:=2;
  if ssCtrl in Shift then ms:=1 else ms:=0;
  mx:=x; my:=y;
  ShowMark(false);
  Shape10.Left:=Shape1.Left;
  Shape10.Top:=Shape1.Top;
  Shape10.Width:=Shape1.Width;
  Shape10.Height:=Shape1.Height;
  Shape10.Visible:=true;
  Label7.Caption:=inttostr(Shape10.Width)+' x '+inttostr(Shape10.Height);
end;

procedure TFormJVu.Shape1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var x0,y0,x1,y1,x2,y2:integer; zz:extended;
begin
  if Shape11.Tag = 2 then if ms = 1 then begin  //Bildausschnitt kopieren
    zz:=Bmp1.Width/Image1.Width;
    x0:=Round((Shape10.Left-Image1.Left)*zz);
    y0:=Round((Shape10.Top-Image1.Top)*zz);
    x1:=Round((Shape1.Left-Image1.Left)*zz);
    y1:=Round((Shape1.Top-Image1.Top)*zz);
    x2:=Round(Shape1.Width*zz);
    y2:=Round(Shape1.Height*zz);
    Bmp2.Assign(Bmp1);
    Bmp2.Width:=x2;
    Bmp2.Height:=y2;
    BitBlt(Bmp2.Canvas.Handle,0,0,x2,y2,Bmp1.Canvas.Handle,x1,y1,SRCCOPY);
    BitBlt(Bmp1.Canvas.Handle,x0,y0,x2,y2,Bmp2.Canvas.Handle,0,0,SRCCOPY);
    ScrollBox1Resize(Sender);
  end;
  mb:=0;
  SetShapesFrom10;
  ShowMark(true);
  Shape10.Visible:=false;
end;

procedure TFormJVu.Shape1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  if mb = 0 then exit;
  Shape10.Visible:=false;
  if (Sender as TShape) = Shape1 then begin
    Shape10.Left:=Shape1.Left+x-mx;
    Shape10.Top:=Shape1.Top+y-my;
  end;
  if (Sender as TShape) = Shape2 then begin
    Shape10.Left:=Shape1.Left+x-mx; Shape10.Top:=Shape1.Top+y-my;
    Shape10.Width:=Shape1.Width-x+mx; Shape10.Height:=Shape1.Height-y+my;
  end;
  if (Sender as TShape) = Shape3 then begin
    Shape10.Top:=Shape1.Top+y-my;
    Shape10.Width:=Shape1.Width+x-mx; Shape10.Height:=Shape1.Height-y+my;
  end;
  if (Sender as TShape) = Shape4 then begin
    Shape10.Width:=Shape1.Width+x-mx; Shape10.Height:=Shape1.Height+y-my;
  end;
  if (Sender as TShape) = Shape5 then begin
    Shape10.Left:=Shape1.Left+x-mx;
    Shape10.Width:=Shape1.Width-x+mx; Shape10.Height:=Shape1.Height+y-my;
  end;
  if (Sender as TShape) = Shape6 then begin
    Shape10.Top:=Shape1.Top+y-my; Shape10.Height:=Shape1.Height-y+my;
  end;
  if (Sender as TShape) = Shape7 then begin
    Shape10.Width:=Shape1.Width+x-mx;
  end;
  if (Sender as TShape) = Shape8 then begin
    Shape10.Height:=Shape1.Height+y-my;
  end;
  if (Sender as TShape) = Shape9 then begin
    Shape10.Left:=Shape1.Left+x-mx; Shape10.Width:=Shape1.Width-x+mx;
  end;
  if Shape10.Left < Shape11.Left+1 then Shape10.Left:=Shape11.Left+1;
  if Shape10.Top < Shape11.Top+1 then Shape10.Top:=Shape11.Top+1;
  if Shape10.Width > Shape11.Width-1 then Shape10.Width:=Shape11.Width-1;
  if Shape10.Height > Shape11.Height-1 then Shape10.Height:=Shape11.Height-1;
  if Shape10.Left+Shape10.Width > Shape11.Left+Shape11.Width-1 then Shape10.Left:=Shape11.Left+Shape11.Width-1-Shape10.Width;
  if Shape10.Top+Shape10.Height > Shape11.Top+Shape11.Height-1 then Shape10.Top:=Shape11.Top+Shape11.Height-1-Shape10.Height;
  Shape10.Visible:=True;
  Label7.Caption:=inttostr(Shape10.Width)+' x '+inttostr(Shape10.Height);
end;

procedure TFormJVu.Shape11MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var x1,y1,x2,y2,i,j,d,f,i1,i2,j1,j2:integer; zz:extended; P,P1: PByteArray;
begin
  BmpRueck.Assign(Bmp1);
  ScrollBox2.Enabled:=true;
  BtnAbbruch.Visible:=false;
  ShowMark(false);
  if Shape1.Width < 0 then begin
    Shape1.Width:=-Shape1.Width;
    Shape1.Left:=Shape1.Left-Shape1.Width;
  end;
  if Shape1.Width = 0 then Shape1.Width:=4;
  if Shape1.Height < 0 then begin
    Shape1.Height:=-Shape1.Height;
    Shape1.Top:=Shape1.Top-Shape1.Height;
  end;
  if Shape1.Height = 0 then Shape1.Height:=4;
  zz:=Bmp1.Width/Image1.Width;
  if Shape11.Tag = 0 then begin  //Bild zuschneiden
    x1:=Round((Shape1.Left-Image1.Left)*zz);
    y1:=Round((Shape1.Top-Image1.Top)*zz);
    x2:=Round(Shape1.Width*zz);
    y2:=Round(Shape1.Height*zz);
    Bmp1.Width:=x2;
    Bmp1.Height:=y2;
    StretchBlt(Bmp1.Canvas.Handle,0,0,x2,y2,BmpRueck.Canvas.Handle,x1,y1,x2,y2,SRCCOPY);
    ScrollBox1Resize(Sender);
  end;
  if Shape11.Tag = 1 then begin  //Rote Augen entfernen
    x1:=Round((Shape1.Left-Image1.Left)*zz);
    y1:=Round((Shape1.Top-Image1.Top)*zz);
    x2:=Round(Shape1.Width*zz);
    y2:=Round(Shape1.Height*zz);
    i1:=x1+x2; i2:=x1;
    j1:=y1+y2; j2:=y1;
    for j:=y1 to y1+y2 do begin
      P:=Bmp1.ScanLine[j];
      for i:=x1 to x1+x2 do begin
        if P[i*3+2] > 100 then if P[i*3+2] > P[i*3]+P[i*3+1] then begin
          P[i*3+2]:=P[i*3+2] div 5;
          P[i*3+1]:=P[i*3+1] div 3;
          P[i*3]:=P[i*3] div 3;
          if i < i1 then i1:=i;
          if j < j1 then j1:=j;
          if i > i2 then i2:=i;
          if j > j2 then j2:=j;
        end;
      end;
    end;
    dec(i1); if i1 < 0 then i1:=0;
    dec(j1); if j1 < 0 then j1:=0;
    inc(i2); if i2 > Bmp1.Width-1 then i2:=Bmp1.Width-1;
    inc(j2); if j2 > Bmp1.Height-1 then j2:=Bmp1.Height-1;
    for j:=j1 to j2-1 do begin
      P:=Bmp1.ScanLine[j];
      P1:=Bmp1.ScanLine[j+1];
      for i:=i1 to i2-1 do begin
        for f:=0 to 2 do begin
          d:=P[i*3+f]-P[(i+1)*3+f];
          if abs(d) > 40 then begin
            P[i*3+f]:=P[i*3+f]-(d div 2);
            P[(i+1)*3+f]:=P[(i+1)*3+f]+(d div 2);
          end;
          d:=P[i*3+f]-P1[i*3+f];
          if abs(d) > 40 then begin
            P[i*3+f]:=P[i*3+f]-(d div 2);
            P1[i*3+f]:=P1[i*3+f]+(d div 2);
          end;
        end;
      end;
    end;
    Image1.Canvas.StretchDraw(Image1.Clientrect,Bmp1);
  end;
  if Shape11.Tag = 3 then begin  //einfügen aus Clipboard
    Bmp2.Assign(Clipboard);
    x1:=Round((Shape1.Left-Image1.Left)*zz);
    y1:=Round((Shape1.Top-Image1.Top)*zz);
    x2:=Round(Shape1.Width*zz);
    y2:=Round(Shape1.Height*zz);
    j2:=GetStretchBltMode(Bmp1.Canvas.Handle);
    SetStretchBltMode(Bmp1.Canvas.Handle,HALFTONE);
    StretchBlt(Bmp1.Canvas.Handle,x1,y1,x2,y2,Bmp2.Canvas.Handle,0,0,Bmp2.Width,Bmp2.Height,SRCCOPY);
    SetStretchBltMode(Bmp1.Canvas.Handle,j2);
    ScrollBox1Resize(Sender);
  end;
  sbSpeichern.Enabled:=true;
end;

procedure TFormJVu.BtnAbbruchClick(Sender: TObject);
begin
  ScrollBox2.Enabled:=true;
  BtnAbbruch.Visible:=false;
  ShowMark(false);
end;

//##### Image-Mausbewegung #####

procedure TFormJVu.Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  mb:=1; mx:=x; my:=y;
end;

procedure TFormJVu.Image1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  mb:=0;
end;

procedure TFormJVu.Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var f,r,g,b:integer;
begin
  if mb = 0 then begin
    f:=GetPixel(Image1.Picture.Bitmap.Canvas.Handle,x,y);
    Panel26.Color:=f;
    r:=f and 255;
    g:=(f div 256) and 255;
    b:=(f div 65536) and 255;
    Label5.Caption:=Format('X:%4d  Y:%4d',[x,y]);
    Label4.Caption:=Format('R:%3d  G:%3d  B:%3d',[r,g,b]);
    Label6.Caption:=inttostr(ScrollBox1.HorzScrollBar.Position);
  end;
  if mb = 1 then begin
    ScrollBox1.HorzScrollBar.Position:=ScrollBox1.HorzScrollBar.Position-x+mx;
    ScrollBox1.VertScrollBar.Position:=ScrollBox1.VertScrollBar.Position-y+my;
  end;
end;

//##### Panels zeigen + Hints ausgeben #####

procedure TFormJVu.Panel20Click(Sender: TObject);
begin
  if (Sender as TPanel) = Panel23 then Panel24.Visible:=not(Panel24.Visible);
  if (Sender as TPanel) = Panel20 then Panel21.Visible:=not(Panel21.Visible);
  if (Sender as TPanel) = Panel17 then Panel18.Visible:=not(Panel18.Visible);
  if (Sender as TPanel) = Panel14 then Panel15.Visible:=not(Panel15.Visible);
  if (Sender as TPanel) = Panel11 then Panel12.Visible:=not(Panel12.Visible);
  if (Sender as TPanel) = Panel8 then Panel9.Visible:=not(Panel9.Visible);
  if (Sender as TPanel) = Panel5 then Panel6.Visible:=not(Panel6.Visible);
  if (Sender as TPanel) = Panel2 then Panel3.Visible:=not(Panel3.Visible);
end;

procedure TFormJVu.sbSpeichernUnterMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var z:string; i:integer;
begin
  if Sender is TSpeedButton then begin
    z:=(Sender as TSpeedButton).Hint;
    i:=(Sender as TSpeedButton).Parent.Tag;
  end;
  if Sender is TPanel then begin
    z:=(Sender as TPanel).Hint;
    i:=(Sender as TPanel).Tag;
  end;
  case i of
    0: Panel20.Caption:=GetShortHint(z);
    1: Panel17.Caption:=GetShortHint(z);
    2: Panel14.Caption:=GetShortHint(z);
    3: Panel11.Caption:=GetShortHint(z);
    4: Panel8.Caption:=GetShortHint(z);
    5: Panel5.Caption:=GetShortHint(z);
    6: Panel23.Caption:=GetShortHint(z);
  end;
end;

//##### Speichern und Laden #####

procedure TFormJVu.sbSpeichernUnterClick(Sender: TObject);
begin
  SavePictureDialog1.InitialDir:=ExtractFilePath(Caption);
  SavePictureDialog1.FileName:=ExtractFileName(Caption);
  if SavePictureDialog1.Execute then begin
    Caption:=SavePictureDialog1.FileName;
    if DateiTyp(Caption) = 0 then Caption:=Caption+'.jpg';
    sbSpeichernClick(Sender);
  end;
end;

procedure TFormJVu.sbSpeichernBClick(Sender: TObject);
begin
  Caption:=copy(Caption,1,length(Caption)-4);
  Caption:=Caption+'B.jpg';
  sbSpeichernClick(Sender);
end;

procedure TFormJVu.sbSpeichernClick(Sender: TObject);
begin
  GlobalBmp.Assign(Bmp1);
  GlobalComment:=Edit1.Text;
  BildSpeichern(Caption,FormInput.sbComp.Position);
  Bmp1.Assign(GlobalBmp);
  Bmp1.PixelFormat:=pf24bit;
  ScrollBox1Resize(Sender);
  sbSpeichern.Enabled:=false;
end;

procedure TFormJVu.sbDateiOptionenClick(Sender: TObject);
var i:Integer;
begin
  i:=FormInput.sbComp.Position;
  FormInput.PageControl1.ActivePage:=FormInput.TabSheet5;
  FormInput.TabSheet5.Visible:=true;
  if FormInput.ShowModal <> mrCancel then begin
    i:=FormInput.sbComp.Position;
    BmpRueck.Assign(Bmp1);
    GlobalJpg.Assign(Bmp1);
    GlobalJpg.CompressionQuality:=FormInput.sbComp.Position;
    GlobalJpg.Compress;
    GlobalJpg.Smoothing:=not GlobalJpg.Smoothing;
    Bmp1.Assign(GlobalJpg);
    ScrollBox1Resize(Sender);
    sbSpeichern.Enabled:=true;
  end;
  FormInput.sbComp.Position:=i;
end;

procedure TFormJVu.sbInsClipboardClick(Sender: TObject);
begin
  Clipboard.Assign(Bmp1);
end;

procedure TFormJVu.sbLadenClick(Sender: TObject);
begin
  OpenPictureDialog1.InitialDir:=ExtractFilePath(Caption);
  if not(OpenPictureDialog1.Execute) then exit;
  Caption:=OpenPictureDialog1.FileName;
  FormShow(Sender);
end;

procedure TFormJVu.sbNeuesBildClick(Sender: TObject);
begin
  Caption:=ExtractFilePath(Caption)+'Neu.JPG';
  Bmp1.Assign(Image1.Picture.Bitmap);
  Bmp1.PixelFormat:=pf24bit;
  Bmp1.Width:=1600;
  Bmp1.Height:=1200;
  BitBlt(Bmp1.Canvas.Handle,0,0,Bmp1.Width,Bmp1.Height,Bmp1.Canvas.Handle,0,0,WHITENESS);
  BmpRueck.Assign(Bmp1);
  ScrollBox1.HorzScrollBar.Position:=0;
  ScrollBox1.VertScrollBar.Position:=0;
  ShowMark(false);
  mb:=0;
  ScrollBox1Resize(Sender);
  sbSpeichern.Enabled:=false;
end;

//##### Bearbeiten, Ansicht #####

procedure TFormJVu.sbRueckgaengigClick(Sender: TObject);
begin
  Bmp1.Assign(BmpRueck);
  ScrollBox1Resize(Sender);
end;

procedure TFormJVu.sbZuschneidenClick(Sender: TObject);
begin
  ScrollBox2.Enabled:=false;
  BtnAbbruch.Visible:=true;
  SetShapes1011;
  SetShapesFrom10;
  ShowMark(true);
  Shape11.Tag:=(Sender as TSpeedButton).Tag;
end;

procedure TFormJVu.sbGroesseClick(Sender: TObject);
var b,h:integer;
begin
  FormInput.PageControl1.ActivePage:=FormInput.TabSheet6;
  FormInput.TabSheet6.Visible:=true;
  FormInput.Edit1.Text:=IntToStr(Bmp1.Width);
  FormInput.Edit2.Text:=IntToStr(Bmp1.Height);
  FormInput.Label15.Caption:=IntToStr(Bmp1.Width);
  FormInput.Label16.Caption:=IntToStr(Bmp1.Height);
  FormInput.sbZoom.Position:=100;
  FormInput.Label18.Caption:='100%';
  if FormInput.ShowModal <> mrCancel then begin
    BmpRueck.Assign(Bmp1);
    b:=strtoint(FormInput.edit1.text);
    h:=strtoint(FormInput.edit2.text);
    if b < 2 then b:=2;
    if h < 2 then h:=2;
    Bmp1.Width:=b;
    Bmp1.Height:=h;
    Bmp1.Canvas.StretchDraw(Rect(0,0,b,h),BmpRueck);
    ScrollBox1.VertScrollBar.Position:=0;
    ScrollBox1.HorzScrollBar.Position:=0;
    ScrollBox1Resize(Sender);
    sbSpeichern.Enabled:=true;
  end;
end;

procedure TFormJVu.sb1Zu1Click(Sender: TObject);
begin
  Zoom:=100;
  ScrollBox1.VertScrollBar.Position:=0;
  ScrollBox1.HorzScrollBar.Position:=0;
  ScrollBox1Resize(Sender);
end;

procedure TFormJVu.sbZoomAnpassenClick(Sender: TObject);
begin
  Zoom:=0;
  ScrollBox1.VertScrollBar.Position:=0;
  ScrollBox1.HorzScrollBar.Position:=0;
  ScrollBox1Resize(Sender);
end;

procedure TFormJVu.sbZoomPlusClick(Sender: TObject);
var n,i:integer;
begin
  ScrollBox1.VertScrollBar.Position:=0;
  ScrollBox1.HorzScrollBar.Position:=0;
  if Zoom = 0 then Zoom:=trunc(Image1.Width/Bmp1.Width*100);
  n:=0;
  for i:=0 to 19 do if ZoomInt[i] <= Zoom then n:=i;
  if (Sender as TSpeedButton) = sbZoomPlus then if n < 19 then Zoom:=ZoomInt[n+1];
  if (Sender as TSpeedButton) = sbZoomMinus then if n > 0 then Zoom:=ZoomInt[n-1];
  ScrollBox1Resize(Sender);
end;

//##### Drehen und Spiegeln #####

procedure TFormJVu.sbRotateR90Click(Sender: TObject);
var pp:array[0..2] of Point;
begin
  BmpRueck.Assign(Bmp1);
  Bmp1.Height:=BmpRueck.Width;
  Bmp1.Width:=BmpRueck.Height;
  Image1.Height:=Bmp1.Height;
  Image1.Width:=Bmp1.Width;
  if (Sender as TSpeedbutton) = sbRotateR90 then begin
    pp[0].x:=Bmp1.Width; pp[0].y:=0;
    pp[1].x:=Bmp1.Width; pp[1].y:=Bmp1.Height;
    pp[2].x:=0; pp[2].y:=0;
  end;
  if (Sender as TSpeedbutton) = sbRotateL90 then begin
    pp[0].x:=0; pp[0].y:=Bmp1.Height;
    pp[1].x:=0; pp[1].y:=0;
    pp[2].x:=Bmp1.Width; pp[2].y:=Bmp1.Height;
  end;
  if (Sender as TSpeedbutton) = sbRotate180 then begin
    pp[0].x:=Bmp1.Width; pp[0].y:=Bmp1.Height;
    pp[1].x:=0; pp[1].y:=Bmp1.Height;
    pp[2].x:=Bmp1.Width; pp[2].y:=0;
  end;
  PlgBlt(Bmp1.Canvas.Handle,pp,BmpRueck.Canvas.Handle,0,0,BmpRueck.Width,BmpRueck.Height,0,0,0);
  ScrollBox1Resize(Sender);
  sbSpeichern.Enabled:=true;
end;

procedure TFormJVu.sbRotate180Click(Sender: TObject);
begin
  BmpRueck.Assign(Bmp1);
  StretchBlt(Bmp1.Canvas.Handle,0,0,Bmp1.Width,Bmp1.Height,BmpRueck.Canvas.Handle,Bmp1.Width-1,Bmp1.Height-1,-Bmp1.Width,-Bmp1.Height,SRCCOPY);
  ScrollBox1Resize(Sender);
  sbSpeichern.Enabled:=true;
end;

procedure TFormJVu.sbSpiegelnHClick(Sender: TObject);
begin
  BmpRueck.Assign(Bmp1);
  StretchBlt(Bmp1.Canvas.Handle,0,0,Bmp1.Width,Bmp1.Height,BmpRueck.Canvas.Handle,Bmp1.Width-1,0,-Bmp1.Width,Bmp1.Height,SRCCOPY);
  ScrollBox1Resize(Sender);
  sbSpeichern.Enabled:=true;
end;

procedure TFormJVu.sbSpiegelnVClick(Sender: TObject);
begin
  BmpRueck.Assign(Bmp1);
  StretchBlt(Bmp1.Canvas.Handle,0,0,Bmp1.Width,Bmp1.Height,BmpRueck.Canvas.Handle,0,Bmp1.Height-1,Bmp1.Width,-Bmp1.Height,SRCCOPY);
  ScrollBox1Resize(Sender);
  sbSpeichern.Enabled:=true;
end;

procedure TFormJVu.sbSpiegelbildClick(Sender: TObject);
var x,y,f,n1,n2: Integer; P: PByteArray;
begin
  BmpRueck.Assign(Bmp1);
  Gauge1.Progress:=0;
  Gauge1.Visible:=true;
  for y:=0 to Bmp1.Height-1 do begin
    P:=Bmp1.ScanLine[y];
    for x:=0 to Bmp1.Width-1 do begin
      for f:=0 to 2 do begin
        n1:=x*3+f;
        n2:=(Bmp1.Width-1-x)*3+f;
        P[n1]:=(P[n1]+P[n2]) div 2; P[n2]:=P[n1];
      end;
    end;
    Gauge1.Progress:=Trunc(y/Bmp1.Height*100);
  end;
  ScrollBox1Resize(Sender);
  Gauge1.Visible:=false;
  sbSpeichern.Enabled:=true;
end;

procedure TFormJVu.sbDrehenClick(Sender: TObject);
begin
  with FormInput do begin
    Image1.Picture.Bitmap.canvas.StretchDraw(Image1.Clientrect,Bmp1);
    GlobalBmp.Assign(Image1.Picture.Bitmap);
    Image1b.Picture.Bitmap.Assign(Image1.Picture.Bitmap);
    PageControl1.ActivePage:=TabSheet4;
    MitVorschau:=true;
    TabSheet4.Visible:=true;
  end;
  if FormInput.ShowModal <> mrCancel then begin
    BmpRueck.Assign(Bmp1);
    Gauge1.Progress:=0;
    Gauge1.Visible:=true;
    GlobalBmp.Assign(Bmp1);
    BildDrehen(Bmp1,FormInput.sbDreh.Position,false);
    ScrollBox1Resize(Sender);
    Gauge1.Visible:=false;
    sbSpeichern.Enabled:=true;
  end;
end;

procedure TFormJVu.sbRauteClick(Sender: TObject);
begin
  with FormInput do begin
    Image1.Picture.Bitmap.canvas.StretchDraw(Image1.Clientrect,Bmp1);
    GlobalBmp.Assign(Image1.Picture.Bitmap);
    Image1b.Picture.Bitmap.Assign(Image1.Picture.Bitmap);
    PageControl1.ActivePage:=TabSheet4;
    MitVorschau:=true;
    TabSheet4.Visible:=true;
  end;
  if FormInput.ShowModal <> mrCancel then begin
    BmpRueck.Assign(Bmp1);
    Gauge1.Progress:=0;
    Gauge1.Visible:=true;
    GlobalBmp.Assign(Bmp1);
    BildDrehen(Bmp1,FormInput.sbDreh.Position,false);
    ScrollBox1Resize(Sender);
    Gauge1.Visible:=false;
    sbSpeichern.Enabled:=true;
  end;
end;

//##### Farbe, Helligkeit #####

procedure TFormJVu.sbHelligkeitClick(Sender: TObject);
begin
  FormInput.Image1.Picture.Bitmap.canvas.StretchDraw(FormInput.Image1.Clientrect,Bmp1);
  FormInput.Image1b.Picture.Bitmap.Assign(FormInput.Image1.Picture.Bitmap);
  FormInput.MitVorschau:=true;
  FormInput.PageControl1.ActivePage:=FormInput.TabSheet1;
  FormInput.TabSheet1.Visible:=true;
  if FormInput.ShowModal <> mrCancel then begin
    BmpRueck.Assign(Bmp1);
    FormInput.ChangeRGB(Bmp1,true);
    ScrollBox1Resize(Sender);
    sbSpeichern.Enabled:=true;
  end;
end;

procedure TFormJVu.sbHelligkeitPlusClick(Sender: TObject);
begin
  FormInput.Image1.Picture.Bitmap.canvas.StretchDraw(FormInput.Image1.Clientrect,Bmp1);
  FormInput.Image1b.Picture.Bitmap.Assign(FormInput.Image1.Picture.Bitmap);
  FormInput.PageControl1.ActivePage:=FormInput.TabSheet7;
  FormInput.MitVorschau:=true;
  FormInput.TabSheet7.Visible:=true;
  if FormInput.ShowModal <> mrCancel then begin
    BmpRueck.Assign(Bmp1);
    FormInput.DoRGB2(Bmp1,true);
    ScrollBox1Resize(Sender);
    sbSpeichern.Enabled:=true;
  end;
end;

procedure TFormJVu.sbMonochromClick(Sender: TObject);
var x,y,f: Integer; P: PByteArray;
begin
  BmpRueck.Assign(Bmp1);
  for y := 0 to Bmp1.height -1 do begin
    P := Bmp1.ScanLine[y];
    for x := 0 to Bmp1.width -1 do begin
      f:=(P[x*3]+P[x*3+1]+P[x*3+2]) div 3;
      if random(256) < f then f:=255 else f:=0;
      P[x*3]:=f; P[x*3+1]:=f; P[x*3+2]:=f;
    end;
  end;
  ScrollBox1Resize(Sender);
  sbSpeichern.Enabled:=true;
end;

procedure TFormJVu.sbGraustufenClick(Sender: TObject);
var x,y,f: Integer; P: PByteArray;
begin
  BmpRueck.Assign(Bmp1);
  Gauge1.Progress:=0;
  Gauge1.Visible:=true;
  for y := 0 to Bmp1.height -1 do begin
    P := Bmp1.ScanLine[y];
    for x := 0 to Bmp1.width -1 do begin
      f:=(P[x*3]+P[x*3+1]+P[x*3+2]) div 3;
      P[x*3]:=f; P[x*3+1]:=f; P[x*3+2]:=f;
    end;
    Gauge1.Progress:=Trunc(y/Bmp1.Height*100);
  end;
  ScrollBox1Resize(Sender);
  Gauge1.Visible:=false;
  sbSpeichern.Enabled:=true;
end;

procedure TFormJVu.sbKontrastClick(Sender: TObject);
begin
  FormInput.Image1.Picture.Bitmap.canvas.StretchDraw(FormInput.Image1.Clientrect,Bmp1);
  FormInput.Image1b.Picture.Bitmap.Assign(FormInput.Image1.Picture.Bitmap);
  FormInput.MitVorschau:=true;
  FormInput.PageControl1.ActivePage:=FormInput.TabSheet2;
  FormInput.TabSheet2.Visible:=true;
  if FormInput.ShowModal <> mrCancel then begin
    BmpRueck.Assign(Bmp1);
    FormInput.ChangeCS(Bmp1,true);
    ScrollBox1Resize(Sender);
    sbSpeichern.Enabled:=true;
  end;
end;

procedure TFormJVu.sbInvertClick(Sender: TObject);
begin
  BmpRueck.Assign(Bmp1);
  StretchBlt(Bmp1.Canvas.Handle,0,0,Bmp1.Width,Bmp1.Height,BmpRueck.Canvas.Handle,0,0,Bmp1.Width,Bmp1.Height,NOTSRCCOPY);
  ScrollBox1Resize(Sender);
  sbSpeichern.Enabled:=true;
end;

procedure TFormJVu.sbFarbePlusMinusRMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var z:string;
begin
  BmpRueck.Assign(Bmp1);
  z:=(Sender as TSpeedButton).Hint;
  with FormInput do begin
    Shape5.Left:=0; Shape5.Top:=100;
    if Button = mbLeft then begin
      Shape6.Left:=45; Shape6.Top:=45;
    end else begin
      Shape6.Left:=55; Shape6.Top:=55;
    end;
    Shape7.Left:=100; Shape7.Top:=0;
    cbRot.Checked:=false;
    cbGruen.Checked:=false;
    cbBlau.Checked:=false;
    if (pos('rot',z) > 0) or (pos('weiss',z) > 0)  then cbRot.Checked:=true;
    if (pos('grün',z) > 0) or (pos('weiss',z) > 0) then cbGruen.Checked:=true;
    if (pos('blau',z) > 0) or (pos('weiss',z) > 0) then cbBlau.Checked:=true;
    MakeSpline;
    DoRGB2(Bmp1,true);
  end;
  ScrollBox1Resize(Sender);
  sbSpeichern.Enabled:=true;
end;

//##### Filter #####

procedure TFormJVu.sbWeichZeichnenClick(Sender: TObject);
var x,y,f,n0,n1,n2: Integer; P0,P1,P2,P: PByteArray;
begin
  BmpRueck.Assign(Bmp1);
  Gauge1.Progress:=0;
  Gauge1.Visible:=true;
  for y:=0 to BmpRueck.Height -1 do begin
    P1:=BmpRueck.ScanLine[y];
    P:=Bmp1.ScanLine[y];
    if y > 0 then P0:=BmpRueck.ScanLine[y-1] else P0:=P1;
    if y < BmpRueck.Height -1 then P2:=BmpRueck.ScanLine[y+1] else P2:=P1;
    for x:=0 to BmpRueck.Width -1 do begin
      for f:=0 to 2 do begin
        n1:=x*3+f;
        if x > 0 then n0:=x*3-3+f else n0:=n1;
        if x < Bmp1.Width -1 then n2:=x*3+3+f else n2:=n1;
        P[n1]:=(P0[n0]+P0[n1]+P0[n2]+P1[n0]+P1[n1]+P1[n2]+P2[n0]+P2[n1]+P2[n2]) div 9;
      end;
    end;
    Gauge1.Progress:=Trunc(y/BmpRueck.Height*100);
  end;
  ScrollBox1Resize(Sender);
  Gauge1.Visible:=false;
  sbSpeichern.Enabled:=true;
end;

procedure TFormJVu.sbSchaerfenClick(Sender: TObject);
var x,y,f,n0,n1,n2,m: Integer; P0,P1,P2,P: PByteArray;
begin
  BmpRueck.Assign(Bmp1);
  Gauge1.Progress:=0;
  Gauge1.Visible:=true;
  for y:=0 to BmpRueck.Height -1 do begin
    P1:=BmpRueck.ScanLine[y];
    P:=Bmp1.ScanLine[y];
    if y > 0 then P0:=BmpRueck.ScanLine[y-1] else P0:=P1;
    if y < BmpRueck.Height -1 then P2:=BmpRueck.ScanLine[y+1] else P2:=P1;
    for x:=0 to BmpRueck.Width -1 do begin
      for f:=0 to 2 do begin
        n1:=x*3+f;
        if x > 0 then n0:=x*3-3+f else n0:=n1;
        if x < Bmp1.Width -1 then n2:=x*3+3+f else n2:=n1;
        m:=(P0[n0]+P0[n1]+P0[n2]+P1[n0]+P1[n2]+P2[n0]+P2[n1]+P2[n2]) div 8;
        m:=P1[n1]+(P1[n1]-m)*2;
        if m < 0 then m:=0;
        if m > 255 then m:=255;
        P[n1]:=m;
      end;
    end;
    Gauge1.Progress:=Trunc(y/BmpRueck.Height*100);
  end;
  ScrollBox1Resize(Sender);
  Gauge1.Visible:=false;
  sbSpeichern.Enabled:=true;
end;

procedure TFormJVu.sbKonturenClick(Sender: TObject);
var x,y,f,n0,n1,n2,m: Integer; P0,P1,P2,P: PByteArray;
begin
  BmpRueck.Assign(Bmp1);
  Gauge1.Progress:=0;
  Gauge1.Visible:=true;
  for y:=0 to BmpRueck.Height -1 do begin
    P1:=BmpRueck.ScanLine[y];
    P:=Bmp1.ScanLine[y];
    if y > 0 then P0:=BmpRueck.ScanLine[y-1] else P0:=P1;
    if y < BmpRueck.Height -1 then P2:=BmpRueck.ScanLine[y+1] else P2:=P1;
    for x:=0 to BmpRueck.Width -1 do begin
      for f:=0 to 2 do begin
        n1:=x*3+f;
        if x > 0 then n0:=x*3-3+f else n0:=n1;
        if x < Bmp1.Width -1 then n2:=x*3+3+f else n2:=n1;
        m:=(P0[n0]+P0[n1]+P0[n2]+P1[n0]+P1[n2]+P2[n0]+P2[n1]+P2[n2]) div 8;
        if abs(P1[n1]-m) > 5 then P[n1]:=0 else P[n1]:=255;
      end;
    end;
    Gauge1.Progress:=Trunc(y/BmpRueck.Height*100);
  end;
  ScrollBox1Resize(Sender);
  Gauge1.Visible:=false;
  sbSpeichern.Enabled:=true;
end;

//##### Spezialeffekte #####

procedure TFormJVu.SBEmbossClick(Sender: TObject);
var x,y,f,n0,n1,n2,f1,f2,ff: Integer; P0,P1,P2,P: PByteArray;
begin
  BmpRueck.Assign(Bmp1);
  Gauge1.Progress:=0;
  Gauge1.Visible:=true;
  for y:=0 to BmpRueck.Height-1 do begin
    P:=Bmp1.ScanLine[y];
    P1:=BmpRueck.ScanLine[y];
    if y > 0 then P0:=BmpRueck.ScanLine[y-1] else P0:=P1;
    if y < BmpRueck.Height-1 then P2:=BmpRueck.ScanLine[y+1] else P2:=P1;
    for x:=0 to BmpRueck.Width-1 do begin
      for f:=0 to 2 do begin
        n1:=x*3+f;
        if x > 0 then n0:=n1-1 else n0:=n1;
        if x < BmpRueck.Width-1 then n2:=n1+1 else n2:=n1;
        f1:=P0[n1]+P1[n0];
        f2:=P2[n1]+P1[n2];
        ff:=(f2-f1) div 2;
        if ff < 0 then ff:=0;
        if ff > 255 then ff:=255;
        P[n1]:=128+ff;
      end;
      ff:=P[x*3]+P[x*3+1]+P[x*3+2]-255;
      if ff < 0 then ff:=0;
      if ff > 255 then ff:=255;
      for f:=0 to 2 do P[x*3+f]:=ff;
    end;
    Gauge1.Progress:=Trunc(y/Bmp1.Height*100);
  end;
  ScrollBox1Resize(Sender);
  Gauge1.Visible:=false;
  sbSpeichern.Enabled:=true;
end;

//##### Zeichnen, Malen, Text #####

procedure TFormJVu.sbPlusHintergrundClick(Sender: TObject);
var i,j,k,m,i2,j2:integer; b1,b2:byte; z:string; p1,p2:PByteArray;
    f:single;
begin
  if bgstring = '' then begin
    OpenPictureDialog1.InitialDir:=ExtractFilePath(Caption);
    if not(OpenPictureDialog1.Execute) then exit;
    z:=OpenPictureDialog1.FileName;
  end else z:=bgstring;
  BildLaden(z);
  Bmp2.Assign(GlobalBmp);
  Bmp2.PixelFormat:=pf24bit;
  BmpRueck.Assign(Bmp1);
  for j:=0 to bmp1.height-1 do begin
    p1:=Bmp1.ScanLine[j];
    j2:=j mod Bmp2.Height;
    p2:=Bmp2.ScanLine[j2];
    for i:=0 to bmp1.Width-1 do begin
      i2:=i mod Bmp2.Width;
      for k:=0 to 2 do begin
        b1:=p1[i*3+k];
        b2:=255-p2[i2*3+k];
        f:=b1/255;
        m:=b1-trunc(b2*f);
        if m < 0 then p1[i*3+k]:=0 else p1[i*3+k]:=m;
      end;
    end;
  end;
  ScrollBox1Resize(Sender);
  sbSpeichern.Enabled:=true;
end;

procedure TFormJVu.sbPlusRahmenClick(Sender: TObject);
var rb,sb,vb,fr,fg,fb,i,j,i2,j2,h,r,d,b,m,n,dreh: integer; p1,p2,p3: PByteArray;
    ff: boolean; cd,sd,x,y,dx,dy,sx,sy: double;
begin
  with FormInput do begin
    b:=Image1.Width;
    h:=Image1.Height;
    if cbhg.Checked then begin
      if Edit3.Text = '' then GlobalBmp.Assign(FormJVuBasics.ImageHG.Picture.Bitmap) else
      if FileExists(Edit3.Text) then BildLaden(Edit3.Text);
      Image1b.Picture.Bitmap.Assign(GlobalBmp);
      Image1.Picture.Bitmap.Canvas.StretchDraw(Rect(0,0,b,h),Image1b.Picture.Bitmap);
    end;
    MitVorschau:=cbhg.Checked;
    PageControl1.ActivePage:=TabSheet3;
    TabSheet3.Visible:=true;
  end;
  if FormInput.ShowModal <> mrCancel then begin
    BmpRueck.Assign(Bmp1);
    if FormInput.cbhg.Checked then Bmp3.Assign(FormInput.Image1b.Picture.Bitmap);
    rb:=FormInput.seRB.Value; //Rahmenbreite
    sb:=FormInput.seSB.Value; //Schattenbreite
    vb:=FormInput.seVB.Value; //Verlauf
    fr:=FormInput.seFR.Value; //Rahmenfarbe
    dreh:=FormInput.seDreh.Value; //Drehwinkel
    fg:=FormInput.seFG.Value;
    fb:=FormInput.seFB.Value;
    if fr = 255 then if fg = 255 then if fb = 255 then begin
      fr:=254; fg:=254; fb:=254;
    end;
    if rb > 0 then begin //Rahmen hinzufügen
      Bmp1.Width:=Bmp1.Width+2*rb;
      Bmp1.Height:=Bmp1.Height+2*rb;
      Bmp1.Canvas.Brush.Color:=$02000000+fb*256*256+fg*256+fr;
      Bmp1.Canvas.FillRect(Rect(0,0,Bmp1.Width,Bmp1.Height));
      Bmp1.Canvas.Draw(rb,rb,BmpRueck);
    end;
    for j:=0 to Bmp1.Height-1 do begin //Weiß im Bild um 1 abdunkeln
      p1:=Bmp1.ScanLine[j];
      for i:=0 to Bmp1.Width-1 do begin
        if p1[i*3]+p1[i*3+1]+p1[i*3+2] = 765 then begin
          p1[i*3]:=254; p1[i*3+1]:=254; p1[i*3+2]:=254;
        end;
      end;
    end;
    if FormInput.cbz.Checked then begin //zerfusseln
      Bmp1.Canvas.Pen.Color:=$02ffffff; //weiß zerfusselt drumrum malen
      h:=rb div 3;
      for i:=0 to Bmp1.Width-1 do begin
        if i = 0 then j:=0 else j:=r;
        r:=random(6);
        if r = 0 then if j <> 1 then if h > 1 then dec(h);
        if r = 1 then if j <> 0 then if h < rb div 2 then inc(h);
        Bmp1.Canvas.MoveTo(i,0);
        Bmp1.Canvas.LineTo(i,h);
      end;
      for i:=0 to Bmp1.Width-1 do begin
        if i = 0 then j:=0 else j:=r;
        r:=random(6);
        if r = 0 then if j <> 1 then if h > 1 then dec(h);
        if r = 1 then if j <> 0 then if h < rb div 2 then inc(h);
        Bmp1.Canvas.MoveTo(i,Bmp1.Height-1);
        Bmp1.Canvas.LineTo(i,Bmp1.Height-1-h);
      end;
      for i:=0 to Bmp1.Height-1 do begin
        if i = 0 then j:=0 else j:=r;
        r:=random(6);
        if r = 0 then if j <> 1 then if h > 1 then dec(h);
        if r = 1 then if j <> 0 then if h < rb div 2 then inc(h);
        Bmp1.Canvas.MoveTo(0,i);
        Bmp1.Canvas.LineTo(h,i);
      end;
      for i:=0 to Bmp1.Height-1 do begin
        if i = 0 then j:=0 else j:=r;
        r:=random(6);
        if r = 0 then if j <> 1 then if h > 1 then dec(h);
        if r = 1 then if j <> 0 then if h < rb div 2 then inc(h);
        Bmp1.Canvas.MoveTo(Bmp1.Width-1,i);
        Bmp1.Canvas.LineTo(Bmp1.Width-1-h,i);
      end;
    end;
    GlobalBmp.Assign(Bmp1);
    BildDrehen(Bmp1,dreh,false);
    Bmp1.Canvas.Brush.Color:=$02ffffff;
    Bmp1.Width:=Bmp1.Width+sb+vb;      //Bmp1 für Schatten vergrößern
    Bmp1.Height:=Bmp1.Height+sb+vb;
    Bmp2.Assign(Bmp1);
    for j:=0 to Bmp2.Height-1 do begin //Bmp2=Maske: Bild schwarz, Rand weiß
      p1:=Bmp2.ScanLine[j];
      for i:=0 to Bmp2.Width-1 do begin
        if p1[i*3]+p1[i*3+1]+p1[i*3+2] < 765 then begin
          p1[i*3]:=0; p1[i*3+1]:=0; p1[i*3+2]:=0;
        end;
      end;
    end;
    if sb+vb > 0 then begin //Schattenbereich hinzufügen
      j2:=160 div (vb+1); j2:=j2 div (vb+1);
      if j2 = 0 then j2:=1;
      for m:=0 to vb-1 do for n:=0 to vb-1 do begin
        if n*m > (vb-1)*(vb-1) then ff:=false else ff:=true;
        if ff then for j:=0 to Bmp2.Height-sb-vb-1 do begin //Schatten zeichnen
          p1:=Bmp1.ScanLine[j+sb+m];
          p2:=Bmp2.ScanLine[j];
          p3:=Bmp2.ScanLine[j+sb+m];
          for i:=0 to Bmp2.Width-sb-vb-1 do begin
            i2:=(i+sb+n)*3;
            if p3[i2]+p3[i2+1]+p3[i2+2] = 765 then
             if p2[i*3]+p2[i*3+1]+p2[i*3+2] = 0 then begin
              p1[i2]:=p1[i2]-j2;
              p1[i2+1]:=p1[i2+1]-j2;
              p1[i2+2]:=p1[i2+2]-j2;
            end;
          end;
        end;
      end;
    end;
    if FormInput.cbhg.Checked then begin //Hintergrundbild aufaddieren
      for j:=0 to Bmp1.Height-1 do begin
        p1:=Bmp1.ScanLine[j];
        p2:=Bmp2.ScanLine[j];
        j2:=j mod Bmp3.Height;
        p3:=Bmp3.ScanLine[j2];
        for i:=0 to Bmp1.Width-1 do begin
          if p2[i*3]+p2[i*3+1]+p2[i*3+2] > 0 then begin
            i2:=i mod Bmp3.Width;
            if p1[i*3]+p3[i2*3] >= 255 then p1[i*3]:=p1[i*3]-255+p3[i2*3] else p1[i*3]:=0;
            if p1[i*3+1]+p3[i2*3+1] >= 255 then p1[i*3+1]:=p1[i*3+1]-255+p3[i2*3+1] else p1[i*3+1]:=0;
            if p1[i*3+2]+p3[i2*3+2] >= 255 then p1[i*3+2]:=p1[i*3+2]-255+p3[i2*3+2] else p1[i*3+2]:=0;
          end;
        end;
      end;
    end;
    if FormInput.cbGlatt.Checked then for j:=0 to Bmp1.Height-2 do begin //Glätten
      p1:=Bmp1.ScanLine[j];
      p2:=Bmp1.ScanLine[j+1];
      for i:=0 to Bmp1.Width-2 do begin
        p1[i*3]:=round(p1[i*3]*0.25+p1[(i+1)*3]*0.25+p2[i*3]*0.25+p2[(i+1)*3]*0.25);
        p1[i*3+1]:=round(p1[i*3+1]*0.25+p1[(i+1)*3+1]*0.25+p2[i*3+1]*0.25+p2[(i+1)*3+1]*0.25);
        p1[i*3+2]:=round(p1[i*3+2]*0.25+p1[(i+1)*3+2]*0.25+p2[i*3+2]*0.25+p2[(i+1)*3+2]*0.25);
      end;
    end;
    ScrollBox1.VertScrollBar.Position:=0;
    ScrollBox1.HorzScrollBar.Position:=0;
    ScrollBox1Resize(Sender);
    sbSpeichern.Enabled:=true;
  end;
end;

end.

// Image1.Picture.Bitmap nicht vergrößern, dann reicht auch der Speicherplatz!
// Beim zuschneiden keinen rahmen vorgeben, sondern aufziehen

