iPXE
pnm.c File Reference

Portable anymap format (PNM) More...

#include <stdlib.h>
#include <string.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_type * pnm_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()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ pnm_ascii()

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 47 of file pnm.c.

47 {
48 char buf[ pnm->ascii_len + 1 /* NUL */ ];
49 char *endp;
50 char ch;
51 size_t len;
52 int value;
53 int in_comment = 0;
54
55 /* Skip any leading whitespace and comments */
56 for ( ; pnm->offset < image->len ; pnm->offset++ ) {
57 ch = *( ( ( const uint8_t * ) image->data ) + pnm->offset );
58 if ( in_comment ) {
59 if ( ch == '\n' )
60 in_comment = 0;
61 } else {
62 if ( ch == '#' ) {
63 in_comment = 1;
64 } else if ( ! isspace ( ch ) ) {
65 break;
66 }
67 }
68 }
69
70 /* Fail if no value is present */
71 len = ( image->len - pnm->offset );
72 if ( len == 0 ) {
73 DBGC ( image, "PNM %s ran out of ASCII data\n", image->name );
74 return -EINVAL;
75 }
76
77 /* Copy ASCII value to buffer and ensure string is NUL-terminated */
78 if ( len > ( sizeof ( buf ) - 1 /* NUL */ ) )
79 len = ( sizeof ( buf ) - 1 /* NUL */ );
80 memcpy ( buf, ( image->data + pnm->offset ), len );
81 buf[len] = '\0';
82
83 /* Parse value and update offset */
84 value = strtoul ( buf, &endp, 0 );
85 pnm->offset += ( endp - buf );
86
87 /* Check and skip terminating whitespace character, if present */
88 if ( ( pnm->offset != image->len ) && ( *endp != '\0' ) ) {
89 if ( ! isspace ( *endp ) ) {
90 DBGC ( image, "PNM %s invalid ASCII integer\n",
91 image->name );
92 return -EINVAL;
93 }
94 pnm->offset++;
95 }
96
97 return value;
98}
pseudo_bit_t value[0x00020]
Definition arbel.h:2
unsigned char uint8_t
Definition stdint.h:10
int isspace(int character)
Check to see if character is a space.
Definition ctype.c:42
ring len
Length.
Definition dwmac.h:226
#define DBGC(...)
Definition compiler.h:505
#define EINVAL
Invalid argument.
Definition errno.h:429
void * memcpy(void *dest, const void *src, size_t len) __nonnull
uint8_t ch
Definition registers.h:1
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition string.c:485
An executable image.
Definition image.h:24
const void * data
Read-only data.
Definition image.h:51
char * name
Name.
Definition image.h:38
size_t len
Length of raw file image.
Definition image.h:56
size_t ascii_len
Maximum length of ASCII values.
Definition pnm.h:35
size_t offset
Current byte offset.
Definition pnm.h:33

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

Referenced by pnm_pixbuf().

◆ pnm_binary()

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 107 of file pnm.c.

107 {
108 const uint8_t *value;
109
110 /* Sanity check */
111 if ( pnm->offset == image->len ) {
112 DBGC ( image, "PNM %s ran out of binary data\n",
113 image->name );
114 return -EINVAL;
115 }
116
117 /* Extract value */
118 value = ( image->data + pnm->offset++ );
119 return *value;
120}

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

◆ pnm_scale()

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 130 of file pnm.c.

131 {
132
133 if ( value > pnm->max ) {
134 DBGC ( image, "PNM %s has out-of-range value %d (max %d)\n",
135 image->name, value, pnm->max );
136 return -EINVAL;
137 }
138 return ( ( 255 * value ) / pnm->max );
139}
unsigned int max
Maximum pixel value.
Definition pnm.h:37

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

Referenced by pnm_data().

◆ pnm_bitmap()

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 148 of file pnm.c.

148 {
149
150 /* Composite value is an 8-bit bitmask */
151 return ( ( ( composite << index ) & 0x80 ) ? 0x000000 : 0xffffff );
152}
long index
Definition bigint.h:65

References index.

◆ pnm_greymap()

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 161 of file pnm.c.

161 {
162
163 /* Composite value is an 8-bit greyscale value */
164 return ( ( composite << 16 ) | ( composite << 8 ) | composite );
165}

References __unused, and index.

◆ pnm_pixmap()

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 174 of file pnm.c.

174 {
175
176 /* Composite value is already an RGB value */
177 return composite;
178}

References __unused, and index.

◆ pnm_data()

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 188 of file pnm.c.

