Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/FreeImage/PluginPNM.cpp  view on Meta::CPAN

// ==========================================================
// PNM (PPM, PGM, PBM) Loader and Writer
//
// Design and implementation by
// - Floris van den Berg (flvdberg@wxs.nl)
// - Hervé Drolon (drolon@infonie.fr)
//
// This file is part of FreeImage 3
//
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
// THIS DISCLAIMER.
//
// Use at your own risk!
// ==========================================================

#include "FreeImage.h"
#include "Utilities.h"

// ==========================================================
// Internal functions
// ==========================================================

/**
Get an integer value from the actual position pointed by handle
*/
static int
GetInt(FreeImageIO *io, fi_handle handle) {
    char c = 0;
	BOOL bFirstChar;

    // skip forward to start of next number

	if(!io->read_proc(&c, 1, 1, handle)) {
		throw FI_MSG_ERROR_PARSING;
	}

    while (1) {
        // eat comments

        if (c == '#') {
			// if we're at a comment, read to end of line

            bFirstChar = TRUE;

            while (1) {
				if(!io->read_proc(&c, 1, 1, handle)) {
					throw FI_MSG_ERROR_PARSING;
				}

				if (bFirstChar && c == ' ') {
					// loop off 1 sp after #
					bFirstChar = FALSE;
				} else if (c == '\n') {
					break;
				}
			}
		}

        if (c >= '0' && c <='9') {
			// we've found what we were looking for
            break;
		}

		if(!io->read_proc(&c, 1, 1, handle)) {
			throw FI_MSG_ERROR_PARSING;
		}
    }

    // we're at the start of a number, continue until we hit a non-number

    int i = 0;

    while (1) {
        i = (i * 10) + (c - '0');

		if(!io->read_proc(&c, 1, 1, handle)) {
			throw FI_MSG_ERROR_PARSING;
		}

		if (c < '0' || c > '9') {
			break;
		}
    }

    return i;
}

/**
Read a WORD value taking into account the endianess issue
*/
static inline WORD 
ReadWord(FreeImageIO *io, fi_handle handle) {
	WORD level = 0;
	io->read_proc(&level, 2, 1, handle); 
#ifndef FREEIMAGE_BIGENDIAN
	SwapShort(&level);	// PNM uses the big endian convention
#endif
	return level;
}

/**
Write a WORD value taking into account the endianess issue
*/
static inline void 
WriteWord(FreeImageIO *io, fi_handle handle, const WORD value) {
	WORD level = value;
#ifndef FREEIMAGE_BIGENDIAN
	SwapShort(&level);	// PNM uses the big endian convention
#endif
	io->write_proc(&level, 2, 1, handle);
}


// ==========================================================
// Plugin Interface
// ==========================================================

static int s_format_id;

// ==========================================================
// Plugin Implementation
// ==========================================================

static const char * DLL_CALLCONV
Format() {
	return "PNM";
}

static const char * DLL_CALLCONV
Description() {
	return "Portable Network Media";
}

static const char * DLL_CALLCONV
Extension() {
	return "pbm,pgm,ppm";
}

src/Source/FreeImage/PluginPNM.cpp  view on Meta::CPAN

	if (memcmp(ppm_id1, signature, sizeof(ppm_id1)) == 0)
		return TRUE;

	if (memcmp(ppm_id2, signature, sizeof(ppm_id2)) == 0)
		return TRUE;

	return FALSE;
}

static BOOL DLL_CALLCONV
SupportsExportDepth(int depth) {
	return (
			(depth == 1) ||
			(depth == 8) ||
			(depth == 24)
		);
}

static BOOL DLL_CALLCONV 
SupportsExportType(FREE_IMAGE_TYPE type) {
	return (
		(type == FIT_BITMAP)  ||
		(type == FIT_UINT16)  ||
		(type == FIT_RGB16)
	);
}

static BOOL DLL_CALLCONV
SupportsNoPixels() {
	return TRUE;
}

// ----------------------------------------------------------

static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	char id_one = 0, id_two = 0;
	int x, y;
	FIBITMAP *dib = NULL;
	RGBQUAD *pal;	// pointer to dib palette
	int i;

	if (!handle) {
		return NULL;
	}

	BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;

	try {
		FREE_IMAGE_TYPE image_type = FIT_BITMAP;	// standard image: 1-, 8-, 24-bit

		// Read the first two bytes of the file to determine the file format
		// "P1" = ascii bitmap, "P2" = ascii greymap, "P3" = ascii pixmap,
		// "P4" = raw bitmap, "P5" = raw greymap, "P6" = raw pixmap

		io->read_proc(&id_one, 1, 1, handle);
		io->read_proc(&id_two, 1, 1, handle);

		if ((id_one != 'P') || (id_two < '1') || (id_two > '6')) {			
			// signature error
			throw FI_MSG_ERROR_MAGIC_NUMBER;
		}

		// Read the header information: width, height and the 'max' value if any

		int width  = GetInt(io, handle);
		int height = GetInt(io, handle);
		int maxval = 1;

		if((id_two == '2') || (id_two == '5') || (id_two == '3') || (id_two == '6')) {
			maxval = GetInt(io, handle);
			if((maxval <= 0) || (maxval > 65535)) {
				FreeImage_OutputMessageProc(s_format_id, "Invalid max value : %d", maxval);
				throw (const char*)NULL;
			}
		}

		// Create a new DIB

		switch (id_two) {
			case '1':
			case '4':
				// 1-bit
				dib = FreeImage_AllocateHeader(header_only, width, height, 1);
				break;

			case '2':
			case '5':
				if(maxval > 255) {
					// 16-bit greyscale
					image_type = FIT_UINT16;
					dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height);
				} else {
					// 8-bit greyscale
					dib = FreeImage_AllocateHeader(header_only, width, height, 8);
				}
				break;

			case '3':
			case '6':
				if(maxval > 255) {
					// 48-bit RGB
					image_type = FIT_RGB16;
					dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height);
				} else {
					// 24-bit RGB
					dib = FreeImage_AllocateHeader(header_only, width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
				}
				break;
		}

		if (dib == NULL) {
			throw FI_MSG_ERROR_DIB_MEMORY;
		}

		// Build a greyscale palette if needed

		if(image_type == FIT_BITMAP) {
			switch(id_two)  {
				case '1':
				case '4':
					pal = FreeImage_GetPalette(dib);
					pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
					pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
					break;

				case '2':
				case '5':
					pal = FreeImage_GetPalette(dib);
					for (i = 0; i < 256; i++) {
						pal[i].rgbRed	=
						pal[i].rgbGreen =
						pal[i].rgbBlue	= (BYTE)i;
					}
					break;

				default:
					break;
			}
		}

		if(header_only) {
			// header only mode
			return dib;
		}

		// Read the image...

		switch(id_two)  {
			case '1':
			case '4':
				// write the bitmap data

				if (id_two == '1') {	// ASCII bitmap
					for (y = 0; y < height; y++) {		
						BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);

						for (x = 0; x < width; x++) {
							if (GetInt(io, handle) == 0)
								bits[x >> 3] |= (0x80 >> (x & 0x7));
							else
								bits[x >> 3] &= (0xFF7F >> (x & 0x7));
						}
					}
				}  else {		// Raw bitmap
					int line = CalculateLine(width, 1);

					for (y = 0; y < height; y++) {	
						BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);

						for (x = 0; x < line; x++) {
							io->read_proc(&bits[x], 1, 1, handle);



( run in 0.689 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )