123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588 |
- MODULE SVGFilters;
- IMPORT SVG, SVGColors, SVGUtilities, XML, XMLObjects, Raster, Math;
- (* Constants that determine the input, the blend-mode and the type of color-matrix *)
- CONST
- InSourceGraphic*=0;
- InFilterElement*=1;
- BlendModeNormal=0;
- BlendModeMultiply=1;
- BlendModeScreen=2;
- BlendModeDarken=3;
- BlendModeLighten=4;
- ColorMatrixTypeMatrix=0;
- ColorMatrixTypeSaturate=1;
- ColorMatrixTypeHueRotate=2;
- ColorMatrixTypeLuminanceToAlpha=3;
- TYPE
- Buffer*=SVG.Document;
- FilterWindow*=POINTER TO FilterWindowDesc;
- FilterWindowDesc*=RECORD
- x*, y*, width*, height*: SVG.Length;
- modeBlend, modeCopy: Raster.Mode;
- sourceGraphic: Buffer;
- END;
- In*=POINTER TO InDesc;
- InDesc*=RECORD
- type*: SHORTINT;
- fe*: FilterElement;
- END;
- FilterElement*=OBJECT
- VAR
- in*: In;
- x*,y*,width*,height*: SVG.Length;
- (* Apply this filter element to a new target *)
- PROCEDURE Apply*(window: FilterWindow): Buffer;
- VAR target: Buffer;
- BEGIN
- target := SVG.NewDocument(ENTIER(width),ENTIER(height));
- ApplyFilter(window, target);
- RETURN target;
- END Apply;
- (* Apply this filter element to the specifies target *)
- PROCEDURE ApplyFilter*(window: FilterWindow; target: Buffer);
- BEGIN
- HALT(99)
- END ApplyFilter;
- (* Get the buffer of the processed input *)
- PROCEDURE GetInBuffer(in: In; window: FilterWindow): Buffer;
- VAR b:Buffer; fe: FilterElement;
- BEGIN
- CASE in.type OF
- InSourceGraphic: RETURN window.sourceGraphic;
- | InFilterElement: fe:=in.fe; b:=fe.Apply(window); RETURN b;
- END
- END GetInBuffer;
- (* Get a pixel from the source buffer*)
- PROCEDURE GetInPixel(x,y, tx0,ty0: LONGINT; window: FilterWindow; in: In; source: Buffer; VAR pix: Raster.Pixel);
- BEGIN
- IF in.type#InFilterElement THEN
- x:=x+tx0-ENTIER(window.x);
- y:=y+ty0-ENTIER(window.y);
- END;
- IF (0 <= x) & (x < source.width) & (0 <= y) & (y < source.height) THEN
- Raster.Get(source,x,y, pix, window.modeCopy);
- ELSE
- Raster.SetRGBA(pix,0,0,0,0)
- END
- END GetInPixel;
- END FilterElement;
- feBlend*=OBJECT(FilterElement)
- VAR
- in2*: In;
- mode*: SHORTINT;
- (* Apply this filter element *)
- PROCEDURE ApplyFilter*(window: FilterWindow; target: Buffer);
- VAR tx,ty: LONGINT;
- source,source2: Buffer;
- pix,pix2: Raster.Pixel;
- BEGIN
- source := GetInBuffer(in,window);
- source2 := GetInBuffer(in2,window);
- FOR ty:=0 TO target.height-1 DO
- FOR tx:=0 TO target.width-1 DO
- GetInPixel(tx,ty, ENTIER(x),ENTIER(y), window, in,source, pix);
- GetInPixel(tx,ty, ENTIER(x),ENTIER(y), window, in2,source2, pix2);
- Blend(pix,pix2);
- Raster.Put(target, tx,ty, pix, window.modeCopy)
- END; END;
- END ApplyFilter;
- (* Blend two pixels *)
- PROCEDURE Blend(VAR a, b: Raster.Pixel);
- VAR fa, fb, ta, tb, i: LONGINT;
- BEGIN
- CASE mode OF
- | BlendModeNormal: (* (1-qa)*cb+ca *)
- fa := 255;
- fb := 255-ORD(a[3]);
- FOR i := 0 TO 2 DO
- a[i] := Raster.Clamp[200H + (fa * ORD(a[i]) + fb * ORD(b[i])) DIV 255]
- END
- | BlendModeMultiply: (* (1-qa)*cb+(1-qb)*ca+ca*cb *)
- fb := 255-ORD(a[3]);
- FOR i := 0 TO 2 DO
- fa := 255-ORD(b[3])+ORD(b[i]);
- a[i] := Raster.Clamp[200H + (fa * ORD(a[i]) + fb * ORD(b[i])) DIV 255]
- END
- | BlendModeScreen: (* cb+ca-ca*cb *)
- fb := 255;
- FOR i := 0 TO 2 DO
- fa := 255-ORD(b[i]);
- a[i] := Raster.Clamp[200H + (fa * ORD(a[i]) + fb * ORD(b[i])) DIV 255]
- END
- | BlendModeDarken: (* Min((1-qa)*cb+ca,(1-qb)*ca+cb) *)
- fa := 255-ORD(b[3]);
- fb := 255-ORD(a[3]);
- FOR i := 0 TO 2 DO
- ta := fa * ORD(a[i]) + 255 * LONG(ORD(b[i]));
- tb := 255 * LONG(ORD(a[i])) + fb * ORD(b[i]);
- IF ta<tb THEN
- a[i] := Raster.Clamp[200H + ta DIV 255]
- ELSE
- a[i] := Raster.Clamp[200H + tb DIV 255]
- END
- END
- | BlendModeLighten: (* Max((1-qa)*cb+ca,(1-qb)*ca+cb) *)
- fa := 255-ORD(b[3]);
- fb := 255-ORD(a[3]);
- FOR i := 0 TO 2 DO
- ta := fa * ORD(a[i]) + 255 * LONG(ORD(b[i]));
- tb := 255 * LONG(ORD(a[i])) + fb * ORD(b[i]);
- IF ta>tb THEN
- a[i] := Raster.Clamp[200H + ta DIV 255]
- ELSE
- a[i] := Raster.Clamp[200H + tb DIV 255]
- END
- END
- END;
- (* 1- (1-qa)*(1-qb) *)
- fa := 255-ORD(a[3]);
- fb := 255-ORD(b[3]);
- a[3] := Raster.Clamp[200H + 255 - (fa*fb) DIV 255]
- END Blend;
- END feBlend;
- feOffset*=OBJECT(FilterElement)
- VAR
- dx*,dy*: SVG.Length;
- (* Apply this filter element *)
- PROCEDURE ApplyFilter*(window: FilterWindow; target: Buffer);
- VAR tx,ty, sx,sy: LONGINT;
- source: Buffer;
- pix: Raster.Pixel;
- BEGIN
- source := GetInBuffer(in,window);
- FOR ty:=0 TO target.height-1 DO
- FOR tx:=0 TO target.width-1 DO
- sx := ENTIER(tx-dx);
- sy := ENTIER(ty-dy);
- GetInPixel(sx,sy, ENTIER(x),ENTIER(y), window, in,source, pix);
- Raster.Put(target, tx,ty, pix, window.modeCopy)
- END; END;
- END ApplyFilter;
- END feOffset;
- ColorMatrix*=RECORD
- a: ARRAY 5,4 OF LONGREAL;
- END;
- feColorMatrix*=OBJECT(FilterElement)
- VAR
- type*: SHORTINT;
- matrix*: ColorMatrix;
- (* Apply this filter element *)
- PROCEDURE ApplyFilter*(window: FilterWindow; target: Buffer);
- VAR tx,ty: LONGINT;
- source: Buffer;
- pix: Raster.Pixel;
- BEGIN
- source := GetInBuffer(in,window);
- FOR ty:=0 TO target.height-1 DO
- FOR tx:=0 TO target.width-1 DO
- GetInPixel(tx,ty, ENTIER(x),ENTIER(y), window, in,source, pix);
- TransformByColorMatrix(pix,matrix);
- Raster.Put(target, tx,ty, pix, window.modeCopy)
- END; END;
- END ApplyFilter;
- END feColorMatrix;
- feGaussianBlur*=OBJECT(FilterElement)
- VAR
- stdDeviationX*, stdDeviationY*: SVG.Length;
- (* Apply this filter element *)
- PROCEDURE ApplyFilter*(window: FilterWindow; target: Buffer);
- VAR tx,ty, k: LONGINT;
- source: Buffer;
- pix: Raster.Pixel;
- temp: Buffer;
- kernel: POINTER TO ARRAY OF LONGREAL;
- kernelSizeX, kernelSizeY, kernelHalfX, kernelHalfY: LONGINT;
- norm, sSquared2: LONGREAL;
- sum: SVGColors.ColorSum;
- BEGIN
- (* Gaussian Kernel is seperable into a vertical part and a horizontal part. *)
- (* Prepare the buffers for both parts using the larger stdDeviation. *)
- kernelHalfX := 3*ENTIER(stdDeviationX);
- kernelHalfY := 3*ENTIER(stdDeviationY);
- kernelSizeX := 2*kernelHalfX+1;
- kernelSizeY := 2*kernelHalfY+1;
- IF stdDeviationX>stdDeviationY THEN NEW(kernel,kernelSizeX)
- ELSE NEW(kernel,kernelSizeY);
- END;
- source := GetInBuffer(in,window);
- temp := SVG.NewDocument(source.width, source.height);
- (* horizontal part *)
- sSquared2 := 2*stdDeviationX*stdDeviationX;
- norm := Math.sqrt(SHORT(sSquared2)*Math.pi);
- FOR k :=-kernelHalfX TO kernelHalfX DO
- kernel[kernelHalfX+k] := Math.exp(SHORT(-k*k/sSquared2)) / norm;
- END;
- FOR ty:=0 TO temp.height-1 DO
- FOR tx:=0 TO temp.width-1 DO
- sum[0] := 0; sum[1] := 0; sum[2] := 0; sum[3] := 0;
- FOR k:=-kernelHalfX TO kernelHalfX DO
- GetInPixel(tx+k,ty, ENTIER(x),ENTIER(y), window, in,source, pix);
- SVGColors.WeightedAdd(sum, kernel[kernelHalfX+k], pix);
- END;
- SVGColors.ColorSumToPixel(sum, pix);
- Raster.Put(temp, tx,ty, pix, window.modeCopy)
- END; END;
- (* vertical part *)
- sSquared2 := 2*stdDeviationY*stdDeviationY;
- norm := Math.sqrt(SHORT(sSquared2)*Math.pi);
- FOR k :=-kernelHalfY TO kernelHalfY DO
- kernel[kernelHalfY+k] := Math.exp(SHORT(-k*k/sSquared2)) / norm;
- END;
- FOR ty:=0 TO target.height-1 DO
- FOR tx:=0 TO target.width-1 DO
- sum[0] := 0; sum[1] := 0; sum[2] := 0; sum[3] := 0;
- FOR k:=-kernelHalfY TO kernelHalfY DO
- GetInPixel(tx,ty+k, ENTIER(x),ENTIER(y), window, in,temp, pix);
- SVGColors.WeightedAdd(sum, kernel[kernelHalfY+k], pix);
- END;
- SVGColors.ColorSumToPixel(sum, pix);
- Raster.Put(target, tx,ty, pix, window.modeCopy)
- END; END
- END ApplyFilter;
- END feGaussianBlur;
- feMerge*=OBJECT(FilterElement)
- VAR in2: XMLObjects.List;
- (* Apply this filter element *)
- PROCEDURE ApplyFilter*(window: FilterWindow; target: Buffer);
- VAR tx,ty: LONGINT;
- source: Buffer;
- pix: Raster.Pixel;
- enum: XMLObjects.Enumerator;
- next: In;
- nextPtr: ANY;
- BEGIN
- IF in#NIL THEN
- source := GetInBuffer(in,window);
- FOR ty:=0 TO target.height-1 DO
- FOR tx:=0 TO target.width-1 DO
- GetInPixel(tx,ty, ENTIER(x),ENTIER(y), window, in,source, pix);
- Raster.Put(target, tx,ty, pix, window.modeCopy)
- END; END;
- IF in2#NIL THEN
- enum := in2.GetEnumerator();
- WHILE enum.HasMoreElements() DO
- nextPtr := enum.GetNext();
- next := nextPtr(In);
- source := GetInBuffer(next,window);
- FOR ty:=0 TO target.height-1 DO
- FOR tx:=0 TO target.width-1 DO
- GetInPixel(tx,ty, ENTIER(x),ENTIER(y), window, in,source, pix);
- Raster.Put(target, tx,ty, pix, window.modeBlend)
- END; END;
- END
- END
- END
- END ApplyFilter;
- (* Add a mergeNode *)
- PROCEDURE AddNode*(in: In);
- BEGIN
- IF in2=NIL THEN NEW(in2) END;
- in2.Add(in);
- END AddNode;
- END feMerge;
- feFlood*=OBJECT(FilterElement)
- VAR
- pix*: Raster.Pixel;
- (* Apply this filter element *)
- PROCEDURE ApplyFilter*(window: FilterWindow; target: Buffer);
- VAR tx,ty: LONGINT;
- BEGIN
- FOR ty:=0 TO target.height-1 DO
- FOR tx:=0 TO target.width-1 DO
- Raster.Put(target, tx,ty, pix, window.modeCopy)
- END; END;
- END ApplyFilter;
- END feFlood;
- feImage*=OBJECT(FilterElement)
- VAR image*: Buffer;
- (* Apply this filter element *)
- PROCEDURE ApplyFilter*(window: FilterWindow; target: Buffer);
- VAR tx,ty, sx,sy: LONGINT;
- pix: Raster.Pixel;
- BEGIN
- FOR ty:=0 TO target.height-1 DO
- FOR tx:=0 TO target.width-1 DO
- sx := ENTIER(tx*image.width/width);
- sy := ENTIER(ty*image.height/height);
- IF (sx <image.width) & (sy < image.height) THEN
- Raster.Get(image, sx,sy, pix, window.modeCopy);
- ELSE
- Raster.SetRGBA(pix,0,0,0,0)
- END;
- Raster.Put(target, tx,ty, pix, window.modeCopy)
- END; END;
- END ApplyFilter;
- END feImage;
- feTile*=OBJECT(FilterElement)
- (* Apply this filter element *)
- PROCEDURE ApplyFilter*(window: FilterWindow; target: Buffer);
- VAR tx,ty, sx,sy: LONGINT;
- source: Buffer;
- pix: Raster.Pixel;
- BEGIN
- source := GetInBuffer(in,window);
- FOR ty:=0 TO target.height-1 DO
- FOR tx:=0 TO target.width-1 DO
- sx := tx MOD source.width;
- sy := ty MOD source.height;
- GetInPixel(sx,sy, ENTIER(x),ENTIER(y), window, in,source, pix);
- Raster.Put(target, tx,ty, pix, window.modeCopy)
- END; END;
- END ApplyFilter;
- END feTile;
- Filter*=OBJECT
- VAR fElements: XMLObjects.ArrayDict;
- rootElement*: FilterElement;
- window*: FilterWindow;
- PROCEDURE &New*;
- BEGIN
- NEW(fElements);
- NEW(window);
- Raster.InitMode(window.modeBlend, Raster.srcOverDst);
- Raster.InitMode(window.modeCopy, Raster.srcCopy);
- END New;
- (* Add a filter element *)
- PROCEDURE AddFilterElement*(fElement: FilterElement; id: SVG.String);
- BEGIN
- fElements.Remove(id^);
- fElements.Add(id^, fElement);
- END AddFilterElement;
- (* Get a filter element with some specified id *)
- PROCEDURE GetFilterElement*(id: SVG.String):FilterElement;
- VAR p: ANY;
- BEGIN
- p := fElements.Get(id^);
- IF p = NIL THEN RETURN NIL
- ELSE RETURN p(FilterElement) END
- END GetFilterElement;
- (* Apply this filter *)
- PROCEDURE Apply*(source, target: Buffer);
- VAR result: Buffer;
- minx, miny, maxx, maxy: LONGINT;
- BEGIN
- IF rootElement#NIL THEN
- window.sourceGraphic := SVG.NewDocument(window.width,window.height);
- Raster.Copy(source, window.sourceGraphic,
- ENTIER(window.x), ENTIER(window.y), ENTIER(window.x+window.width), ENTIER(window.y+window.height),
- 0, 0, window.modeCopy);
- result := rootElement.Apply(window);
- minx := ENTIER(rootElement.x);
- miny := ENTIER(rootElement.y);
- maxx := ENTIER(rootElement.x+result.width);
- maxy := ENTIER(rootElement.y+result.height);
- IF minx<0 THEN minx := 0 END;
- IF miny<0 THEN miny := 0 END;
- IF maxx>target.width THEN maxx := target.width END;
- IF maxy>target.height THEN maxy := target.height END;
- IF (minx<=maxx) & (miny<=maxy) THEN
- Raster.Copy(result, target,
- minx-ENTIER(rootElement.x), miny-ENTIER(rootElement.y), maxx-ENTIER(rootElement.x), maxy-ENTIER(rootElement.y),
- minx, miny, window.modeBlend)
- END
- ELSE
- SVG.Log("Filter has no elements");
- END
- END Apply;
- END Filter;
- FilterDict*=OBJECT
- VAR filters: XMLObjects.ArrayDict;
- PROCEDURE &New*;
- BEGIN
- NEW(filters)
- END New;
- (* Add a filter *)
- PROCEDURE AddFilter*(filter: Filter; id: SVG.String);
- BEGIN
- filters.Add(id^, filter)
- END AddFilter;
- (* Get a filter with some specified id *)
- PROCEDURE GetFilter*(id: SVG.String):Filter;
- VAR p: ANY;
- BEGIN
- p := filters.Get(id^);
- IF p = NIL THEN RETURN NIL
- ELSE RETURN p(Filter) END
- END GetFilter;
- END FilterDict;
- FilterStack*=OBJECT
- VAR
- topFilter: Filter;
- next: FilterStack;
- (* Push a new filter onto the stack *)
- PROCEDURE Push*(filter: Filter);
- VAR pushed: FilterStack;
- BEGIN
- NEW(pushed);
- pushed^ := SELF^;
- next := pushed;
- topFilter:=filter;
- END Push;
- (* Pop the top filter from the stack *)
- PROCEDURE Pop*(VAR filter: Filter);
- BEGIN
- filter := topFilter;
- SELF^ := next^;
- END Pop;
- END FilterStack;
- (* Parse some in attribute of a filter element *)
- PROCEDURE ParseIn*(value: SVG.String; VAR in: SHORTINT);
- BEGIN
- IF value^ = "SourceGraphic" THEN in := InSourceGraphic
- ELSE
- in := InFilterElement
- END
- END ParseIn;
- (* Parse the blendMode attribute of some feBlend element *)
- PROCEDURE ParseBlendMode*(value: SVG.String; VAR mode: SHORTINT);
- BEGIN
- IF value^ = "normal" THEN mode := BlendModeNormal
- ELSIF value^ = "multiply" THEN mode := BlendModeMultiply
- ELSIF value^ = "screen" THEN mode := BlendModeScreen
- ELSIF value^ = "darken" THEN mode := BlendModeDarken
- ELSIF value^ = "lighten" THEN mode := BlendModeLighten
- ELSE
- SVG.Error("mode attribute feBlend must be 'normal', 'multiply', 'screen', 'darken' or 'lighten'");
- mode := BlendModeNormal
- END
- END ParseBlendMode;
- (* Parse some type attribute of some feColorMatrix element *)
- PROCEDURE ParseColorMatrixType*(value: XML.String; VAR type: SHORTINT);
- BEGIN
- IF value^ = "matrix" THEN type := ColorMatrixTypeMatrix
- ELSIF value^ = "saturate" THEN type := ColorMatrixTypeSaturate
- ELSIF value^ = "hueRotate" THEN type := ColorMatrixTypeHueRotate
- ELSIF value^ = "luminanceToAlpha" THEN type := ColorMatrixTypeLuminanceToAlpha
- ELSE
- SVG.Error("type attribute feColorMatrix must be 'matrix', 'saturate', 'hueRotate' or 'luminanceToAlpha'");
- type := ColorMatrixTypeMatrix
- END
- END ParseColorMatrixType;
- (* Parse some values attribute of some feColorMatrix element *)
- PROCEDURE ParseColorMatrixValues*(values: XML.String; type: SHORTINT; VAR matrix: ColorMatrix):BOOLEAN;
- VAR pos: SIZE; i,j: LONGINT;
- angle, s,c: LONGREAL;
- BEGIN
- (* Init to the zero matrix *)
- FOR i := 0 TO 4 DO
- FOR j := 0 TO 3 DO
- matrix.a[i,j] := 0;
- END; END;
- IF type=ColorMatrixTypeLuminanceToAlpha THEN
- (* In this case the 'values' attribute is not applicable as the matrix is predefined: *)
- matrix.a[0,3] := 0.2125;
- matrix.a[1,3] := 0.7154;
- matrix.a[2,3] := 0.0721;
- RETURN TRUE
- END;
- (* Otherwise the default is the identity matrix *)
- matrix.a[0,0] := 1;
- matrix.a[1,1] := 1;
- matrix.a[2,2] := 1;
- matrix.a[3,3] := 1;
- IF values=NIL THEN RETURN TRUE END;
- pos :=0;
- CASE type OF
- | ColorMatrixTypeMatrix:
- FOR j := 0 TO 3 DO
- FOR i := 0 TO 4 DO
- SVGUtilities.SkipCommaWhiteSpace(pos, values);
- SVGUtilities.StrToFloatPos(values^, matrix.a[i,j], pos);
- END;END;
- RETURN TRUE
- | ColorMatrixTypeSaturate:
- SVGUtilities.SkipCommaWhiteSpace(pos, values);
- SVGUtilities.StrToFloatPos(values^, s, pos);
- matrix.a[0,0] := 0.213+0.787*s; matrix.a[1,0] := 0.715-0.715*s; matrix.a[2,0] := 0.072-0.072*s;
- matrix.a[0,1] := 0.213-0.213*s; matrix.a[1,1] := 0.715+0.285*s; matrix.a[2,1] := 0.072-0.072*s;
- matrix.a[0,2] := 0.213-0.213*s; matrix.a[1,2] := 0.715-0.715*s; matrix.a[2,2] := 0.072+0.928*s;
- RETURN TRUE
- | ColorMatrixTypeHueRotate:
- SVGUtilities.SkipCommaWhiteSpace(pos, values);
- SVGUtilities.StrToFloatPos(values^, angle, pos);
- s := Math.sin(-SHORT(angle)/180.0*Math.pi);
- c := Math.cos(-SHORT(angle)/180.0*Math.pi);
- matrix.a[0,0] := 0.213+0.787*c-0.213*s; matrix.a[1,0] := 0.715-0.715*c-0.715*s; matrix.a[2,0] := 0.072-0.072*c+0.928*s;
- matrix.a[0,1] := 0.213-0.213*c+0.143*s; matrix.a[1,1] := 0.715+0.285*c+0.140*s; matrix.a[2,1] := 0.072-0.072*c-0.283*s;
- matrix.a[0,2] := 0.213-0.213*c-0.787*s; matrix.a[1,2] := 0.715-0.715*c+0.715*s; matrix.a[2,2] := 0.072+0.928*c+0.072*s;
- RETURN TRUE
- END;
- RETURN FALSE
- END ParseColorMatrixValues;
- (* Transform a pixel by a matrix *)
- PROCEDURE TransformByColorMatrix(VAR pix: Raster.Pixel; VAR matrix: ColorMatrix);
- VAR p, result: ARRAY 4 OF LONGREAL;
- BEGIN
- p[0] := ORD(pix[0])/255.0;
- p[1] := ORD(pix[1])/255.0;
- p[2] := ORD(pix[2])/255.0;
- p[3] := ORD(pix[3])/255.0;
- result[0] := matrix.a[0,0]*p[0] + matrix.a[1,0]*p[1] + matrix.a[2,0]*p[2] + matrix.a[3,0]*p[3] + matrix.a[4,0];
- result[1] := matrix.a[0,1]*p[0] + matrix.a[1,1]*p[1] + matrix.a[2,1]*p[2] + matrix.a[3,1]*p[3] + matrix.a[4,1];
- result[2] := matrix.a[0,2]*p[0] + matrix.a[1,2]*p[1] + matrix.a[2,2]*p[2] + matrix.a[3,2]*p[3] + matrix.a[4,2];
- result[3] := matrix.a[0,3]*p[0] + matrix.a[1,3]*p[1] + matrix.a[2,3]*p[2] + matrix.a[3,3]*p[3] + matrix.a[4,3];
- pix[0] := Raster.Clamp[200H+ENTIER(result[0]*255)];
- pix[1] := Raster.Clamp[200H+ENTIER(result[1]*255)];
- pix[2] := Raster.Clamp[200H+ENTIER(result[2]*255)];
- pix[3] := Raster.Clamp[200H+ENTIER(result[3]*255)];
- END TransformByColorMatrix;
- END SVGFilters.
|