Index: fviewer.lfm
===================================================================
--- fviewer.lfm	(revision 6394)
+++ fviewer.lfm	(working copy)
@@ -2406,6 +2406,14 @@
         Caption = 'Stretch'
         OnClick = miStretchClick
       end
+      object miStretchOnlyLarge: TMenuItem
+        Caption = 'Stretch only large'
+        OnClick = miStretchOnlyLargeClick
+      end
+      object miCenter: TMenuItem
+        Caption = 'Center'
+        OnClick = miCenterClick
+      end
       object miRotate: TMenuItem
         Caption = 'Rotate'
         object mi90: TMenuItem
Index: fviewer.lrt
===================================================================
--- fviewer.lrt	(revision 6394)
+++ fviewer.lrt	(working copy)
@@ -57,6 +57,8 @@
 TFRMVIEWER.MIENCODING.CAPTION=En&coding
 TFRMVIEWER.MIIMAGE.CAPTION=&Image
 TFRMVIEWER.MISTRETCH.CAPTION=Stretch
+TFRMVIEWER.MISTRETCHONLYLARGE.CAPTION=Stretch only large
+TFRMVIEWER.MICENTER.CAPTION=Center
 TFRMVIEWER.MIROTATE.CAPTION=Rotate
 TFRMVIEWER.MI90.CAPTION=+ 90
 TFRMVIEWER.MI180.CAPTION=+ 180
Index: fviewer.pas
===================================================================
--- fviewer.pas	(revision 6394)
+++ fviewer.pas	(working copy)
@@ -146,6 +146,8 @@
     miExit: TMenuItem;
     miImage: TMenuItem;
     miStretch: TMenuItem;
+    miStretchOnlyLarge: TMenuItem;
+    miCenter: TMenuItem;
     miText: TMenuItem;
     miBin: TMenuItem;
     miHex: TMenuItem;
@@ -216,6 +218,8 @@
       Shift: TShiftState);
     procedure miExitClick(Sender: TObject);
     procedure miStretchClick(Sender: TObject);
+    procedure miStretchOnlyLargeClick(Sender: TObject);
+    procedure miCenterClick(Sender: TObject);
     procedure miTextClick(Sender: TObject);
     procedure miAbout2Click(Sender: TObject);
     procedure miSearchClick(Sender: TObject);
@@ -226,6 +230,8 @@
     procedure miChangeEncodingClick(Sender:TObject);
     procedure ViewerPositionChanged(Sender:TObject);
     procedure miRotateClick(Sender: TObject);
+    function  PluginShowFlags : Integer;
+    procedure UpdateImagePlacement;
 
   private
     FileList: TStringList;
@@ -436,8 +442,6 @@
 end;
 
 procedure TfrmViewer.LoadNextFile(const aFileName: String);
-var
-  ShowFlags: Integer;
 begin
   if bPlugin then
     with WlxPlugins.GetWlxModule(ActivePlugin) do
@@ -444,8 +448,7 @@
     begin
       if FileParamVSDetectStr(aFileName, False) then
       begin
-        ShowFlags:= IfThen(miStretch.Checked, lcp_fittowindow, 0);
-        if CallListLoadNext(Self.Handle, aFileName, ShowFlags) <> LISTPLUGIN_ERROR then
+        if CallListLoadNext(Self.Handle, aFileName, PluginShowFlags) <> LISTPLUGIN_ERROR then
           Exit;
       end;
     end;
@@ -878,10 +881,6 @@
   btnReload.Visible:=not(miFullScreen.Checked);
   Status.Visible:=not(miFullScreen.Checked);
   gboxSlideShow.Visible:=miFullScreen.Checked;
-
-  Image.Stretch:= miFullScreen.Checked;
-  Image.AutoSize:= not Image.Stretch;
-  Image.Proportional:= Image.Stretch;
   AdjustImageSize;
   ShowOnTop;
 end;
@@ -1012,14 +1011,18 @@
   EndY:=0;
 end;
 
