graphlcd-base/tools/convpic/tuxbox.c
changeset 4 df6a40031aa5
equal deleted inserted replaced
3:d0e62fc47285 4:df6a40031aa5
       
     1 /**
       
     2  *  GraphLCD plugin for the Video Disk Recorder
       
     3  *
       
     4  *  tuxbox.c  -  tuxbox logo class
       
     5  *
       
     6  *  (c) 2004 Andreas Brachold <vdr04 AT deltab de>
       
     7  **/
       
     8 
       
     9 /***************************************************************************
       
    10  *                                                                         *
       
    11  *   This program is free software; you can redistribute it and/or modify  *
       
    12  *   it under the terms of the GNU General Public License as published by  *
       
    13  *   the Free Software Foundation; either version 2 of the License, or     *
       
    14  *   (at your option) any later version.                                   *
       
    15  *                                                                         *
       
    16  *   This program is distributed in the hope that it will be useful,       *
       
    17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
       
    18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
       
    19  *   GNU General Public License for more details.                          *
       
    20  *                                                                         *
       
    21  *   You should have received a copy of the GNU General Public License     *
       
    22  *   along with this program;                                              *
       
    23  *   if not, write to the Free Software Foundation, Inc.,                  *
       
    24  *   59 Temple Place, Suite 330, Boston, MA  02111-1307  USA               *
       
    25  *                                                                         *
       
    26  ***************************************************************************/
       
    27 
       
    28 #include <stdio.h>
       
    29 #include <string.h>
       
    30 #include <netinet/in.h>
       
    31 
       
    32 #include <string>
       
    33 
       
    34 #include <glcdgraphics/bitmap.h>
       
    35 #include <glcdgraphics/image.h>
       
    36 
       
    37 #include "tuxbox.h"
       
    38 
       
    39 #pragma pack(1)
       
    40 struct ani_header {
       
    41     unsigned char magic[4]; // = "LCDA"
       
    42     unsigned short format; // Format
       
    43     unsigned short width;  // Breite
       
    44     unsigned short height; // Höhe
       
    45     unsigned short count;  // Anzahl Einzelbilder
       
    46     unsigned long delay;  // µs zwischen Einzelbildern
       
    47 };
       
    48 #pragma pack()
       
    49 
       
    50 cTuxBoxFile::cTuxBoxFile()
       
    51 {
       
    52 }
       
    53 
       
    54 cTuxBoxFile::~cTuxBoxFile()
       
    55 {
       
    56 }
       
    57 
       
    58 bool cTuxBoxFile::Load(GLCD::cImage & image, const std::string & fileName)
       
    59 {
       
    60     bool ret = false;
       
    61     FILE * fIN;
       
    62     long fileLen;
       
    63     struct ani_header header;
       
    64     bool bInvert = false;
       
    65 
       
    66     fIN = fopen(fileName.c_str(), "rb");
       
    67     if (fIN)
       
    68     {
       
    69         // get len of file
       
    70         if (fseek(fIN, 0, SEEK_END))
       
    71         {
       
    72             fclose(fIN);
       
    73             return false;
       
    74         }
       
    75         fileLen = ftell(fIN);
       
    76 
       
    77         // rewind and get Header
       
    78         if (fseek(fIN, 0, SEEK_SET))
       
    79         {
       
    80             fclose(fIN);
       
    81             return false;
       
    82         }
       
    83 
       
    84         // Read header
       
    85         if (fread(&header, sizeof(header), 1, fIN) != 1)
       
    86         {
       
    87             fclose(fIN);
       
    88             return false;
       
    89         }
       
    90 
       
    91         image.Clear();
       
    92         image.SetWidth(ntohs(header.width));
       
    93         image.SetHeight(ntohs(header.height));
       
    94         image.SetDelay(ntohl(header.delay) / 1000);
       
    95 
       
    96         // check Header
       
    97         if (strncmp((const char*)header.magic, "LCDA", sizeof(header.magic)) ||
       
    98                 !image.Width() || !image.Height() || ntohs(header.format) != 0)
       
    99         {
       
   100             fprintf(stderr, "ERROR: load %s failed, wrong header.\n", fileName.c_str());
       
   101             fclose(fIN);
       
   102             return false;
       
   103         }
       
   104 
       
   105         //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);
       
   106 
       
   107         // check file length
       
   108         if (!ntohs(header.count)
       
   109                 || (fileLen != (long) ( (ntohs(header.count) * (image.Width() * ((image.Height() + 7) / 8))) + sizeof(header))))
       
   110         {
       
   111             fprintf(stderr, "ERROR: load %s failed, wrong size.\n", fileName.c_str());
       
   112             fclose(fIN);
       
   113             return false;
       
   114         }
       
   115         // Set minimal limit for next image
       
   116         if (image.Delay() < 10)
       
   117             image.SetDelay(10);
       
   118         for (unsigned int n=0;n<ntohs(header.count);++n)
       
   119         {
       
   120             ret = false;
       
   121             unsigned int nBmpSize = image.Height() * ((image.Width() + 7) / 8);
       
   122             unsigned char *bitmap = new unsigned char[nBmpSize];
       
   123             if (!bitmap)
       
   124             {
       
   125                 fprintf(stderr, "ERROR: malloc failed.");
       
   126                 break;
       
   127             }
       
   128             unsigned int nAniSize = image.Width() * ((image.Height() + 7) / 8);
       
   129             unsigned char *pAni = new unsigned char[nAniSize];
       
   130             if (!pAni)
       
   131             {
       
   132                 delete[] bitmap;
       
   133                 fprintf(stderr, "ERROR: malloc failed.");
       
   134                 break;
       
   135             }
       
   136 
       
   137             if (1 != fread(pAni, nAniSize, 1, fIN))
       
   138             {
       
   139                 fprintf(stderr,"ERROR: Cannot read filedata: %s\n", fileName.c_str());
       
   140                 delete[] bitmap;
       
   141                 delete[] pAni;
       
   142                 break;
       
   143             }
       
   144 
       
   145             vert2horz(pAni,bitmap, image.Width(), image.Height());
       
   146             delete[] pAni;
       
   147 
       
   148             if (bInvert)
       
   149                 for (unsigned int i=0;i<nBmpSize;++i)
       
   150                     bitmap[i] ^= 0xFF;
       
   151 
       
   152             image.AddBitmap(new GLCD::cBitmap(image.Width(), image.Height(), bitmap));
       
   153             ret = true;
       
   154         }
       
   155         fclose(fIN);
       
   156         if (!ret)
       
   157             image.Clear();
       
   158     }
       
   159     return ret;
       
   160 }
       
   161 
       
   162 
       
   163 bool cTuxBoxFile::Save(GLCD::cImage & image, const std::string & fileName)
       
   164 {
       
   165     FILE *      fOut;
       
   166     struct ani_header header;
       
   167     bool bRet = false;
       
   168 
       
   169     if (image.Count() > 0
       
   170         && image.Width()
       
   171         && image.Height())
       
   172     {
       
   173         memcpy(header.magic, "LCDA", 4);
       
   174         header.format = htons(0);
       
   175         header.width = htons(image.Width());
       
   176         header.height = htons(image.Height());
       
   177         header.count = htons(image.Count());
       
   178         header.delay = htonl(image.Delay() * 1000);
       
   179 
       
   180 
       
   181         if (image.Width() != 120 || image.Height() != 64)
       
   182         {
       
   183             fprintf(stderr,"WARNING: Maybe wrong image dimension (for all I know is 120x64 wanted) %s\n", fileName.c_str());
       
   184         }
       
   185 
       
   186         fOut = fopen(fileName.c_str(), "wb");
       
   187         if (!fOut) {
       
   188             fprintf(stderr,"ERROR: Cannot create file: %s\n", fileName.c_str());
       
   189             return false;
       
   190         }
       
   191 
       
   192         if (1 != fwrite(&header, sizeof(header), 1, fOut))
       
   193         {
       
   194             fprintf(stderr,"ERROR: Cannot write fileheader: %s\n", fileName.c_str());
       
   195             fclose(fOut);
       
   196             return false;
       
   197         }
       
   198 
       
   199         for (unsigned int n = 0; n < image.Count(); n++)
       
   200         {
       
   201             bRet = false;
       
   202             unsigned int nAniSize = image.Width() * ((image.Height() + 7) / 8);
       
   203             unsigned char *pAni = new unsigned char[nAniSize];
       
   204             if (!pAni)
       
   205             {
       
   206                 fprintf(stderr, "ERROR: malloc failed.");
       
   207                 break;
       
   208             }
       
   209             horz2vert(image.GetBitmap(n)->Data(), pAni, image.Width(), image.Height());
       
   210 
       
   211             if (1 != fwrite(pAni, nAniSize, 1,  fOut))
       
   212             {
       
   213                 delete [] pAni;
       
   214                 fprintf(stderr,"ERROR: Cannot write filedata: %s\n", fileName.c_str());
       
   215                 break;
       
   216             }
       
   217             delete [] pAni;
       
   218             bRet = true;
       
   219         }
       
   220 
       
   221         fclose(fOut);
       
   222     }
       
   223     return bRet;
       
   224 }
       
   225 
       
   226 /** Translate memory alignment from vertical to horizontal
       
   227 rotate from {Byte} to {Byte}
       
   228 {o}[o][o][o][o][o][o][o] => { oooooooo }
       
   229 {o}[o][o][o][o][o][o][o] => [ oooooooo ]
       
   230 {o}[o][o][o][o][o][o][o] => [ oooooooo ]
       
   231 {o}[o][o][o][o][o][o][o] => [ oooooooo ]
       
   232 {o}[o][o][o][o][o][o][o] => [ oooooooo ]
       
   233 {o}[o][o][o][o][o][o][o] => [ oooooooo ]
       
   234 {o}[o][o][o][o][o][o][o] => [ oooooooo ]
       
   235 {o}[o][o][o][o][o][o][o] => [ oooooooo ]*/
       
   236 void cTuxBoxFile::vert2horz(const unsigned char* source, unsigned char* dest, int width, int height) {
       
   237     int x, y, off;
       
   238     memset(dest,0,height*((width+7)/8));
       
   239 
       
   240     for (y=0; y<height; ++y)
       
   241     {
       
   242         for (x=0; x<width; ++x)
       
   243         {
       
   244             off = x + ((y/8) * width);
       
   245             if (source[off] & (0x1 << (y % 8)))
       
   246             {
       
   247                 off = (x / 8) + (y * ((width+7)/8));
       
   248                 dest[off] |= (unsigned char)(0x80 >> (x % 8));
       
   249             }
       
   250         }
       
   251     }
       
   252 }
       
   253 
       
   254 /** Translate memory alignment from horizontal to vertical (rotate byte)
       
   255 rotate from {Byte} to {Byte}
       
   256 { oooooooo } => {o}[o][o][o][o][o][o][o]
       
   257 [ oooooooo ] => {o}[o][o][o][o][o][o][o]
       
   258 [ oooooooo ] => {o}[o][o][o][o][o][o][o]
       
   259 [ oooooooo ] => {o}[o][o][o][o][o][o][o]
       
   260 [ oooooooo ] => {o}[o][o][o][o][o][o][o]
       
   261 [ oooooooo ] => {o}[o][o][o][o][o][o][o]
       
   262 [ oooooooo ] => {o}[o][o][o][o][o][o][o]
       
   263 [ oooooooo ] => {o}[o][o][o][o][o][o][o]*/
       
   264 void cTuxBoxFile::horz2vert(const unsigned char* source, unsigned char* dest, int width, int height) {
       
   265     int x, y, off;
       
   266     memset(dest,0,width*((height+7)/8));
       
   267 
       
   268     for (y=0; y<height; ++y)
       
   269     {
       
   270         for (x=0; x<width; ++x)
       
   271         {
       
   272             off = (x / 8) + ((y) * ((width+7)/8));
       
   273             if (source[off] & (0x80 >> (x % 8)))
       
   274             {
       
   275                 off = x + ((y/8) * width);
       
   276                 dest[off] |= (unsigned char)(0x1 << (y % 8));
       
   277             }
       
   278         }
       
   279     }
       
   280 }