如何实现可调整(1-100)的抖动算法?(50分)

  • 主题发起人 主题发起人 kiss2
  • 开始时间 开始时间
K

kiss2

Unregistered / Unconfirmed
GUEST, unregistred user!
就象Photoshop中的那个
 
没人知道?
 
大哥,太高深啦,什么叫抖动算法啊,先说来听听吧,或许可以帮你想想
 
其中著名的抖动算法有Floyed-Steinberg、Stucki、Burkes等
但是我只要能可调整(0-100, 0表示不抖动)的抖动算法,不管是什么类型的
 
我以前编过抖动处理,主要是为了在DOS下黑白打印机打印彩色图片,可惜
源代码找不到了,那是94年编的了,我现在还可惜当时的程序没有保留下来
 
高深啊,各位富翁,以后要向你们多多请教!
 
关注。
高手很多啊,希望能早日看到答案。
 
Floyd-Steinberg Dithering

Classical Algorithm - Developed Algorithms


This technique generates the best results of any classical method here, and is naturally the slowest. In fact, there are many variants of this technique as well, and the better they get, the slower they are.

The Floyd-Steinberg dithering algorithm is based on error dispersion. The error dispersion technique is very simple to describe: for each point in the image, first find the closest color available. Calculate the difference between the value in the image and the color you have. Now divide up these error values and distribute them over the neighboring pixels which you have not visited yet. When you get to these later pixels, just add the errors distributed from the earlier ones, clip the values to the allowed range if needed, then continue as above.

If you are dithering a grayscale image for output to a black-and-white device, the "find closest color" is just a simple thresholding operation. In color, it involves matching the input color to the closest available hardware color, which can be difficult depending on the hardware palette.

There are many ways to distribute the errors and many ways to scan the image, but I will deal here with only a few. The two basic ways to scan the image are with a normal left-to-right, top-to-bottom raster, or with an alternating left-to-right then right-to-left raster. The latter method generally produces fewer artifacts and can be used with all the error diffusion patterns discussed below.

The different ways of dividing up the error can be expressed as patterns (called filters, for reasons too boring to go into here).

X 7 This is the Floyd and Steinberg

3 5 1 error diffusion filter.



In this filter, the X represents the pixel you are currently scanning, and the numbers (called weights, for equally boring reasons) represent the proportion of the error distributed to the pixel in that position. Here, the pixel immediately to the right gets 7/16 of the error (the divisor is 16 because the weights add to 16), the pixel directly below gets 5/16 of the error, and the diagonally adjacent pixels get 3/16 and 1/16. When scanning a line right-to-left, this pattern is reversed. This pattern was chosen carefully so that it would produce a checkerboard pattern in areas with intensity of 1/2 (or 128 in our image). It is also fairly easy to calculate when the division by 16 is replaced by shifts.


 
Average Dithering

Classical Algorithm - Developed Algorithms


The Average Dithering is a basic two-level algorithm for halftone image. It consists in choosing a certain constant gray level, in particular the average value of image pixels, and using it as a global threshold in deciding whether a pixel should be quantized to 0 or to 1. All pixels whose intensity level lies above the average value (the threshold) are quantized to 1; all others get a value of 0.

This method is simple to implement but it has a disadvantage: quantization contouring is quite perceptible

 
Ordered Dithering

Classical Algorithm - Developed Algorithms


We can express the patterns in compact form as the order of dots added:

8 3 4 and 1 7 4

6 1 2 5 8 3

7 5 9 6 2 9

Then we can simply use the value in the array as a threshold. If the value of the pixel (scaled into the 0-9 range) is less than the number in the corresponding cell of the matrix, plot that pixel black, otherwise, plot it white. This process is called ordered dither. As before, clustered patterns should be used for devices which blur dots. In fact, the clustered pattern ordered dither is the process used by most newspapers, and the term halftoning refers to this method if not otherwise qualified.

Bayer has shown that for matrices of orders which are powers of two there is an optimal pattern of dispersed dots which results in the pattern noise being as high-frequency as possible. The pattern for a 2x2 and 4x4 matrices are as follows:

1 3 1 9 3 11 These patterns (and their rotations

4 2 13 5 15 7 and reflections) are optimal for a

4 12 2 10 dispersed-pattern ordered dither.

16 8 14 6



Bayer's method is in very common use and is easily identified by the cross-hatch pattern artifacts it produces in the resulting display. This artifact is the major drawback of the technique which is otherwise very fast and powerful. Ordered dithering also performs very badly on images which have already been dithered to some extent. As stated earlier, dithering should be the last stage in producing a physical display from a digitally stored image. The dithered image should never be stored itself.

Exemplifying:



original image


original image after the application of ordered dithering






 
Random Dithering

Classical Algorithm - Developed Algorithms


This is the bubble sort of dithering algorithms. It is not really acceptable as a production method, but it is very simple to describe and implement. For each value in the image, simply generate a random number 1..256; if it is greater than the image value at that point, plot the point white, otherwise plot it black. That's it. This generates a picture with a lot of "white noise", which looks like TV picture "snow". Though the image produced is very inaccurate and noisy, it is free from "artifacts" which are phenomena produced by digital signal processing.