+function TfrmViewer.PluginShowFlags : Integer;
+begin
+  Result:= IfThen(miStretch.Checked, lcp_fittowindow, 0) or
+           IfThen(miCenter.Checked, lcp_center, 0) or
+           IfThen(miStretchOnlyLarge.Checked, lcp_fitlargeronly, 0)
+end;
+
 function TfrmViewer.CheckPlugins(const sFileName: String; bForce: Boolean = False): Boolean;
 var
   I: Integer;
-  ShowFlags: Integer;
   WlxModule: TWlxModule;
 begin
-  ShowFlags:= IfThen(bForce, lcp_forceshow, 0);
-  ShowFlags:= ShowFlags or IfThen(miStretch.Checked, lcp_fittowindow, 0);
   // DCDebug('WlXPlugins.Count = ' + IntToStr(WlxPlugins.Count));
   for I:= 0 to WlxPlugins.Count - 1 do
   if WlxPlugins.GetWlxModule(I).FileParamVSDetectStr(sFileName, bForce) then
@@ -1028,7 +1031,7 @@
     if not WlxPlugins.LoadModule(I) then Continue;
     WlxModule:= WlxPlugins.GetWlxModule(I);
     DCDebug('WlxModule.Name = ', WlxModule.Name);
-    if WlxModule.CallListLoad(Self.Handle, sFileName, ShowFlags) = 0 then
+    if WlxModule.CallListLoad(Self.Handle, sFileName, IfThen(bForce, lcp_forceshow, 0) or PluginShowFlags) = 0 then
     begin
       WlxModule.UnloadModule;
       Continue;
@@ -1147,9 +1150,6 @@
 procedure TfrmViewer.miZoomClick(Sender: TObject);
 begin
   miStretch.Checked := false;
-  Image.Stretch:=true;
-  Image.Proportional:=true;
-  Image.AutoSize := false;
   if (sender=miZoomIn) or (sender=btnZoomIn)
   then
     begin
@@ -1299,6 +1299,8 @@
 begin
   CloseAction:=caFree;
   gImageStretch:= miStretch.Checked;
+  gImageStretchOnlyLarge:= miStretchOnlyLarge.Checked;
+  gImageCenter:= miCenter.Checked;
   gPreviewVisible := miPreview.Checked;
   gImagePaintMode := ComboBoxPaint.text;
   gImagePaintWidth := StrToInt(ComboBoxWidth.Text) ;
@@ -1353,32 +1355,40 @@
   Close;
 end;
 
-procedure TfrmViewer.miStretchClick(Sender: TObject);
-var
-  ShowFlags: Integer;
+procedure TfrmViewer.UpdateImagePlacement;
 begin
-  miStretch.Checked:= not miStretch.Checked;
   if bImage then
   begin
-    Image.Stretch:= miStretch.Checked;
-    Image.AutoSize:= not Image.Stretch;
-    Image.Proportional:= Image.Stretch;
-    if gboxHightlight.Visible then UndoTmp;
-    if miStretch.Checked then
-      begin
-        gboxPaint.Visible:=false;
-        gboxHightlight.Visible:=false;
-        gboxView.Visible:=true;
-      end;
+    if gboxHightlight.Visible then 
+    begin
+      gboxPaint.Visible:=false;
+      gboxHightlight.Visible:=false;
+      gboxView.Visible:=true;
+      UndoTmp;
+    end;
     AdjustImageSize;
   end
   else if bPlugin then
-  begin
-    ShowFlags:= IfThen(miStretch.Checked, lcp_fittowindow, 0);
-    WlxPlugins.GetWLxModule(ActivePlugin).CallListSendCommand(lc_newparams, ShowFlags)
-  end;
+    WlxPlugins.GetWLxModule(ActivePlugin).CallListSendCommand(lc_newparams , PluginShowFlags)
 end;
 
