2009-12-29 9 views
14

Я использую Delphi 2009, и я хотел бы масштабировать изображение в соответствии с доступным пространством. изображение всегда отображается меньше оригинала. проблема заключается в том, что свойство TImage Stretch не делает приятной работы и вредит читаемости изображения.Хорошо масштабировать изображение в Delphi?

ugly way http://xrw.bc.ca/download/so/TImageStretch.gif

Я хотел бы, чтобы он масштабируется, как это вместо:

nicer way http://xrw.bc.ca/download/so/NicerTImageStretch.png

Любые предложения, как лучше это сделать? Пробовал JVCL, но он, похоже, не обладает этой способностью. Бесплатная библиотека была бы неплохой, но, возможно, есть недорогая библиотека, которая делает «только», это было бы хорошо.

ответ

14

Если вы вернетесь к использованию вызовов Win32 API, вы можете использовать SetStretchBltMode для HALFTONE и использовать StretchBlt. Я не уверен, если это предусмотрено с использованием дефолтных вызовов по умолчанию, но я так и решаю эту проблему.

Update (2014-09) Только теперь я был в подобной ситуации (снова) и имел TImage в TScrollBox с многими другим происходят в форме, и действительно хотел Image1.Stretch:=true; сделать полутона. Как указывает Rob, TBitmap.Draw использует только HALFTONE , когда холст назначения составляет 8 бит на пиксель или ниже, а у холста источника больше ... Поэтому я «исправил» его с назначением Image1.Picture.Bitmap:

TBitmapForceHalftone=class(TBitmap) 
protected 
    procedure Draw(ACanvas: TCanvas; const Rect: TRect); override; 
end; 

{ TBitmapForceHalftone } 

procedure TBitmapForceHalftone.Draw(ACanvas: TCanvas; const Rect: TRect); 
var 
    p:TPoint; 
    dc:HDC; 
begin 
    //not calling inherited; here! 
    dc:=ACanvas.Handle; 
    GetBrushOrgEx(dc,p); 
    SetStretchBltMode(dc,HALFTONE); 
    SetBrushOrgEx(dc,p.x,p.y,@p); 
    StretchBlt(dc, 
    Rect.Left,Rect.Top, 
    Rect.Right-Rect.Left,Rect.Bottom-Rect.Top, 
    Canvas.Handle,0,0,Width,Height,ACanvas.CopyMode); 
end; 
+0

спасибо; это обеспечило хорошую сбалансированность скорости и качества. –

+3

Delphi автоматически устанавливает режим растягивания в полутоновый режим, если количество бит-за-пиксел места назначения для места размещения меньше или равно 8, а количество бит-на-пиксель исходного растрового изображения больше, чем место назначения. В противном случае он использует Stretch_DeleteScans для цветовых растровых изображений. –

+0

спасибо, грабли. Мне нужно было всегда использовать HALFTONE. Кстати, благодарю вас за то, что вы сделали много хорошего в переполнении стека. –

31

Вы действительно, действительно хотите использовать Graphics32.

procedure DrawSrcToDst(Src, Dst: TBitmap32); 
var 
    R: TKernelResampler; 
begin 
    R := TKernelResampler.Create(Src); 
    R.Kernel := TLanczosKernel.Create; 
    Dst.Draw(Dst.BoundsRect, Src.BoundsRect, Src); 
end; 

У вас есть несколько методов и фильтров для выбора при повторной выборке изображения. В приведенном выше примере используется ядро ​​resampler (вроде медленное, но с большими результатами) и фильтр Lanczos в качестве ядра восстановления. Вышеприведенный пример должен работать на вас.

+1

Это классный инструмент, но я нашел его слишком медленным для того, что мне нужно. теперь, когда у меня это есть, я уверен, что буду использовать его для чего-то другого. Спасибо! –

+0

Отлично - однако, если вы находите это медленным, я в основном склонен думать, что что-то не так где-то в другом месте. В любом случае, рад, что вы нашли хорошее решение для своей проблемы! –

+2

Возможно, это было медленным для него, потому что он делал быстрые обновления каждую секунду? У меня была такая же проблема с производительностью, и это было на Intel Quad Core I5 ​​с большим количеством памяти.Я переключился с повторного использования ядра на черновик (TDraftResampler), и проблема с производительностью исчезла. В случае с моим приложением я обновлял изображение 1100w x 1100h 20 раз в секунду, а затем уменьшал дискретизацию, а ядро ​​Lanczos было слишком медленным, чтобы не отставать. Спасибо за отзыв о библиотеке Graphics32. Это настоящее благословение, и это действительно помогло улучшить внешний вид моего понижающего изображения. –

6

Вы можете попробовать встроенный в Delphi ScaleImage из GraphUtil

+0

спасибо за отзыв - я не знал о ScaleImage! –

3

Я использую класс GDIPOB.pas в TGPGraphics

если Холст TGPGraphics, Bounds является TGPRectF и NewImage является TGPImage экземпляр:

Canvas.SetInterpolationMode(InterpolationModeHighQualityBicubic); 
Canvas.SetSmoothingMode(SmoothingModeHighQuality); 
Canvas.DrawImage(NewImage, Bounds, 0, 0, NewImage.GetWidth, NewImage.GetHeight, UnitPixel); 

Вы можете выбрать качество VS коэффициент скорости путем изменения режима интерполяции

InterpolationModeDefault    = QualityModeDefault; 
InterpolationModeLowQuality   = QualityModeLow; 
InterpolationModeHighQuality   = QualityModeHigh; 
InterpolationModeBilinear   = 3; 
InterpolationModeBicubic    = 4; 
InterpolationModeNearestNeighbor  = 5; 
InterpolationModeHighQualityBilinear = 6; 
InterpolationModeHighQualityBicubic = 7; 

и режим smooting:

SmoothingModeDefault  = QualityModeDefault; 
SmoothingModeHighSpeed = QualityModeLow; 
SmoothingModeHighQuality = QualityModeHigh; 
SmoothingModeNone  = 3; 
SmoothingModeAntiAlias = 4; 

ПРИМЕЧАНИЕ: Это потребует XP или более поздней версии или в gdiplus.dll соединение в пучки в вашем установщике.

Смежные вопросы