![]()  | 
	
 
  | 
		
			
  | 	
	
	
		
		|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны | 
![]()  | 
	
	
| 
		 | 
	Опции темы | Поиск в этой теме | Опции просмотра | 
| 
		 
			 
			#1  
			
			
			
			
		 
		
		
	 | 
||||
		
		
  | 
||||
| 
	
	
		
			
			 Сабж в том, что мне надо отмасштабировать изображение под размер формы без изменения пропорций. 
		
	
		
		
		
		
			
		
		
		
		
	
		
		
	
	
	Изображение должно занимать всю форму (рамок по краям быть не должно), но и в то же время быть в наименьшем масштабе (не должно улезать за края там, где этого можно избежать). Известны размеры изображения, и размеры прямоугольника, который надо заполнить. Вопрос - по какой формуле можно пересчитать размеры, и как растянуть/сжать и обрезать изображение без особых потерь качества? Можете просто записать пересчёт математически, подгоню сам. Для примера, изображение 1280х800 надо вписать в 800х600.  | 
| 
		 
			 
			#2  
			
			
			
			
		 
		
		
	 | 
||||
		
		
  | 
||||
| 
	
	
		
			
			 А в чем подвох? Для TImage два свойства выставить в истину. Proportional и Stretch. 
		
	
		
		
		
		
			
		
		
		
		
	
		
		
	
	
	 | 
| 
		 
			 
			#3  
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
| 
	
	
		
			
			 Где-то я встречал алгоритмы (в виде готовых процедур) "сжатия" картинок. 
		
	
		
		
		
		
		
	
		
		
	
	
	С объяснениями ... Но хоть убейте - не могу вспомнить, где. То ли в Инете. То ли в книжке. Пороюсь сегодня-завтра. Если найду - кину ссылку.  | 
| 
		 
			 
			#4  
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
| 
	
	
		
			
			 Вот какой-то старый (в библах нашелся). 
		
	
		
		
		
		
		
	
		
		
	
	
	Но не помню, насколько он эффективен. Код: 
	function ResizeBMP_to_small(BMP0 : TBitmap; Kx :  real) : boolean;
//Масштабирование (уменьшение) BitMap
Type
  TRGBTripleArray = array[word] of TRGBTriple;
  pRGBTripleArray = ^TRGBTripleArray;
Var
  BMP_x:  TBitMap;
  Yes : byte;
  kkk : integer;
  i            :  integer;
  j            :  integer;
  lookup       :  integer;
  RowIn        :  pRGBTripleArray;
  RowOut       :  pRGBTripleArray;
begin
  Result:=FALSE;
  Yes:=0;
  if Kx>=0.9999999999 then begin
     if BMP0<>NIL then begin
        if BMP0.Width>0 then begin
           if BMP0.Height>0 then begin
              if round(Kx)<BMP0.Width then begin
                 if round(Kx)<BMP0.Height then begin
                    Yes:=1;
                 end;
              end;
           end;
        end;
     end;
     if Yes>0 then begin
        //ShowMessage('1');
        BMP_x := TBitmap.Create;
        TRY
          BMP_x.Width  := round(BMP0.Width  / Kx);
          BMP_x.Height := round(BMP0.Height / Kx);
          BMP_x.PixelFormat := pf24bit;
          for j := 0 to (BMP_x.Height-1) do
           begin
            kkk:=round(Kx*j);
            RowIn  := BMP0.Scanline[kkk];
            RowOut := BMP_x.Scanline[j];
            for i := 0 to (BMP_x.Width-1) do
             begin
              lookup := round(Kx*i);
              RowOut[i] := RowIn[lookup];
            end;
          end;
          BMP0.Assign(BMP_x);
          Result:=TRUE;
        FINALLY
          BMP_x.Free;
        END;
     end;
  end;
end;
 | 
| 
		 
			 
			#5  
			
			
			
			
		 
		
		
	 | 
||||
		
		
  | 
