Well, I still can't find that super-simple code, but maybe the following
would be of use to you? It's bmptoppm.c, from the netpbm package. The
program as-is reads a .BMP (max 256 colors, IIRC) and then writes a
series of text RGB triplets to STDOUT. Maybe you could appropriate the
reading routines?


/*\
 * $Id: bmptoppm.c,v 1.10 1992/11/24 19:38:17 dws Exp dws $
 *
 * bmptoppm.c - Converts from a Microsoft Windows or OS/2 .BMP file to a
 * PPM file.
 *
 * The current implementation is probably not complete, but it works for
 * all the BMP files I have.  I welcome feedback.
 *
 * Copyright (C) 1992 by David W. Sanderson.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  This software is provided "as is"
 * without express or implied warranty.
 *
 * $Log: bmptoppm.c,v $
 * Revision 1.10  1992/11/24  19:38:17  dws
 * Added code to verify that reading occurred at the correct offsets.
 * Added copyright.
 *
 * Revision 1.9  1992/11/17  02:15:24  dws
 * Changed to include bmp.h.
 * Eliminated need for fseek(), and therefore the need for a
 * temporary file.
 *
 * Revision 1.8  1992/11/13  23:48:57  dws
 * Made definition of Seekable() static, to match its prototype.
 *
 * Revision 1.7  1992/11/11  00:17:50  dws
 * Generalized to use bitio routines.
 *
 * Revision 1.6  1992/11/10  23:51:44  dws
 * Enhanced command-line handling.
 *
 * Revision 1.5  1992/11/08  00:38:46  dws
 * Changed some names to help w/ addition of ppmtobmp.
 *
 * Revision 1.4  1992/10/27  06:28:28  dws
 * Corrected stupid typo.
 *
 * Revision 1.3  1992/10/27  06:17:10  dws
 * Removed a magic constant value.
 *
 * Revision 1.2  1992/10/27  06:09:58  dws
 * Made stdin seekable.
 *
 * Revision 1.1  1992/10/27  05:31:41  dws
 * Initial revision
\*/

#include        "bmp.h"
#include        "ppm.h"
#include        "bitio.h"

#define MAXCOLORS       256

static char    *ifname;

/*
 * Utilities
 */

static int GetByte ARGS((FILE * fp));
static short GetShort ARGS((FILE * fp));
static long GetLong ARGS((FILE * fp));
static void readto ARGS((FILE *fp, unsigned long *ppos, unsigned long dst));
static void BMPreadfileheader ARGS((FILE *fp, unsigned long *ppos,
    unsigned long *poffBits));
static void BMPreadinfoheader ARGS((FILE *fp, unsigned long *ppos,
    unsigned long *pcx, unsigned long *pcy, unsigned short *pcBitCount,
    int *pclass));
static int BMPreadrgbtable ARGS((FILE *fp, unsigned long *ppos,
    unsigned short cBitCount, int class, pixval *R, pixval *G, pixval *B));
static int BMPreadrow ARGS((FILE *fp, unsigned long *ppos, pixel *row,
    unsigned long cx, unsigned short cBitCount, pixval *R, pixval *G, pixval *B));
static pixel ** BMPreadbits ARGS((FILE *fp, unsigned long *ppos,
    unsigned long offBits, unsigned long cx, unsigned long cy,
    unsigned short cBitCount, int class, pixval *R, pixval *G, pixval *B));

static char     er_read[] = "%s: read error";
static char     er_seek[] = "%s: seek error";

static int
GetByte(fp)
        FILE           *fp;
{
        int             v;

        if ((v = getc(fp)) == EOF)
        {
                pm_error(er_read, ifname);
        }

        return v;
}

static short
GetShort(fp)
        FILE           *fp;
{
        short           v;

        if (pm_readlittleshort(fp, &v) == -1)
        {
                pm_error(er_read, ifname);
        }

        return v;
}

static long
GetLong(fp)
        FILE           *fp;
{
        long            v;

        if (pm_readlittlelong(fp, &v) == -1)
        {
                pm_error(er_read, ifname);
        }

        return v;
}

/*
 * readto - read as many bytes as necessary to position the
 * file at the desired offset.
 */

static void
readto(fp, ppos, dst)
        FILE           *fp;
        unsigned long  *ppos;   /* pointer to number of bytes read from fp */
        unsigned long   dst;
{
        unsigned long   pos;

        if(!fp || !ppos)
                return;

        pos = *ppos;

        if(pos > dst)
                pm_error("%s: internal error in readto()", ifname);

        for(; pos < dst; pos++)
        {
                if (getc(fp) == EOF)
                {
                        pm_error(er_read, ifname);
                }
        }

        *ppos = pos;
}

