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;
}