Exemple #1
0
/**
 * Read a string from the file.
 * The semantic is like the C fgets() function.
 */
char* fzgets(char *s, int n, adv_fz* f)
{
	char* r;

	if (n < 2) {
		r = 0;
	} else {
		int c = fzgetc(f);
		if (c == EOF) {
			r = 0;
		} else {
			r = s;
			while (n > 1) {
				*s++ = c;
				--n;
				if (c == '\n')
					break;
				if (n > 1)
					c = fzgetc(f);
			}
			if (n) {
				*s = 0;
			} else {
				r = 0;
			}
		}
	}

	return r;
}
Exemple #2
0
static void pcx_decode(uint8* buffer, unsigned size, adv_fz* f, struct pcx_decode_state* state, unsigned delta)
{
    while (size) {
        unsigned run;
        if (!state->count) {
            uint8 c = fzgetc(f);
            if ((c & 0xC0) == 0xC0) {
                state->count = (c & 0x3F);
                state->value = fzgetc(f);
            } else {
                state->count = 1;
                state->value = c;
            }
        }
        run = state->count;
        if (run > size)
            run = size;
        state->count -= run;
        size -= run;
        while (run) {
            *buffer = state->value;
            buffer += delta;
            --run;
        }
    }
}
Exemple #3
0
static void pcx_ignore(unsigned size, adv_fz* f, struct pcx_decode_state* state)
{
    while (size) {
        unsigned run;
        if (!state->count) {
            uint8 c = fzgetc(f);
            if ((c & 0xC0) == 0xC0) {
                state->count = (c & 0x3F);
                state->value = fzgetc(f);
            } else {
                state->count = 1;
                state->value = c;
            }
        }
        run = state->count;
        if (run > size)
            run = size;
        state->count -= run;
        size -= run;
    }
}
Exemple #4
0
/**
 * Load a .pcx file in a bitmap.
 * Only the 8 and 24 bits format are supported.
 * \param f File to load.
 * \param rgb Where to put the palette information. it must point to a vector of 256 elements.
 * \param rgb_max Where to put the number of palette entries.
 * \return The loaded bitmap or 0 on error.
 */
adv_bitmap* adv_bitmap_load_pcx(adv_color_rgb* rgb, unsigned* rgb_max, adv_fz* f)
{
    struct pcx_header_t h;
    adv_bitmap* bitmap;
    unsigned width, height, depth;

    if (pcx_header_read(f, &h)!=0) {
        goto out;
    }

    /* limitations */
    if (h.bits_per_pixel != 8) {
        goto out;
    }

    if (h.planes != 1 && h.planes != 3) {
        goto out;
    }

    width = h.x_max - h.x_min + 1;
    height = h.y_max - h.y_min + 1;
    depth = h.planes;

    bitmap = adv_bitmap_alloc(width, height, depth);
    if (!bitmap) {
        goto out;
    }

    if (depth == 1) {
        unsigned i;
        unsigned y;

        for(y=0; y<height; ++y) {
            struct pcx_decode_state state;
            uint8* dst_off = adv_bitmap_line(bitmap, y);
            state.count = 0;
            pcx_decode(dst_off, width, f, &state, 1);
            pcx_ignore(h.bytes_per_line - width, f, &state);
            if (state.count!=0)
                goto out_bitmap;
        }

        if (fzgetc(f)!=12)
            goto out_bitmap;

        for (i=0; i<256; ++i) {
            rgb[i].red = fzgetc(f);
            rgb[i].green = fzgetc(f);
            rgb[i].blue = fzgetc(f);
        }
        *rgb_max = 256;
    } else {
        unsigned y;
        for(y=0; y<height; ++y) {
            struct pcx_decode_state state;
            uint8* dst_off = adv_bitmap_line(bitmap, y);
            state.count = 0;
            pcx_decode(dst_off, width, f, &state, 3);
            pcx_ignore(h.bytes_per_line - width, f, &state);
            pcx_decode(dst_off + 1, width, f, &state, 3);
            pcx_ignore(h.bytes_per_line - width, f, &state);
            pcx_decode(dst_off + 2, width, f, &state, 3);
            pcx_ignore(h.bytes_per_line - width, f, &state);
            if (state.count!=0)
                goto out_bitmap;
        }
    }

    return bitmap;

out_bitmap:
    adv_bitmap_free(bitmap);
out:
    return 0;
}
/**
 * Load a .ico file in a bitmap.
 * Only the 16 and 256 color formats are supported.
 * \param f File to load.
 * \param rgb Where to put the palette information. it must point to a vector of 256 elements.
 * \param rgb_max Where to put the number of palette entries.
 * \param bitmap_mask Where to put the mask bitmap. 
 * \return The loaded bitmap or 0 on error.
 */
