iPXE
Functions | Variables
pnm.c File Reference

Portable anymap format (PNM) More...

#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <ipxe/image.h>
#include <ipxe/pixbuf.h>
#include <ipxe/pnm.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static int pnm_ascii (struct image *image, struct pnm_context *pnm)
 Extract PNM ASCII value.
static int pnm_binary (struct image *image, struct pnm_context *pnm)
 Extract PNM binary value.
static int pnm_scale (struct image *image, struct pnm_context *pnm, unsigned int value)
 Scale PNM scalar value.
static uint32_t pnm_bitmap (uint32_t composite, unsigned int index)
 Convert PNM bitmap composite value to RGB.
static uint32_t pnm_greymap (uint32_t composite, unsigned int index __unused)
 Convert PNM greymap composite value to RGB.
static uint32_t pnm_pixmap (uint32_t composite, unsigned int index __unused)
 Convert PNM pixmap composite value to RGB.
static int pnm_data (struct image *image, struct pnm_context *pnm, struct pixel_buffer *pixbuf)
 Extract PNM pixel data.
static struct pnm_typepnm_type (struct image *image)
 Determine PNM image type.
static int pnm_pixbuf (struct image *image, struct pixel_buffer **pixbuf)
 Convert PNM image to pixel buffer.
static int pnm_probe (struct image *image)
 Probe PNM image.
struct image_type pnm_image_type __image_type (PROBE_NORMAL)
 PNM image type.

Variables

static struct pnm_type pnm_types []
 PNM image types.

Detailed Description

Portable anymap format (PNM)

Definition in file pnm.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static int pnm_ascii ( struct image image,
struct pnm_context pnm 
) [static]

Extract PNM ASCII value.

Parameters:
imagePNM image
pnmPNM context
Return values:
valueValue, or negative error

Definition at line 46 of file pnm.c.

References pnm_context::ascii_len, copy_from_user(), image::data, DBGC, EINVAL, isspace(), image::len, len, image::name, pnm_context::offset, strtoul(), and value.

Referenced by pnm_pixbuf().

                                                                      {
        char buf[ pnm->ascii_len + 1 /* NUL */ ];
        char *endp;
        size_t len;
        int value;
        int in_comment = 0;

        /* Skip any leading whitespace and comments */
        for ( ; pnm->offset < image->len ; pnm->offset++ ) {
                copy_from_user ( &buf[0], image->data, pnm->offset,
                                 sizeof ( buf[0] ) );
                if ( in_comment ) {
                        if ( buf[0] == '\n' )
                                in_comment = 0;
                } else {
                        if ( buf[0] == '#' ) {
                                in_comment = 1;
                        } else if ( ! isspace ( buf[0] ) ) {
                                break;
                        }
                }
        }

        /* Fail if no value is present */
        len = ( image->len - pnm->offset );
        if ( len == 0 ) {
                DBGC ( image, "PNM %s ran out of ASCII data\n", image->name );
                return -EINVAL;
        }

        /* Copy ASCII value to buffer and ensure string is NUL-terminated */
        if ( len > ( sizeof ( buf ) - 1 /* NUL */ ) )
                len = ( sizeof ( buf ) - 1 /* NUL */ );
        copy_from_user ( buf, image->data, pnm->offset, len );
        buf[len] = '\0';

        /* Parse value and update offset */
        value = strtoul ( buf, &endp, 0 );
        pnm->offset += ( endp - buf );

        /* Check and skip terminating whitespace character, if present */
        if ( ( pnm->offset != image->len ) && ( *endp != '\0' ) ) {
                if ( ! isspace ( *endp ) ) {
                        DBGC ( image, "PNM %s invalid ASCII integer\n",
                               image->name );
                        return -EINVAL;
                }
                pnm->offset++;
        }

        return value;
}
static int pnm_binary ( struct image image,
struct pnm_context pnm 
) [static]

Extract PNM binary value.

Parameters:
imagePNM image
pnmPNM context
Return values:
valueValue, or negative error

Definition at line 106 of file pnm.c.

References copy_from_user(), image::data, DBGC, EINVAL, image::len, image::name, pnm_context::offset, and value.

                                                                       {
        uint8_t value;

        /* Sanity check */
        if ( pnm->offset == image->len ) {
                DBGC ( image, "PNM %s ran out of binary data\n",
                       image->name );
                return -EINVAL;
        }

        /* Extract value */
        copy_from_user ( &value, image->data, pnm->offset, sizeof ( value ) );
        pnm->offset++;

        return value;
}
static int pnm_scale ( struct image image,
struct pnm_context pnm,
unsigned int  value 
) [static]