#if 0
static void
Seek(fp, off)
        FILE           *fp;
        long            off;
{
        if (fseek(fp, off, 0) == -1)
        {
                pm_error(er_seek, ifname);
        }
}

/*
 * Seekable(f) - makes sure the given FILE* is seekable (for
 * reading). returns f if it is, and a new, seekable FILE* if f is
 * stdin.
 */

static FILE    *
Seekable(f)
        FILE           *f;
{
        int             c;
        FILE           *t;

        if (f != stdin)
        {
                return f;
        }

        t = tmpfile();

        while ((c = getc(f)) != EOF)
        {
                putc(c, t);
        }

        rewind(t);

        return t;
}
#endif


/*
 * BMP reading routines
 */

static void
BMPreadfileheader(fp, ppos, poffBits)
        FILE           *fp;
        unsigned long  *ppos;   /* number of bytes read from fp */
        unsigned long  *poffBits;
{
        unsigned long   cbSize;
        unsigned short  xHotSpot;
        unsigned short  yHotSpot;
        unsigned long   offBits;

        if (GetByte(fp) != 'B')
        {
                pm_error("%s is not a BMP file", ifname);
        }
        if (GetByte(fp) != 'M')
        {
                pm_error("%s is not a BMP file", ifname);
        }

        cbSize = GetLong(fp);
        xHotSpot = GetShort(fp);
        yHotSpot = GetShort(fp);
        offBits = GetLong(fp);

        *poffBits = offBits;

        *ppos += 14;
}

static void
BMPreadinfoheader(fp, ppos, pcx, pcy, pcBitCount, pclass)
        FILE           *fp;
        unsigned long  *ppos;   /* number of bytes read from fp */
        unsigned long  *pcx;
        unsigned long  *pcy;
        unsigned short *pcBitCount;
        int            *pclass;
{
        unsigned long   cbFix;
        unsigned short  cPlanes;

        unsigned long   cx;
        unsigned long   cy;
        unsigned short  cBitCount;
        int             class;

        cbFix = GetLong(fp);

        switch (cbFix)
        {
        case 12:
                class = C_OS2;

                cx = GetShort(fp);
                cy = GetShort(fp);
                cPlanes = GetShort(fp);
                cBitCount = GetShort(fp);

                break;
        case 40:
                class = C_WIN;

                cx = GetLong(fp);
                cy = GetLong(fp);
                cPlanes = GetShort(fp);
                cBitCount = GetShort(fp);

                /*
                 * We've read 16 bytes so far, need to read 24 more
                 * for the required total of 40.
                 */

                GetLong(fp);
                GetLong(fp);
                GetLong(fp);
                GetLong(fp);
                GetLong(fp);
                GetLong(fp);

                break;
        default:
                pm_error("%s: unknown cbFix: %d", ifname, cbFix);
                break;
        }

        if (cPlanes != 1)
        {
                pm_error("%s: don't know how to handle cPlanes = %d"
                         ,ifname
                         ,cPlanes);
        }

        switch (class)
        {
        case C_WIN:
                pm_message("Windows BMP, %dx%dx%d"
                           ,cx
                           ,cy
                           ,cBitCount);
                break;
        case C_OS2:
                pm_message("OS/2 BMP, %dx%dx%d"
                           ,cx
                           ,cy
                           ,cBitCount);
                break;
        }

#ifdef DEBUG
        pm_message("cbFix: %d", cbFix);
        pm_message("cx: %d", cx);
        pm_message("cy: %d", cy);
        pm_message("cPlanes: %d", cPlanes);
        pm_message("cBitCount: %d", cBitCount);
#endif

        *pcx = cx;
        *pcy = cy;
        *pcBitCount = cBitCount;
        *pclass = class;

        *ppos += cbFix;
}

/*
 * returns the number of bytes read, or -1 on error.
 */
static int
BMPreadrgbtable(fp, ppos, cBitCount, class, R, G, B)
        FILE           *fp;
        unsigned long  *ppos;   /* number of bytes read from fp */
        unsigned short  cBitCount;
        int             class;
        pixval         *R;
        pixval         *G;
        pixval         *B;
{
        int             i;
        int             nbyte = 0;

        long            ncolors = (1 << cBitCount);

        for (i = 0; i < ncolors; i++)
        {
                B[i] = (pixval) GetByte(fp);
                G[i] = (pixval) GetByte(fp);
                R[i] = (pixval) GetByte(fp);
                nbyte += 3;

                if (class == C_WIN)
                {
                        (void) GetByte(fp);
                        nbyte++;
                }
        }

        *ppos += nbyte;
        return nbyte;
}

/*
 * returns the number of bytes read, or -1 on error.
 */