Many techniques exist for the reduction of digital artifacts like these, most of which involve using a little randomness to 'perturb' a regular algorithm a little. Random dither obviously takes this to extreme.

I should mention, of course, that unless your computer has a hardware-based random number generator (and most don't) there may be some artifacts from the random number generation algorithm itself.

While random dither adds a lot of high-frequency noise to a picture, it is useful in reproducing very low-frequency images where the absence of artifacts is more important than noise. For example, a whole screen containing a gradient of all levels from black to white would actually look best with a random dither. In this case, ordered dithering would produce diagonal patterns, and error dispersion would produce clustering.

For efficiency, you can take the random number generator "out of the loop" by generating a list of random numbers beforehand for use in the dither. Make sure that the list is larger than the number of pixels in the image or you may get artifacts from the reuse of numbers. The worst case would be if the size of your list of random numbers is a multiple or near-multiple of the horizontal size of the image, in which case unwanted vertical or diagonal lines will appear.

Exemplifying:



original image


original image after the application of random dithering






 
to huazai:
谢谢,我不是要这些简介啊!
我要的是可调整(1-100)的抖动算法的源码??????
 
打开笔记本,听课~
 
以下是我做的一个256色调色板抖动动画的控件,你拉回去看看吧,或许能给你带来灵感,改动一下可以实现
多种颜色的渐进抖动动画,跟98启动时底下的蓝白色滚动条一样。

{
256色调色板抖动动画 BY zhuancha
email:zhuancha@inhe.net
date :2001-04-20
}

unit CoolTitleBar;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,ExtCtrls;

type
TCoolTitleBar = class;
TRegionType = class(TPersistent)
public
FRegion:hRgn;
Owner:TCoolTitleBar;
end;
TCoolTitleBar = class(TPanel)

private
Fregion : TRegionType;
FOrgRgn : PRgnData;
FOrgSize : Integer;
Dummy:TRegionType;
FDraggable:boolean;
CycleTimer: TTimer;
FCycleInterval: Cardinal;
FBackMove:Boolean;
{---------------------------调色板变量定义--------------------------------}
LogicalPalette:tagLogPalette;
pNum:Integer;
iRed,iGreen,iBlue:Integer;
pe:tagPALETTEENTRY;
hEntryNum:Integer;
FPALENTRIES:Integer;
hNum:Integer;
pbAnm:TPaintBox;

{-------------------------------------------------------------------------}
procedure SetBackMove(Value: Boolean);
procedure TimerCycle(Sender: TObject);
procedure SetCycleInterval(Value: Cardinal);
procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
//procedure AnimateDemoPalette;//建立动画调色板
procedure MakeSpectrumSegments;//在指定区域内画方格
procedure SegmentColor(Entry:integer);//对所划的方格根据建立的调色板进行着色
protected
procedure pbAnmMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
procedure SetRegion(Value:TRegionType);
procedure SetParent(Value:TWinControl); override;
procedure SetTop(Value:integer); virtual;
procedure SetLeft(Value:integer); virtual;
procedure Setwidth(Value:integer); virtual;
procedure SetHeight(Value:integer); virtual;
function GetRegion:TRegionType;
procedure size;
public
constructor Create(Aowner:TComponent); override;
destructor Destroy; override;
procedure RefreshRegion;
published
property Draggable:boolean read FDraggable write FDraggable default true;
property CycleInterval: Cardinal read FCycleInterval write SetCycleInterval;
property PALENTRIES:Integer read FPALENTRIES write FPALENTRIES default 80;
property BackMove:Boolean read FBackMove write SetBackMove;
property Top write settop;
property Left write setleft;
property Width write setwidth;
property Height write setheight;

end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Custom', [TCoolTitleBar]);
end;

{----------------------------------建立控件------------------------------------}

constructor TCoolTitleBar.Create(Aowner:TComponent);

begin
inherited; //Create(Aowner);
hNum:=1;
FPALENTRIES:=80;
FCycleInterval:=100;
Align := alTop;
Alignment:=taLeftJustify;
BevelInner:=bvLowered;
BevelOuter :=bvRaised;
BorderWidth :=2;
Fregion := TRegionType.Create;
Dummy := TRegionType.Create;
Fregion.Fregion := 0;
Fregion.owner := self;
Draggable := true;
CycleTimer := TTimer.Create(Self);
CycleTimer.Enabled := False;
CycleTimer.Interval := FCycleInterval;
CycleTimer.OnTimer := TimerCycle;
pbAnm:=TPaintBox.Create(Self);
pbAnm.Parent:=Self;
pbAnm.ParentColor :=True;
pbAnm.ParentFont :=True;
pbAnm.Align :=alClient;
end;

procedure TCoolTitleBar.pbAnmMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
//拖动窗体
If button = mbleft then
begin
releasecapture;
TWincontrol(Parent.Parent).Perform(WM_syscommand, $F012, 0);
end;
end;

procedure TCoolTitleBar.SegmentColor(Entry:integer);

begin
if hNum>=PALENTRIES-1 then hNum:=1 Else inc(hNum,1);
pe:= LogicalPalette.palPalEntry[Entry];
iRed := pe.peRed;
iGreen := pe.peGreen;
pNum := 512 div PALENTRIES;
If (hNum <= PALENTRIES div 2) Then
iBlue := hNum * pNum
Else
iBlue := (PALENTRIES - hNum) * pNum;
pbAnm.Canvas.Pen.Color := RGB(0,0,iBlue);
pbAnm.Canvas.Brush.Color := RGB(0,0,iBlue);
pbAnm.Canvas.Font.Color:= RGB(255,255,255);
end;

procedure TCoolTitleBar.MakeSpectrumSegments;
var
Counter:Integer;
TotalWidth:Integer;
StartPoint:Integer;
EndPoint:Integer;
begin
//---------------------在指定的动画区域画方格实现动画运转--------------------
TotalWidth:=pbAnm.Width;
For Counter := 0 To (PALENTRIES-1) do begin
StartPoInt := (TotalWIdth * Counter) div PALENTRIES;
EndPoInt := (TotalWIdth * (Counter + 1)) div PALENTRIES;
pbAnm.Canvas.Pen.Width :=1;
hEntryNum:=Counter;
SegmentColor(hEntryNum);
pbAnm.Canvas.RoundRect(EndPoInt,pbAnm.Height,StartPoInt, 0,0,0);
SetBKMode(pbAnm.Canvas.Handle,TRANSPARENT);
pbAnm.Canvas.TextOut(20,2,Self.Caption)
end;

//---------------------------------------------------------------------------
end;

procedure TCoolTitleBar.SetTop(Value:integer);
begin
inherited top := 0;
end;

procedure TCoolTitleBar.SetLeft(Value:integer);
begin
inherited left := 0;
end;

procedure TCoolTitleBar.RefreshRegion;
begin
FRegion.FRegion := ExtCreateRegion (nil, FOrgSize, FOrgRgn^);
SetWindowRgn (parent.handle, FRegion.Fregion, true);
end;



destructor TCoolTitleBar.destroy;
begin
If FOrgRgn <> Nil then
FreeMem (FOrgRgn, FOrgSize);

if fregion.fregion <> 0 then deleteobject (fregion.fregion);
Dummy.Free;
FRegion.free;
inherited;
end;

function TCoolTitleBar.GetRegion:TRegionType;
begin
result := FRegion;
end;

procedure TCoolTitleBar.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin
//拖动窗体
If button = mbleft then
begin
releasecapture;
TWincontrol(Parent).Perform(WM_syscommand, $F012, 0);
end;
end;

procedure TCoolTitleBar.SetRegion(Value:TRegionType);
begin
if Value <> nil then
begin
FRegion := Value;
FRegion.owner := self;
end;
end;


procedure TCoolTitleBar.SetParent(Value:TWinControl);
begin
inherited;
if Value <> nil then
if not (Value is TWinControl) then
begin
raise Exception.Create ('Drop the CoolTitleBar on a FORM!');
end else
with TWincontrol (Value) do
begin
if Value is TForm then
begin
TForm(Value).BorderStyle := bsNone;
TForm(Value).Position:=poScreenCenter;
Self.Caption :=TForm(Value).Caption;
end;
end;
top := 0;
left := 0;
end;

procedure TCoolTitleBar.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
message.Result := 1;
end;

procedure TCoolTitleBar.size;
var
size : integer;
rgndata : pRGNData;
xf : TXform;

begin
if (fregion.fregion<>0) then
begin
size := getregiondata (FRegion.FRegion, 0, nil);
getmem (rgndata, size);
getregiondata (FRegion.FRegion, size, rgndata);

xf.eM11 := 1;
xf.eM12 := 0;
xf.eM21 := 0;
xf.eM22 := 1;
xf.eDx := 0;
xf.eDy := 0;
FRegion.FRegion := ExtCreateRegion (nil, size, rgndata^);

if not (csDesigning in ComponentState) and (FRegion.FRegion <> 0) then
SetWindowRgn (parent.handle, FRegion.Fregion, true);
end;
end;

procedure TCoolTitleBar.Setwidth(Value:integer);
begin
inherited Width := Value;
// Size;
end;

procedure TCoolTitleBar.SetHeight(Value:integer);
begin
inherited Height := Value;
// Size;
end;

procedure TCoolTitleBar.SetCycleInterval(Value: Cardinal);
begin
FCycleInterval := Value;
CycleTimer.Interval := FCycleInterval;
end;

procedure TCoolTitleBar.TimerCycle(Sender: TObject);
begin
//AnimateDemoPalette;
MakeSpectrumSegments;
end;

procedure TCoolTitleBar.SetBackMove(Value: Boolean);
begin
FBackMove := Value;
if Value then CycleTimer.Enabled := Value else CycleTimer.Enabled := False;
end;

end.
 
to Jack_long谢谢啦。
我已经回家试验了。
 
to Jack_long:你的好象没有使用什么抖动算法?
 
后退
顶部