||||
| 
	
	
		
			
			 Вот: 
		
	
		
		
		
		
			
		
		
		
		
		
			Код: 
	procedure DrawBitmaptRect(dc : hdc; bmp : HBITMAP; Rect : TRect);
var
  cdc : HDC;
  bInfo : TBitmapInfo;
  prevSetStretchBltMode : Integer;
  dx, dy, dr : Double;
  BitmapCx, BitmapCy : Integer;
  ClipCx, ClipCy : Integer;
  OffsX, OffxY : Integer; 
begin
  cdc := CreateCompatibleDC(dc);
  SelectObject(cdc, bmp);
  GetObject(bmp, SizeOf(bInfo), @Binfo);
  ClipCx := Rect.Right - Rect.Left;
  ClipCy := Rect.Bottom - Rect.Top;
  OffsX := Rect.Left;
  OffxY := Rect.Top;
  BitmapCx := Binfo.bmiHeader.biWidth;
  BitmapCy := bInfo.bmiHeader.biHeight;
  //Считаем оптимальный размер
  if (BitmapCx > ClipCx)or(BitmapCy > ClipCy) then
  begin
    dx := ClipCx / BitmapCx;
    dy := ClipCy / BitmapCy;
    //dr := min(dx, dy);
    if dx < dy then dr := dx else dr := dy;
    Rect.Right := Trunc(BitmapCx * dr);
    Rect.Bottom := Trunc(BitmapCY * dr);
  end
    else
  begin
    Rect.Right := BitmapCx;
    Rect.Bottom := BitmapCy;
  end;
  //Центрируес
  Rect.Left := (ClipCx - Rect.Right) div 2;
  Rect.Top := (ClipCy - Rect.Bottom) div 2;
  OffsetRect(Rect, OffsX, OffxY);
  //Рисуем со сглаживанием
  prevSetStretchBltMode := SetStretchBltMode(dc, HALFTONE);
  with Rect do
    StretchBlt(dc,
      Left, Top, Right - OffsX, Bottom - OffxY,
      cdc,
      0, 0, BitmapCx, BitmapCy,
      SRCCOPY);
    SetStretchBltMode(dc, prevSetStretchBltMode);
  DeleteDC(cdc);
end;Рисуй так Код: 
	DrawBitmaptRect(Canvas.Handle, Bitmap.Handle, GetClientRect); Последний раз редактировалось 0nni, 20.09.2009 в 20:23.  | 
| 
		 
			 
			#6  
			
			
			
			
		 
		
		
	 | 
||||
		
		
  | 
||||
| 
	
	
		
			
			 Цитата: 
	
 0nni, Код: 
	procedure LoadMainBack;
var
  sr:TSearchRec;
  path: string;
  i:integer;
  dat: TStringList;
  r:TRect;
begin
  dat:=TStringList.Create;
  path:=ExtractFilePath(ParamStr(0))+'load\';
  i:=FindFirst(path+'*.jpg',faAnyFile xor faDirectory,sr);
  while i=0 do begin
    i:=FindNext(sr);
    dat.Add(path+sr.Name);
  end;
  FindClose(sr);
  i:=FindFirst(path+'*.jpeg',faAnyFile xor faDirectory,sr);
  while i=0 do begin
    i:=FindNext(sr);
    dat.Add(path+sr.Name);
  end;
  FindClose(sr);
  i:=FindFirst(path+'*.bmp',faAnyFile xor faDirectory,sr);
  while i=0 do begin
    i:=FindNext(sr);
    dat.Add(path+sr.Name);
  end;
  FindClose(sr);
  frmMain.Image1.Picture.RegisterFileFormat('.jpg','JPEG Image',TJPEGImage);
  frmMain.Image1.Picture.RegisterFileFormat('.jpeg','JPEG Image',TJPEGImage);
  frmMain.Image1.Picture.LoadFromFile(dat[Random(dat.Count-1)]);
  GetClientRect(frmMain.Handle,r);
  DrawBitmaptRect(frmMain.Canvas.Handle, frmMain.Image1.Picture.Bitmap.Handle, r);
  dat.Clear;
  dat.Free;
