views:

385

answers:

1

Do exist any algorithms to create programmatically images, for use then a base for a color picking control?

If you know some useful sources for document or code about this topic they are welcome.

EDIT: my idea is to create a WPF Picker Control, I know there already some for WPF, Sacha's one, or the one from Microsoft Sample. The point of this question is not too much oriented to the technology I will use later, but to the algorithm for creating the image.

EDIT2: I would like to create something like the gradient image in the square, programmatically.

alt text

+2  A: 

Here are some possibilities:

  1. Create the image using overlapping linear gradient brushes.
  2. Create the image as a bitmap.
  3. Create the image during rendering using pixel shaders.

Overlapping gradient brushes

For the image you showed, you may be able to achieve the effect you need by using something along these lines:

<Grid>
  <Rectangle>
    <Rectangle.Fill>
      <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
        <GradientStop Offset="0" Color="#FFFF8040" />
        <GradientStop Offset="1" Color="#FFFFFFFF" />
      </LinearGradientBrush>
    </Rectangle.Fill>
  </Rectangle>
  <Rectangle>
    <Rectangle.Fill>
      <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
        <GradientStop Offset="0" Color="#FF000000" />
        <GradientStop Offset="1" Color="#00000000" />
      </LinearGradientBrush>
    </Rectangle.Fill>
  </Rectangle>
</Grid>

The first fill sets the color and the second fill darkens it. Obviously this could be done in a Drawing or a VisualBrush.

This is the easiest solution but is limited in what it can produce.

Creating the image as a bitmap

Using a bitmap will work but is not resolution-independent. You'll need to pick the resolution at which to create the bitmap. If you choose too low a resolution you'll get poor quality. If you choose too high a resolution you'll waste resources. Automatically selecting the resolution based on screen resolution and transforms is difficult but possible: You must subscribe to several events to detect resolution changes and use TransformToDevice on the target to determine the transform from WPF coordinates to device coordinates.

Once you have decided on the resolution for your bitmap, the rest is easy:

uint[] pixels = new uint[width*height];
for(int x=0; x<width; x++)
  for(int y=0; y<height; y++)
    pixels[y*width + x] = ComputeColor(x, y);

var bitmap = new WritableBitmap(width, height, 96, 96, PixelFormat.Pbgra32, null);
bitmap.WritePixels(new Rect(0, 0, width, height), pixels, width*4, 0);

Using pixel shaders

Pixel shaders actually run within the GPU itself, and they run for each pixel. They already know the target resolution, so the color computation is easy. What is difficult is that you can't write the algorithm in C# or VB.NET: You must write it in the High Level Shader Language (HLSL), which can be a significant learning curve.

Here are some web sites with examples of custom shaders:

Pixel shaders and silverlight WPF pixel shader effects library Interactive example

Ray Burns
GPU can stuff can also be done using Brahma http://brahma.ananthonline.net/
Dykam
@Dykam: Brahma looks very interesting, and quite useful for many purposes. Thanks for the link! For this particular question, without any integration with MILCore I don't think it could accomplish the same result as pixel shaders. In other words, Marco needs something that can run during WPF rendering when all graphics parameters inlcluding transforms, resolutions etc are available and not just as a LINQ query.
Ray Burns
Using the GPU using pixel shaders for graphics sounds indeed more obvious.
Dykam
@Ray thank you very much, for the answer, I am trying to implement the Bitmap solution, pixel shader it too much for me, at list now :D. Do you have any hints for a possible implementation of ComputeColor method?
marco.ragogna
For the colors in the example, your ComputeColor might generate coordinates in HSV color space by using a H=current_hue, S=1-y/ymax, V=x/xmax, then convert to RGB via the formulas given at http://en.wikipedia.org/wiki/HSV_color_space . The explanations there are very helpful as well.
Ray Burns
thank you, i have done it using the bitmap approach
marco.ragogna