adv_bitmap* adv_bitmap_load_icon(adv_color_rgb* rgb, unsigned* rgb_max, adv_bitmap** bitmap_mask, adv_fz* f)
{
	adv_bitmap* bitmap;
	struct icon_header_t header;
	struct icon_entry_t* entry;
	int i;

	if (icon_header_read(f, &header) != 0)
		goto out;

	if (header.reserved != 0)
		goto out;

	if (header.type != 1)
		goto out;

	if (header.count < 1)
		goto out;

	entry = malloc(header.count * sizeof(struct icon_entry_t));
	if (!entry)
		goto out;

	for(i=0;i<header.count;++i) {
		if (icon_entry_read(f, entry + i)!=0)
			goto out_entry;
	}

	for(i=0;i<header.count;++i) {
		struct icon_bitmap_header_t bitmap_header;
		unsigned j, y;
		unsigned colors;

		if (entry[i].color == 0) {
			colors = 256;
			if (entry[i].bit != 8 && entry[i].bit != 0) /* 0 is out of standard but acceptable */
				continue; /* unsupported */
		} else if (entry[i].color == 16) {
			colors = 16;
			if (entry[i].bit != 4 && entry[i].bit != 0) /* 0 is out of standard but acceptable */
				continue; /* unsupported */
		} else {
			continue; /* unsupported */
		}

		if (entry[i].planes != 1 && entry[i].planes != 0) /* 0 is out of standard but acceptable */
			continue; /* unsupported */

		if (fzseek(f, entry[i].offset, SEEK_SET)!=0)
			goto out_entry;

		if (icon_bitmap_header_read(f, &bitmap_header) != 0)
			goto out_entry;

		if (colors == 256) {
			if (bitmap_header.bit != 8)
				continue; /* unsupported */
		} else if (colors == 16) {
			if (bitmap_header.bit != 4)
				continue; /* unsupported */
		}

		if (bitmap_header.planes != 1)
			continue; /* unsupported */

		if (bitmap_header.compression != 0) 
			continue; /* unsupported */

		for(j=0;j<colors;++j) {
			struct icon_rgb_t color;
			if (icon_rgb_read(f, &color) != 0)
				goto out_entry;
			rgb[j].red = color.red;
			rgb[j].green = color.green;
			rgb[j].blue = color.blue;
		}
		*rgb_max = colors;

		bitmap = adv_bitmap_alloc(entry[i].width, entry[i].height, 1);
		if (!bitmap)
			goto out_entry;

		*bitmap_mask = adv_bitmap_alloc(entry[i].width, entry[i].height, 1);
		if (!*bitmap_mask)
			goto out_bitmap;

		if (colors == 256) {
			/* read bitmap xor data (8 bit per pixel) */
			for(y=0;y<bitmap->size_y;++y) {
				unsigned char* line = adv_bitmap_line(bitmap, bitmap->size_y - y - 1);
				if (fzread(line, bitmap->size_x*bitmap->bytes_per_pixel, 1, f)!=1)
					goto out_bitmap_mask;
			}
		} else if (colors == 16) {
			/* read bitmap xor data (4 bit per pixel) */
			for(y=0;y<bitmap->size_y;++y) {
				int k;
				unsigned char* line = adv_bitmap_line(bitmap, bitmap->size_y - y - 1);
				if (fzread(line, bitmap->size_x / 2, 1, f)!=1)
					goto out_bitmap_mask;
				/* convert */
				for(k=bitmap->size_x-1;k>=0;--k) {
					if (k & 1)
						line[k] = line[k/2] & 0xF;
					else
						line[k] = line[k/2] >> 4;
				}
			}
		}

		/* read bitmap mask data (1 bit per pixel) */
		for(y=0;y<bitmap->size_y;++y) {
			unsigned x ;
			unsigned char* line = adv_bitmap_line(*bitmap_mask, bitmap->size_y - y - 1);
			x = 0;
			while (x < bitmap->size_x) {
				unsigned bc;
				int b = fzgetc(f);
				if (b==EOF)
					goto out_bitmap_mask;
				if (x + 8 > bitmap->size_x)
					bc = bitmap->size_x - x; /* waste unused bit */
				else
					bc = 8;
				x += bc;
				while (bc) {
					if (b & 0x80)
						*line = 0;
					else
						*line = 1;
					b = b << 1;
					++line;
					--bc;
				}
			}
		}

		free(entry);
		return bitmap;
	}

	goto out_entry;

out_bitmap_mask:
	adv_bitmap_free(*bitmap_mask);
out_bitmap:
	adv_bitmap_free(bitmap);
out_entry:
	free(entry);
out:
	return 0;
}