end;Последний раз редактировалось PhoeniX, 20.09.2009 в 19:44.  | 
| 
		 
			 
			#7  
			
			
			
			
		 
		
		
	 | 
||||
		
		
  | 
||||
| 
	
	
		
			
			 Ну, если без рамок, то потеряются пропорции, либо придется отсекать часть изображения. 
		
	
		
		
		
		
			
		
		
		
		
		
			_______________ Можешь взять мой код и заменить Код: 
	    dx := ClipCx / BitmapCx;
    dy := ClipCy / BitmapCy;
    //dr := min(dx, dy);
    if dx > dy then dr := dx else dr := dy; //<<< эту строчку
    Rect.Right := Trunc(BitmapCx * dr);
    Rect.Bottom := Trunc(BitmapCY * dr);Тогда будет обрезать, но вписывать Последний раз редактировалось 0nni, 20.09.2009 в 19:45.  | 
| 
		 
			 
			#8  
			
			
			
			
		 
		
		
	 | 
||||
		
		
  | 
||||
| 
	
	
		
			
			 Вот, изначально говорилось - надо без рамок, можно отсекать. 
		
	
		
		
		
		
			
		
		
		
		
	
		
		
	
	
	Но тем не менее, даже Код: 
	procedure LoadMainBack;
var
  sr:TSearchRec;
  path: string;
  i:integer;
  dat: TStringList;
  r:TRect;
  j: TJPEGImage;
  b: TBitmap;
begin
  dat:=TStringList.Create;
  path:=ExtractFilePath(ParamStr(0))+'load\';
  i:=FindFirst(path+'*.jpg',faAnyFile xor faDirectory,sr);
  while i=0 do begin
    i:=FindNext(sr);
    dat.Add(path+sr.Name);
  end;
  FindClose(sr);
  j:=TJPEGImage.Create;
  j.LoadFromFile(dat[Random(dat.Count-1)]);
  b:=TBitmap.Create;
  b.Assign(j);
  GetClientRect(frmMain.Handle,r);
  DrawBitmaptRect(frmMain.Image1.Picture.Bitmap.Canvas.Handle, b.Handle, r);
  dat.Clear;
  dat.Free;
end; | 
| 
		 
			 
			#9  
			
			
			
			
		 
		
		
	 | 
||||
		
		
  | 
||||
| 
	
	
		
			
			 Цитата: 
	
 Либо обрезать часть изображения, либо будут рамки по краям, других вариантов вроде не придумано.  | 
| 
		 
			 
			#10  
			
			
			
			
		 
		
		
	 | 
||||
		
		
  | 
||||
| 
	
	
		
			
			 Обрезать, я ж изначально сказал! 
		
	
		
		
		
		
			
		
		
		
		
	
		
		
	
	
	 | 
| 
		 
			 
			#11  
			
			
			
			
		 
		
		
	 | 
||||
		
		
  | 
||||
| 
	
	
		
			
			 Воспользуйся регионами: 
		
	
		
		
		
		
			
		
		
		
		
	
		
		
	
	
	Код: 
	unit mAIN;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtDlgs;