189 {
190 struct pnm_type *type = pnm->type;
191 unsigned int pixels = pixbuf->pixels;
192 unsigned int index = 0;
193 unsigned int xpos = 0;
194 int scalar;
195 uint32_t composite;
196 unsigned int i;
197
198 /* Fill pixel buffer */
199 while ( index < pixels ) {
200
201 /* Extract a scaled composite scalar value from the file */
202 composite = 0;
203 for ( i = 0 ; i < type->depth ; i++ ) {
204 scalar = type->scalar ( image, pnm );
205 if ( scalar < 0 )
206 return scalar;
207 scalar = pnm_scale ( image, pnm, scalar );
208 if ( scalar < 0 )
209 return scalar;
210 composite = ( ( composite << 8 ) | scalar );
211 }
212
213 /* Extract 24-bit RGB values from composite value */
214 for ( i = 0 ; i < type->packing ; i++ ) {
215 if ( index >= pixels ) {
216 DBGC ( image, "PNM %s has too many pixels\n",
217 image->name );
218 return -EINVAL;
219 }
220 pixbuf->data[index++] = type->rgb ( composite, i );
221 if ( ++xpos == pixbuf->width ) {
222 xpos = 0;
223 break;
224 }
225 }
226 }
227
228 return 0;
229}
unsigned int uint32_t
Definition stdint.h:12
uint32_t type
Operating system type.
Definition ena.h:1
static int pnm_scale(struct image *image, struct pnm_context *pnm, unsigned int value)
Scale PNM scalar value.
Definition pnm.c:130
unsigned int pixels
Total number of pixels.
Definition pixbuf.h:27
unsigned int width
Width.
Definition pixbuf.h:21
uint32_t * data
32-bit (8:8:8:8) xRGB pixel data, in host-endian order
Definition pixbuf.h:25
struct pnm_type * type
PNM type.
Definition pnm.h:31
PNM type.
Definition pnm.h:44
int(* scalar)(struct image *image, struct pnm_context *pnm)
Extract scalar value.
Definition pnm.h:59

References pixel_buffer::data, DBGC, EINVAL, index, image::name, pixel_buffer::pixels, pnm_scale(), pnm_type::scalar, pnm_context::type, type, and pixel_buffer::width.

◆ pnm_type()

struct pnm_type * pnm_type ( struct image * image)
static

Determine PNM image type.

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

Definition at line 285 of file pnm.c.

285 {
286 const struct pnm_signature *signature;
287 struct pnm_type *type;
288 unsigned int i;
289
290 /* Extract signature */
291 assert ( image->len >= sizeof ( *signature ) );
293
294 /* Check for supported types */
295 for ( i = 0 ; i < ( sizeof ( pnm_types ) /
296 sizeof ( pnm_types[0] ) ) ; i++ ) {
297 type = &pnm_types[i];
298 if ( type->type == signature->type )
299 return type;
300 }
301 return NULL;
302}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
u8 signature
CPU signature.
Definition CIB_PRM.h:7
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
static struct pnm_type pnm_types[]
PNM image types.
Definition pnm.c:232
PNM signature.
Definition pnm.h:16

References assert, image::data, image::len, NULL, pnm_types, signature, and type.

Referenced by pnm_pixbuf().

◆ pnm_pixbuf()

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 311 of file pnm.c.

311 {
312 struct pnm_context pnm;
313 int width;
314 int height;
315 int max;
316 int rc;
317
318 /* Initialise PNM context */
319 pnm.type = pnm_type ( image );
320 if ( ! pnm.type ) {
321 rc = -ENOTSUP;
322 goto err_type;
323 }
324 pnm.offset = sizeof ( struct pnm_signature );
325 pnm.ascii_len = PNM_ASCII_LEN;
326
327 /* Extract width */
328 if ( ( width = pnm_ascii ( image, &pnm ) ) < 0 ) {
329 rc = width;
330 goto err_width;
331 }
332
333 /* Extract height */
334 if ( ( height = pnm_ascii ( image, &pnm ) ) < 0 ) {
335 rc = height;
336 goto err_height;
337 }
338
339 /* Extract maximum scalar value, if not predefined */
340 if ( pnm.type->flags & PNM_BITMAP ) {
341 pnm.max = ( ( 1 << pnm.type->packing ) - 1 );
342 pnm.ascii_len = 1;
343 } else {
344 if ( ( max = pnm_ascii ( image, &pnm ) ) < 0 ) {
345 rc = max;
346 goto err_max;
347 }
348 pnm.max = max;
349 }
350 if ( pnm.max == 0 ) {
351 DBGC ( image, "PNM %s has invalid maximum value 0\n",
352 image->name );
353 rc = -EINVAL;
354 goto err_max;
355 }
356 DBGC ( image, "PNM %s is type %c width %d height %d max %d\n",
357 image->name, pnm.type->type, width, height, pnm.max );
358
359 /* Allocate pixel buffer */
360 *pixbuf = alloc_pixbuf ( width, height );
361 if ( ! *pixbuf ) {
362 rc = -ENOMEM;
363 goto err_alloc_pixbuf;
364 }
365
366 /* Extract pixel data */
367 if ( ( rc = pnm_data ( image, &pnm, *pixbuf ) ) != 0 )
368 goto err_data;
369
370 return 0;
371
372 err_data:
373 pixbuf_put ( *pixbuf );
374 err_alloc_pixbuf:
375 err_max:
376 err_height:
377 err_width:
378 err_type:
379 return rc;
380}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define max(x, y)
Definition ath.h:41
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOTSUP
Operation not supported.
Definition errno.h:590
struct pixel_buffer * alloc_pixbuf(unsigned int width, unsigned int height)
Allocate pixel buffer.
Definition pixbuf.c:60
static int pnm_ascii(struct image *image, struct pnm_context *pnm)
Extract PNM ASCII value.
Definition pnm.c:47
static struct pnm_type * pnm_type(struct image *image)
Determine PNM image type.
Definition pnm.c:285
static int pnm_data(struct image *image, struct pnm_context *pnm, struct pixel_buffer *pixbuf)
Extract PNM pixel data.
Definition pnm.c:188
#define PNM_ASCII_LEN
Default maximum length of ASCII values.
Definition pnm.h:41
@ PNM_BITMAP
Bitmap format.
Definition pnm.h:80
PNM context.
Definition pnm.h:29

