Re: Linen Texture

ed44 <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <[email protected]>
On 07/30/2013 02:00 PM, Bobby Salazar wrote:
> On 7/29/13, Simon Sapin<[email protected]>  wrote:
>> Le 29/07/2013 13:35, Bobby Salazar a écrit :
>>> Does anyone know if it is possible to produce a linen texture using
>>> Cairo? Ideally I would like to create a Cairo pattern than can be used
>>> to fill a path. Ideally, I would like something similar to this:
>>>
>>> http://tutvid.com/create-linen-texture-photoshop/
>>>
>>> Does anyone have any ideas how to accomplish this?
>> If you’re doing something pixel-based:
>>
>> 1. Do as in that link you gave
>> 2. Save the result as PNG
>> 3. Use cairo_image_surface_create_from_png() to get a cairo surface
>> 4. Make a surface pattern from that
>> 5. Set the pattern’s "extend" to CAIRO_EXTEND_REPEAT
>> 6. Use the pattern as a source.
>>
>> http://cairographics.org/manual/cairo-PNG-Support.html
>> http://cairographics.org/manual/cairo-cairo-pattern-t.html
>> http://cairographics.org/manual/cairo-cairo-t.html
>>
>>
>> If you want vectors it’s gonna be more tricky: you’ll need to express
>> the effect you want in terms of paths, colors, gradients, etc.
> I was hoping that somebody knew a good way to produce the linen
> texture using Cairo calls instead of me having to import raw pixel
> data from an outside source.
>
> Does anyone know of a way to reproduce this kind of look at run-time?


Interesting problem.

The attached little example comes close.

compile with : gcc linepatterns_cairo.c `pkg-config cairo --cflags 
--libs` -o patterns

scrollwheel changes linewidth (makesthe result darker/lighter )
Hold MB1 to pause
MB3 while holding MB1 will produce two png's
MB2 switch between REPEAT/REFLECT

There are many values that influence the result and it might need
some more randomness somewhere...just experiment...

Ed.

-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
Linepattern_with_cairo.png (image/png, 42.3 KB) - not displayed
linepatterns_cairo.c (text/plain, 6.2 KB)
/*
*	Linepatterns with Cairo
* 	07-31-2013 Ed44
* 	
* 	Compile with :   gcc linepatterns_cairo.c `pkg-config cairo --cflags --libs` -o patterns
*/

#include <stdio.h>
#include <stdlib.h>
#include <cairo.h>
#include<cairo-xlib.h>
#include<X11/Xlib.h>
#include <X11/Xutil.h>
#include <cairo/cairo-xlib.h>

#include <sys/time.h>

static Display	*disp;
static Window 	rootwindow, mainwindow;
static Atom	wm_delete;
static int		screennumber;
static Visual	*visual;
static int		depth;
static GC		Gc;
int ww=500, wh=500;
static cairo_t *win_cr, *im_cr, *cr;

int64_t
current_time()
{
	struct timeval time;

	gettimeofday(&time, NULL);
	return (int64_t)time.tv_sec*1000000+time.tv_usec;
}