type
  TForm1 = class(TForm)
    OpenPictureDialog1: TOpenPictureDialog;
    procedure FormClick(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    bmp : TBitmap;
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
procedure DrawBitmaptRect(dc : hdc; bmp : HBITMAP; Rect : TRect);
var
  cdc : HDC;
  bInfo : TBitmapInfo;
  prevSetStretchBltMode : Integer;
  dx, dy, dr : Double;
  BitmapCx, BitmapCy : Integer;
  ClipCx, ClipCy : Integer;
  OffsX, OffxY : Integer; 
begin
  cdc := CreateCompatibleDC(dc);
  SelectObject(cdc, bmp);
  GetObject(bmp, SizeOf(bInfo), @Binfo);
  ClipCx := Rect.Right - Rect.Left;
  ClipCy := Rect.Bottom - Rect.Top;
  OffsX := Rect.Left;
  OffxY := Rect.Top;
  BitmapCx := Binfo.bmiHeader.biWidth;
  BitmapCy := bInfo.bmiHeader.biHeight;
  //Считаем оптимальный размер
  if (BitmapCx > ClipCx)or(BitmapCy > ClipCy) then
  begin
    dx := ClipCx / BitmapCx;
    dy := ClipCy / BitmapCy;
    //dr := min(dx, dy);
    //if dx < dy then dr := dx else dr := dy;
    if dx > dy then dr := dx else dr := dy;
    Rect.Right := Trunc(BitmapCx * dr);
    Rect.Bottom := Trunc(BitmapCY * dr);
  end
    else
  begin
    Rect.Right := BitmapCx;
    Rect.Bottom := BitmapCy;
  end;
  //Центрируес
  Rect.Left := (ClipCx - Rect.Right) div 2;
  Rect.Top := (ClipCy - Rect.Bottom) div 2;
  OffsetRect(Rect, OffsX, OffxY);
  //Рисуем со сглаживанием
  prevSetStretchBltMode := SetStretchBltMode(dc, HALFTONE);
  with Rect do
    StretchBlt(dc,
      Left, Top, Right - OffsX, Bottom - OffxY,
      cdc,
      0, 0, BitmapCx, BitmapCy,
      SRCCOPY);
    SetStretchBltMode(dc, prevSetStretchBltMode);
  DeleteDC(cdc);
end;
procedure TForm1.FormClick(Sender: TObject);
begin
  if not OpenPictureDialog1.Execute then exit;
  bmp.LoadFromFile(OpenPictureDialog1.FileName);
  Caption := OpenPictureDialog1.FileName + ' - zeView';
  Invalidate;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
  sz : TSize;
  Str : string;
begin
  bmp := TBitmap.Create;
  str := 'Click to open bitmap file...';
  GetTextExtentPoint32(bmp.Canvas.Handle, Pchar(str), Length(str), sz);
  bmp.Width := sz.cx;
  bmp.Height := sz.cy;
  bmp.Canvas.TextOut(0, 0, str);
  DoubleBuffered := true;
  OpenPictureDialog1.Filter := '*.bmp|*.bmp';
  Caption := 'zeView';
end;
procedure TForm1.FormPaint(Sender: TObject);
var
  ClipRgn : HRGN;
  Rt : TRect;
begin
  //Моя функция не образает т.к. по логике изображение не выходит
  //за граници прямоугольника
  //в твоем случае такая логика не работает, поэтому
  //можно использовать регионы
  Rt := rect(8, 8, ClientWidth - 8, ClientHeight - 8);
  ClipRgn := CreateRectRgn(8, 8, ClientWidth - 8, ClientHeight - 8);
  SelectClipRgn(Canvas.Handle, ClipRgn);
  DrawBitmaptRect(Canvas.Handle, bmp.Handle, rt);
  SelectClipRgn(Canvas.Handle, 0);
  DeleteObject(ClipRgn);
end;
procedure TForm1.FormResize(Sender: TObject);
begin
  Invalidate;
end;
end. | 
| 
		 
			 
			#12  
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
| 
	
	
		
			
			 "Хорошая болезнь склероз. Ничего не болит и каждый день новости ...". 
		
	
		
		
		
		
		
	
		
		
	
	
	Или : "Я вспомнил, группен-фюрер, я все вспомнил" - повторял Штирлиц, сидя на металлической, привинченной к полу кровати в подвале гестапо, при этом изображая честную уверенность в себе" ... :-) Вот в этом файле (DRKB3_Full.chm), который должен быть на http://www.drkb.ru/ (DRKB Explorer), есть раздел "Графические фильтры и эффекты". Там есть ряд алгоритмов, ориентированных на ReSize изображений ...  |