Scale PNM scalar value.

Parameters:
imagePNM image
pnmPNM context
valueRaw value
Return values:
valueScaled value (in range 0-255)

Definition at line 131 of file pnm.c.

References DBGC, EINVAL, pnm_context::max, and image::name.

Referenced by pnm_data().

                                            {

        if ( value > pnm->max ) {
                DBGC ( image, "PNM %s has out-of-range value %d (max %d)\n",
                       image->name, value, pnm->max );
                return -EINVAL;
        }
        return ( ( 255 * value ) / pnm->max );
}
static uint32_t pnm_bitmap ( uint32_t  composite,
unsigned int  index 
) [static]

Convert PNM bitmap composite value to RGB.

Parameters:
compositeComposite value
indexPixel index within this composite value
Return values:
rgb24-bit RGB value

Definition at line 149 of file pnm.c.

                                                                      {

        /* Composite value is an 8-bit bitmask */
        return ( ( ( composite << index ) & 0x80 ) ? 0x000000 : 0xffffff );
}
static uint32_t pnm_greymap ( uint32_t  composite,
unsigned int index  __unused 
) [static]

Convert PNM greymap composite value to RGB.

Parameters:
compositeComposite value
indexPixel index within this composite value
Return values:
rgb24-bit RGB value

Definition at line 162 of file pnm.c.

                                                                               {

        /* Composite value is an 8-bit greyscale value */
        return ( ( composite << 16 ) | ( composite << 8 ) | composite );
}
static uint32_t pnm_pixmap ( uint32_t  composite,
unsigned int index  __unused 
) [static]

Convert PNM pixmap composite value to RGB.

Parameters:
compositeComposite value
indexPixel index within this composite value
Return values:
rgb24-bit RGB value

Definition at line 175 of file pnm.c.

                                                                               {

        /* Composite value is already an RGB value */
        return composite;
}
static int pnm_data ( struct image image,
struct pnm_context pnm,
struct pixel_buffer pixbuf 
) [static]

Extract PNM pixel data.

Parameters:
imagePNM image
pnmPNM context
pixbufPixel buffer
Return values:
rcReturn status code

Definition at line 189 of file pnm.c.

References copy_to_user(), pixel_buffer::data, DBGC, pnm_type::depth, EINVAL, pixel_buffer::len, len, image::name, offset, pnm_type::packing, pnm_scale(), pnm_type::rgb, pnm_type::scalar, pnm_context::type, type, and pixel_buffer::width.

Referenced by pnm_pixbuf().

                                                    {
        struct pnm_type *type = pnm->type;
        size_t offset = 0;
        unsigned int xpos = 0;
        int scalar;
        uint32_t composite;
        uint32_t rgb;
        unsigned int i;

        /* Fill pixel buffer */
        while ( offset < pixbuf->len ) {

                /* Extract a scaled composite scalar value from the file */
                composite = 0;
                for ( i = 0 ; i < type->depth ; i++ ) {
                        scalar = type->scalar ( image, pnm );
                        if ( scalar < 0 )
                                return scalar;
                        scalar = pnm_scale ( image, pnm, scalar );
                        if ( scalar < 0 )
                                return scalar;
                        composite = ( ( composite << 8 ) | scalar );
                }

                /* Extract 24-bit RGB values from composite value */
                for ( i = 0 ; i < type->packing ; i++ ) {
                        if ( offset >= pixbuf->len ) {
                                DBGC ( image, "PNM %s has too many pixels\n",
                                       image->name );
                                return -EINVAL;
                        }
                        rgb = type->rgb ( composite, i );
                        copy_to_user ( pixbuf->data, offset, &rgb,
                                       sizeof ( rgb ) );
                        offset += sizeof ( rgb );
                        if ( ++xpos == pixbuf->width ) {
                                xpos = 0;
                                break;
                        }
                }
        }

        return 0;
}
static struct pnm_type* pnm_type ( struct image image) [static, read]

Determine PNM image type.

Parameters:
imagePNM image
Return values:
typePNM image type, or NULL if not found

Definition at line 289 of file pnm.c.

References assert, copy_from_user(), image::data, image::len, NULL, pnm_types, pnm_signature::type, pnm_type::type, and type.

