summaryrefslogtreecommitdiff
path: root/tools/convpic/tuxbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/convpic/tuxbox.c')
-rw-r--r--tools/convpic/tuxbox.c280
1 files changed, 280 insertions, 0 deletions
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));
+ }
+ }
+ }
+}