C语言作图库(kplot)示例

时间:2022-07-23
本文章向大家介绍C语言作图库(kplot)示例,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

分享一个c语言作图的库kplot,github链接为 https://github.com/kristapsdz/kplot 。

我们首先要安装好kplot, kplot依赖cairo 和 libbsd,我们以centOS 7.4为例进行安装。

sudo yum -y install libbsd.x86_64 libbsd-devel.x86_64 cairo.x86_64 cairo-devel.x86_64
git clone https://github.com/kristapsdz/kplotcd kplot;
make PREFIX=/usr 
sudo make install

安装好了之后我们就可写我们的示例代码了,代码由scatterPlot.c, kvec.h(来自klib,一般情况我们直接git clone https://github.com/attractivechaos/klib 到与 scatterPlot.c 同一目录就行), IO_stream.h 三个文件组成。编译命令和源码如下,编译后我们就可用以下命令测试并画图如下的图:

编译

gcc -g -O3 -Wall `pkg-config --cflags --silence-errors cairo || echo '-I/opt/X11/include/cairo'` -Iklib scatterPlot.c -o scatterPlot `pkg-config --libs --silence-errors cairo || echo '-L/opt/X11/lib -lcairo'` -lz -lkplot -lm

运行测试

Rscript -e 'print(cbind(cars,loess(dist~speed,data=cars)$fit),row.names =FALSE)'|sed '1d'| ./scatterPlot -o out -

结果如下图:

源码:

IO_stream.h

#ifndef _IO_H#define _IO_H#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <zlib.h>//#include <err.h>#include <fcntl.h>#include <unistd.h>#include <time.h>#include <sys/time.h>/*
typedef pFILE FILE *;
#define OPEN_STREAM(TYPE,fileno,mode)    
TYPE open_stream_##TYPE(char* filename,void(*f)(int , const char *)) {        
    int fd ;                                                                
    if (strncmp(filename,"-", 1)==0) {                                        
        fd = fileno;                                                        
    } else {                                                                
        fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666 );            
        if (fd==-1) err(1, "Failed to create output file (%s)", filename);    
    }                                                                        
    TYPE out = f(fd,mode);                                                    
    return out;                                                                
}

#define CREATE_OUTFILE(TYPE)    
TYPE creat_outfile_##TYPE(char *outfile,char *suffix) {
    char *out=(char *)calloc(strlen(outfile)+strlen(suffix)+2,sizeof(char));
    sprintf(out,"%s%s",outfile,suffix);
    if (!strncmp(outfile,"-",1)){
        TYPE fo=open_stream_##TYPE(out,fdopen);
    }
    else{
        TYPE fo=open_stream_##TYPE(out,gzdopen);
    }
    return fo;
}

OPEN_STREAM(pFILE,STDOUT_FILENO,"wb")
OPEN_STREAM(gzFile,STDOUT_FILENO,"wb")

CREATE_OUTFILE(gzFile)
CREATE_OUTFILE(pFILE)
*/static inline FILE *fopen_input_stream(const char *filename);static inline FILE *fopen_output_stream(const char *filename);static inline FILE *fcreat_infile(const char *infile,const char *suffix);static inline FILE *fcreat_outfile(const char *outfile,const char *suffix);static inline gzFile open_output_stream(const char* filename);static inline gzFile creat_outfile(char *outfile,char *suffix);static inline gzFile open_input_stream(const char *filename);//static inline void error(const char *format, ...);static inline long long usec(void);long long usec(void){    struct timeval tv;
    gettimeofday(&tv,NULL);    return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;
}void error(const char *format, ...) {
    va_list ap;
    va_start(ap, format);    vfprintf(stderr, format, ap);
    va_end(ap);    exit(EXIT_FAILURE);
}

FILE *fopen_input_stream(const char *filename){    int fd ;    if (strncmp(filename,"-", 1)==0 || !strcmp(filename,"")) {
        fd = STDIN_FILENO;
    } else {#if defined(__APPLE__) && defined(__MACH__) || defined(unix) || defined(linux)
        fd = open(filename, O_CREAT | O_RDONLY , 0666 );#else
        fd = _open(filename, _O_CREAT|_O_BINARY | _O_RDONLY , 0666 );#endif
        if (fd==-1) fprintf(stderr, "Failed to create input file (%s)", filename);
    }
    FILE *in = fdopen(fd,"rb");    return in;
}

FILE *fopen_output_stream(const char *filename) {    int fd ;    if (strncmp(filename,"-", 1)==0 || !strcmp(filename,"")) {
        fd = STDOUT_FILENO;
    } else {#if defined(__APPLE__) && defined(__MACH__) || defined(unix) || defined(linux)
        fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666 );#else
        fd = _open(filename, _O_CREAT|_O_BINARY | _O_WRONLY | _O_APPEND |_O_TRUNC, 0666 );#endif
        if (fd==-1) fprintf(stderr, "Failed to create output file (%s)", filename);
    }
    FILE *out = fdopen(fd,"wb");    return out;
}