+procedure TfrmViewer.miStretchClick(Sender: TObject);
+begin
+  miStretch.Checked:= not miStretch.Checked;
+  UpdateImagePlacement;
+end;
+procedure TfrmViewer.miCenterClick(Sender: TObject);
+begin
+   miCenter.Checked:= not miCenter.Checked;
+   UpdateImagePlacement;
+end;
+
+procedure TfrmViewer.miStretchOnlyLargeClick(Sender: TObject);
+begin
+  miStretchOnlyLarge.Checked:= not miStretchOnlyLarge.Checked;
+  UpdateImagePlacement;
+end;
+
 procedure TfrmViewer.miTextClick(Sender: TObject);
 begin
   ExitPluginMode;
@@ -1447,14 +1457,16 @@
   
   sboxImage.DoubleBuffered := True;
   miStretch.Checked := gImageStretch;
+  miStretchOnlyLarge.Checked := gImageStretchOnlyLarge;
+  miCenter.Checked := gImageCenter;
   miPreview.Checked := gPreviewVisible;
   ComboBoxPaint.Text := gImagePaintMode;
   ComboBoxWidth.Text := IntToStr(gImagePaintWidth);
   ColorBoxPaint.Selected := gImagePaintColor;
 
-  Image.Stretch:= miStretch.Checked;
-  Image.AutoSize:= not Image.Stretch;
-  Image.Proportional:= Image.Stretch;
+  Image.Stretch:= True;
+  Image.AutoSize:= False;
+  Image.Proportional:= False;
   Image.SetBounds(0, 0, sboxImage.ClientWidth, sboxImage.ClientHeight);
 
   FThumbSize := gThumbSize;
@@ -1723,67 +1735,43 @@
 // Adjust Image size (width and height) to sboxImage size
 procedure TfrmViewer.AdjustImageSize;
 const
-  fmtImageInfo = '%s (%s %%)';
+  fmtImageInfo = '%dx%d (%.0f %%)';
 var
-  sResolution: String;
-  iScale: Integer = 0;
+  dScaleFactor : Double = 1.0;
+  var iLeft,iTop,iWidth,iHeight : integer;
 begin
-  if miStretch.Checked then
-     begin
-       Image.Stretch:= True;
-       Image.AutoSize:= True;
-       Image.Center:= True;
-       if (Image.Picture.Width > sboxImage.ClientWidth) or (Image.Picture.Height > sboxImage.ClientHeight) then
-         begin
-           Image.AutoSize := False;
-           Image.SetBounds(0, 0, sboxImage.ClientWidth, sboxImage.ClientHeight);
-           sboxImage.HorzScrollBar.Visible:= False;
-           sboxImage.VertScrollBar.Visible:= False;
-           // show image resolution and scale
-           if Image.Picture.Width < Image.Width then
-             begin
-             iScale:= 100*(Image.Picture.Width * Image.ClientHeight) div (Image.Picture.Width* Image.Picture.Height);
-             sResolution:= IntToStr(Image.Picture.Width) + 'x' + IntToStr(Image.Height);
-             end;
-           if Image.Picture.Height < Image.Height then
-             begin
-              iScale:= 100*(Image.ClientWidth * Image.Picture.Height) div (Image.Picture.Width* Image.Picture.Height);
-              sResolution:= IntToStr(Image.Width) + 'x' + IntToStr(Image.Picture.Height);
-             end;
-           if (Image.Picture.Width >= Image.Width) and  (Image.Picture.Height >= Image.Height) then
-             begin
-              iScale:= 100*(Image.Width * Image.Height) div (Image.Picture.Width* Image.Picture.Height);
-              sResolution:= IntToStr(Image.Width) + 'x' + IntToStr(Image.Height);
-             end;
-           Status.Panels[sbpCurrentResolution].Text:= Format(fmtImageInfo, [sResolution, IntToStr(iScale)]);
-           sResolution:= IntToStr(Image.Picture.Width) + 'x' + IntToStr(Image.Picture.Height);
-           Status.Panels[sbpFullResolution].Text:= Format(fmtImageInfo, [sResolution, '100']);
-         end
-       else
-         begin
-           Image.Left:= (sboxImage.ClientWidth-Image.Picture.Width) div 2;        //move image to center
-           Image.Top:=  (sboxImage.ClientHeight-Image.Picture.Height) div 2;
-           sResolution:= IntToStr(Image.Picture.Width) + 'x' + IntToStr(Image.Picture.Height);
-           Status.Panels[sbpCurrentResolution].Text:= Format(fmtImageInfo, [sResolution, '100']);
-           Status.Panels[sbpFullResolution].Text:= Status.Panels[2].Text;
-         end;
-     end
+  // Place and resize image
+  if (miStretch.Checked) then
+  begin
+    dScaleFactor:= Min(sboxImage.ClientWidth / Image.Picture.Width ,sboxImage.ClientHeight / Image.Picture.Height);
+    dScaleFactor:= IfThen((miStretchOnlyLarge.Checked) and (dScaleFactor > 1.0), 1.0, dScaleFactor);
+  end;
+
+  iWidth:= trunc(Image.Picture.Width * dScaleFactor);
+  iHeight:= trunc(Image.Picture.Height * dScaleFactor);
+  if (miCenter.Checked) then
+  begin
+    iLeft:= (sboxImage.ClientWidth - iWidth) div 2;
+    iTop:= (sboxImage.ClientHeight - iHeight) div 2;
+  end
   else