Referenced by pnm_pixbuf().

                                                          {
        struct pnm_signature signature;
        struct pnm_type *type;
        unsigned int i;

        /* Extract signature */
        assert ( image->len >= sizeof ( signature ) );
        copy_from_user ( &signature, image->data, 0, sizeof ( signature ) );

        /* Check for supported types */
        for ( i = 0 ; i < ( sizeof ( pnm_types ) /
                            sizeof ( pnm_types[0] ) ) ; i++ ) {
                type = &pnm_types[i];
                if ( type->type == signature.type )
                        return type;
        }
        return NULL;
}
static int pnm_pixbuf ( struct image image,
struct pixel_buffer **  pixbuf 
) [static]

Convert PNM image to pixel buffer.

Parameters:
imagePNM image
pixbufPixel buffer to fill in
Return values:
rcReturn status code

Definition at line 315 of file pnm.c.

References alloc_pixbuf(), pnm_context::ascii_len, DBGC, EINVAL, ENOMEM, ENOTSUP, pnm_type::flags, pnm_context::max, max, image::name, pnm_context::offset, pnm_type::packing, pnm_ascii(), PNM_ASCII_LEN, PNM_BITMAP, pnm_data(), pnm_type(), rc, pnm_context::type, and pnm_type::type.

                                                                            {
        struct pnm_context pnm;
        int width;
        int height;
        int max;
        int rc;

        /* Initialise PNM context */
        pnm.type = pnm_type ( image );
        if ( ! pnm.type ) {
                rc = -ENOTSUP;
                goto err_type;
        }
        pnm.offset = sizeof ( struct pnm_signature );
        pnm.ascii_len = PNM_ASCII_LEN;

        /* Extract width */
        if ( ( width = pnm_ascii ( image, &pnm ) ) < 0 ) {
                rc = width;
                goto err_width;
        }

        /* Extract height */
        if ( ( height = pnm_ascii ( image, &pnm ) ) < 0 ) {
                rc = height;
                goto err_height;
        }

        /* Extract maximum scalar value, if not predefined */
        if ( pnm.type->flags & PNM_BITMAP ) {
                pnm.max = ( ( 1 << pnm.type->packing ) - 1 );
                pnm.ascii_len = 1;
        } else {
                if ( ( max = pnm_ascii ( image, &pnm ) ) < 0 ) {
                        rc = max;
                        goto err_max;
                }
                pnm.max = max;
        }
        if ( pnm.max == 0 ) {
                DBGC ( image, "PNM %s has invalid maximum value 0\n",
                       image->name );
                rc = -EINVAL;
                goto err_max;
        }
        DBGC ( image, "PNM %s is type %c width %d height %d max %d\n",
               image->name, pnm.type->type, width, height, pnm.max );

        /* Allocate pixel buffer */
        *pixbuf = alloc_pixbuf ( width, height );
        if ( ! *pixbuf ) {
                rc = -ENOMEM;
                goto err_alloc_pixbuf;
        }

        /* Extract pixel data */
        if ( ( rc = pnm_data ( image, &pnm, *pixbuf ) ) != 0 )
                goto err_data;

        return 0;

 err_data:
        pixbuf_put ( *pixbuf );
 err_alloc_pixbuf:
 err_max:
 err_height:
 err_width:
 err_type:
        return rc;
}
static int pnm_probe ( struct image image) [static]

Probe PNM image.

Parameters:
imagePNM image
Return values:
rcReturn status code

Definition at line 392 of file pnm.c.

References copy_from_user(), image::data, DBGC, ENOEXEC, isdigit(), isspace(), image::len, pnm_signature::magic, image::name, PNM_MAGIC, pnm_signature::space, and pnm_signature::type.

                                             {
        struct pnm_signature signature;

        /* Sanity check */
        if ( image->len < sizeof ( signature ) ) {
                DBGC ( image, "PNM %s is too short\n", image->name );
                return -ENOEXEC;
        }

        /* Check signature */
        copy_from_user ( &signature, image->data, 0, sizeof ( signature ) );
        if ( ! ( ( signature.magic == PNM_MAGIC ) &&
                 ( isdigit ( signature.type ) ) &&
                 ( isspace ( signature.space ) ) ) ) {
                DBGC ( image, "PNM %s has invalid signature\n", image->name );
                return -ENOEXEC;
        }
        DBGC ( image, "PNM %s is type %c\n", image->name, signature.type );

        return 0;
}
struct image_type pnm_image_type __image_type ( PROBE_NORMAL  ) [read]

PNM image type.


Variable Documentation

struct pnm_type pnm_types[] [static]

PNM image types.

Definition at line 236 of file pnm.c.

Referenced by pnm_type().