References pnm_context::ascii_len, ENOTSUP, pnm_type::flags, max, pnm_context::max, pnm_context::offset, pnm_ascii(), PNM_ASCII_LEN, PNM_BITMAP, pnm_type(), rc, and pnm_context::type.

Referenced by __image_type().

◆ pnm_probe()

int pnm_probe ( struct image * image)
static

Probe PNM image.

Parameters
imagePNM image
Return values
rcReturn status code

Definition at line 388 of file pnm.c.

388 {
389 const struct pnm_signature *signature;
390
391 /* Sanity check */
392 if ( image->len < sizeof ( *signature ) ) {
393 DBGC ( image, "PNM %s is too short\n", image->name );
394 return -ENOEXEC;
395 }
396
397 /* Check signature */
399 if ( ! ( ( signature->magic == PNM_MAGIC ) &&
400 ( isdigit ( signature->type ) ) &&
401 ( isspace ( signature->space ) ) ) ) {
402 DBGC ( image, "PNM %s has invalid signature\n", image->name );
403 return -ENOEXEC;
404 }
405 DBGC ( image, "PNM %s is type %c\n", image->name, signature->type );
406
407 return 0;
408}
static int isdigit(int character)
Check if character is a decimal digit.
Definition ctype.h:30
#define ENOEXEC
Exec format error.
Definition errno.h:520
#define PNM_MAGIC
PNM magic byte.
Definition pnm.h:26

References image::data, DBGC, ENOEXEC, isdigit(), isspace(), image::len, image::name, PNM_MAGIC, and signature.

Referenced by __image_type().

◆ __image_type()

struct image_type pnm_image_type __image_type ( PROBE_NORMAL )

PNM image type.

References __image_type, pnm_pixbuf(), pnm_probe(), and PROBE_NORMAL.

Variable Documentation

◆ pnm_types

struct pnm_type pnm_types[]
static

PNM image types.

Definition at line 232 of file pnm.c.

232 {
233 {
234 .type = '1',
235 .depth = 1,
236 .packing = 1,
237 .flags = PNM_BITMAP,
238 .scalar = pnm_ascii,
239 .rgb = pnm_bitmap,
240 },
241 {
242 .type = '2',
243 .depth = 1,
244 .packing = 1,
245 .scalar = pnm_ascii,
246 .rgb = pnm_greymap,
247 },
248 {
249 .type = '3',
250 .depth = 3,
251 .packing = 1,
252 .scalar = pnm_ascii,
253 .rgb = pnm_pixmap,
254 },
255 {
256 .type = '4',
257 .depth = 1,
258 .packing = 8,
259 .flags = PNM_BITMAP,
260 .scalar = pnm_binary,
261 .rgb = pnm_bitmap,
262 },
263 {
264 .type = '5',
265 .depth = 1,
266 .packing = 1,
267 .scalar = pnm_binary,
268 .rgb = pnm_greymap,
269 },
270 {
271 .type = '6',
272 .depth = 3,
273 .packing = 1,
274 .scalar = pnm_binary,
275 .rgb = pnm_pixmap,
276 },
277};
static uint32_t pnm_pixmap(uint32_t composite, unsigned int index __unused)
Convert PNM pixmap composite value to RGB.
Definition pnm.c:174
static uint32_t pnm_greymap(uint32_t composite, unsigned int index __unused)
Convert PNM greymap composite value to RGB.
Definition pnm.c:161
static int pnm_binary(struct image *image, struct pnm_context *pnm)
Extract PNM binary value.
Definition pnm.c:107
static uint32_t pnm_bitmap(uint32_t composite, unsigned int index)
Convert PNM bitmap composite value to RGB.
Definition pnm.c:148

Referenced by pnm_type().