Jump to content

asciiArt effect plugin


joejoe

Recommended Posts

hello all,

i'm trying to create asciiArt effect plugin and i don't understand how to draw any text into image.

Function Fonts.DrawText putting into image text with some kind of strange alias or overlay.

string wholeText = "hello world";
textFont = new Font("Arial", 10); // from FontDialog
int characterIndex = 0;
string selectedChar = wholeText.Substring(characterIndex,1); 
Fonts.DrawText(
 dstArgs.Graphics,
 textFont,
 selectedChar,
 new Point(x - textFont.Height / 3, y - textFont.Height / 2),
 true,
 FontSmoothing.Smooth);

Example of image created with this plugin:

http://www.stud.fit.vutbr.cz/~xmlich02/foto/showDetail.php?id=79

Binnary of this plugin: http://www.stud.fit.vutbr.cz/~xmlich02/AsciiArt_dll.rar

Source codes of plugin: [private message, email, <spam>]

Can anybody help with this problem?

Link to comment
Share on other sites

A quick look at your example image tells me that you are probably not clipping your output string to the ROI.

I would recommend studying the source code I wrote for the Polygon plugin. Once you understand it, you should be able to easily write your plugin.

http://paintdotnet.12.forumer.com/viewtopic.php?t=2580

(Look near the bottom of my first post for the section called Source Code. The VS2005 code includes some comments that sould help you.)

You may also want to study the composition technique used in my Ink Sketch plugin (search the plugin forum for the post, the source code is included). You'll probably want to Black and White (desaturate) the image and adjust the image's brightness (adjustable) and contrast (100%) before attempting to convert to ASCII.

As for the overlay problem, I believe that the destination canvas already contains a copy of the source canvas when your effect starts.

Hope this stuff helps you. Let me know if I can answer any more questions.

BTW, I had considered making one of these plugins myself, but before I wrote Polyogn and Ink Sketch I didn't have the proper knowledge yet. I have a small ASCII art page here: http://www.geocities.com/boltbaits/ascii_art/index.html

Link to comment
Share on other sites

A quick look at your example image tells me that you are probably not clipping your output string to the ROI.

Probably i misundersands how to use clipping rectangles, because when i turn on clipping then no text is rendered.

for (int i = startIndex; i < startIndex + length; ++i) {
 Rectangle rect = rois[i];
 dstArgs.Graphics.Clip = new Region(rect); 
//  for (x) { for (y) { if (indexMatrix(x,y)) drawChar(...); }}
}

You'll probably want to Black and White (desaturate) the image and adjust the image's brightness (adjustable) and contrast (100%) before attempting to convert to ASCII.

I'm using 2 pass method:

1st pass: transform color to grayscale, threshold, store position to matrix and clear destination image.

2nd pass: read matrix with positions and draw text.

As for the overlay problem, I believe that the destination canvas already contains a copy of the source canvas when your effect starts.

Overlay is maybe not well definition of problem. Rendered characters are corupted and not readable. When is a good constalation of font size and style, then can i recognise "hello world" string in image, but it's harder than captcha image (-;

I've made another experiment with code. Instead of drawing string i'm trying to draw 4x4 filled rectangles.

source code for codelab plugin

leaf_part.png

On the image can i see the same problem. There should be blue 4x4px rectangles.

Link to comment
Share on other sites

bool [,] surfaceIndex = null;
int div = 40000;
int treshold = 200;
int distanceX = 5;
int distanceY = 5;

int color_element;
bool applyFilter = true; // if (false) { tresholding_only(); }
unsafe void Render(Surface dst, Surface src, Rectangle rect)
{
   surfaceIndex = new bool[rect.Right,rect.Bottom];

 for (int y = rect.Top; y < rect.Bottom; ++y)
 {
     for (int x = rect.Left; x < rect.Right; ++x)
     {
         ColorBgra color = src[x, y];
         // RGB to grayscale
         color_element = (byte)((double)color.R * 0.299 + (double)color.G * 0.587 + (double)color.B * 0.114);
         if (!applyFilter) // tresholding only
         {
             dst[x, y] = (color_element > treshold)
                 ? ColorBgra.FromBgra(255, 255, 255, 255)
                 : ColorBgra.FromBgra(0, 0, 0, 255);
         }
         else // if applyFilter
         {
            // clear destination image
            dst[x, y] = ColorBgra.FromBgra(255,255,255, 255);
            // store position matrix
            surfaceIndex[x, y] = ((x % distanceX == 0) && (y % distanceY == 0) && (color_element < treshold));
         } // endof if applyFilter

     } // foreach(x)
 } // foreach(y)

 if (applyFilter) {

       // second pass    

   for (int y = rect.Top; y < rect.Bottom; ++y)
   {
     for (int x = rect.Left; x < rect.Right; ++x)
     {
           if (surfaceIndex[x,y]) {
               // draw square 4x4 pixel 
               for (int i = 0; i < 4; i++) {
                 for (int j = 0; j < 4; j++) {
                   dst[x + i,y + j] = ColorBgra.FromBgra(128, 0, 0, 255);
                 }
               }
               // graphics.DrawString()
           }
     } // foreach(x)
   } // foreach(y)
 } // if applyFilter
}

Laziness rules, BoltBait.

~~

Link to comment
Share on other sites

I have probably found the solution of my problems with rendering:

The rendering loop is probably implemented by a few calls of function Render(...). So when i'm trying to draw text on position defined by pixel inside of this selection, then the letter almost aways is outside of roi rectagles.

1st problem: i cant use Clipping with roi boundaries to clip the text (i have to use different clipping recangle)

2nd problem: Selection is not aways rectangle, but sometimes elipse or any strange shape

3rd problem: Render function is called a few times for one "refresh" (not once for one refresh as i have assumed earlier). So second call of Render function overwrites result of first call, etc.

1st a 2nd problem solution: i'm using self-made checking of boundaries:

Rectangle letterRect = new Rectangle(x, y, letter.Width, letter.Height);
if (isInside(letterRect, selectionBoundarie)) { drawString(...) }

- better solution whould be design pattern map

( int[,] selectionMap = new int[picture.Width, picture.Height]; foreach (x,y) { selectionMap[x,y] = isSelected(x,y) ? 0xFFFF : 0x0;} ), but it's a lot of work and it's not task of effect plugin, it's task of API

3rd problem solution:

- i have disabled multiprocessor (multithread) support for this effect plugin

-> position of next part of selection shape for rendering function is down in comparsion with previous part of selection shape.

- drawString(x, y - Font.Height, ...)

So final result of this dicussion is almost done plugin. I have to cleanup source codes - delete messy code, add comments and make some culture in source code at all. After that i will send links for download.

Link to comment
Share on other sites

  • 1 month later...

Join the conversation

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

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

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

×
×
  • Create New...