diff options
author | andreas 'randy' weinberger <vdr@smue.org> | 2010-02-21 19:58:27 +0100 |
---|---|---|
committer | andreas 'randy' weinberger <vdr@smue.org> | 2010-02-21 19:58:27 +0100 |
commit | 10ab31fa86dbf9875b5f6baa6ac59fefaaf86be3 (patch) | |
tree | 60ad7c856565f03e145b2996d1bb5f9cd64c0532 /tools/convpic | |
download | graphlcd-base-10ab31fa86dbf9875b5f6baa6ac59fefaaf86be3.tar.gz graphlcd-base-10ab31fa86dbf9875b5f6baa6ac59fefaaf86be3.tar.bz2 |
initial git upload, based on graphlcd-base-0.1.5
Diffstat (limited to 'tools/convpic')
-rw-r--r-- | tools/convpic/Makefile | 46 | ||||
-rw-r--r-- | tools/convpic/bmp.c | 375 | ||||
-rw-r--r-- | tools/convpic/bmp.h | 45 | ||||
-rwxr-xr-x | tools/convpic/c_bmp2glcd | 10 | ||||
-rwxr-xr-x | tools/convpic/c_tif2glcd | 10 | ||||
-rwxr-xr-x | tools/convpic/convall | 10 | ||||
-rw-r--r-- | tools/convpic/convpic.c | 279 | ||||
-rw-r--r-- | tools/convpic/formats.txt | 32 | ||||
-rw-r--r-- | tools/convpic/tiff.c | 201 | ||||
-rw-r--r-- | tools/convpic/tiff.h | 42 | ||||
-rw-r--r-- | tools/convpic/tuxbox.c | 280 | ||||
-rw-r--r-- | tools/convpic/tuxbox.h | 44 |
12 files changed, 1374 insertions, 0 deletions
diff --git a/tools/convpic/Makefile b/tools/convpic/Makefile new file mode 100644 index 0000000..91aaed4 --- /dev/null +++ b/tools/convpic/Makefile @@ -0,0 +1,46 @@ +# +# Makefile for the GraphLCD tool convpic +# + +-include ../../Make.config + +PRGNAME = convpic + +OBJS = $(PRGNAME).o bmp.o tiff.o tuxbox.o + +INCLUDES += -I../../ +LIBDIRS += -L../../glcdgraphics/ + + +all: $(PRGNAME) +.PHONY: all + +# Implicit rules: + +%.o: %.c + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $< + +# Dependencies: + +MAKEDEP = $(CXX) -MM -MG +DEPFILE = .dependencies +$(DEPFILE): Makefile + @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@ + +-include $(DEPFILE) + +# The main program: + +$(PRGNAME): $(OBJS) + $(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(LIBS) $(LIBDIRS) -lglcdgraphics -lstdc++ -o $(PRGNAME) + +install: $(PRGNAME) + install -d $(BINDIR) + install -m 755 -o root -g root -s $(PRGNAME) $(BINDIR) + +uninstall: + rm -f $(BINDIR)/$(PRGNAME) + +clean: + @-rm -f $(OBJS) $(DEPFILE) $(PRGNAME) *~ + diff --git a/tools/convpic/bmp.c b/tools/convpic/bmp.c new file mode 100644 index 0000000..2316b6c --- /dev/null +++ b/tools/convpic/bmp.c @@ -0,0 +1,375 @@ +/** + * GraphLCD plugin for the Video Disk Recorder + * + * bmp.c - bmp logo class + * + * (C) 2004 Andreas Brachold <vdr04 AT deltab de> + * (C) 2001-2004 Carsten Siebholz <c.siebholz AT t-online de> + **/ + +/*************************************************************************** + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + ***************************************************************************/ + +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +#include <string> + +#include <glcdgraphics/bitmap.h> +#include <glcdgraphics/image.h> + +#include "bmp.h" + + +#pragma pack(1) +typedef struct BMPH { + uint16_t bmpIdentifier; + uint32_t bmpFileSize; + uint32_t bmpReserved; + uint32_t bmpBitmapDataOffset; + uint32_t bmpBitmapHeaderSize; + uint32_t bmpWidth; + uint32_t bmpHeight; + uint16_t bmpPlanes; + uint16_t bmpBitsPerPixel; + uint32_t bmpCompression; + uint32_t bmpBitmapDataSize; + uint32_t bmpHResolution; + uint32_t bmpVResolution; + uint32_t bmpColors; + uint32_t bmpImportantColors; +} BMPHEADER; // 54 bytes + +typedef struct RGBQ { + uint8_t rgbBlue; + uint8_t rgbGreen; + uint8_t rgbRed; + uint8_t rgbReserved; +} RGBQUAD; // 4 bytes +#pragma pack() + + +uint8_t bitmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; +uint8_t bitmaskl[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; +uint8_t bitmaskr[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; + +cBMPFile::cBMPFile() +{ +} + +cBMPFile::~cBMPFile() +{ +} + +bool cBMPFile::Load(GLCD::cImage & image, const std::string & fileName) +{ + FILE *fIN; + BMPHEADER bmpHeader; + RGBQUAD *pPalette; + char *pByte; + char Dummy; + long iNumColors; + long iSize; + uint32_t x, y; + uint16_t iRead; + uint8_t * bitmap = NULL; + bool bInvert = false; + + if (fileName.length() > 0) + { + fIN = fopen(fileName.c_str(), "rb"); + if (fIN) + { + if (fread(&bmpHeader, sizeof(BMPHEADER), 1, fIN)!=1) + { + fclose(fIN); + return false; + } + + // check for Windows BMP + if (bmpHeader.bmpBitmapHeaderSize != 0x00000028 ) + { + fprintf(stderr, "ERROR: only Windows BMP images are allowed.\n"); + fclose(fIN); + return false; + } + + // check for 2 color + iNumColors = (1 << bmpHeader.bmpBitsPerPixel); + if (iNumColors != 2) + { + fprintf(stderr, "ERROR: the image has %ld colors, but only images with 2 colors are allowed.\n", iNumColors); + fclose(fIN); + return false; + } + + iSize = bmpHeader.bmpHeight * bmpHeader.bmpWidth; + + pPalette = (RGBQUAD *) malloc( iNumColors*sizeof(RGBQUAD)); + if (!pPalette) + { + fprintf(stderr, "ERROR: cannot allocate memory\n"); + fclose(fIN); + return false; + } + + if (fread( pPalette, iNumColors*sizeof(RGBQUAD), 1, fIN)!=1) + { + free(pPalette); + fclose(fIN); + return false; + } + + // check colors + if (pPalette->rgbBlue+pPalette->rgbGreen+pPalette->rgbRed < + (pPalette+1)->rgbBlue+(pPalette+1)->rgbGreen+(pPalette+1)->rgbRed) + { + // index 0 represents 'black', index 1 'white' + bInvert = !bInvert; + } + else + { + // index 0 represents 'white', index 1 'black' + } + + if (fseek(fIN, bmpHeader.bmpBitmapDataOffset, SEEK_SET)==EOF) + { + free(pPalette); + fclose(fIN); + return false; + } + + switch (bmpHeader.bmpCompression) + { + case 0: // BI_RGB no compression + image.Clear(); + image.SetWidth(bmpHeader.bmpWidth); + image.SetHeight(bmpHeader.bmpHeight); + image.SetDelay(100); + bitmap = new unsigned char[bmpHeader.bmpHeight * ((bmpHeader.bmpWidth + 7) / 8)]; + if (!bitmap) + { + fprintf(stderr, "ERROR: cannot allocate memory\n"); + free(pPalette); + fclose(fIN); + image.Clear(); + return false; + } + + for (y = bmpHeader.bmpHeight; y > 0; y--) + { + pByte = (char*)bitmap + (y-1)*((bmpHeader.bmpWidth+7)/8); + iRead = 0; + for (x = 0; x < bmpHeader.bmpWidth / 8; x++) + { + if (fread(pByte, sizeof(char), 1, fIN) != 1) + { + delete[] bitmap; + free(pPalette); + fclose(fIN); + image.Clear(); + return false; + } + iRead++; + if (bInvert) + *pByte = *pByte ^ 0xff; + pByte++; + } + + if (bmpHeader.bmpWidth % 8) + { + if (fread(pByte, sizeof(char), 1, fIN) != 1) + { + delete [] bitmap; + free(pPalette); + fclose(fIN); + image.Clear(); + return false; + } + iRead++; + if (bInvert) + *pByte = *pByte^0xff; + *pByte = *pByte & bitmaskl[bmpHeader.bmpWidth%8]; + pByte++; + } + + // Scan line must be 4-byte-alligned + while (iRead % 4) + { + if (fread(&Dummy, sizeof(char), 1, fIN) != 1) + { + delete [] bitmap; + free(pPalette); + fclose(fIN); + image.Clear(); + return false; + } + iRead++; + } + } + image.AddBitmap(new GLCD::cBitmap(bmpHeader.bmpWidth, bmpHeader.bmpHeight, bitmap)); + break; + case 1: // BI_RLE4 RLE 4bit/pixel + case 2: // BI_RLE8 RLE 8bit/pixel + case 3: // BI_BITFIELDS + default: + fprintf(stderr, "ERROR: only uncompressed RGB images are allowed.\n"); + + free(pPalette); + fclose(fIN); + return false; + } + fclose(fIN); + } + else + { + fprintf(stderr, "ERROR: cannot open picture %s\n", fileName.c_str()); + } + } + else + { + fprintf(stderr, "ERROR: no FileName given!\n"); + } + return true; +} + +bool cBMPFile::Save(const GLCD::cBitmap * bitmap, const std::string & fileName) +{ + FILE *fOut; + BMPHEADER bmpHeader; + RGBQUAD bmpColor1, bmpColor2; + uint32_t dBDO, dBDSx, dBDS; + char *pByte; + char Dummy = 0x00; + uint32_t x, y; + uint16_t iWrote; + const uint8_t * bmpdata = bitmap->Data(); + + if (bitmap + && bitmap->Width() > 0 + && bitmap->Height() > 0) + { + memset(&bmpHeader, 0, sizeof(BMPHEADER)); + + dBDO = sizeof(BMPHEADER)+2*sizeof(RGBQUAD); + dBDSx = ((bitmap->Width() + 7) / 8 + 3) & 0xfffffffc; + dBDS = dBDSx * bitmap->Height(); + + bmpHeader.bmpIdentifier = 0x4d42; // "BM" + bmpHeader.bmpFileSize = dBDO + dBDS; + bmpHeader.bmpBitmapDataOffset = dBDO; + bmpHeader.bmpBitmapHeaderSize = 0x28; + bmpHeader.bmpWidth = bitmap->Width(); + bmpHeader.bmpHeight = bitmap->Height(); + bmpHeader.bmpPlanes = 0x01; + bmpHeader.bmpBitsPerPixel = 0x01; + bmpHeader.bmpCompression = 0x00; + bmpHeader.bmpBitmapDataSize = dBDS; + bmpHeader.bmpHResolution = 0xb13; // 72dpi + bmpHeader.bmpVResolution = 0xb13; // 72dpi + bmpHeader.bmpColors = 0x02; + bmpHeader.bmpImportantColors = 0x02; + + bmpColor1.rgbBlue = 0x00; + bmpColor1.rgbGreen = 0x00; + bmpColor1.rgbRed = 0x00; + bmpColor1.rgbReserved = 0x00; + bmpColor2.rgbBlue = 0xff; + bmpColor2.rgbGreen = 0xff; + bmpColor2.rgbRed = 0xff; + bmpColor2.rgbReserved = 0x00; + + + fOut = fopen(fileName.c_str(), "wb"); + if (!fOut) + { + fprintf(stderr,"Cannot create file: %s\n", fileName.c_str()); + return false; + } + fwrite(&bmpHeader, sizeof(BMPHEADER), 1, fOut); + fwrite(&bmpColor1, sizeof(RGBQUAD), 1, fOut); + fwrite(&bmpColor2, sizeof(RGBQUAD), 1, fOut); + + for (y=bitmap->Height(); y>0; y--) + { + pByte = (char*)bmpdata + (y-1)*((bitmap->Width()+7)/8); + iWrote = 0; + for (x=0; x<(uint32_t) bitmap->Width()/8; x++) + { + *pByte = *pByte^0xff; + if (fwrite(pByte, sizeof(char), 1, fOut)!=1) + { + fclose(fOut); + return false; + } + iWrote++; + pByte++; + } + // Scan line must be 4-byte-alligned + while (iWrote%4) + { + if (fwrite(&Dummy, sizeof(char), 1, fOut)!=1) + { + fclose(fOut); + return 3; + } + iWrote++; + } + } + fclose(fOut); + } + return true; +} + +bool cBMPFile::Save(GLCD::cImage & image, const std::string & fileName) +{ + const GLCD::cBitmap * bitmap; + + if (image.Count() == 1) + { + bitmap = image.GetBitmap(0); + if (bitmap) + { + if (!Save(bitmap, fileName)) + { + return false; + } + } + } + else + { + uint16_t i; + char tmpStr[256]; + + for (i = 0; i < image.Count(); i++) + { + sprintf(tmpStr, "%.248s.%05d", fileName.c_str(), i); + bitmap = image.GetBitmap(i); + if (bitmap) + { + if (!Save(bitmap, tmpStr)) + { + return false; + } + } + } + } + return true; +} diff --git a/tools/convpic/bmp.h b/tools/convpic/bmp.h new file mode 100644 index 0000000..8419838 --- /dev/null +++ b/tools/convpic/bmp.h @@ -0,0 +1,45 @@ +/** + * GraphLCD plugin for the Video Disk Recorder + * + * bmp.h - bmp logo class + * + * (C) 2004 Andreas Brachold <vdr04 AT deltab de> + * (C) 2001-2004 Carsten Siebholz <c.siebholz AT t-online de> + **/ + +/*************************************************************************** + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + ***************************************************************************/ + +#ifndef _BMP_H_ +#define _BMP_H_ + +#include <glcdgraphics/imagefile.h> + +class cBMPFile : public GLCD::cImageFile +{ +private: + bool Save(const GLCD::cBitmap * bitmap, const std::string & fileName); +public: + cBMPFile(); + virtual ~cBMPFile(); + virtual bool Load(GLCD::cImage & image, const std::string & fileName); + virtual bool Save(GLCD::cImage & image, const std::string & fileName); +}; + +#endif diff --git a/tools/convpic/c_bmp2glcd b/tools/convpic/c_bmp2glcd new file mode 100755 index 0000000..b629ee6 --- /dev/null +++ b/tools/convpic/c_bmp2glcd @@ -0,0 +1,10 @@ +#!/bin/sh +# Converts all BMP images to *.glcd + +old=bmp +new=glcd + +for file in ./*."$old"; do + convpic -i "$file" -o "`basename \"$file\" \"$old\"`$new" +done + diff --git a/tools/convpic/c_tif2glcd b/tools/convpic/c_tif2glcd new file mode 100755 index 0000000..d3983b8 --- /dev/null +++ b/tools/convpic/c_tif2glcd @@ -0,0 +1,10 @@ +#!/bin/sh +# Converts all TIFF images to *.glcd + +old=tif +new=glcd + +for file in ./*."$old"; do + convpic -i "$file" -o "`basename \"$file\" \"$old\"`$new" +done + diff --git a/tools/convpic/convall b/tools/convpic/convall new file mode 100755 index 0000000..f0f0207 --- /dev/null +++ b/tools/convpic/convall @@ -0,0 +1,10 @@ +#!/bin/sh +# Converts all images in current directory + +old=$1 +new=$2 + +for file in ./*."$old"; do + convpic -i "$file" -o "`basename \"$file\" \"$old\"`$new" +done + diff --git a/tools/convpic/convpic.c b/tools/convpic/convpic.c new file mode 100644 index 0000000..732738c --- /dev/null +++ b/tools/convpic/convpic.c @@ -0,0 +1,279 @@ +/** + * convpic.c - a tool to convert images to + * own proprietary format of the logos and pictures + * for graphlcd plugin + * + * (C) 2004 Andreas Brachold <vdr04 AT deltab de> + * (C) 2001-2003 by Carsten Siebholz <c.siebholz AT t-online.de> + **/ + +/*************************************************************************** + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + ***************************************************************************/ + +#include <getopt.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> + +#include <string> + +#include <glcdgraphics/bitmap.h> +#include <glcdgraphics/image.h> +#include <glcdgraphics/imagefile.h> +#include <glcdgraphics/glcd.h> +#include <glcdgraphics/pbm.h> + +#include "bmp.h" +#include "tiff.h" +#include "tuxbox.h" + +static const char *prgname = "convpic"; +static const char *VERSION = "0.1.1"; + +unsigned int delay = 250; + + +enum ePicFormat +{ + pfUndefined, + pfTIFF, + pfBMP, + pfGLCD, + pfPBM, + pfTUXBOX +}; + +void usage(void); + +ePicFormat getFormat(const char* szFile) +{ + static const struct tagformats {const char* szExt; ePicFormat picformat;} formats[] = + { + {".tiff", pfTIFF }, + {".tif", pfTIFF }, + {".bmp", pfBMP }, + {".glcd", pfGLCD }, + {".pbm", pfPBM }, + {".ani", pfTUXBOX} + }; + ePicFormat pf = pfUndefined; + + if (szFile) + { + for (int i = strlen(szFile) - 1; i >= 0; i--) + { + if (*(szFile+i) == '.' && strlen(szFile + i + 1)) + { + for (unsigned int n = 0; n < sizeof(formats)/sizeof(*formats); n++) + { + if (!strcasecmp((szFile+i), formats[n].szExt)) + { + return formats[n].picformat; + } + } + } + } + } + return pf; +} + +GLCD::cImageFile * GetFileTranslator(ePicFormat Format) +{ + switch (Format) + { + case pfGLCD: + return new GLCD::cGLCDFile(); + + case pfPBM: + return new GLCD::cPBMFile(); + + case pfBMP: + return new cBMPFile(); + + case pfTIFF: + return new cTIFFFile(); + + case pfTUXBOX: + return new cTuxBoxFile(); + + default: + return NULL; + } + +} + +int main(int argc, char *argv[]) { + ePicFormat inFormat = pfUndefined; + ePicFormat outFormat = pfUndefined; + std::string inFile = ""; + std::string outFile = ""; + GLCD::cImage image; + GLCD::cImage nextImage; + GLCD::cImageFile * pInBitmap = NULL; + GLCD::cImageFile * pOutBitmap = NULL; + bool bError = false; + bool bInvert = false; + bool bDelay = false; + + + static struct option long_options[] = + { + {"invert", no_argument, NULL, 'n'}, + {"infile", required_argument, NULL, 'i'}, + {"outfile", required_argument, NULL, 'o'}, + {"delay", required_argument, NULL, 'd'}, + { NULL} + }; + + int c, option_index = 0; + while ((c=getopt_long(argc,argv,"ni:o:d:",long_options, &option_index))!=-1) { + switch (c) { + case 'n': + bInvert = true; + break; + + case 'i': + inFile = optarg; + break; + + case 'o': + outFile = optarg; + break; + + case 'd': + delay = atoi(optarg); + bDelay = true; + if (delay < 10) + { + fprintf(stderr, "Warning: You have specify a to short delay, minimum are 10 ms\n"); + delay = 10; + } + break; + + default: + return 1; + } + } + + if (inFile.length() == 0) + { + fprintf(stderr, "ERROR: You have to specify the infile (-i filename)\n"); + bError = true; + } + + if (pfUndefined == (inFormat = getFormat(inFile.c_str()))) + { + fprintf(stderr, "ERROR: You have to specify a correct extension for the %s\n", inFile.c_str()); + bError = true; + } + + if (outFile.length() == 0) + { + fprintf(stderr, "ERROR: You have to specify the outfile (-o filename)\n"); + bError = true; + } + + if (pfUndefined == (outFormat = getFormat(outFile.c_str()))) + { + fprintf(stderr, "ERROR: You have to specify a correct extension for the %s \n", outFile.c_str()); + bError = true; + } + + if (bError) + { + usage(); + return 1; + } + + + pInBitmap = GetFileTranslator(inFormat); + if (!pInBitmap) + return 2; + + pOutBitmap = GetFileTranslator(outFormat); + if (!pOutBitmap) + return 3; + + // Load Picture + fprintf(stdout, "loading %s\n", inFile.c_str()); + bError = !pInBitmap->Load(image, inFile); + if (!bError) + { + // Load more in files + while (optind < argc && !bError) + { + inFile = argv[optind++]; + inFormat = getFormat(inFile.c_str()); + if (inFormat == pfUndefined) + { + fprintf(stderr, "ERROR: You have to specify a correct extension for the %s\n", inFile.c_str()); + bError = true; + break; + } + pInBitmap = GetFileTranslator(inFormat); + if (!pInBitmap) + break; + + fprintf(stdout, "loading %s\n", inFile.c_str()); + if (pInBitmap->Load(nextImage, inFile)) + { + uint16_t i; + for (i = 0; i < nextImage.Count(); i++) + { + image.AddBitmap(new GLCD::cBitmap(*nextImage.GetBitmap(i))); + } + } + } + if (bDelay) + image.SetDelay(delay); + if (bInvert) + { + uint16_t i; + for (i = 0; i < image.Count(); i++) + { + image.GetBitmap(i)->Invert(); + } + } + fprintf(stdout, "saving %s\n", outFile.c_str()); + bError = !pOutBitmap->Save(image, outFile); + } + if (bError) { + return 4; + } + + fprintf(stdout, "conversion compeleted successfully.\n\n"); + + return 0; +} + +void usage(void) +{ + fprintf(stdout, "\n"); + fprintf(stdout, "%s v%s\n", prgname, VERSION); + fprintf(stdout, "%s is a tool to convert images to a simple format (*.glcd)\n", prgname); + fprintf(stdout, " that is used by the graphlcd plugin for VDR.\n\n"); + fprintf(stdout, " Usage: %s [-n] -i file[s...] -o outfile \n\n", prgname); + fprintf(stdout, " -n --invert inverts the output (default: none)\n"); + fprintf(stdout, " -i --infile specifies the name of the input file[s]\n"); + fprintf(stdout, " -o --outfile specifies the name of the output file\n"); + fprintf(stdout, " -d --delay specifies the delay between multiple images [Default: %d ms] \n",delay); + fprintf(stdout, "\n" ); + fprintf(stdout, " example: %s -i vdr-logo.bmp -o vdr-logo.glcd \n", prgname ); +} diff --git a/tools/convpic/formats.txt b/tools/convpic/formats.txt new file mode 100644 index 0000000..578a211 --- /dev/null +++ b/tools/convpic/formats.txt @@ -0,0 +1,32 @@ +Dateiformat von "Graphlcd-Logo" + + +Einzelbild für LCD +================================= + +HEADER +Position Typ Name Bedeutung +0x0000 char[4] magic - "GLCD" +0x0004 word width - Breite der Bilder (LE) +0x0006 word height - Höhe der Bilder (LE) +0x0008 char[] data - Einzel-Bild + +DATEN +char[height][width/8], pro Byte 8 nebeneinander liegende Pixel + +Animation für LCD +================================= + +HEADER +Position Typ Name Bedeutung +0x0000 char[4] magic - "GLCA" +0x0004 word width - Breite der Bilder (LE) +0x0006 word height - Höhe der Bilder (LE) +0x0008 word count - Anzahl der Bilder (LE) +0x000a long delay - Wartezeit zwischen den Bildern (in ms; LE) +0x0010 char[] data - Einzel-Bilder + +DATEN +char[height][width/8], pro Byte 8 nebeneinander liegende Pixel (1 = Pixel gesetzt) + +LE = Little Endian byte order = wie bei intel ;) diff --git a/tools/convpic/tiff.c b/tools/convpic/tiff.c new file mode 100644 index 0000000..4b8bf0e --- /dev/null +++ b/tools/convpic/tiff.c @@ -0,0 +1,201 @@ +/** + * GraphLCD plugin for the Video Disk Recorder + * + * tiff.c - tiff logo class + * + * (c) 2004 Andreas Brachold <vdr04 AT deltab de> + * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online de> + **/ + +/*************************************************************************** + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + ***************************************************************************/ + +#include <stdio.h> +#include <string.h> + +#include <string> + +#include <glcdgraphics/bitmap.h> +#include <glcdgraphics/image.h> + +#include "tiff.h" + + +#pragma pack(1) +typedef struct TIFFT{ + unsigned short tag; + unsigned short type; + unsigned long length; + /* 1 = BYTE. 8-bit unsigned integer. */ + /* 2 = ASCII. 8-bit bytes that store ASCII codes; the last byte must be null. */ + /* 3 = SHORT. A 16-bit (2-byte) unsigned integer. */ + /* 4 = LONG. A 32-bit (4-byte) unsigned integer. */ + /* 5 = RATIONAL. Two LONGs: the first represents the numerator of a fraction, the second the denominator. */ + unsigned long off_val; +} TIFFTAG; +#pragma pack() + +#define GETANDCHECK { t=fgetc(fIN);if(t==EOF) {fclose(fIN);return false;};} + +cTIFFFile::cTIFFFile() +{ +} + +cTIFFFile::~cTIFFFile() +{ +} + +bool cTIFFFile::Load(GLCD::cImage & image, const std::string & fileName) +{ + FILE *fIN; + TIFFTAG tifftag; + unsigned int tiff_header, tiff_anztags, tiff_data; + unsigned char cl,ch,y,i; + unsigned char height, width, strip, invert; + unsigned char fLittleEndian=0; + int j; + int t; + unsigned char *bitmap = NULL; + bool bInvert = false; + + if (fileName.length() > 0) + { + fIN = fopen(fileName.c_str(), "rb"); + if (fIN) + { + // isyslog("graphlcd plugin: try to load logo %s.", szFileName); + if (fseek(fIN, 0, SEEK_SET)==EOF) + { + fclose(fIN); + return false; + } + GETANDCHECK; cl=(unsigned char)t; + GETANDCHECK; ch=(unsigned char)t; + if ((cl==0x49) && (ch==0x49)) + { + fLittleEndian=1; + } + + if (fseek(fIN, 4, SEEK_SET)==EOF) + { + fclose(fIN); + return false; + } + GETANDCHECK; cl=(unsigned char)t; + GETANDCHECK; ch=(unsigned char)t; + tiff_header = cl+256*ch; + //printf("tiff_header:%d %x\n", tiff_header, tiff_header); + + if (fseek(fIN, tiff_header, SEEK_SET)==EOF) + { + fclose(fIN); + return false; + } + + GETANDCHECK; cl=(unsigned char)t; + GETANDCHECK; ch=(unsigned char)t; + tiff_anztags = cl+256*ch; + //printf("tiff_anztags:%d %x\n", tiff_anztags, tiff_anztags); + + height=0; + width=0; + strip=0; + invert=0; + for (i=0; (i<tiff_anztags)&&(!height||!width||!strip||!invert); i++) + { + if (fread(&tifftag, sizeof(tifftag), 1, fIN)!=1) + { + fclose(fIN); + return false; + } + if (tifftag.tag==0x0100) width=tifftag.off_val; + if (tifftag.tag==0x0101) height=tifftag.off_val; + if (tifftag.tag==0x0111) strip=tifftag.off_val; + if (tifftag.tag==0x0106) invert=tifftag.off_val+1; + //printf("tag%d: %d %d %ld %ld\n", i,tifftag.tag, tifftag.type, tifftag.length, tifftag.off_val ); + } + + if (fseek(fIN,strip, SEEK_SET)==EOF) + { + fclose(fIN); + return false; + } + GETANDCHECK; cl=(unsigned char)t; + GETANDCHECK; ch=(unsigned char)t; + tiff_data = cl+256*ch; + //printf("tiff_data:%d %x\n", tiff_data, tiff_data); + + if (fseek(fIN, tiff_data, SEEK_SET)==EOF) + { + fclose(fIN); + return false; + } + + + image.Clear(); + image.SetWidth(width); + image.SetHeight(height); + image.SetDelay(100); + bitmap = new unsigned char[height * ((width + 7) / 8)]; + if (bitmap) + { + if (fread(bitmap, height*((width+7)/8), 1, fIN)!=1) + { + delete [] bitmap; + fclose(fIN); + image.Clear(); + return false; + } + + if (invert-1==1) bInvert = !bInvert; // 'Black is zero' + if (bInvert) + { + for (j=0; j < height * ((width+7)/8); j++) + { + (*(bitmap+j)) = (*(bitmap+j))^0xff; + } + } + + // cut the rest of the line + if (width%8) + { + for (y=1; y<=height; y++) { + j=y*((width+7)/8)-1; + (*(bitmap+j)) = ((*(bitmap+j))>>(8-width%8))<<(8-width%8); + } + } + image.AddBitmap(new GLCD::cBitmap(width, height, bitmap)); + } + else + { + fprintf(stderr, "ERROR: cannot allocate memory\n"); + } + fclose(fIN); + } + else + { + fprintf(stderr, "ERROR: cannot open picture %s\n", fileName.c_str()); + } + } + else + { + fprintf(stderr, "ERROR: no szFileName given!\n"); + } + return true; +} diff --git a/tools/convpic/tiff.h b/tools/convpic/tiff.h new file mode 100644 index 0000000..f6e66c1 --- /dev/null +++ b/tools/convpic/tiff.h @@ -0,0 +1,42 @@ +/** + * GraphLCD plugin for the Video Disk Recorder + * + * tiff.h - tiff logo class + * + * (c) 2004 Andreas Brachold <vdr04 AT deltab de> + * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online de> + **/ + +/*************************************************************************** + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + ***************************************************************************/ + +#ifndef _TIFF_H_ +#define _TIFF_H_ + +#include <glcdgraphics/imagefile.h> + +class cTIFFFile : public GLCD::cImageFile +{ +public: + cTIFFFile(); + virtual ~cTIFFFile(); + virtual bool Load(GLCD::cImage & image, const std::string & fileName); +}; + +#endif diff --git a/tools/convpic/tuxbox.c b/tools/convpic/tuxbox.c new file mode 100644 index 0000000..55d6e1d --- /dev/null +++ b/tools/convpic/tuxbox.c @@ -0,0 +1,280 @@ +/** + * GraphLCD plugin for the Video Disk Recorder + * + * tuxbox.c - tuxbox logo class + * + * (c) 2004 Andreas Brachold <vdr04 AT deltab de> + **/ + +/*************************************************************************** + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + ***************************************************************************/ + +#include <stdio.h> +#include <string.h> +#include <netinet/in.h> + +#include <string> + +#include <glcdgraphics/bitmap.h> +#include <glcdgraphics/image.h> + +#include "tuxbox.h" + +#pragma pack(1) +struct ani_header { + unsigned char magic[4]; // = "LCDA" + unsigned short format; // Format + unsigned short width; // Breite + unsigned short height; // Höhe + unsigned short count; // Anzahl Einzelbilder + unsigned long delay; // µs zwischen Einzelbildern +}; +#pragma pack() + +cTuxBoxFile::cTuxBoxFile() +{ +} + +cTuxBoxFile::~cTuxBoxFile() +{ +} + +bool cTuxBoxFile::Load(GLCD::cImage & image, const std::string & fileName) +{ + bool ret = false; + FILE * fIN; + long fileLen; + struct ani_header header; + bool bInvert = false; + + fIN = fopen(fileName.c_str(), "rb"); + if (fIN) + { + // get len of file + if (fseek(fIN, 0, SEEK_END)) + { + fclose(fIN); + return false; + } + fileLen = ftell(fIN); + + // rewind and get Header + if (fseek(fIN, 0, SEEK_SET)) + { + fclose(fIN); + return false; + } + + // Read header + if (fread(&header, sizeof(header), 1, fIN) != 1) + { + fclose(fIN); + return false; + } + + image.Clear(); + image.SetWidth(ntohs(header.width)); + image.SetHeight(ntohs(header.height)); + image.SetDelay(ntohl(header.delay) / 1000); + + // check Header + if (strncmp((const char*)header.magic, "LCDA", sizeof(header.magic)) || + !image.Width() || !image.Height() || ntohs(header.format) != 0) + { + fprintf(stderr, "ERROR: load %s failed, wrong header.\n", fileName.c_str()); + fclose(fIN); + return false; + } + + //fprintf(stderr,"%d %dx%d (%d %d) %d\n",ntohs(header.count),image.Width(),image.Height(),fileLen, ( (ntohs(header.count) * (image.Width() * ((image.Height() + 7) / 8))) + sizeof(header)),lhdr.delay); + + // check file length + if (!ntohs(header.count) + || (fileLen != (long) ( (ntohs(header.count) * (image.Width() * ((image.Height() + 7) / 8))) + sizeof(header)))) + { + fprintf(stderr, "ERROR: load %s failed, wrong size.\n", fileName.c_str()); + fclose(fIN); + return false; + } + // Set minimal limit for next image + if (image.Delay() < 10) + image.SetDelay(10); + for (unsigned int n=0;n<ntohs(header.count);++n) + { + ret = false; + unsigned int nBmpSize = image.Height() * ((image.Width() + 7) / 8); + unsigned char *bitmap = new unsigned char[nBmpSize]; + if (!bitmap) + { + fprintf(stderr, "ERROR: malloc failed."); + break; + } + unsigned int nAniSize = image.Width() * ((image.Height() + 7) / 8); + unsigned char *pAni = new unsigned char[nAniSize]; + if (!pAni) + { + delete[] bitmap; + fprintf(stderr, "ERROR: malloc failed."); + break; + } + + if (1 != fread(pAni, nAniSize, 1, fIN)) + { + fprintf(stderr,"ERROR: Cannot read filedata: %s\n", fileName.c_str()); + delete[] bitmap; + delete[] pAni; + break; + } + + vert2horz(pAni,bitmap, image.Width(), image.Height()); + delete[] pAni; + + if (bInvert) + for (unsigned int i=0;i<nBmpSize;++i) + bitmap[i] ^= 0xFF; + + image.AddBitmap(new GLCD::cBitmap(image.Width(), image.Height(), bitmap)); + ret = true; + } + fclose(fIN); + if (!ret) + image.Clear(); + } + return ret; +} + + +bool cTuxBoxFile::Save(GLCD::cImage & image, const std::string & fileName) +{ + FILE * fOut; + struct ani_header header; + bool bRet = false; + + if (image.Count() > 0 + && image.Width() + && image.Height()) + { + memcpy(header.magic, "LCDA", 4); + header.format = htons(0); + header.width = htons(image.Width()); + header.height = htons(image.Height()); + header.count = htons(image.Count()); + header.delay = htonl(image.Delay() * 1000); + + + if (image.Width() != 120 || image.Height() != 64) + { + fprintf(stderr,"WARNING: Maybe wrong image dimension (for all I know is 120x64 wanted) %s\n", fileName.c_str()); + } + + fOut = fopen(fileName.c_str(), "wb"); + if (!fOut) { + fprintf(stderr,"ERROR: Cannot create file: %s\n", fileName.c_str()); + return false; + } + + if (1 != fwrite(&header, sizeof(header), 1, fOut)) + { + fprintf(stderr,"ERROR: Cannot write fileheader: %s\n", fileName.c_str()); + fclose(fOut); + return false; + } + + for (unsigned int n = 0; n < image.Count(); n++) + { + bRet = false; + unsigned int nAniSize = image.Width() * ((image.Height() + 7) / 8); + unsigned char *pAni = new unsigned char[nAniSize]; + if (!pAni) + { + fprintf(stderr, "ERROR: malloc failed."); + break; + } + horz2vert(image.GetBitmap(n)->Data(), pAni, image.Width(), image.Height()); + + if (1 != fwrite(pAni, nAniSize, 1, fOut)) + { + delete [] pAni; + fprintf(stderr,"ERROR: Cannot write filedata: %s\n", fileName.c_str()); + break; + } + delete [] pAni; + bRet = true; + } + + fclose(fOut); + } + return bRet; +} + +/** Translate memory alignment from vertical to horizontal +rotate from {Byte} to {Byte} +{o}[o][o][o][o][o][o][o] => { oooooooo } +{o}[o][o][o][o][o][o][o] => [ oooooooo ] +{o}[o][o][o][o][o][o][o] => [ oooooooo ] +{o}[o][o][o][o][o][o][o] => [ oooooooo ] +{o}[o][o][o][o][o][o][o] => [ oooooooo ] +{o}[o][o][o][o][o][o][o] => [ oooooooo ] +{o}[o][o][o][o][o][o][o] => [ oooooooo ] +{o}[o][o][o][o][o][o][o] => [ oooooooo ]*/ +void cTuxBoxFile::vert2horz(const unsigned char* source, unsigned char* dest, int width, int height) { + int x, y, off; + memset(dest,0,height*((width+7)/8)); + + for (y=0; y<height; ++y) + { + for (x=0; x<width; ++x) + { + off = x + ((y/8) * width); + if (source[off] & (0x1 << (y % 8))) + { + off = (x / 8) + (y * ((width+7)/8)); + dest[off] |= (unsigned char)(0x80 >> (x % 8)); + } + } + } +} + +/** Translate memory alignment from horizontal to vertical (rotate byte) +rotate from {Byte} to {Byte} +{ oooooooo } => {o}[o][o][o][o][o][o][o] +[ oooooooo ] => {o}[o][o][o][o][o][o][o] +[ oooooooo ] => {o}[o][o][o][o][o][o][o] +[ oooooooo ] => {o}[o][o][o][o][o][o][o] +[ oooooooo ] => {o}[o][o][o][o][o][o][o] +[ oooooooo ] => {o}[o][o][o][o][o][o][o] +[ oooooooo ] => {o}[o][o][o][o][o][o][o] +[ oooooooo ] => {o}[o][o][o][o][o][o][o]*/ +void cTuxBoxFile::horz2vert(const unsigned char* source, unsigned char* dest, int width, int height) { + int x, y, off; + memset(dest,0,width*((height+7)/8)); + + for (y=0; y<height; ++y) + { + for (x=0; x<width; ++x) + { + off = (x / 8) + ((y) * ((width+7)/8)); + if (source[off] & (0x80 >> (x % 8))) + { + off = x + ((y/8) * width); + dest[off] |= (unsigned char)(0x1 << (y % 8)); + } + } + } +} diff --git a/tools/convpic/tuxbox.h b/tools/convpic/tuxbox.h new file mode 100644 index 0000000..1214fb5 --- /dev/null +++ b/tools/convpic/tuxbox.h @@ -0,0 +1,44 @@ +/** + * GraphLCD plugin for the Video Disk Recorder + * + * tuxbox.h - tuxbox logo class + * + * (c) 2004 Andreas Brachold <vdr04 AT deltab de> + **/ + +/*************************************************************************** + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + ***************************************************************************/ +#ifndef _TUXBOX_H_ +#define _TUXBOX_H_ + +#include <glcdgraphics/imagefile.h> + +class cTuxBoxFile : public GLCD::cImageFile +{ +private: + void vert2horz(const unsigned char* source, unsigned char* dest, int width, int height); + void horz2vert(const unsigned char* source, unsigned char* dest, int width, int height); +public: + cTuxBoxFile(); + virtual ~cTuxBoxFile(); + virtual bool Load(GLCD::cImage & image, const std::string & fileName); + virtual bool Save(GLCD::cImage & image, const std::string & fileName); +}; + +#endif |