Exemple #1
0
//this function takes in 2 struct v4l2_format and a libvideo palette index
//it will try and see if the chosen palette can be obtained, either straight
//from the driver or after conversion using libv4lconvert
//it returns the libvideo palette to use in order to get the requested
//libvideo palette, or -1 upon return, src * dst will contain meaningful values
static int try_image_format(struct capture_device *c, struct v4l2_format *src,
		struct v4l2_format *dst, int palette_idx){
	int index = -1;
	CLEAR(*src);
	CLEAR(*dst);

	dst->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	dst->fmt.pix.width = c->width;
	dst->fmt.pix.height = c->height;
	dst->fmt.pix.field = V4L2_FIELD_ANY;
	dst->fmt.pix.pixelformat = libvideo_palettes[palette_idx].v4l2_palette;
	if(0 == v4lconvert_try_format(c->convert->priv, dst, src)){
		dprint(LIBVIDEO_SOURCE_CAP, LIBVIDEO_LOG_DEBUG1,
				"CAP: For dest palette %#x (%s - %d) %dx%d - ...\n",\
				dst->fmt.pix.pixelformat,
				libvideo_palettes[palette_idx].name,
				palette_idx,
				dst->fmt.pix.width,
				dst->fmt.pix.height);
		dprint(LIBVIDEO_SOURCE_CAP, LIBVIDEO_LOG_DEBUG1,
				"CAP: libv4lconvert said to use palette %#x %dx%d - ...\n",\
				src->fmt.pix.pixelformat,
				src->fmt.pix.width,
				src->fmt.pix.height);

		if((index = get_palette_index(src->fmt.pix.pixelformat))!= -1){
			dprint(LIBVIDEO_SOURCE_CAP, LIBVIDEO_LOG_DEBUG1,
					"CAP: which is libvideo index %d, palette %s\n",\
					index,
					libvideo_palettes[index].name);


			dprint(LIBVIDEO_SOURCE_CAP, LIBVIDEO_LOG_DEBUG,
					"CAP: libv4lconvert required ? %s\n",
					(v4lconvert_needs_conversion(
							c->convert->priv,
							src,
							dst)==0?"No":"Yes"
					)
				);

		} else {
			dprint(LIBVIDEO_SOURCE_CAP, LIBVIDEO_LOG_DEBUG1,
					"CAP: palette returned by libv4lconvert is unknown to "
					"libvideo\n");
			info("The source image format returned by libv4l_convert is ");
			info("unknown\nPlease, let the author known about this error:\n");
			info("Destination palette: %#x (%s)\n",\
						libvideo_palettes[palette_idx].v4l2_palette,
						libvideo_palettes[palette_idx].name);
			info("libv4l_convert source palette: %#x", src->fmt.pix.pixelformat);
			info("See the README file on how to submit bug reports.");
		}
	}

	return index;
}
Exemple #2
0
bool sprite_file_import(const char *path, rct_g1_element *outElement, uint8 **outBuffer, int *outBufferLength, int mode)
{
	unsigned char *pixels;
	unsigned int width, height;
	unsigned int pngError;

	memcpy(spriteFilePalette, _standardPalette, 256 * 4);

	pngError = lodepng_decode_file(&pixels, &width, &height, path, LCT_RGBA, 8);
	if (pngError != 0) {
		fprintf(stderr, "Error creating PNG data, %u: %s", pngError, lodepng_error_text(pngError));
		return false;
	}

	if (width > 256 || height > 256) {
		fprintf(stderr, "Only images 256x256 or less are supported.");
		free(pixels);
		return false;
	}

	uint8 *buffer = malloc((height * 2) + (width * height * 16));
	uint16 *yOffsets = (uint16*)buffer;

	// A larger range is needed for proper dithering
	sint16 *src = malloc(height * width * 4 * 2);
	for (uint32 x = 0; x < height * width * 4; x++){
		src[x] = (sint16) pixels[x];
	}

	uint8 *dst = buffer + (height * 2);
	
	for (unsigned int y = 0; y < height; y++) {
		rle_code *previousCode, *currentCode;

		yOffsets[y] = (dst - buffer);

		previousCode = NULL;
		currentCode = (rle_code*)dst;
		dst += 2;
		int startX = 0;
		int pixels = 0;
		bool pushRun = false;
		for (unsigned int x = 0; x < width; x++) {
			int paletteIndex = get_palette_index(src);

			if (mode == MODE_CLOSEST || mode == MODE_DITHERING)
				if (paletteIndex == -1 && !is_transparent_pixel(src))
					paletteIndex = get_closest_palette_index(src);
			

			if (mode == MODE_DITHERING)
				if (!is_transparent_pixel(src) && is_changable_pixel(get_palette_index(src))){
					sint16 dr = src[0] - (sint16)(spriteFilePalette[paletteIndex].r);
					sint16 dg = src[1] - (sint16)(spriteFilePalette[paletteIndex].g);
					sint16 db = src[2] - (sint16)(spriteFilePalette[paletteIndex].b);

					if (x + 1 < width){
						if (!is_transparent_pixel(src + 4) && is_changable_pixel(get_palette_index(src + 4))){
							// Right
							src[4] += dr * 7 / 16;
							src[5] += dg * 7 / 16;
							src[6] += db * 7 / 16;
						}
					}

					if (y + 1 < height){
						if (x > 0){
							if (!is_transparent_pixel(src + 4 * (width - 1)) && is_changable_pixel(get_palette_index(src + 4 * (width - 1)))){
								// Bottom left
								src[4 * (width - 1)] += dr * 3 / 16;
								src[4 * (width - 1) + 1] += dg * 3 / 16;
								src[4 * (width - 1) + 2] += db * 3 / 16;
							}
						}

						// Bottom
						if (!is_transparent_pixel(src + 4 * width) && is_changable_pixel(get_palette_index(src + 4 * width))){
							src[4 * width] += dr * 5 / 16;
							src[4 * width + 1] += dg * 5 / 16;
							src[4 * width + 2] += db * 5 / 16;
						}

						if (x + 1 < width){
							if (!is_transparent_pixel(src + 4 * (width - 1)) && is_changable_pixel(get_palette_index(src + 4 * (width + 1)))){
								// Bottom right
								src[4 * (width + 1)] += dr * 1 / 16;
								src[4 * (width + 1) + 1] += dg * 1 / 16;
								src[4 * (width + 1) + 2] += db * 1 / 16;
							}
						}
					}
				}

			src += 4;
			if (paletteIndex == -1) {
				if (pixels != 0) {
					x--;
					src -= 4;
					pushRun = true;
				}
			} else {
				if (pixels == 0)
					startX = x;
				pixels++;
				*dst++ = (uint8)paletteIndex;
			}
			if (pixels == 127 || x == width - 1)
				pushRun = true;

			if (pushRun) {
				if (pixels > 0) {
					previousCode = currentCode;
					currentCode->num_pixels = pixels;
					currentCode->offset_x = startX;

					if (x == width - 1)
						currentCode->num_pixels |= 0x80;

					currentCode = (rle_code*)dst;
					dst += 2;
				} else {
					if (previousCode == NULL) {
						currentCode->num_pixels = 0x80;
						currentCode->offset_x = 0;
					} else {
						previousCode->num_pixels |= 0x80;
						dst -= 2;
					}
				}
				startX = 0;
				pixels = 0;
				pushRun = false;
			}
		}
	}
	free(pixels);

	int bufferLength = (int)(dst - buffer);
	buffer = realloc(buffer, bufferLength);

	outElement->offset = buffer;
	outElement->width = width;
	outElement->height = height;
	outElement->flags = G1_FLAG_RLE_COMPRESSION;
	outElement->x_offset = 0;
	outElement->y_offset = 0;
	outElement->zoomed_offset = 0;

	*outBuffer = buffer;
	*outBufferLength = bufferLength;
	return true;
}