-    begin
-      // show image resolution and scale
-      Image.Left:= 0;
-      Image.Top:= 0;
-      Image.Stretch:= False;
-      Image.AutoSize:= True;
-      sboxImage.HorzScrollBar.Visible:= Image.Width > sboxImage.ClientWidth;
-      sboxImage.VertScrollBar.Visible:= Image.Height > sboxImage.ClientHeight;
-      if (Image.Picture.Width <> 0) and (Image.Picture.Height <> 0) then
-        iScale:= 100 * (Image.Width * Image.Height) div (Image.Picture.Width * Image.Picture.Height);
-      sResolution:= IntToStr(Image.Width) + 'x' + IntToStr(Image.Height);
-      Status.Panels[sbpCurrentResolution].Text:= Format(fmtImageInfo, [sResolution, IntToStr(iScale)]);
-      sResolution:= IntToStr(Image.Picture.Width) + 'x' + IntToStr(Image.Picture.Height);
-      Status.Panels[sbpFullResolution].Text:= Format(fmtImageInfo, [sResolution, '100']);
-    end;
+  begin
+    iLeft:= 0;
+    iTop:= 0;
+  end;
+  Image.SetBounds(Max(iLeft,0), Max(iTop,0), iWidth , iHeight);
+
+  // Update scrollbars
+  //TODO: fix - calculations are correct but it seems like scroll bars
+  // are being updated only after a second call to Form.Resize
+  if (iLeft < 0) then
+    sboxImage.HorzScrollBar.Position:= -iLeft;
+  if (iTop < 0) then
+    sboxImage.VertScrollBar.Position:= -iTop;
+
+  // Update status bar
+  Status.Panels[sbpCurrentResolution].Text:= Format(fmtImageInfo, [iWidth,iHeight,  100.0 * dScaleFactor]);
+  Status.Panels[sbpFullResolution].Text:= Format(fmtImageInfo, [Image.Picture.Width,Image.Picture.Height, 100.0]);
 end;
 
 // Try to rotate image
@@ -2170,18 +2158,15 @@
 
 procedure TfrmViewer.cm_LoadNextFile(const Params: array of string);
 var
-  I, ShowFlags: Integer;
+  I : Integer;
 begin
   I:= iActiveFile + 1;
   if I >= FileList.Count then
     I:= 0;
 