int
main()
{
	XWindowAttributes attr;
	cairo_pattern_t *pathor, *patvert, *pats;	
	XEvent event;
	cairo_extend_t etype=CAIRO_EXTEND_REPEAT;
	
	
	
	if((disp=XOpenDisplay(NULL))==NULL){
		printf("[PQ] Cannot open display...\n");
		return 1;
	}	
	screennumber=DefaultScreen(disp);
	rootwindow=RootWindow(disp, screennumber);

	depth=DefaultDepth(disp, screennumber);
	visual=DefaultVisual(disp, screennumber);
	Gc=DefaultGC(disp, screennumber);		
	wm_delete=XInternAtom(disp, "WM_DELETE_WINDOW", False);	
	
	mainwindow=XCreateWindow(disp, rootwindow, 0, 0, 500, 500,
		0, depth, InputOutput, visual, 0, NULL);
	XSetWindowBackgroundPixmap(disp, mainwindow, None);
	XSelectInput(disp, mainwindow, StructureNotifyMask
					|ExposureMask|KeyPressMask|
					ButtonPressMask|ButtonReleaseMask|
					Button1MotionMask|Button3MotionMask|Button2MotionMask|
					PointerMotionMask);

	XSetWMProtocols (disp, mainwindow, &wm_delete, 1);
	XSetWindowBackgroundPixmap(disp, mainwindow, None);

	XSizeHints hints;
	hints.max_width = 2048;
	hints.max_height = 2048;
	hints.win_gravity = StaticGravity;
	hints.flags = PMaxSize|PWinGravity;
	XSetWMNormalHints(disp, mainwindow, &hints);

	XStoreName(disp, mainwindow, "Linepatterns with cairo");
	
	XMapWindow(disp, mainwindow);
	usleep(10000);
	
	XGetWindowAttributes(disp, mainwindow, &attr);

	while(attr.map_state !=IsViewable){
		printf("Waiting for window mapping...\n");
		usleep(10000);
		XGetWindowAttributes(disp, mainwindow, &attr);
	}
	win_cr=cairo_create(cairo_xlib_surface_create(disp, mainwindow, visual,
						      500, 500));

	cr=cairo_create(cairo_image_surface_create(CAIRO_FORMAT_RGB24, 200, 200));	

	int x;
	unsigned short int rseed[3]={(short int)current_time(), 4573, 63132};
	seed48(rseed);	
	
	pathor=cairo_pattern_create_linear(0, 0, 39, 0);
	cairo_pattern_add_color_stop_rgba(pathor, 0,
					  0, 0, 0, 0);
	cairo_pattern_add_color_stop_rgba(pathor, 0.35,
					  0., 0.0, 0., 1);
	cairo_pattern_add_color_stop_rgba(pathor, 0.65,
					  0., 0.0, 0., 1);
	cairo_pattern_add_color_stop_rgba(pathor, 1,
					  0, 0, 0, 0);
	
	patvert=cairo_pattern_create_linear(0, 0, 0, 37);
	cairo_pattern_add_color_stop_rgba(patvert, 0,
					  0, 0, 0, 0);
	cairo_pattern_add_color_stop_rgba(patvert, 0.35,
					  0., 0., 0., 1);
	cairo_pattern_add_color_stop_rgba(patvert, 0.65,
					  0., 0., 0., 1);
	cairo_pattern_add_color_stop_rgba(patvert, 1,
					  0, 0, 0, 0);
		
	double linewidth=0.05;
	
	while(1)
	{
		cairo_set_source_rgb(cr, .5, .5, .5);
		cairo_paint(cr);

		int linelength=37, dirx=0, diry=0;
		double dx=0, dy=4;
	
		cairo_set_line_width(cr, linewidth);
	
		/*  create the pattern  */	
		for( x=0; x < 10000; x++)
		{
			if((x%100)==0){
				if(x%300)
					rseed[0]=(short int)(current_time()/(x+123));
				if(x%700)
					rseed[1]=(short int)(current_time() * x);
				rseed[2]=(short int)current_time()-x;
				seed48(rseed);

			}
			cairo_save(cr);
			
			if(dx > 235.0)
				dirx=1;		
			else if(dx < -35.0)
					dirx=0;
				
			if(dirx)	
				dx -=drand48()*63;
			else
				dx +=drand48()*83;

			if(dy > 235.0)
				diry=1;
			else if(dy < -35.0)
				diry=0;
			
			if(diry)	
				dy -=drand48()*63;
			else
				dy +=drand48()*73;

			cairo_translate(cr, dx, dy);
			cairo_scale(cr, drand48()*0.8 + 0.6, drand48()*0.9 + 0.6);
	
			cairo_set_source(cr, pathor);
			cairo_move_to(cr, 0, 0);
			cairo_line_to(cr, linelength, 0);
			cairo_stroke(cr);
	
			cairo_set_source(cr, patvert);
			cairo_move_to(cr, 0, 0);
			cairo_line_to(cr, 0, linelength);
			cairo_stroke(cr);

			cairo_restore(cr);
		}
		pats=cairo_pattern_create_for_surface(cairo_get_target(cr));
		cairo_pattern_set_extend(pats, etype);
		

		/*  paint the pattern to the window */	
		cairo_set_source(win_cr, pats);
		cairo_paint(win_cr);

		cairo_pattern_destroy(pats);
/*		cairo_surface_flush(cairo_get_target(win_cr));
		XSync(disp, 0);
*/	
		usleep(10000);
	
		while(XPending(disp)){
			XNextEvent(disp, &event);
		
			switch(event.type)
			{
				case ButtonPress:
					if(event.xbutton.button==1){
						do{
							usleep(40000);
							XNextEvent(disp, &event);
							if(event.type==ButtonPress
							&& event.xbutton.button==3){
								cairo_surface_write_to_png(cairo_get_target(win_cr),
											   "Linepattern_with_cairo.png");
								cairo_surface_write_to_png(cairo_get_target(cr),
											   "Linepattern_with_cairo_tile.png");
								
								printf("png..\n");
							}
						}while(event.type!=ButtonRelease);
					}
					if(event.xbutton.button==2){
						if(etype==CAIRO_EXTEND_REPEAT)
							etype=CAIRO_EXTEND_REFLECT;
						else
							etype=CAIRO_EXTEND_REPEAT;
					}
					if(event.xbutton.button==4){
						linewidth +=0.001;
						printf("linewidth=%f\n", linewidth);
					}	
					if(event.xbutton.button==5){
						linewidth -=0.001;
						if(linewidth < 0.005)
							linewidth=0.005;				
					
						printf("linewidth=%f\n", linewidth);
					}
					break;
				
				case ClientMessage:
					
					goto clean_and_exit;
					break;
				
				case ConfigureNotify:
					while(XCheckTypedWindowEvent(disp,
					event.xconfigure.window, ConfigureNotify, &event));
	
					if(event.xconfigure.send_event==True
					&& (	ww !=event.xconfigure.width
					|| 	wh !=event.xconfigure.height)){
						ww=event.xconfigure.width;
						wh=event.xconfigure.height;
						cairo_xlib_surface_set_size(cairo_get_target(win_cr), ww, wh);
					}

					break;
			
				default:

					break;
			}
		}
	}
	
clean_and_exit:
	
	cairo_pattern_destroy(pathor);
	cairo_pattern_destroy(patvert);
	cairo_surface_destroy(cairo_get_target(cr));
	cairo_destroy(cr);
	cairo_destroy(win_cr);
	XDestroyWindow(disp, mainwindow);
	XCloseDisplay(disp);
	return 0;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.