RandomImagerImpl:
CEDAR PROGRAM
IMPORTS Random, Imager, ImagerColor, ImagerFont, Process, ImagerBackdoor, ImagerPixelArray, ImagerTransformation, ImagerSample, ImagerColorOperator, ImagerInterpress, ImagerDitheredDevice, Rope
EXPORTS ImagerPixelArrayDefs
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
VEC: TYPE ~ Imager.VEC;
Context: TYPE ~ Imager.Context;
PixelArray:
TYPE ~ ImagerPixelArrayDefs.PixelArray;
random: Random.RandomStream ← Random.Create[];
Rand:
PROC
RETURNS [
REAL] ~ {
RETURN [RandI[0, INT.LAST]/REAL[INT.LAST]];
};
RandI:
PROC [min,max:
INT]
RETURNS [
INT] ~ {
RETURN [random.ChooseInt[min,max]];
};
imagePA: Imager.PixelArray ← ImagerPixelArray.FromAIS["Mandrill.ais"];
imageColorOperator: Imager.ColorOperator ← ImagerColorOperator.GrayLinearColorModel[255, 0, 255,
NIL];
SetGrayImage:
PROC [rootName:
ROPE] ~ {
imagePA ← ImagerPixelArray.FromAIS[rootName.Concat[".ais"]];
};
rgbImagePA: Imager.PixelArray ← ImagerPixelArray.Join3AIS["Umbrella-red.ais", "Umbrella-grn.ais", "Umbrella-blu.ais"];
rgbImageColorOperator: Imager.ColorOperator ← ImagerColorOperator.RGBLinearColorModel[255];
SetColorImage:
PROC [rootName:
ROPE] ~ {
rgbImagePA ← ImagerPixelArray.Join3AIS[rootName.Concat["-red.ais"], rootName.Concat["-grn.ais"], rootName.Concat["-blu.ais"]];
};
RandomColor:
PROC [context: Context] ~ {
selectR: PROC [NAT] RETURNS [NAT] ~ {RETURN [RandI[0, pixelMasks.samplesPerPixel-1]]};
SELECT Rand[]
FROM
IN [0.0..0.15] => Imager.SetColor[context, Imager.black];
IN [0.15..0.2] => Imager.SetColor[context, ImagerDitheredDevice.ColorFromSpecialPixel[[55H, xor]]];
IN [0.2..0.3] => Imager.SetGray[context, Rand[]];
IN [0.3..0.6] => Imager.SetColor[context, ImagerColor.ColorFromRGB[[Rand[], Rand[], Rand[]]]];
IN [0.6..0.7] => Imager.SetSampledColor[context, rgbImagePA, ImagerTransformation.Scale[Rand[]+0.1], rgbImageColorOperator];
IN [0.7..0.75] => Imager.SetSampledBlack[context, ImagerPixelArray.Extract[old: pixelMasks, samplesPerPixel: 1, select: selectR], ImagerTransformation.Scale[RandI[1, 8]/2.0], 0=RandI[0,1]];
IN [0.75..0.8] => Imager.SetSampledColor[context, imagePA, ImagerTransformation.Scale[Rand[]+0.1], imageColorOperator];
IN [0.9..1.0] => Imager.SetColor[context, Imager.white];
ENDCASE => NULL;
};
goodForText: BOOL ← FALSE;
Anything is OK for text, but we try not to get too many different transformations to keep it quick.
RandomScaleRotate:
PROC [context: Context] ~ {
SELECT Rand[]
FROM
IN [0.0..0.5] => {Imager.ScaleT[context, 0.5*(1+ABS[RandI[1, 6]+RandI[-5, 5]])]; goodForText ← TRUE};
IN [0.5..0.7] => Imager.ScaleT[context, Rand[]*Rand[]*10+0.01];
IN [0.7..0.8] => Imager.Scale2T[context, [2*Rand[]+0.01, 2*Rand[]+0.01]];
IN [0.9..0.95] => {Imager.Scale2T[context, [0.5*RandI[1, 3], 0.5*RandI[1, 3]]]; goodForText ← TRUE};
ENDCASE => goodForText ← TRUE;
SELECT Rand[]
FROM
IN [0.0..0.7] => Imager.RotateT[context, 90*RandI[-20, 19]];
IN [0.7..0.9] => {Imager.RotateT[context, 360*4*Rand[]-360*2]; goodForText ← FALSE};
IN [0.9..0.95] => {Imager.RotateT[context, 23.0*RandI[-1, 1]]};
ENDCASE => NULL;
};
RandomTranslate:
PROC [context: Context] ~ {
RandBI: PROC RETURNS [INT] ~ {RETURN [RandI[-50, 50]+RandI[-50, 50]+RandI[-50, 50+RandI[-50, 50]]]};
SELECT Rand[]
FROM
IN [0.0..0.7] => Imager.TranslateT[context, [RandBI[], RandBI[]]];
IN [0.7..1.0] => Imager.TranslateT[context, [RandBI[]*Rand[], RandBI[]*Rand[]]];
ENDCASE => NULL;
};
CoordSys:
PROC [context: Context] ~ {
it:
PROC ~ {
Imager.MaskVector[context, [0,0], [0,5]];
Imager.MaskVector[context, [0,0], [4.8,0]];
Imager.MaskVector[context, [1,-0.2], [1,0.2]];
Imager.MaskVector[context, [-0.2,1], [0.2,1]];
Imager.MaskVector[context, [5,0], [4.8, 0.1]];
Imager.MaskVector[context, [4.8, 0.1], [4.8, -0.1]];
Imager.MaskVector[context, [4.8, -0.1], [5,0]];
Imager.MaskVector[context, [0,5], [0.1,4.8]];
Imager.MaskVector[context, [0,5], [-0.1,4.8]];
};
inner:
PROC ~ {
Imager.SetStrokeWidth[context, 0.2];
Imager.SetStrokeEnd[context, round];
Imager.SetColor[context, Imager.white];
Imager.SetStrokeWidth[context, 0.3];
Imager.MaskVector[context, [0,0], [0,0]];
it[];
Imager.SetStrokeWidth[context, 0];
Imager.SetColor[context, Imager.black];
it[];
Imager.SetStrokeWidth[context, 0.15];
it[];
};
Imager.DoSaveAll[context, inner];
};
Interp:
PROC [a, b:
VEC, r:
REAL]
RETURNS [
VEC] ~ {
s: REAL ~ 1.0-r;
RETURN [[a.x*s+b.x*r, a.y*s+b.y*r]]
};
RandomSplinePath:
PROC [n: [3..10), close:
BOOL, moveTo:
PROC [
VEC], curveTo:
PROC [
VEC,
VEC,
VEC]] ~ {
k: ARRAY [0..11) OF VEC;
nn: INT ← IF close THEN INT[n]+1 ELSE n;
Mod:
PROC [i:
INT]
RETURNS [
INT] ~ {
WHILE i<0 DO i ← i + nn ENDLOOP;
WHILE i>=nn DO i ← i - nn ENDLOOP;
RETURN [i];
};
FOR i:
INT
IN [0..nn)
DO
k[i] ← [Rand[]*scale.x, Rand[]*scale.y];
ENDLOOP;
FOR i:
INT
IN [0..n)
DO
a: VEC ← Interp[k[Mod[i-2]], k[Mod[i-1]], 2/3.0];
c: VEC ← Interp[k[Mod[i-1]], k[Mod[i]], 1/3.0];
b: VEC ← Interp[a, c, 0.5];
d: VEC ← Interp[k[Mod[i-1]], k[Mod[i]], 2/3.0];
f: VEC ← Interp[k[Mod[i]], k[Mod[i+1]], 1/3.0];
e: VEC ← Interp[d, f, 0.5];
IF i=0 THEN moveTo[b];
curveTo[c, d, e];
ENDLOOP;
};
RandomArc:
PROC [start:
VEC, arcTo:
PROC [
VEC,
VEC]]
RETURNS [lp:
VEC] ~ {
lp ← [Rand[]*scale.x, Rand[]*scale.y];
arcTo[[Rand[]*scale.x, Rand[]*scale.y], lp];
};
RandomLine:
PROC [start:
VEC, lineTo:
PROC [
VEC]]
RETURNS [lp:
VEC] ~ {
lp ← [Rand[]*scale.x, Rand[]*scale.y];
lineTo[lp];
};
RandVec:
PROC
RETURNS [lp:
VEC] ~ {
lp ← [Rand[]*scale.x, Rand[]*scale.y];
};
strokeScale: REAL ← 10.0;
RandomStrokeStyle:
PROC [context: Context] ~ {
Imager.SetStrokeWidth[context, strokeScale*Rand[]];
Imager.SetStrokeEnd[context, VAL[NAT[RandI[0,2]]]];
Imager.SetStrokeJoint[context, VAL[NAT[RandI[0,1]]]];
};
scale: VEC ← [1.0, 1.0];
closed: BOOL ← FALSE;
RandomPath: Imager.PathProc ~ {
lp: VEC ← RandVec[];
SELECT Rand[]
FROM
IN [0.0..0.3] => {
FOR i:
INT
IN [0..RandI[0,3]*RandI[0,1])
DO
RandomSplinePath[RandI[3,9], closed, moveTo, curveTo];
ENDLOOP;
};
IN [0.3..0.4] => {
RandomSplinePath[RandI[3,9], FALSE, moveTo, curveTo];
};
IN [0.4..0.6] => {
n: INT ← RandI[1,4];
moveTo[lp];
FOR i:
INT
IN [0..n)
DO
lp ← RandomArc[lp, arcTo];
ENDLOOP;
};
IN [0.6..1.0] => {
n: INT ← RandI[0,20];
moveTo[lp];
FOR i:
INT
IN [0..n)
DO
lp ← RandomLine[lp, lineTo];
ENDLOOP;
};
ENDCASE => NULL;
};
PixelArrayImpl: TYPE ~ ImagerPixelArrayPrivate.PixelArrayImpl;
PixelArrayImplRep: PUBLIC TYPE ~ ImagerPixelArrayPrivate.PixelArrayImplRep;
PixelArrayClass: TYPE ~ ImagerPixelArrayPrivate.PixelArrayClass;
PixelArrayClassRep: PUBLIC TYPE ~ ImagerPixelArrayPrivate.PixelArrayClassRep;
RandomStippleColor:
PROC
RETURNS [Imager.Color] ~ {
IF 0=RandI[0,4]
THEN {
bits: REF ARRAY [0..16) OF WORD ← NEW[ARRAY [0..16) OF WORD];
height: NAT ~ RandI[1,16];
width: NAT ~ RandI[1,16];
pa: PixelArray ~ NEW[ImagerPixelArrayDefs.PixelArrayRep ← [
samplesPerPixel: 1, sSize: height, fSize: width,
m: ImagerTransformation.Scale[1], class: bitsClass, data: bits]];
t: CARDINAL ← 1;
FOR i:
NAT
DECREASING
IN [0..16)
DO
bits^[i] ← t;
t ← 2*t;
ENDLOOP;
RETURN [ImagerColor.MakeSampledBlack[pa, ImagerTransformation.Scale[1], 0=RandI[0,1]]]
};
RETURN [ImagerBackdoor.MakeStipple[RandI[0, LAST[WORD]]]]
};
bitsClass: PixelArrayClass ~
NEW[PixelArrayClassRep ← [
type: $Bits,
MaxSampleValue: BitsMaxSampleValue,
UnsafeGetSamples: BitsUnsafeGetSamples
]];
BitsMaxSampleValue:
PROC [pa: PixelArray, i:
NAT]
RETURNS [ImagerPixelArray.Sample] ~ {
RETURN [1];
};
BitsUnsafeGetSamples:
UNSAFE
PROC [pa: PixelArray, i:
NAT, s, f:
INT,
samples: ImagerSample.UnsafeSamples, count:
NAT] ~
UNCHECKED {
data: REF ARRAY [0..16) OF WORD ~ NARROW[pa.data];
ImagerSample.UnsafeGetF[samples: samples, count: count, base: LOOPHOLE[data, LONG POINTER], wordsPerLine: 1, bitsPerSample: 1, s: s, f: f]
};
RandomClip:
PROC [context: Context] ~ {
path: Imager.PathProc ~ {
RandomSplinePath[5, TRUE, moveTo, curveTo];
};
Imager.Clip[context, path, FALSE, RandI[0,4]=0];
Imager.SetColor[context, RandomStippleColor[]];
Imager.MaskBox[context, [-99999, -99999, 99999, 99999]];
};
RandomFill:
PROC [context: Context] ~ {
closed ← TRUE;
Imager.MaskFill[context, RandomPath, RandI[0,1]=0];
};
RandomStroke:
PROC [context: Context] ~ {
closed ← RandI[0,1]=0;
RandomStrokeStyle[context];
Imager.MaskStroke[context, RandomPath, closed];
};
RandomVector:
PROC [context: Context] ~ {
RandomStrokeStyle[context];
Imager.MaskVector[context, RandVec[], RandVec[]];
};
RandomRectangle:
PROC [context: Context] ~ {
p0: VEC ← RandVec[];
p1: VEC ← RandVec[];
Imager.MaskRectangle[context, [p0.x, p0.y, p1.x-p0.x, p1.y-p0.y]];
};
pa1: PixelArray ← ImagerPixelArray.FromAIS["Mask1.ais"];
pa2: PixelArray ← ImagerPixelArray.FromAIS["Mask2.ais"];
pa3: PixelArray ← ImagerPixelArray.FromAIS["Mask3.ais"];
pixelMasks: PixelArray ← ImagerPixelArray.Join3[pa1, pa2, pa3];
RandomPixels:
PROC [context: Context] ~ {
selectR: PROC [NAT] RETURNS [NAT] ~ {RETURN [RandI[0, pixelMasks.samplesPerPixel-1]]};
pa: PixelArray ~ ImagerPixelArray.Extract[old: pixelMasks, samplesPerPixel: 1, select: selectR];
Imager.MaskPixel[context, pa];
};
RandomMask:
PROC [context: Context, textBounds:
BOOL ←
FALSE] ~ {
SELECT Rand[]
FROM
IN [0.0..0.2] => RandomFill[context];
IN [0.2..0.3] => RandomStroke[context];
IN [0.3..0.58] => {IF goodForText THEN RandomShow[context, textBounds] ELSE RandomFill[context]};
IN [0.58..0.6] => RandomShow[context, textBounds];
IN [0.6..0.65] => RandomRectangle[context];
IN [0.65..0.85] => {IF goodForText THEN RandomPixels[context] ELSE RandomRectangle[context]};
IN [0.85..0.9] => RandomPixels[context];
ENDCASE => RandomVector[context];
};
nfonts: NAT ← 9;
xerox: BOOL ← FALSE;
logo: ROPE ~ "xerox/pressfonts/logo-mrr";
fontName: ARRAY [0..35) OF ROPE ← ["xerox/pressfonts/helvetica-bir", "xerox/pressfonts/modern-bir", "xerox/pressfonts/timesroman-brr", "xerox/pressfonts/modernpione-brr", logo, "xerox/pressfonts/classic-brr", "xerox/pressfonts/classic-mir", "xerox/pressfonts/timesroman-mrr", "xerox/pressfonts/oldenglish-mrr", "xerox/pressfonts/classic-mrr", "xerox/pressfonts/classicpione-brr", "xerox/pressfonts/classicpione-mir", "xerox/pressfonts/classicpione-mrr", "xerox/pressfonts/gacha-mrr", "xerox/pressfonts/gates-mrr", "xerox/pressfonts/helvetica-brr", "xerox/pressfonts/helvetica-mir", "xerox/pressfonts/helvetica-mrr", "xerox/pressfonts/hippo-mrr", "xerox/pressfonts/keyhole-brr", "xerox/pressfonts/laurel-mrr", "xerox/pressfonts/math-mrr", "xerox/pressfonts/mockingbird-mrr", "xerox/pressfonts/modern-brr", "xerox/pressfonts/modern-mir", "xerox/pressfonts/modern-mrr", "xerox/pressfonts/modernpione-bir", "xerox/pressfonts/modernpione-mir", "xerox/pressfonts/modernpione-mrr", "xerox/pressfonts/template-mrr", "xerox/pressfonts/timesroman-bir", "xerox/pressfonts/timesroman-mrr", "xerox/pressfonts/timesroman-mir", "xerox/pressfonts/xeroxbook-mrr", "xerox/pressfonts/arrows-mrr"];
RandomFont:
PROC [context: Context] ~ {
name: ROPE ~ fontName[RandI[0,MIN[nfonts, 35]-1]];
font: Imager.Font ~ ImagerFont.Find[name];
Imager.SetFont[context, ImagerFont.Scale[font, 8]];
xerox ← (name = logo);
};
text:
ARRAY [0..11)
OF
ROPE ~ ["Now is the time for all good ", "people to party", "The Quick Brown ", "Fox Jumps Over Lazy Dogs ", "Flash ", "Dazzle ", "Imager ", "Cedar ", "Dorado ", "Color Is Fun ", "XEROX "];
RandomShow:
PROC [context: Context, checkBounds:
BOOL] ~ {
amp: REAL ← IF RandI[0,3] = 0 THEN 0.5+1.5*Rand[] ELSE 1.0;
RandomFont[context];
Imager.SetAmplifySpace[context, amp];
IF checkBounds
THEN {
bounds: Imager.Rectangle ~ ImagerBackdoor.GetBounds[context];
cp: VEC ~ ImagerBackdoor.GetCP[context];
IF cp.x IN [bounds.x..bounds.x+bounds.w) AND cp.y IN [bounds.y..bounds.y+bounds.h) THEN NULL
ELSE Imager.SetXY[context, [bounds.x+0.5*bounds.w*Rand[], bounds.y+0.5*bounds.h*Rand[]]];
};
Imager.ShowRope[context, IF xerox THEN "XEROX " ELSE text[RandI[0, 11-1]]];
};
limit: INT ← 0;
Setup:
PROC [n:
INT ← -1, newRand:
BOOL ←
FALSE] ~ {
IF newRand THEN random ← Random.Create[];
limit ← n;
};
Run:
PROC [context: Context] ~ {
Do20:
PROC ~ {
bounds: Imager.Rectangle ← ImagerBackdoor.GetBounds[context];
scale ← [bounds.w, bounds.h];
RandomTranslate[context];
Imager.TranslateT[context, [bounds.w/2, bounds.h/2]];
RandomScaleRotate[context];
Imager.TranslateT[context, [-bounds.w/2, -bounds.h/2]];
CoordSys[context];
Imager.SetXY[context, [0, 0]];
IF 0 = RandI[0,5] THEN RandomClip[context];
FOR i:
INT
IN [0..20)
UNTIL limit = 0
DO
IF 0 = RandI[0,99] THEN RandomClip[context];
RandomColor[context];
RandomMask[context, TRUE];
limit ← limit - 1;
Process.CheckForAbort[];
ENDLOOP;
};
UNTIL limit = 0
DO
Imager.DoSaveAll[context, Do20];
ENDLOOP;
};
WriteInterpress:
PROC [nOpsPerPage, nPages:
INT ← 1] ~ {
page:
PROC [context: Context] ~ {
n: INT ← nOpsPerPage;
bounds: Imager.Rectangle ~ [0, 0, 8.5*72, 11*72];
Do20:
PROC ~ {
Imager.TranslateT[context, [bounds.w/2, bounds.h/2]];
RandomScaleRotate[context];
Imager.TranslateT[context, [-bounds.w/2, -bounds.h/2]];
CoordSys[context];
Imager.SetXY[context, [0, 0]];
IF 0 = RandI[0,5] THEN RandomClip[context];
FOR i:
INT
IN [0..20)
UNTIL n = 0
DO
IF 0 = RandI[0, 99] THEN RandomClip[context];
RandomColor[context];
RandomMask[context];
n ← n - 1;
Process.CheckForAbort[];
ENDLOOP;
};
Imager.ScaleT[context, 0.0254/72];
scale ← [bounds.w, bounds.h];
UNTIL n <= 0
DO
Imager.DoSaveAll[context, Do20];
ENDLOOP;
};
interpress: ImagerInterpress.Ref ~ ImagerInterpress.Create["Random.interpress"];
FOR i:
NAT
IN [0..5)
DO
ImagerInterpress.DeclareFont[interpress, ImagerFont.Find[fontName[i]]];
ENDLOOP;
ImagerInterpress.DeclarePixelArray[interpress, imagePA];
ImagerInterpress.DeclarePixelArray[interpress, rgbImagePA];
ImagerInterpress.DeclarePixelArray[interpress, pa1];
ImagerInterpress.DeclarePixelArray[interpress, pa2];
ImagerInterpress.DeclarePixelArray[interpress, pa3];
ImagerInterpress.DeclareColorOperator[interpress, imageColorOperator];
THROUGH [0..nPages) DO ImagerInterpress.DoPage[interpress, page] ENDLOOP;
ImagerInterpress.Close[interpress];
};
END.
Run InterpressPackage
Run RandomImagerImpl
Run ImagerViewerImpl
← &c ← ImagerViewer.Create[[name: "Random Imager"], pixels]
← RandomImagerImpl.Setup[]
← RandomImagerImpl.Run[&c]