Now, were do you get them from? Sure, there is knobman which runs fine in wine or as java version, but, I'm not really satisfied with the results. A much better result could be reached with blender, just blender has a somewhat step learning curve that I give up on it, special because I'm not a designer, more a developer.
So, cairo comes on the plan, and I wrote a little prog which creates basic knob images for me, as shown below.
The prog just cover the basics, and only takes 3 args on command line , that's the size of the knob, the frame count and, optional a offset, which means space around the knob. Other parameters like knob colour, border colour, 3d shading, pointer size and stuff like that, needs to be edited in the source, to cover the needs. So this is a tool for developers. The prog create the image in svg and png format.
I place the source below in public domain, so, you could grab it and do with it what ever you wont. Maybe you are the one who extend it to make it a knobman like tool for linux?
The gif above was created with a size of 61 and 65 frames.
So here it is:
Code: Select all
#include <cairo.h>
#include <cairo-svg.h>
#include <math.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
// gcc -Wall -g make_knob_image.c -lm `pkg-config --cflags --libs cairo` -o knobmake
#ifndef min
#define min(x, y) ((x) < (y) ? (x) : (y))
#endif
#ifndef max
#define max(x, y) ((x) < (y) ? (y) : (x))
#endif
const double scale_zero = 20 * (M_PI/180); // defines "dead zone" for knobs
static void paint_knob_state(cairo_t *cr, int knob_size, int knob_offset, double knobstate)
{
/** set knob size **/
int arc_offset = knob_offset;
double knob_x = knob_size-arc_offset;
double knob_y = knob_size-arc_offset;
double knobx = arc_offset/2;
double knobx1 = knob_x/2;
double knoby = arc_offset/2;
double knoby1 = knob_y/2;
/** create the knob, set the knob and border color to your needs,
* or set knob color alpa to 0.0 to draw only the border **/
cairo_arc(cr,knobx1+arc_offset/2, knoby1+arc_offset/2, knob_x/2.1, 0, 2 * M_PI );
cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, 1.0); // knob color
cairo_fill_preserve (cr);
cairo_set_source_rgb (cr, 0.2, 0.2, 0.2); // knob border color
cairo_set_line_width(cr,min(5, max(2,knob_x/30)));
cairo_stroke(cr);
/** calculate the pointer **/
double angle = scale_zero + knobstate * 2 * (M_PI - scale_zero);
double pointer_off =knob_x/10;
double radius = min(knob_x-pointer_off, knob_y-pointer_off) / 2;
double length_x = (knobx+radius+pointer_off/2) - radius * sin(angle);
double length_y = (knoby+radius+pointer_off/2) + radius * cos(angle);
double radius_x = (knobx+radius+pointer_off/2) - radius/ 1.5 * sin(angle);
double radius_y = (knoby+radius+pointer_off/2) + radius/ 1.5 * cos(angle);
/** create the rotating pointer on the knob,
* set the color to your needs **/
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
cairo_set_line_join(cr, CAIRO_LINE_JOIN_BEVEL);
cairo_move_to(cr, radius_x, radius_y);
cairo_line_to(cr,length_x,length_y);
cairo_set_source_rgb (cr, 0.2, 0.2, 0.2); // knob pointer color
cairo_set_line_width(cr,min(5, max(2,knob_x/30)));
cairo_stroke(cr);
/** 3d shading comment out, or set alpa to 0.0, for flat knobs
* or set alpa to a higher value for more shading effect **/
cairo_arc(cr,knobx1+arc_offset/2, knoby1+arc_offset/2, knob_x/2.1, 0, 2 * M_PI );
cairo_pattern_t*pat =
cairo_pattern_create_radial (knobx1+arc_offset-knob_x/6,knoby1+arc_offset-knob_x/6, 1,knobx1+arc_offset,knoby1+arc_offset,knob_x/2.1 );
cairo_pattern_add_color_stop_rgba (pat, 0, 0.8, 0.8, 0.8, 0.2);
cairo_pattern_add_color_stop_rgba (pat, 1, 0.0, 0.0, 0.0, 0.2);
cairo_set_source (cr, pat);
cairo_fill (cr);
cairo_pattern_destroy (pat);
}
int main(int argc, char* argv[])
{
if (argc < 3) {
fprintf(stdout, "usage: %s knob_size frame_count [offset] \n", basename(argv[0]));
return 1;
}
int knob_size = atoi(argv[1]);
int knob_frames = atoi(argv[2]);
int knob_image_width = knob_size * knob_frames;
int knob_offset = 0;
if (argc >= 4) {
knob_offset = atoi(argv[3]);
}
char* sz = argv[1];
char* fr = argv[2];
char png_file[80];
char svg_file[80];
sprintf(png_file, "knob_%sx%s.png", sz,fr);
sprintf(svg_file, "knob_%sx%s.svg", sz,fr);
/** use this instead the svg surface when you don't need the svg format **/
//cairo_surface_t *frame = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, knob_size, knob_size);
cairo_surface_t *frame = cairo_svg_surface_create(NULL, knob_size, knob_size);
cairo_t *crf = cairo_create(frame);
/** use this instead the svg surface when you don't need the svg format **/
//cairo_surface_t *knob_img = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, knob_image_widht, knob_size);
cairo_surface_t *knob_img = cairo_svg_surface_create(svg_file, knob_image_width, knob_size);
cairo_t *cr = cairo_create(knob_img);
/** draw the knob per frame to image **/
for (int i = 0; i < knob_frames; i++) {
paint_knob_state(crf, knob_size, knob_offset, (double)((double)i/ knob_frames));
cairo_set_source_surface(cr, frame, knob_size*i, 0);
cairo_paint(cr);
cairo_set_operator(crf,CAIRO_OPERATOR_CLEAR);
cairo_paint(crf);
cairo_set_operator(crf,CAIRO_OPERATOR_OVER);
}
/** save to png file **/
cairo_surface_flush(knob_img);
cairo_surface_write_to_png(knob_img, png_file);
/** clean up **/
cairo_destroy(crf);
cairo_destroy(cr);
cairo_surface_destroy(knob_img);
cairo_surface_destroy(frame);
return 0;
}