/* $Id: drv_Image.c,v 1.3 2004/05/31 06:24:42 reinelt Exp $ * * new style Image (PPM/PNG) Driver for LCD4Linux * * Copyright 1999-2004 Michael Reinelt * Copyright 2004 The LCD4Linux Team * * This file is part of LCD4Linux. * * LCD4Linux is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * LCD4Linux is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * $Log: drv_Image.c,v $ * Revision 1.3 2004/05/31 06:24:42 reinelt * * fixed symlink security issue with the image driver * * Revision 1.2 2004/05/29 23:30:20 reinelt * * fixed a compiler issue with drv_Image.c (thanks to Frank Stratmann) * * Revision 1.1 2004/05/25 14:27:21 reinelt * * added drv_Image.c (this time really!) * */ /* * * exported fuctions: * * struct DRIVER drv_Image * */ #include "config.h" #include #include #include #include #include #include #include #include #ifdef WITH_PNG #ifdef HAVE_GD_GD_H #include #else #ifdef HAVE_GD_H #include #else #error "gd.h not found!" #error "cannot compile PNG driver" #endif #endif #endif #include "debug.h" #include "cfg.h" #include "timer.h" #include "qprintf.h" #include "plugin.h" #include "widget.h" #include "widget_text.h" #include "widget_icon.h" #include "widget_bar.h" #include "drv.h" #include "drv_generic_graphic.h" #ifdef WITH_DMALLOC #include #endif static char Name[]="Image"; static enum {PPM, PNG} Format; static unsigned int fg_col, bg_col, hg_col; static int pixel = -1; // pointsize in pixel static int pgap = 0; // gap between points static int rgap = 0; // row gap between lines static int cgap = 0; // column gap between characters static int border = 0; // window border static int dimx, dimy; // total window dimension in pixel static unsigned char *drv_IMG_FB = NULL; static int dirty = 1; // **************************************** // *** hardware dependant functions *** // **************************************** #ifdef WITH_PPM static int drv_IMG_flush_PPM (void) { static int seq=0; static unsigned char *bitbuf=NULL; static unsigned char *rowbuf=NULL; int xsize, ysize, row, col; unsigned char R[3], G[3], B[3]; char path[256], tmp[256], buffer[256]; int fd; xsize = 2*border + (DCOLS/XRES-1)*cgap + DCOLS*pixel + (DCOLS-1)*pgap; ysize = 2*border + (DROWS/YRES-1)*rgap + DROWS*pixel + (DROWS-1)*pgap; if (bitbuf == NULL) { if ((bitbuf = malloc(xsize*ysize*sizeof(*bitbuf))) == NULL) { error ("%s: malloc(%d) failed: %s", Name, xsize*ysize*sizeof(*bitbuf), strerror(errno)); return -1; } } if (rowbuf == NULL) { if ((rowbuf = malloc(3*xsize*sizeof(*rowbuf))) == NULL) { error ("Raster: malloc(%d) failed: %s", 3*xsize*sizeof(*rowbuf), strerror(errno)); return -1; } } memset (bitbuf, 0, xsize*ysize*sizeof(*bitbuf)); for (row = 0; row < DROWS; row++) { int y = border + (row/YRES)*rgap + row*(pixel+pgap); for (col = 0; col < DCOLS; col++) { int x = border + (col/XRES)*cgap + col*(pixel+pgap); int a, b; for (a = 0; a < pixel; a++) for (b = 0; b < pixel; b++) bitbuf[y*xsize+x+a*xsize+b] = drv_IMG_FB[row*DCOLS+col]+1; } } snprintf (path, sizeof(path), output, seq++); qprintf(tmp, sizeof(tmp), "%s.tmp", path); // remove the file unlink (tmp); // avoid symlink security hole: // open it with O_EXCL will fail if the file exists. // This should not happen because we just unlinked it. if ((fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, 0644))<0) { error ("%s: open(%s) failed: %s", Name, tmp, strerror(errno)); return -1; } qprintf(buffer, sizeof(buffer), "P6\n%d %d\n255\n", xsize, ysize); if (write (fd, buffer, strlen(buffer)) < 0) { error ("%s: write(%s) failed: %s", Name, tmp, strerror(errno)); return -1; } R[0] = 0xff & bg_col>>16; G[0] = 0xff & bg_col>>8; B[0] = 0xff & bg_col; R[1] = 0xff & hg_col>>16; G[1] = 0xff & hg_col>>8; B[1] = 0xff & hg_col; R[2] = 0xff & fg_col>>16; G[2] = 0xff & fg_col>>8; B[2] = 0xff & fg_col; for (row = 0; row < ysize; row++) { int c = 0; for (col = 0; col < xsize; col++) { int i = bitbuf[row*xsize+col]; rowbuf[c++] = R[i]; rowbuf[c++] = G[i]; rowbuf[c++] = B[i]; } if (write (fd, rowbuf, c) < 0) { error ("%s: write(%s) failed: %s", Name, tmp, strerror(errno)); break; } } if (close (fd) < 0) { error ("%s: close(%s) failed: %s", Name, tmp, strerror(errno)); return -1; } if (rename (tmp, path)<0) { error ("%s: rename(%s) failed: %s", Name, tmp, strerror(errno)); return -1; } return 0; } #endif #ifdef WITH_PNG static int drv_IMG_flush_PNG (void) { static int seq = 0; int xsize, ysize, row, col; char path[256], tmp[256]; FILE *fp; int fd; gdImagePtr im; int bg, hg, fg; xsize = 2*border + (DCOLS/XRES-1)*cgap + DCOLS*pixel + (DCOLS-1)*pgap; ysize = 2*border + (DROWS/YRES-1)*rgap + DROWS*pixel + (DROWS-1)*pgap; im = gdImageCreate(xsize, ysize); /* first color = background */ bg = gdImageColorAllocate(im, 0xff & bg_col>>16, 0xff & bg_col>>8, 0xff & bg_col); hg = gdImageColorAllocate(im, 0xff & hg_col>>16, 0xff & hg_col>>8, 0xff & hg_col); fg = gdImageColorAllocate(im, 0xff & fg_col>>16, 0xff & fg_col>>8, 0xff & fg_col); for (row = 0; row < DROWS; row++) { int y = border + (row/YRES)*rgap + row*(pixel+pgap); for (col = 0; col < DCOLS; col++) { int x = border + (col/XRES)*cgap + col*(pixel+pgap); gdImageFilledRectangle(im, x, y, x + pixel - 1 , y + pixel - 1, drv_IMG_FB[row*DCOLS+col]? fg : hg); } } snprintf (path, sizeof(path), output, seq++); qprintf (tmp, sizeof(tmp), "%s.tmp", path); // remove the file unlink (tmp); // avoid symlink security hole: // open it with O_EXCL will fail if the file exists. // This should not happen because we just unlinked it. if ((fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, 0644))<0) { error ("%s: open(%s) failed: %s", Name, tmp, strerror(errno)); return -1; } if ((fp = fdopen(fd, "w")) == NULL) { error("%s: fdopen(%s) failed: %s\n", Name, tmp, strerror(errno)); close (fd); return -1; } gdImagePng(im, fp); gdImageDestroy(im); if (fclose (fp) != 0) { error("%s: fclose(%s) failed: %s\n", Name, tmp, strerror(errno)); return -1; } if (rename (tmp, path) < 0) { error("%s: rename(%s) failed: %s\n", Name, tmp, strerror(errno)); return -1; } return 0; } #endif static void drv_IMG_flush (void) { switch (Format) { #ifdef WITH_PPM case PPM: drv_IMG_flush_PPM(); break; #endif #ifdef WITH_PNG case PNG: drv_IMG_flush_PNG(); break; #endif } } static void drv_IMG_timer (void *notused) { if (dirty) { drv_IMG_flush(); dirty = 0; } } static void drv_IMG_blit(int row, int col, int height, int width) { int r, c; for (r=row; r