FILE *fcreat_infile(const char *infile,const char *suffix) {    char in[strlen(infile)+strlen(suffix)+2];    sprintf(in,"%s%s",infile,suffix);
    FILE *fi=fopen_output_stream(in);    return fi;
}

FILE *fcreat_outfile(const char *outfile,const char *suffix) {    char *out=(char *)calloc(strlen(outfile)+strlen(suffix)+2,sizeof(char));    sprintf(out,"%s%s",outfile,suffix);
    FILE *fo=fopen_output_stream(out);    return fo;
}

gzFile open_output_stream(const char* filename) {    int fd ;    if (strncmp(filename,"-", 1)==0 || !strcmp(filename,"")) {
        fd = STDOUT_FILENO;
    } else {#if defined(__APPLE__) && defined(__MACH__) || defined(unix) || defined(linux)
        fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666 );#else
        fd = _open(filename, _O_CREAT|_O_BINARY | _O_WRONLY | _O_APPEND |_O_TRUNC, 0666 );#endif
        if (fd==-1) fprintf(stderr, "Failed to create output file (%s)", filename);
    }
    gzFile out = gzdopen(fd,"wb");    return out;
}

gzFile creat_outfile(char *outfile,char *suffix) {    char *out=(char *)calloc(strlen(outfile)+strlen(suffix)+2,sizeof(char));    sprintf(out,"%s%s",outfile,suffix);
    gzFile fo=open_output_stream(out);    return fo;
}

gzFile open_input_stream(const char *filename){    int fd ;    if (strncmp(filename,"-", 1)==0 || !strcmp(filename,"")) {
        fd = STDIN_FILENO;
    } else {#if defined(__APPLE__) && defined(__MACH__) || defined(unix) || defined(linux)
        fd = open(filename, O_CREAT | O_RDONLY, 0666 );#else
        fd = _open(filename, _O_CREAT|_O_BINARY | _O_RDONLY , 0666 );#endif
        if (fd==-1) fprintf(stderr, "Failed to create input file (%s)", filename);
    }
    gzFile in = gzdopen(fd,"rb");    return in;
}#endif

kvec.h

/* The MIT License

   Copyright (c) 2008, by Attractive Chaos <attractor@live.co.uk>

   Permission is hereby granted, free of charge, to any person obtaining
   a copy of this software and associated documentation files (the
   "Software"), to deal in the Software without restriction, including
   without limitation the rights to use, copy, modify, merge, publish,
   distribute, sublicense, and/or sell copies of the Software, and to
   permit persons to whom the Software is furnished to do so, subject to
   the following conditions:

   The above copyright notice and this permission notice shall be
   included in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   SOFTWARE.
*//*
  An example:

#include "kvec.h"
int main() {
    kvec_t(int) array;
    kv_init(array);
    kv_push(int, array, 10); // append
    kv_a(int, array, 20) = 5; // dynamic
    kv_A(array, 20) = 4; // static
    kv_destroy(array);
    return 0;
}
*//*
  2008-09-22 (0.1.0):

    * The initial version.

*/#ifndef AC_KVEC_H#define AC_KVEC_H#include <stdlib.h>#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))#define kvec_t(type) struct { size_t n, m; type *a; }#define kv_init(v) ((v).n = (v).m = 0, (v).a = 0)#define kv_destroy(v) free((v).a)#define kv_A(v, i) ((v).a[(i)])#define kv_pop(v) ((v).a[--(v).n])#define kv_size(v) ((v).n)#define kv_max(v) ((v).m)#define kv_resize(type, v, s)  ((v).m = (s), (v).a = (type*)realloc((v).a, sizeof(type) * (v).m))#define kv_copy(type, v1, v0) do {                            
        if ((v1).m < (v0).n) kv_resize(type, v1, (v0).n);    
        (v1).n = (v0).n;                                            memcpy((v1).a, (v0).a, sizeof(type) * (v0).n);        
    } while (0)                                                #define kv_push(type, v, x) do {                                    
        if ((v).n == (v).m) {                                        
            (v).m = (v).m? (v).m<<1 : 2;                            
            (v).a = (type*)realloc((v).a, sizeof(type) * (v).m);    
        }                                                            
        (v).a[(v).n++] = (x);                                        
    } while (0)#define kv_pushp(type, v) (((v).n == (v).m)?                            
                           ((v).m = ((v).m? (v).m<<1 : 2),                
                            (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0)    
                           : 0), ((v).a + ((v).n++))#define kv_a(type, v, i) (((v).m <= (size_t)(i)? 
                          ((v).m = (v).n = (i) + 1, kv_roundup32((v).m), 
                           (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) 
                          : (v).n <= (size_t)(i)? (v).n = (i) + 1 
                          : 0), (v).a[(i)])#endif