# I'm working on a Kaleidoscope plugin:need help V2!

## Recommended Posts

This plugin will have several versions, I will just start with a simple one.

For now I am able to create like a pie chart to help to cut the picture and select (manually) one piece for the repeating reflection.

Imagine a pie cut into 12 equal portions.

Then we select one of these portion to be the one to duplicate.

Then we read as usualy :

for(int y = rect.Top; y < rect.Bottom; y++) {

for (int x = rect.Left; x < rect.Right; x++) {

...

The tricky part for me now is to determin for dst[x,y] what is the corresponding src[x,y] knowing :

- it is a pixel from the selected portion...

- and for ode portion (dst) we have to apply a symetric reflection...

Any (all) idea/suggestion are welcome.

I visited some developper forum or math forum but I find nothing really helping me!

##### Share on other sites

Seems similar to the Fragment plugin, isn't it?

No. Way. I've just seen Bob. And... *poof!*—just like that—he disappears into the mist again. ~Helio

##### Share on other sites

No because fragments plugin duplicate the image and distribut the copies around the center without rotating it (the picture).

##### Share on other sites

Some previews:

Random kaleidoscopes generator:

(the first is retouched : blur, color levels etc, the others are raw versions)

Image "kaleidoscopor":

Original:

Actual result (I'm missing symetric rotation one part on two):

Expected result:

Does anyone could help me for the symetric rotation?

##### Share on other sites

If you reflect it once along any of those axes and then begin to rotate that bigger piece, you should have it.

Thus, every other piece is reflected along its own normal axis*; so, the destination pixel will be drawn from the point on the other side of that normal axis at the same distance from the axis.

Questions?

*That normal axis would be the one that bisects the triangle, as so:

The axis runs from A to D, where D is the midpoint of line BC.

~~

##### Share on other sites

But I've built this plugin using the 'normal' loops

for y=0;y

for x=0;x

dst[x,y]=src[xsrc,ysrc];

it's ok for normal rotation, but I'm blocking to the reflected part...

##### Share on other sites

For the other plugin, I'm using Dst.Graphics.Fillpolygone... But I've really strange preview (missing lines)..

##### Share on other sites

Ah... Yeah, well I guess you can't do much if you're using that, then... But if you want to remake it, just take any triangle as your source pixels, and then your destination pixels will draw from that triangle, with a rotational offset depending on the triangle the destination is in, and also possibly a mirror offset (along that "normal" axis), also depending on the triangle the destination is in.

~~

##### Share on other sites

That's the way I do (like you described).

I've trouble to write the formulas concerning the mirror offset.

EDIT: I've done it... Now I'm finalizing it...

##### Share on other sites

• 2 weeks later...

I'm working on a generator using triangles.

Sometimes it works and sometimes not.

Example:

Anyhow the rendering shows strange lines not linked to the final result...

While rendering:

And the final result could be corrupted with some remaining lines...

Result:

This is the code (used with a normal three slider UI):

```using KaleidoGen.Properties;
using PaintDotNet;
using PaintDotNet.Effects;
using System;
using System.Drawing;

namespace KaleidoGen
{
//Kaleidoscope generator based on http://sprott.physics.wisc.edu/pickover/ekscop.html
//Thanks to Nemerle http://www.developpez.net/forums/member.php?s=de428a11138f7d0dcb6c474af5d673aa&u=25295
public class KaleidoGen
: Effect
{
int reseed = 0;

public override void Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, System.Drawing.Rectangle[] rois, int startIndex, int length)
{
ThreeAmountsConfigToken token = (ThreeAmountsConfigToken)parameters;
int tkNbTriangles = (int)token.Amount1;   // Nb of triangles to draw
int tkOverlay = (int)token.Amount2;       // Overlay between quarters
int KWidth = (int)token.Amount3;          // Width of a square

int x1, x2, x3, y1, y2, y3, ba, br, bg, bb, sav;
int px1, px2, px3, py1, py2, py3;

PdnRegion selectionRegion = EnvironmentParameters.GetSelection(srcArgs.Bounds);
Rectangle selection = this.EnvironmentParameters.GetSelection(srcArgs.Bounds).GetBoundsInt();
long CenterX = (long)(((selection.Right - selection.Left) / 2) + selection.Left);
long CenterY = (long)(((selection.Bottom - selection.Top) / 2) + selection.Top);

if (KWidth > (int)(CenterX * 2)) { KWidth = (int)(CenterX * 2); }
if (KWidth > (int)(CenterY * 2)) { KWidth = (int)(CenterY * 2); }
Random randinit = new Random();

if (reseed == 0)
{
reseed = randinit.Next((int)(CenterX * CenterY));
}

lock (dstArgs.Graphics)
{

// Make sure we don't draw outside of our current rectangle of intrest
dstArgs.Graphics.Clip = new Region(selection);
// Set Antialiasing ON
dstArgs.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

for (int i = startIndex; i < startIndex + length; ++i)
{
Random rand = new Random(reseed);
Rectangle rect = rois[i];
// Copy existing image (source) to destination
for (int y = rect.Top; y < rect.Bottom; ++y)
{
for (int x = rect.Left; x < rect.Right; ++x)
{
dstArgs.Surface[x, y] = srcArgs.Surface[x, y];
}
}

for (int tr = 0; tr < tkNbTriangles; ++tr)
{
x1 = rand.Next(Math.Abs(KWidth + tkOverlay)) - tkOverlay;
x2 = rand.Next(Math.Abs(KWidth + tkOverlay)) - tkOverlay;
x3 = rand.Next(Math.Abs(KWidth + tkOverlay)) - tkOverlay;
y1 = rand.Next(Math.Abs(KWidth + tkOverlay)) - tkOverlay;
y2 = rand.Next(Math.Abs(KWidth + tkOverlay)) - tkOverlay;
y3 = rand.Next(Math.Abs(KWidth + tkOverlay)) - tkOverlay;

//br = (byte)(col * (int)(rand.Next(16) * 16 * colF));
ba = (byte)(rand.Next(256));
br = (byte)(rand.Next(256));
bg = (byte)(rand.Next(256));
bb = (byte)(rand.Next(256));

SolidBrush myBrush = new SolidBrush(Color.FromArgb(ba, br, bg, bb));

if (x1 > y1) { sav = x1; x1 = y1; y1 = sav; }
if (x2 > y2) { sav = x2; x2 = y2; y2 = sav; }
if (x3 > y3) { sav = x3; x3 = y3; y3 = sav; }

for (int pt = 0; pt < 8; ++pt)
{
switch (pt)
{
case 0:
px1 = x1;
px2 = x2;
px3 = x3;
py1 = y1;
py2 = y2;
py3 = y3;
break;
case 1:
px1 = x1;
px2 = x2;
px3 = x3;
py1 = -y1;
py2 = -y2;
py3 = -y3;
break;
case 2:
px1 = -x1;
px2 = -x2;
px3 = -x3;
py1 = -y1;
py2 = -y2;
py3 = -y3;
break;
case 3:
px1 = -x1;
px2 = -x2;
px3 = -x3;
py1 = y1;
py2 = y2;
py3 = y3;
break;
case 4:
px1 = y1;
px2 = y2;
px3 = y3;
py1 = x1;
py2 = x2;
py3 = x3;
break;
case 5:
px1 = y1;
px2 = y2;
px3 = y3;
py1 = -x1;
py2 = -x2;
py3 = -x3;
break;
case 6:
px1 = -y1;
px2 = -y2;
px3 = -y3;
py1 = -x1;
py2 = -x2;
py3 = -x3;
break;
default:
px1 = -y1;
px2 = -y2;
px3 = -y3;
py1 = x1;
py2 = x2;
py3 = x3;
break;
}

// Create points that define polygon (x,y).
Point point1 = new Point((int)(CenterX + px1), (int)(CenterY + py1));
Point point2 = new Point((int)(CenterX + px2), (int)(CenterY + py2));
Point point3 = new Point((int)(CenterX + px3), (int)(CenterY + py3));
Point[] Piece = { point1, point2, point3 };
dstArgs.Graphics.FillPolygon(myBrush, Piece);
}
}
}
}
}

public override EffectConfigDialog CreateConfigDialog()
{
ThreeAmountsConfigDialog dialog = new ThreeAmountsConfigDialog();
dialog.Amount1Label = Strings.KaleidoGen_Amount1_Name;
dialog.Amount1Minimum = +1;
dialog.Amount1Maximum = +100;
dialog.Amount1Default = 10;

dialog.Amount2Label = Strings.KaleidoGen_Amount2_Name;
dialog.Amount2Minimum = -200;
dialog.Amount2Maximum = +200;
dialog.Amount2Default = 50;

dialog.Amount3Label = Strings.KaleidoGen_Amount3_Name;
dialog.Amount3Minimum = +1;
dialog.Amount3Maximum = +1000;
dialog.Amount3Default = 300;

dialog.Text = Strings.KaleidoGen_Name;

return dialog;
}
public KaleidoGen()
: base(Strings.KaleidoGen_Name, Resources.KaleidoGen, null, EffectDirectives.None, true)
{
}

}
}
```

As you could see I use the Clip...

##### Share on other sites

MadJik, sure, you are using clipping, but I do not believe you are using it correctly.

Remember, your render routine is being passed in an ARRAY of rectangles of interest (ROI). You are not processing through all of them. As you do, you need to clip to each one of them as you are rendering the image.

##### Share on other sites

I've moved down the 'clip' instruction in the ROI for/loop.

It seems a bit better, but still not enought for publishing...

I give up for now on this projet.

This is the last source version.

If anyone got a better solution, please let me know on this topic...

The DLL is included in the zip...

Don't add this version in the PPP

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×