-  if bPlugin then
-    begin
-      ShowFlags:= IfThen(miStretch.Checked, lcp_fittowindow, 0);
-      if WlxPlugins.GetWlxModule(ActivePlugin).CallListLoadNext(Self.Handle, FileList[I], ShowFlags) <> LISTPLUGIN_ERROR then
-        Exit;
-    end;
+  if (bPlugin)
+    And (WlxPlugins.GetWlxModule(ActivePlugin).CallListLoadNext(Self.Handle, FileList[I], PluginShowFlags) <> LISTPLUGIN_ERROR) then
+      Exit;
   ExitPluginMode;
   if pnlPreview.Visible then
     begin
@@ -2198,18 +2183,15 @@
 
 procedure TfrmViewer.cm_LoadPrevFile(const Params: array of string);
 var
-  I, ShowFlags: Integer;
+  I: Integer;
 begin
   I:= iActiveFile - 1;
   if I < 0 then
     I:= FileList.Count - 1;
+  if (bPlugin)
+      And (WlxPlugins.GetWlxModule(ActivePlugin).CallListLoadNext(Self.Handle, FileList[I], PluginShowFlags) <> LISTPLUGIN_ERROR) then
+        Exit;
 
-  if bPlugin then
-    begin
-      ShowFlags:= IfThen(miStretch.Checked, lcp_fittowindow, 0);
-      if WlxPlugins.GetWlxModule(ActivePlugin).CallListLoadNext(Self.Handle, FileList[I], ShowFlags) <> LISTPLUGIN_ERROR then
-        Exit;
-    end;
   if pnlPreview.Visible then
     begin
       if DrawPreview.Col = 0  then
Index: uglobs.pas
===================================================================
--- uglobs.pas	(revision 6394)
+++ uglobs.pas	(working copy)
@@ -403,6 +403,8 @@
   {Viewer}
   gPreviewVisible,
   gImageStretch: Boolean;
+  gImageStretchOnlyLarge: Boolean;
+  gImageCenter: Boolean;
   gCopyMovePath1,
   gCopyMovePath2,
   gCopyMovePath3,
@@ -1343,6 +1345,8 @@
 
   {Viewer}
   gImageStretch := False;
+  gImageStretchOnlyLarge := False;
+  gImageCenter := True;
   gPreviewVisible := False;
   gCopyMovePath1 := '';
   gCopyMovePath2 := '';
@@ -1904,6 +1908,8 @@
   gCutTextToColWidth := gIni.ReadBool('Configuration', 'CutTextToColWidth', True);
 
   gImageStretch:=  gIni.ReadBool('Viewer', 'Image.Stretch', False);
+  gImageStretchOnlyLarge:=  gIni.ReadBool('Viewer', 'Image.StretchLargeOnly', False);
+  gImageCenter:=  gIni.ReadBool('Viewer', 'Image.Center', True);
 
   { Operations options }
   gOperationOptionSymLinks := TFileSourceOperationOptionSymLink(
@@ -2423,6 +2429,8 @@
     if Assigned(Node) then
     begin
       gImageStretch := GetValue(Node, 'ImageStretch', gImageStretch);
+      gImageStretchOnlyLarge := GetValue(Node, 'ImageStretchLargeOnly', gImageStretchOnlyLarge);
+      gImageCenter := GetValue(Node, 'ImageCenter', gImageCenter);
       gPreviewVisible := GetValue(Node, 'PreviewVisible', gPreviewVisible);
       gCopyMovePath1 := GetValue(Node, 'CopyMovePath1', gCopyMovePath1);
       gCopyMovePath2 := GetValue(Node, 'CopyMovePath2', gCopyMovePath2);
@@ -2810,6 +2818,8 @@
     Node := FindNode(Root, 'Viewer',True);
     SetValue(Node, 'PreviewVisible',gPreviewVisible);
     SetValue(Node, 'ImageStretch',gImageStretch);
+    SetValue(Node, 'ImageStretchLargeOnly',gImageStretchOnlyLarge);
+    SetValue(Node, 'ImageCenter',gImageCenter);
     SetValue(Node, 'CopyMovePath1', gCopyMovePath1);
     SetValue(Node, 'CopyMovePath2', gCopyMovePath2);
     SetValue(Node, 'CopyMovePath3', gCopyMovePath3);