static int
BMPreadrow(fp, ppos, row, cx, cBitCount, R, G, B)
        FILE           *fp;
        unsigned long  *ppos;   /* number of bytes read from fp */
        pixel          *row;
        unsigned long   cx;
        unsigned short  cBitCount;
        pixval         *R;
        pixval         *G;
        pixval         *B;
{
        BITSTREAM       b;
        unsigned        nbyte = 0;
        int             rc;
        unsigned        x;

        if ((b = pm_bitinit(fp, "r")) == (BITSTREAM) 0)
        {
                return -1;
        }

        for (x = 0; x < cx; x++, row++)
        {
                unsigned long   v;

                if ((rc = pm_bitread(b, cBitCount, &v)) == -1)
                {
                        return -1;
                }
                nbyte += rc;

                PPM_ASSIGN(*row, R[v], G[v], B[v]);
        }

        if ((rc = pm_bitfini(b)) != 0)
        {
                return -1;
        }

        /*
         * Make sure we read a multiple of 4 bytes.
         */
        while (nbyte % 4)
        {
                GetByte(fp);
                nbyte++;
        }

        *ppos += nbyte;
        return nbyte;
}

static pixel **
BMPreadbits(fp, ppos, offBits, cx, cy, cBitCount, class, R, G, B)
        FILE           *fp;
        unsigned long  *ppos;   /* number of bytes read from fp */
        unsigned long   offBits;
        unsigned long   cx;
        unsigned long   cy;
        unsigned short  cBitCount;
        int             class;
        pixval         *R;
        pixval         *G;
        pixval         *B;
{
        pixel         **pixels; /* output */
        long            y;

        readto(fp, ppos, offBits);

        pixels = ppm_allocarray(cx, cy);

        if(cBitCount > 24)
        {
                pm_error("%s: cannot handle cBitCount: %d"
                         ,ifname
                         ,cBitCount);
        }

        /*
         * The picture is stored bottom line first, top line last
         */

        for (y = cy - 1; y >= 0; y--)
        {
                int rc;
                rc = BMPreadrow(fp, ppos, pixels[y], cx, cBitCount, R, G, B);

                if(rc == -1)
                {
                        pm_error("%s: couldn't read row %d"
                                 ,ifname
                                 ,y);
                }
                if(rc%4)
                {
                        pm_error("%s: row had bad number of bytes: %d"
                                 ,ifname
                                 ,rc);
                }
        }

        return pixels;
}

int
main(argc, argv)
        int             argc;
        char          **argv;
{
        FILE           *ifp = stdin;
        char           *usage = "[bmpfile]";
        int             argn;

        int             rc;
        unsigned long   pos = 0;

        unsigned long   offBits;

        unsigned long   cx;
        unsigned long   cy;
        unsigned short  cBitCount;
        int             class;

        pixval          R[MAXCOLORS];   /* reds */
        pixval          G[MAXCOLORS];   /* greens */
        pixval          B[MAXCOLORS];   /* blues */

        pixel         **pixels;


        ppm_init(&argc, argv);

        /*
         * Since this command takes no flags, produce an error message
         * if the user tries to give any.
         * This is friendlier than if the command were to say
         * 'no such file: -help'.
         */

        argn = 1;
        while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0')
        {
                pm_usage(usage);
                ++argn;
        }

        if (argn < argc)
        {
                ifname = argv[argn];
                ifp = pm_openr(ifname);
                ++argn;
        }
        else
        {
                ifname = "standard input";
                ifp = stdin;
        }

        if (argn != argc)
        {
                pm_usage(usage);
        }

        BMPreadfileheader(ifp, &pos, &offBits);
        BMPreadinfoheader(ifp, &pos, &cx, &cy, &cBitCount, &class);

        if(offBits != BMPoffbits(class, cBitCount))
        {
                pm_message("warning: offBits is %d, expected %d"
                        , pos
                        , BMPoffbits(class, cBitCount));
        }

        rc = BMPreadrgbtable(ifp, &pos, cBitCount, class, R, G, B);

        if(rc != BMPlenrgbtable(class, cBitCount))
        {
                pm_message("warning: %d-byte RGB table, expected %d bytes"
                        , rc
                        , BMPlenrgbtable(class, cBitCount));
        }


        pixels = BMPreadbits(ifp, &pos, offBits, cx, cy
                        , cBitCount, class, R, G, B);

        if(pos != BMPlenfile(class, cBitCount, cx, cy))
        {
                pm_message("warning: read %d bytes, expected to read %d bytes"
                        , pos
                        , BMPlenfile(class, cBitCount, cx, cy));
        }

        pm_close(ifp);
        ppm_writeppm(stdout, pixels, cx, cy, (pixval) (MAXCOLORS-1), 0);
        pm_close(stdout);

        exit(0);
}


------------------------------------------------------------------
Unsubscribe:  To:   [EMAIL PROTECTED]
              Body: unsubscribe linux-svgalib

Reply via email to