views:

162

answers:

2

I am working on applying artistic effects to image . Can you please tell me how to achieve this effect ?

Any inputs are appreciated .....

Input Image : alt text http://www.flickr.com/photos/vineet%5Faggarwal/4205359333/

Output Image: alt text http://www.flickr.com/photos/vineet%5Faggarwal/4205359335/,

A: 

The koala in the second image is a 3D image... the computer cannot easily work out from your first image which bits should be raised and which bits should be lowered.

I suggest a >Human Being< to do the job, though a computer could help...

If you have a list of the heights of all the tiles, (created by a graphics artist... yourself perhaps?) you can render them into a blank frame buffer one at a time. Render them using anti-aliasing in sequence from ther backmost tiles to the front-most. It appears that the colour value selected for each tile is based on the average colour values in a corresponding squarish rectangle (that may or may not fall on exact pixel boundaries). But how the average is calculated is not clear to me, it may be based on RGB or HSV it may be a simple mean or a weighted mean, non-linear or whatever and you may need to consider gamma correction (see links).

Presumably the tile (before being rendered) to the canvas has its color space warped to match the colour of the corresponding area in the original image.

I am ignoring subtleties I imagine you probably don't care about or want to make time for like whether the shadows and highlights should be corrected to be darker or lighter on darker or lighter tiles than some reference tile after colour warping, and reflection in the scene. OTOH If these fine details are important, you should consider building up the whole thing in 3D using OpenGL. OTOOH (three hands - whoopee) maybe you should not use VC++ at all and do this using a drawing package...

Here's a code outline illustration, I haven't thought it through entirely, this is just a rough sketch, you'll need to get to grips with this, fix any problems and mistakes I may have made and make it your own:-

int input_width, input_height, tile_width, tile_height;
int heights_width, heights_height, err=0, height, x, y;
char* input_pixels=NULL, *output_pixels=NULL, *tile_pixels=NULL;

char* modified_tile=NULL; int *heights_data=NULL;

if (!err) err =my_jpeg_read_func("koala.jpg",&width,&height,&input_pixels);
if (!err) err =my_png_read_func("ref-tile.png",&width,&height,&tile_pixels);
if (!err) err =my_read_tile_heights_func("tile-heights.csv",
  &heights_width,&heights_height,&heights_data);
if (!err) err =(output_pixels = malloc(input_width*input_height*3))==NULL;
if (!err) err =(modified_tile = malloc(tile_width*tile_height*4))==NULL;
if (!err) for (height=0; height<256; height++) for (x=0; x < heights_width; x++)
  for (y=0; y<heights_height; y++) if (heights_data[y*heights_width+x]==height) {
  int colorvalue = grabcolorvalue(input_pixels, input_widthh, input_height,
    heights_width, heights_height, x, y);
  create_colored_tile_by_color_space_warping(tile_pixels, modified_tile,
    tile_height, tile_width, colorvaLue);
  draw_tile(output_pixels, input_width, input_height, x, y, heights_width,
    heights_height, modified_tile, tile_width, tile_height);
}
if (!err) err=my_jpeg_wrapper_write("koala-out.jpg", output_pixels,
  input_width, input_height);
if (input_pixels) free(input_pixels); input_pixels=NULL;
if (output_pixels) free(output_pixels); output_pixels=NULL;
if (tile_pixels) free(tile_pixels); tile_pixels=NULL;
if (modified_tile) free(modified_tile); modifie_tile=NULL;
if (err) report_error_to_user(err);

The JPEG library will not necessarily give you data in RGB, it might be in HSV or something else, I forget now. But the color space transformations you need are a matter largely of maths with a little bit of fudging and rounding and other kludges where required.

There's lots of rounding and scaling and positioning issues too that I haven't mentioned.

In the above 3 bytes per pixel for main pixel buffers but 4 bytes (RGBA) for tiles.

Read about:

http://en.wikipedia.org/wiki/Anti-aliasing

AND

http://en.wikipedia.org/wiki/Alpha%5Fcompositing

AND

http://en.wikipedia.org/wiki/Color%5Fspace

AND

http://en.wikipedia.org/wiki/Libjpeg

AND

http://en.wikipedia.org/wiki/Libpng

AND

http://en.wikipedia.org/wiki/Zlib (since libpng uses zlib)

AND

http://en.wikipedia.org/wiki/Gamma%5Fcorrection

IMHO Using C++ is fine, but you'll be working so low-level and not using polymorphism so probably OO concepts and encapsulation is not going to benefit you that much over C concepts and encapsulation. Feel free to write the methods as functions in a C++ namespace and/or methods on a C++ object and include the pixel buffers as member variables (or whatever) if you want to make the code more consistent in form with some other C++ you have though. Personally I would try to write it in pure C for maximum reusability. You can make most C modules work with C++ by using extern "C" conditionally with preprocessor directives in the headers.

EDIT

The my_jpeg_read_func, my_png_read_func, grabcolorvalue, create_colored_tile_by_color_space_warping, draw_tile, my_jpeg_wrapper_write, and report_error_to_user and maybe some others have to be written yourself, and you may need to include libjpg, zlib and libpng in your project and add headers and/or #includes.

EDIT

Though this could be done in OpenGL, I would suggest that rendering the rounded highlighted shapes of the tops of the tiles well might be a teensy bit hard to do convincingly. Any OpenGLers or Direct3D programmers got an answer?

EDIT

Changed ref-tile.jpg to ref-tile.png.

martinr
+1  A: 

Please See: http://www.codeproject.com/KB/graphics/CBitmapEx.aspx?msg=3312512#xx3312512xx

PS: You have to First understand the CBitmapEx class written by the Author.

vineet
Hey the way to emboss the image without greying it is to correct the overall hue and brightness to match the pre-embossed tile (ie single flat colour), to the extent that that is possible for a given tile colour. It may be desirable to mix in some of the flat colour as well to get a closer colour match, but this is perhaps a compromise. Obviously there are fundamental limits for colours close to the edge of the colour spectrum - you cannot highlight a white tile without greying it, and you cannot shade a black tile without greying it. It depends what you want the image to look like.
martinr
If it was me, I'd do compromises on the white, close-to-white, black and close-to-black tiles and not the others, and recommend users to use colours not too close to black or white.
martinr
Another option is to go in the direction of some cartoonists - keep a bit buffer for which pixels should really be whiter-than-white or blacker-than-black, but can't be because of color space limitations, and in the final image, draw a fine line round splashes of those areas. Another option, if you are not outputting to a computer monitor is to increase the apparent brightness of some areas in some other way, eg with specialist lighting. Within the bounds of computer imaging on a computer monitor, without cartoonist compromises, your options are severely limited! "Bad koala - too white"?
martinr