graphlcd-base/glcdgraphics/glcd.c
author root@rika
Wed, 06 Feb 2008 17:32:55 +0000
changeset 4 df6a40031aa5
permissions -rw-r--r--
added graphlcd-base
root@4
     1
/*
root@4
     2
 * GraphLCD graphics library
root@4
     3
 *
root@4
     4
 * glcd.c  -  GLCD file loading and saving
root@4
     5
 *
root@4
     6
 * based on graphlcd plugin 0.1.1 for the Video Disc Recorder
root@4
     7
 *  (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
root@4
     8
 *
root@4
     9
 * This file is released under the GNU General Public License. Refer
root@4
    10
 * to the COPYING file distributed with this package.
root@4
    11
 *
root@4
    12
 * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
root@4
    13
 */
root@4
    14
root@4
    15
#include <stdio.h>
root@4
    16
#include <stdint.h>
root@4
    17
#include <syslog.h>
root@4
    18
root@4
    19
#include <string>
root@4
    20
root@4
    21
#include "bitmap.h"
root@4
    22
#include "glcd.h"
root@4
    23
#include "image.h"
root@4
    24
root@4
    25
root@4
    26
namespace GLCD
root@4
    27
{
root@4
    28
root@4
    29
using namespace std;
root@4
    30
root@4
    31
const char * kGLCDFileSign = "GLC";
root@4
    32
root@4
    33
/*
root@4
    34
#pragma pack(1)
root@4
    35
struct tGLCDHeader
root@4
    36
{
root@4
    37
    char sign[3];    // = "GLC"
root@4
    38
    char format;     // D - single image, A - animation
root@4
    39
    uint16_t width;  // width in pixels
root@4
    40
    uint16_t height; // height in pixels
root@4
    41
    // only for animations
root@4
    42
    uint16_t count;  // number of pictures
root@4
    43
    uint32_t delay;  // delay in ms
root@4
    44
};
root@4
    45
#pragma pack()
root@4
    46
*/
root@4
    47
root@4
    48
cGLCDFile::cGLCDFile()
root@4
    49
{
root@4
    50
}
root@4
    51
root@4
    52
cGLCDFile::~cGLCDFile()
root@4
    53
{
root@4
    54
}
root@4
    55
root@4
    56
bool cGLCDFile::Load(cImage & image, const string & fileName)
root@4
    57
{
root@4
    58
    FILE * fp;
root@4
    59
    long fileSize;
root@4
    60
    char sign[4];
root@4
    61
    uint8_t buf[6];
root@4
    62
    uint16_t width;
root@4
    63
    uint16_t height;
root@4
    64
    uint16_t count;
root@4
    65
    uint32_t delay;
root@4
    66
root@4
    67
    fp = fopen(fileName.c_str(), "rb");
root@4
    68
    if (!fp)
root@4
    69
    {
root@4
    70
        syslog(LOG_ERR, "glcdgraphics: open %s failed (cGLCDFile::Load).", fileName.c_str());
root@4
    71
        return false;
root@4
    72
    }
root@4
    73
root@4
    74
    // get len of file
root@4
    75
    if (fseek(fp, 0, SEEK_END) != 0)
root@4
    76
    {
root@4
    77
        fclose(fp);
root@4
    78
        return false;
root@4
    79
    }
root@4
    80
    fileSize = ftell(fp);
root@4
    81
root@4
    82
    // rewind and get Header
root@4
    83
    if (fseek(fp, 0, SEEK_SET) != 0)
root@4
    84
    {
root@4
    85
        fclose(fp);
root@4
    86
        return false;
root@4
    87
    }
root@4
    88
root@4
    89
    // read header sign
root@4
    90
    if (fread(sign, 4, 1, fp) != 1)
root@4
    91
    {
root@4
    92
        fclose(fp);
root@4
    93
        return false;
root@4
    94
    }
root@4
    95
root@4
    96
    // check header sign
root@4
    97
    if (strncmp(sign, kGLCDFileSign, 3) != 0)
root@4
    98
    {
root@4
    99
        syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong header (cGLCDFile::Load).", fileName.c_str());
root@4
   100
        fclose(fp);
root@4
   101
        return false;
root@4
   102
    }
root@4
   103
root@4
   104
    // read width and height
root@4
   105
    if (fread(buf, 4, 1, fp) != 1)
root@4
   106
    {
root@4
   107
        fclose(fp);
root@4
   108
        return false;
root@4
   109
    }
root@4
   110
root@4
   111
    width = (buf[1] << 8) | buf[0];
root@4
   112
    height = (buf[3] << 8) | buf[2];
root@4
   113
    if (width == 0 || height == 0)
root@4
   114
    {
root@4
   115
        syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong header (cGLCDFile::Load).", fileName.c_str());
root@4
   116
        fclose(fp);
root@4
   117
        return false;
root@4
   118
    }
root@4
   119
root@4
   120
    if (sign[3] == 'D')
root@4
   121
    {
root@4
   122
        count = 1;
root@4
   123
        delay = 10;
root@4
   124
        // check file length
root@4
   125
        if (fileSize != (long) (height * ((width + 7) / 8) + 8))
root@4
   126
        {
root@4
   127
            syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong size (cGLCDFile::Load).", fileName.c_str());
root@4
   128
            fclose(fp);
root@4
   129
            return false;
root@4
   130
        }
root@4
   131
    }
root@4
   132
    else if (sign[3] == 'A')
root@4
   133
    {
root@4
   134
        // read count and delay
root@4
   135
        if (fread(buf, 6, 1, fp) != 1)
root@4
   136
        {
root@4
   137
            syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong header (cGLCDFile::Load).", fileName.c_str());
root@4
   138
            fclose(fp);
root@4
   139
            return false;
root@4
   140
        }
root@4
   141
        count = (buf[1] << 8) | buf[0];
root@4
   142
        delay = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
root@4
   143
        // check file length
root@4
   144
        if (count == 0 ||
root@4
   145
            fileSize != (long) (count * (height * ((width + 7) / 8)) + 14))
root@4
   146
        {
root@4
   147
            syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong size (cGLCDFile::Load).", fileName.c_str());
root@4
   148
            fclose(fp);
root@4
   149
            return false;
root@4
   150
        }
root@4
   151
        // Set minimal limit for next image
root@4
   152
        if (delay < 10)
root@4
   153
            delay = 10;
root@4
   154
    }
root@4
   155
    else
root@4
   156
    {
root@4
   157
        syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong header (cGLCDFile::Load).", fileName.c_str());
root@4
   158
        fclose(fp);
root@4
   159
        return false;
root@4
   160
    }
root@4
   161
root@4
   162
    image.Clear();
root@4
   163
    image.SetWidth(width);
root@4
   164
    image.SetHeight(height);
root@4
   165
    image.SetDelay(delay);
root@4
   166
    unsigned char * bmpdata = new unsigned char[height * ((width + 7) / 8)];
root@4
   167
    if (bmpdata)
root@4
   168
    {
root@4
   169
        for (unsigned int n = 0; n < count; n++)
root@4
   170
        {
root@4
   171
            if (fread(bmpdata, height * ((width + 7) / 8), 1, fp) != 1)
root@4
   172
            {
root@4
   173
                delete[] bmpdata;
root@4
   174
                fclose(fp);
root@4
   175
                image.Clear();
root@4
   176
                return false;
root@4
   177
            }
root@4
   178
            image.AddBitmap(new cBitmap(width, height, bmpdata));
root@4
   179
        }
root@4
   180
        delete[] bmpdata;
root@4
   181
    }
root@4
   182
    else
root@4
   183
    {
root@4
   184
        syslog(LOG_ERR, "glcdgraphics: malloc failed (cGLCDFile::Load).");
root@4
   185
        fclose(fp);
root@4
   186
        image.Clear();
root@4
   187
        return false;
root@4
   188
    }
root@4
   189
    fclose(fp);
root@4
   190
root@4
   191
    syslog(LOG_DEBUG, "glcdgraphics: image %s loaded.", fileName.c_str());
root@4
   192
    return true;
root@4
   193
}
root@4
   194
root@4
   195
bool cGLCDFile::Save(cImage & image, const string & fileName)
root@4
   196
{
root@4
   197
    FILE * fp;
root@4
   198
    uint8_t buf[14];
root@4
   199
    uint16_t width;
root@4
   200
    uint16_t height;
root@4
   201
    uint16_t count;
root@4
   202
    uint32_t delay;
root@4
   203
    const cBitmap * bitmap;
root@4
   204
    int i;
root@4
   205
root@4
   206
    if (image.Count() == 0)
root@4
   207
        return false;
root@4
   208
root@4
   209
    fp = fopen(fileName.c_str(), "wb");
root@4
   210
    if (!fp)
root@4
   211
    {
root@4
   212
        syslog(LOG_ERR, "glcdgraphics: open %s failed (cGLCDFile::Save).", fileName.c_str());
root@4
   213
        return false;
root@4
   214
    }
root@4
   215
root@4
   216
    memcpy(buf, kGLCDFileSign, 3);
root@4
   217
    count = image.Count();
root@4
   218
    delay = image.Delay();
root@4
   219
    if (count == 1)
root@4
   220
    {
root@4
   221
        buf[3] = 'D';
root@4
   222
    }
root@4
   223
    else
root@4
   224
    {
root@4
   225
        buf[3] = 'A';
root@4
   226
    }
root@4
   227
    bitmap = image.GetBitmap(0);
root@4
   228
    width = bitmap->Width();
root@4
   229
    height = bitmap->Height();
root@4
   230
    buf[4] = (uint8_t) width;
root@4
   231
    buf[5] = (uint8_t) (width >> 8);
root@4
   232
    buf[6] = (uint8_t) height;
root@4
   233
    buf[7] = (uint8_t) (height >> 8);
root@4
   234
    if (count == 1)
root@4
   235
    {
root@4
   236
        if (fwrite(buf, 8, 1, fp) != 1)
root@4
   237
        {
root@4
   238
            fclose(fp);
root@4
   239
            return false;
root@4
   240
        }
root@4
   241
    }
root@4
   242
    else
root@4
   243
    {
root@4
   244
        buf[8] = (uint8_t) count;
root@4
   245
        buf[9] = (uint8_t) (count >> 8);
root@4
   246
        buf[10] = (uint8_t) delay;
root@4
   247
        buf[11] = (uint8_t) (delay >> 8);
root@4
   248
        buf[12] = (uint8_t) (delay >> 16);
root@4
   249
        buf[13] = (uint8_t) (delay >> 24);
root@4
   250
        if (fwrite(buf, 14, 1, fp) != 1)
root@4
   251
        {
root@4
   252
            fclose(fp);
root@4
   253
            return false;
root@4
   254
        }
root@4
   255
    }
root@4
   256
    for (i = 0; i < count; i++)
root@4
   257
    {
root@4
   258
        bitmap = image.GetBitmap(i);
root@4
   259
        if (bitmap)
root@4
   260
        {
root@4
   261
            if (bitmap->Width() == width && bitmap->Height() == height)
root@4
   262
            {
root@4
   263
                if (fwrite(bitmap->Data(), height * ((width + 7) / 8), 1, fp) != 1)
root@4
   264
                {
root@4
   265
                    fclose(fp);
root@4
   266
                    return false;
root@4
   267
                }
root@4
   268
            }
root@4
   269
        }
root@4
   270
    }
root@4
   271
    fclose(fp);
root@4
   272
root@4
   273
    syslog(LOG_DEBUG, "glcdgraphics: image %s saved.", fileName.c_str());
root@4
   274
    return true;
root@4
   275
}
root@4
   276
root@4
   277
} // end of namespace