Exemple #1
0
gdispImageError gdispImageOpenGFile(gdispImage *img, GFILE *f) {
	gdispImageError err;

	if (!f)
		return GDISP_IMAGE_ERR_NOSUCHFILE;
	img->f = f;
	img->bgcolor = White;
	for(img->fns = ImageHandlers; img->fns < ImageHandlers+sizeof(ImageHandlers)/sizeof(ImageHandlers[0]); img->fns++) {
		err = img->fns->open(img);
		if (err != GDISP_IMAGE_ERR_BADFORMAT) {
			if ((err & GDISP_IMAGE_ERR_UNRECOVERABLE))
				goto unrecoverable;

			// Everything is possible
			return err;
		}

		// Try the next decoder
		gfileSetPos(img->f, 0);
	}

	err = GDISP_IMAGE_ERR_BADFORMAT;
	img->type = GDISP_IMAGE_TYPE_UNKNOWN;

unrecoverable:
	gfileClose(img->f);
	img->f = 0;
	img->flags = 0;
	img->fns = 0;
	img->priv = 0;
	return err;
}
Exemple #2
0
int gstdioSeek(FILE *f, size_t offset, int origin) {
	switch(origin) {
	case SEEK_SET:
		break;
	case SEEK_CUR:
		offset += f->pos;
		break;
	case SEEK_END:
		offset += gfileGetSize(f);
		break;
	default:
		return -1;
	}
	return gfileSetPos(f, offset) ? 0 : -1;
}
gdispImageError gdispGImageDraw_NATIVE(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {
	coord_t		mx, mcx;
	size_t		pos, len;
	gdispImagePrivate_NATIVE *	priv;

	priv = (gdispImagePrivate_NATIVE *)img->priv;

	/* Check some reasonableness */
	if (sx >= img->width || sy >= img->height) return GDISP_IMAGE_ERR_OK;
	if (sx + cx > img->width) cx = img->width - sx;
	if (sy + cy > img->height) cy = img->height - sy;

	/* Draw from the image cache - if it exists */
	if (priv->frame0cache) {
		gdispGBlitArea(g, x, y, cx, cy, sx, sy, img->width, priv->frame0cache);
		return GDISP_IMAGE_ERR_OK;
	}

	/* For this image decoder we cheat and just seek straight to the region we want to display */
	pos = FRAME0POS_NATIVE + (img->width * sy + sx) * sizeof(pixel_t);

	/* Cycle through the lines */
	for(;cy;cy--, y++) {
		/* Move to the start of the line */
		gfileSetPos(img->f, pos);

		/* Draw the line in chunks using BitBlt */
		for(mx = x, mcx = cx; mcx > 0; mcx -= len, mx += len) {
			// Read the data
			len = gfileRead(img->f,
						priv->buf,
						mcx > BLIT_BUFFER_SIZE_NATIVE ? (BLIT_BUFFER_SIZE_NATIVE*sizeof(pixel_t)) : (mcx * sizeof(pixel_t)))
					/ sizeof(pixel_t);
			if (!len)
				return GDISP_IMAGE_ERR_BADDATA;

			/* Blit the chunk of data */
			gdispGBlitArea(g, mx, y, len, 1, 0, 0, len, priv->buf);
		}

		/* Get the position for the start of the next line */
		pos += img->width*sizeof(pixel_t);
	}

	return GDISP_IMAGE_ERR_OK;
}
gdispImageError gdispImageCache_NATIVE(gdispImage *img) {
	size_t		len;
	gdispImagePrivate_NATIVE *	priv;

	/* If we are already cached - just return OK */
	priv = (gdispImagePrivate_NATIVE *)img->priv;
	if (priv->frame0cache)
		return GDISP_IMAGE_ERR_OK;

	/* We need to allocate the cache */
	len = img->width * img->height * sizeof(pixel_t);
	priv->frame0cache = (pixel_t *)gdispImageAlloc(img, len);
	if (!priv->frame0cache)
		return GDISP_IMAGE_ERR_NOMEMORY;

	/* Read the entire bitmap into cache */
	gfileSetPos(img->f, FRAME0POS_NATIVE);
	if (gfileRead(img->f, priv->frame0cache, len) != len)
		return GDISP_IMAGE_ERR_BADDATA;

	return GDISP_IMAGE_ERR_OK;
}
Exemple #5
0
gdispImageError gdispImageOpen_BMP(gdispImage *img) {
	gdispImagePrivate *priv;
	uint8_t		hdr[2];
	uint16_t	aword;
	uint32_t	adword;
	uint32_t	offsetColorTable;

	/* Read the file identifier */
	if (gfileRead(img->f, hdr, 2) != 2)
		return GDISP_IMAGE_ERR_BADFORMAT;		// It can't be us

	/* Process the BITMAPFILEHEADER structure */

	/**
	 * We only accept Windows V2+ bitmaps.
	 *  - we don't support OS/2 bitmaps, icons, pointers, or Windows V1 bitmaps.
	 */
	if (hdr[0] != 'B' || hdr[1] != 'M')
		return GDISP_IMAGE_ERR_BADFORMAT;		// It can't be us

	/* We know we are a BMP format image */
	img->flags = 0;

	/* Allocate our private area */
	if (!(img->priv = (gdispImagePrivate *)gdispImageAlloc(img, sizeof(gdispImagePrivate))))
		return GDISP_IMAGE_ERR_NOMEMORY;

	/* Initialise the essential bits in the private area */
	priv = img->priv;
	priv->frame0cache = 0;
	priv->bmpflags = 0;
#if GDISP_NEED_IMAGE_BMP_1 || GDISP_NEED_IMAGE_BMP_4 || GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8 || GDISP_NEED_IMAGE_BMP_8_RLE
	priv->palette = 0;
#endif

	/* Skip the size field and the 2 reserved fields */
	if (gfileRead(img->f, priv->buf, 8) != 8)
		goto baddatacleanup;

	/* Get the offset to the bitmap data */
	if (gfileRead(img->f, &priv->frame0pos, 4) != 4)
		goto baddatacleanup;
	CONVERT_FROM_DWORD_LE(priv->frame0pos);

	/* Process the BITMAPCOREHEADER structure */

	/* Get the offset to the colour data */
	if (gfileRead(img->f, &offsetColorTable, 4) != 4)
		goto baddatacleanup;
	CONVERT_FROM_DWORD_LE(offsetColorTable);
	offsetColorTable += 14;						// Add the size of the BITMAPFILEHEADER

	// Detect our bitmap version
	if (offsetColorTable == 12+14) {
		img->priv->bmpflags |= BMP_V2;

		// Read the header
		if (gfileRead(img->f, priv->buf, 12-4) != 12-4)
			goto baddatacleanup;
		// Get the width
		img->width = *(uint16_t *)(((uint8_t *)priv->buf)+0);
		CONVERT_FROM_WORD_LE(img->width);
		// Get the height
		img->height = *(uint16_t *)(((uint8_t *)priv->buf)+2);
		CONVERT_FROM_WORD_LE(img->height);
		if (img->height < 0) {
			img->priv->bmpflags |= BMP_TOP_TO_BOTTOM;
			img->height = -img->height;
		}
		// Get the planes
		aword = *(uint16_t *)(((uint8_t *)priv->buf)+4);
		CONVERT_FROM_WORD_LE(aword);
		if (aword != 1)
			goto unsupportedcleanup;
		// Get the bits per pixel
		aword = *(uint16_t *)(((uint8_t *)priv->buf)+6);
		CONVERT_FROM_WORD_LE(aword);
		switch(aword) {
#if GDISP_NEED_IMAGE_BMP_1
		case 1:
#endif
#if GDISP_NEED_IMAGE_BMP_4
		case 4:
#endif
#if GDISP_NEED_IMAGE_BMP_8
		case 8:
#endif
#if GDISP_NEED_IMAGE_BMP_1 || GDISP_NEED_IMAGE_BMP_4 || GDISP_NEED_IMAGE_BMP_8
			priv->bmpflags |= BMP_PALETTE;
			priv->palsize = 1<<aword;
			break;
#endif
#if GDISP_NEED_IMAGE_BMP_24
		case 24:
			break;
#endif
		default:
			goto unsupportedcleanup;
		}
		priv->bitsperpixel = aword;

	} else if (offsetColorTable >= 40+14) {
		if (offsetColorTable > 40+14)
			priv->bmpflags |= BMP_V4;

		// Read the header
		if (gfileRead(img->f, priv->buf, 40-4) != 40-4)
			goto baddatacleanup;
		// Get the width
		adword = *(uint32_t *)(((uint8_t *)priv->buf)+0);
		CONVERT_FROM_DWORD_LE(adword);
		if (adword > 32768)				// This also picks up negative values
			goto unsupportedcleanup;
		img->width = adword;
		// Get the height
		adword = *(uint32_t *)(((uint8_t *)priv->buf)+4);
		CONVERT_FROM_DWORD_LE(adword);
		if ((int32_t)adword < 0) {		// Negative test
			priv->bmpflags |= BMP_TOP_TO_BOTTOM;
			adword = -adword;
		}
		if (adword > 32768)
			goto unsupportedcleanup;
		img->height = adword;
		// Get the planes
		aword = *(uint16_t *)(((uint8_t *)priv->buf)+8);
		CONVERT_FROM_WORD_LE(aword);
		if (aword != 1)
			goto unsupportedcleanup;
		// Get the bits per pixel
		aword = *(uint16_t *)(((uint8_t *)priv->buf)+10);
		CONVERT_FROM_WORD_LE(aword);
		switch(aword) {
#if GDISP_NEED_IMAGE_BMP_1
		case 1:
#endif
#if GDISP_NEED_IMAGE_BMP_4 || GDISP_NEED_IMAGE_BMP_4_RLE
		case 4:
#endif
#if GDISP_NEED_IMAGE_BMP_8 || GDISP_NEED_IMAGE_BMP_8_RLE
		case 8:
#endif
#if GDISP_NEED_IMAGE_BMP_1 || GDISP_NEED_IMAGE_BMP_4 || GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8 || GDISP_NEED_IMAGE_BMP_8_RLE
			priv->bmpflags |= BMP_PALETTE;
			priv->palsize = 1<<aword;
			break;
#endif
#if GDISP_NEED_IMAGE_BMP_16
		case 16:
#endif
#if GDISP_NEED_IMAGE_BMP_24
		case 24:
#endif
#if GDISP_NEED_IMAGE_BMP_32
		case 32:
#endif
#if GDISP_NEED_IMAGE_BMP_16 || GDISP_NEED_IMAGE_BMP_24 || GDISP_NEED_IMAGE_BMP_32
			break;
#endif
		default:
			goto unsupportedcleanup;
		}
		priv->bitsperpixel = aword;
		// Get the compression
		adword = *(uint32_t *)(((uint8_t *)priv->buf)+12);
		CONVERT_FROM_DWORD_LE(adword);
		switch(adword) {
		case 0:					// BI_RGB - uncompressed
			break;
#if GDISP_NEED_IMAGE_BMP_8_RLE
		case 1:					// BI_RLE8 compression
			if (priv->bitsperpixel != 8)
				goto unsupportedcleanup;
			priv->bmpflags |= BMP_COMP_RLE;
			break;
#endif
#if GDISP_NEED_IMAGE_BMP_4_RLE
		case 2:					// BI_RLE4 compression
			if (priv->bitsperpixel != 4)
				goto unsupportedcleanup;
			priv->bmpflags |= BMP_COMP_RLE;
			break;
#endif
#if GDISP_NEED_IMAGE_BMP_16 || GDISP_NEED_IMAGE_BMP_32
		case 3:					// BI_BITFIELDS decoding
			if (priv->bitsperpixel < 16 || priv->bitsperpixel == 24)
				goto unsupportedcleanup;
			priv->bmpflags |= BMP_COMP_MASK;
			if (priv->bmpflags & BMP_V4)		// V4 stored the masks in the header
				offsetColorTable = 40+14;
			break;
#endif
		default:
			goto unsupportedcleanup;
		}
		priv->bitsperpixel = aword;
#if GDISP_NEED_IMAGE_BMP_1 || GDISP_NEED_IMAGE_BMP_4 || GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8 || GDISP_NEED_IMAGE_BMP_8_RLE
		// Get the actual colors used
		adword = *(uint32_t *)(((uint8_t *)priv->buf)+28);
		CONVERT_FROM_DWORD_LE(adword);
		if (adword && adword < priv->palsize)
			priv->palsize = adword;
#endif
	} else
		goto baddatacleanup;

#if GDISP_NEED_IMAGE_BMP_1 || GDISP_NEED_IMAGE_BMP_4 || GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8 || GDISP_NEED_IMAGE_BMP_8_RLE
	/* Load the palette tables */
	if (priv->bmpflags & BMP_PALETTE) {
		gfileSetPos(img->f, offsetColorTable);

		if (!(priv->palette = (color_t *)gdispImageAlloc(img, priv->palsize*sizeof(color_t))))
			return GDISP_IMAGE_ERR_NOMEMORY;
		if (priv->bmpflags & BMP_V2) {
			for(aword = 0; aword < priv->palsize; aword++) {
				if (gfileRead(img->f, &priv->buf, 3) != 3) goto baddatacleanup;
				priv->palette[aword] = RGB2COLOR(((uint8_t *)priv->buf)[2], ((uint8_t *)priv->buf)[1], ((uint8_t *)priv->buf)[0]);
			}
		} else {
			for(aword = 0; aword < priv->palsize; aword++) {
				if (gfileRead(img->f, &priv->buf, 4) != 4) goto baddatacleanup;
				priv->palette[aword] = RGB2COLOR(((uint8_t *)priv->buf)[2], ((uint8_t *)priv->buf)[1], ((uint8_t *)priv->buf)[0]);
			}
		}

	}
#endif

#if GDISP_NEED_IMAGE_BMP_16 || GDISP_NEED_IMAGE_BMP_32
	/* Load the bit masks */
	if (priv->bmpflags & BMP_COMP_MASK) {
		gfileSetPos(img->f, offsetColorTable);
		if (gfileRead(img->f, &priv->maskred, 4) != 4) goto baddatacleanup;
		CONVERT_FROM_DWORD_LE(priv->maskred);
		if (gfileRead(img->f, &priv->maskgreen, 4) != 4) goto baddatacleanup;
		CONVERT_FROM_DWORD_LE(priv->maskgreen);
		if (gfileRead(img->f, &priv->maskblue, 4) != 4) goto baddatacleanup;
		CONVERT_FROM_DWORD_LE(priv->maskblue);
		if (priv->bmpflags & BMP_V4) {
			if (gfileRead(img->f, &priv->maskalpha, 4) != 4) goto baddatacleanup;
			CONVERT_FROM_DWORD_LE(priv->maskalpha);
		} else
			priv->maskalpha = 0;
	} else if (priv->bitsperpixel == 16) {
		priv->bmpflags |= BMP_COMP_MASK;
		priv->maskred = 0x7C00;
		priv->maskgreen = 0x03E0;
		priv->maskblue = 0x001F;
		priv->maskalpha = 0;
	} else if (priv->bitsperpixel == 32) {
		priv->bmpflags |= BMP_COMP_MASK;
		priv->maskred = 0x00FF0000;
		priv->maskgreen = 0x0000FF00;
		priv->maskblue = 0x000000FF;
		priv->maskalpha = 0;
	}

	/* We need to adjust the masks and calculate the shift values so the result scales 0 -> 255 */
	if (priv->bmpflags & BMP_COMP_MASK) {
		priv->shiftred = 0;
		priv->shiftgreen = 0;
		priv->shiftblue = 0;
		if (priv->maskred) {
			if (priv->maskred < 256)
				for(adword = priv->maskred;  adword < 128; priv->shiftred--, adword <<= 1);
			else
				for(adword = priv->maskred;  adword > 255; priv->shiftred++, adword >>= 1);
		}
		if (priv->maskgreen) {
			if (priv->maskgreen < 256)
				for(adword = priv->maskgreen;  adword < 128; priv->shiftgreen--, adword <<= 1);
			else
				for(adword = priv->maskgreen;  adword > 255; priv->shiftgreen++, adword >>= 1);
		}
		if (priv->maskblue) {
			if (priv->maskblue < 256)
				for(adword = priv->maskblue;  adword < 128; priv->shiftblue--, adword <<= 1);
			else
				for(adword = priv->maskblue;  adword > 255; priv->shiftblue++, adword >>= 1);
		}
		if (priv->maskalpha) {
			if (priv->maskalpha < 256)
				for(adword = priv->maskalpha;  adword < 128; priv->shiftalpha--, adword <<= 1);
			else
				for(adword = priv->maskalpha;  adword > 255; priv->shiftalpha++, adword >>= 1);
		}
	}