diff --git a/include/libg1m.h b/include/libg1m.h index dbaae6c..e6893eb 100644 --- a/include/libg1m.h +++ b/include/libg1m.h @@ -30,6 +30,7 @@ # include # include # include +# include # include # include # include diff --git a/include/libg1m/file.h b/include/libg1m/file.h index ab5af3b..39d2dfb 100644 --- a/include/libg1m/file.h +++ b/include/libg1m/file.h @@ -22,7 +22,7 @@ /* This header defines the way storage files are stored here. * * TODO: - * What I think I should do is + * What I think I should do is trees and folders in two different lists. */ /* ************************************************************************** */ /* Storage file types */ diff --git a/include/libg1m/internals.h b/include/libg1m/internals.h index f600c31..6a38abe 100644 --- a/include/libg1m/internals.h +++ b/include/libg1m/internals.h @@ -165,17 +165,6 @@ G1M_CASFUNC(matrix) (I)[PIXPREP_y] = PIXPREP_line; \ PIXPREP_line += (W); \ }} - -/* just wanted to do this macro for fun. */ -# define G1M_PROTOTYPE_PIX(NATURE) \ - void g1m_pixels_from_##NATURE(uint32_t **pixels, unsigned char *raw, \ - int width, int height); \ - void g1m_pixels_to_##NATURE(unsigned char *dest, uint32_t **pixels, \ - int width, int height); - -G1M_PROTOTYPE_PIX(packed1bit) -G1M_PROTOTYPE_PIX(packed4bits) -G1M_PROTOTYPE_PIX(16bits) /* ************************************************************************** */ /* Utilities */ /* ************************************************************************** */ diff --git a/include/libg1m/picture.h b/include/libg1m/picture.h new file mode 100644 index 0000000..e124d16 --- /dev/null +++ b/include/libg1m/picture.h @@ -0,0 +1,51 @@ +/* ***************************************************************************** + * libg1m/picture.h -- libg1m picture formats. + * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey + * + * This file is part of libg1m. + * libg1m is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3.0 of the License, + * or (at your option) any later version. + * + * libg1m is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libg1m; if not, see . + * ************************************************************************** */ +#ifndef LIBG1M_PICTURE_H +# define LIBG1M_PICTURE_H + +/* picture format */ +typedef int g1m_pictureformat_t; +# define g1m_pictureformat_1bit_packed 0x0101 +# define g1m_pictureformat_1bit_reverse 0x0102 +# define g1m_pictureformat_2bit_dual 0x0201 +# define g1m_pictureformat_4bit_rgb 0x0401 +# define g1m_pictureformat_4bit_code 0x0402 +# define g1m_pictureformat_16bit 0x1000 + +/* get size of the raw buffer */ +# define g1m_picturesize_1bit_packed(W, H) \ + ((W) * (H) / 8) +# define g1m_picturesize_2bit_dual(W, H) \ + (((W) * (H) / 4) * 2) +# define g1m_picturesize_4bit(W, H) \ + ((W) * (H) / 2) +# define g1m_picturesize_4bit_rgb(W, H) \ + g1m_picturesize_4bit(W, H) +# define g1m_picturesize_4bit_code(W, H) \ + g1m_picturesize_4bit(W, H) +# define g1m_picturesize_16bit(W, H) \ + ((W) * (H) * 2) + +/* encoding and decoding functions */ +int g1m_decode_picture(uint32_t **pixels, g1m_pictureformat_t format, + const unsigned char *raw, unsigned int width, unsigned int height); +int g1m_encode_picture(const uint32_t **pixels, g1m_pictureformat_t format, + unsigned char *raw, unsigned int width, unsigned int height); + +#endif /* LIBG1M_PICTURE_H */ diff --git a/src/decode/mcs/spreadsheet.c b/src/decode/mcs/spreadsheet.c index feb6fba..22168af 100644 --- a/src/decode/mcs/spreadsheet.c +++ b/src/decode/mcs/spreadsheet.c @@ -33,11 +33,13 @@ int g1m_decode_mcs_spreadsheet(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, { /* read header */ DREAD(hd, mcs_spreadsheetheader) + logm_info(&hd, sizeof(struct mcs_spreadsheetheader)); if (hd.has_subheader != 0x01) return (0); /* read subheader */ DREAD(shd, mcs_spreadsheet_subheader) + logm_info(&shd, sizeof(struct mcs_spreadsheet_subheader)); uint_fast32_t colcount = hd.column_count; colcount = be32toh(colcount << 8); shd.defs_size = be32toh(shd.defs_size); diff --git a/src/decode/std/addin.c b/src/decode/std/addin.c index 76e240e..df656e5 100644 --- a/src/decode/std/addin.c +++ b/src/decode/std/addin.c @@ -115,8 +115,8 @@ int g1m_decode_std_addin(g1m_t *handle, g1m_buffer_t *buffer, prepare_pixels(handle->pixels, G1A_ICON_WIDTH, G1A_ICON_HEIGHT) /* fill icon */ - g1m_pixels_from_packed1bit(handle->pixels, hd.icon, - G1A_ICON_WIDTH, G1A_ICON_HEIGHT); + g1m_decode_picture(handle->pixels, g1m_pictureformat_1bit_packed, + hd.icon, G1A_ICON_WIDTH, G1A_ICON_HEIGHT); /* skip size */ SKIP(hd.filesize - sizeof(struct standard_header) @@ -174,8 +174,8 @@ int g1m_decode_std_addin_cg(g1m_t *handle, g1m_buffer_t *buffer, if (!handle->pixels) return (g1m_error_alloc); prepare_pixels(handle->pixels, G3A_ICON_WIDTH, G3A_ICON_HEIGHT) - g1m_pixels_from_16bits(handle->pixels, shd.unselected_icon_image, - G3A_ICON_WIDTH, G3A_ICON_HEIGHT); + g1m_decode_picture(handle->pixels, g1m_pictureformat_16bit, + shd.unselected_icon_image, G3A_ICON_WIDTH, G3A_ICON_HEIGHT); } else { /* is C1A */ DREAD(shd, c1a_subheader) @@ -185,8 +185,8 @@ int g1m_decode_std_addin_cg(g1m_t *handle, g1m_buffer_t *buffer, if (!handle->pixels) return (g1m_error_alloc); prepare_pixels(handle->pixels, C1A_ICON_WIDTH, C1A_ICON_HEIGHT); - g1m_pixels_from_packed1bit(handle->pixels, shd.icon, - C1A_ICON_WIDTH, C1A_ICON_HEIGHT); + g1m_decode_picture(handle->pixels, g1m_pictureformat_1bit_packed, + shd.icon, C1A_ICON_WIDTH, C1A_ICON_HEIGHT); } /* skip content for now */ diff --git a/src/decode/std/fkey.c b/src/decode/std/fkey.c index f08d56c..950536e 100644 --- a/src/decode/std/fkey.c +++ b/src/decode/std/fkey.c @@ -35,7 +35,8 @@ static uint32_t **fkeydup(uint8_t *fkey) if (!pixels) return (NULL); prepare_pixels(pixels, FKEY_WIDTH, FKEY_HEIGHT) - g1m_pixels_from_packed1bit(pixels, fkey, FKEY_WIDTH, FKEY_HEIGHT); + g1m_decode_picture(pixels, g1m_pictureformat_1bit_packed, + fkey, FKEY_WIDTH, FKEY_HEIGHT); return (pixels); } @@ -53,7 +54,8 @@ static uint32_t **fkeydup3(uint8_t *fkey) if (!pixels) return (NULL); prepare_pixels(pixels, FKEY3_WIDTH, FKEY3_HEIGHT) - g1m_pixels_from_packed1bit(pixels, fkey, FKEY3_WIDTH, FKEY3_HEIGHT); + g1m_decode_picture(pixels, g1m_pictureformat_1bit_packed, + fkey, FKEY3_WIDTH, FKEY3_HEIGHT); return (pixels); } diff --git a/src/decode/std/picture.c b/src/decode/std/picture.c index 83f1333..7e5a40d 100644 --- a/src/decode/std/picture.c +++ b/src/decode/std/picture.c @@ -130,12 +130,9 @@ int g1m_decode_std_g3p(g1m_t *handle, g1m_buffer_t *buffer, prepare_pixels(handle->pixels, w, h) /* then store it */ - switch (ihd.color_depth) { - case g3p_color_4bit: - g1m_pixels_from_packed4bits(handle->pixels, inflated_image, w, h); - default: /* case g3p_color_16bit: */ - g1m_pixels_from_16bits(handle->pixels, inflated_image, w, h); - } + g1m_decode_picture(handle->pixels, ihd.color_depth == g3p_color_4bit + ? g1m_pictureformat_4bit_code : g1m_pictureformat_16bit, + inflated_image, w, h); /* no error */ return (0); @@ -158,7 +155,7 @@ int g1m_decode_std_c2p(g1m_t *handle, g1m_buffer_t *buffer, (void)buffer; /* TODO */ log_info("C2P files are not managed yet."); - log_info("Size is %" PRIuSIZE " o", sizeof(struct c2p_subheader)); + log_info("Size is %" PRIuSIZE "B", sizeof(struct c2p_subheader)); /* no error */ return (0); diff --git a/src/image/16bits.c b/src/image/16bits.c deleted file mode 100644 index da369a9..0000000 --- a/src/image/16bits.c +++ /dev/null @@ -1,81 +0,0 @@ -/* ***************************************************************************** - * image/16bits.c -- encode and decode from 16-bits encoded image. - * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey - * - * This file is part of libg1m. - * libg1m is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3.0 of the License, - * or (at your option) any later version. - * - * libg1m is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with libg1m; if not, see . - * ************************************************************************** */ -#include - -/** - * g1m_pixels_from_16bits: - * Convert from 16-bit format to final 32-bit matrix. - * - * @arg pixels the final pixels. - * @arg raw the raw data. - * @arg width the width. - * @arg height the height. - */ - -void g1m_pixels_from_16bits(uint32_t **pixels, unsigned char *raw, - int width, int height) -{ - uint32_t *cell = (uint32_t*)&pixels[height]; - int cell_count = width * height; - uint16_t *st = (uint16_t*)raw; - const unsigned int rmask = 0x1F << 11, gmask = 0x3F << 5, bmask = 0x1F; - - for (int i = 0; i < cell_count; i++) { - /* get colors - * as colors don't occupy 8-bits each, we'll "split into equal - * halves out of 256"; - * e.g. red can go from 0b00000 to 0b11111, then in 8-bits it - * will go from 0b00000000 to 0b11111000. */ - unsigned int r = (*st & rmask) >> 8; - unsigned int g = (*st & gmask) >> 3; - unsigned int b = (*st++ & bmask) << 3; - - /* put pixel */ - *cell++ = (r << 16) | (g << 8) | b; - } -} - -/** - * g1m_pixels_to_16bits: - * Convert from 32-bit matrix to 16-bit pixels (R5G6B5). - * - * @arg dest the destination buffer. - * @arg pixels the decoded pixels. - * @arg width the width. - * @arg height the height. - */ - -void g1m_pixels_to_16bits(unsigned char *dest, uint32_t **pixels, - int width, int height) -{ - uint32_t *cell = (uint32_t*)&pixels[height]; - int cell_count = width * height; - uint16_t *d = (uint16_t*)dest; - const uint32_t rmask = 0x1F << 19, gmask = 0x3F << 10, bmask = 0x1F << 3; - - for (int i = 0; i < cell_count; i++) { - /* get colors */ - unsigned int r = (*cell & rmask) >> 19; - unsigned int g = (*cell & gmask) >> 10; - unsigned int b = (*cell++ & bmask) >> 3; - - /* put pixel */ - *d++ += (r << 11) | (g << 5) | b; - } -} diff --git a/src/image/packed1bit.c b/src/image/packed1bit.c deleted file mode 100644 index 8876a4f..0000000 --- a/src/image/packed1bit.c +++ /dev/null @@ -1,77 +0,0 @@ -/* ***************************************************************************** - * image/packed1bit.c -- encode and decode from packed monochrome encoded image. - * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey - * - * This file is part of libg1m. - * libg1m is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3.0 of the License, - * or (at your option) any later version. - * - * libg1m is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with libg1m; if not, see . - * ************************************************************************** */ -#include - -/** - * g1m_pixels_from_packed1bit: - * Convert packed monochrome formatted pixels to the final 32-bit matrix. - * - * @arg pixels the final pixels. - * @arg raw the raw data. - * @arg width the width. - * @arg height the height. - */ - -void g1m_pixels_from_packed1bit(uint32_t **pixels, unsigned char *raw, - int width, int height) -{ - uint32_t *cell = (uint32_t*)&pixels[height]; - int cell_count = width * height; - - /* fill cells */ - int byte = 0x80; - for (int i = 0; i < cell_count; i++) { - /* get pixel and iterate */ - int pixel = *raw & byte; - raw += byte & 1; - byte = (byte >> 1) | ((byte & 1) << 7); - - /* put pixel */ - *cell++ = (pixel != 0) * 0xffffff; - } -} - -/** - * g1m_pixels_to_packed1bit: - * Convert 32-bit matrix to packed monochrome pixels. - * - * @arg dest the destination buffer. - * @arg pixels the decoded pixels. - * @arg width the width. - * @arg height the height. - */ - -void g1m_pixels_to_packed1bit(unsigned char *dest, uint32_t **pixels, - int width, int height) -{ - uint32_t *cell = (uint32_t*)&pixels[height]; - int cell_count = width * height; - - /* fill */ - int byte = 0x80; - for (int i = 0; i < cell_count; i++) { - /* get pixel */ - int pixel = ((*cell++ & 0xffffff) != 0) * byte; - *dest |= pixel; - - /* iterate */ - dest += byte & 1; - byte = (byte >> 1) | ((byte & 1) << 7); - } -} diff --git a/src/image/packed4bits.c b/src/image/packed4bits.c deleted file mode 100644 index 3b78f77..0000000 --- a/src/image/packed4bits.c +++ /dev/null @@ -1,97 +0,0 @@ -/* ***************************************************************************** - * image/packed4bits.c -- encode and decode from packed 4-bits encoded image. - * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey - * - * This file is part of libg1m. - * libg1m is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3.0 of the License, - * or (at your option) any later version. - * - * libg1m is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with libg1m; if not, see . - * ************************************************************************** */ -#include - -/* colors correspondance */ -static const uint32_t colors[16] = { - [g1m_color_black] = 0x000000, - [g1m_color_blue] = 0x0000ff, - [g1m_color_green] = 0x00ff00, - [g1m_color_cyan] = 0x00ffff, - [g1m_color_red] = 0xff0000, - [g1m_color_magenta] = 0xff00ff, - [g1m_color_yellow] = 0xffff00, - [g1m_color_white] = 0xffffff, - /* RESERVED */ -}; - -/** - * g1m_pixels_from_packed4bits: - * Convert 4-bits formatted image to the final 32-bit matrix. - * - * @arg pixels the final pixels. - * @arg raw the raw data. - * @arg width the width. - * @arg height the height. - */ - -void g1m_pixels_from_packed4bits(uint32_t **pixels, unsigned char *raw, - int width, int height) -{ - uint32_t *cell = (uint32_t*)&pixels[height]; - int cell_count = width * height; - - /* fill cells */ - int mask = 0xf0; - for (int i = 0; i < cell_count; i++) { - /* get nibble and iterate */ - int b = (*raw & mask) >> (mask & 4); - raw += mask & 1; - mask = ~mask & 0xff; - - /* put pixel */ - *cell++ = colors[b]; - } -} - -/** - * g1m_pixels_to_packed4bits: - * Convert the 32-bit matrix to a 4-bit formatted image. - * - * @arg dest the destination buffer. - * @arg pixels the decoded pixels. - * @arg width the width. - * @arg height the height. - */ - -void g1m_pixels_to_packed4bits(unsigned char *dest, uint32_t **pixels, - int width, int height) -{ - (void)width; - uint32_t *cell = (uint32_t*)&pixels[height]; - int cell_count = width * height; - - /* first of all, clean destination */ - bzero(dest, cell_count / 2 + cell_count % 2); - - /* fill cells */ - int mask = 0xf0; - for (int i = 0; i < cell_count; i++) { - /* get color and iterate */ - int color = 0; - color |= ((0xff0000 & *cell) != 0) << 2; - color |= ((0x00ff00 & *cell) != 0) << 1; - color |= ((0x0000ff & *cell++) != 0); - - /* store nibble */ - *dest |= color << mask & 4; - dest += mask & 1; - mask = ~mask & 0xff; - } -} diff --git a/src/manage/mcsfile.c b/src/manage/mcsfile.c index 4b4d69c..ad92b49 100644 --- a/src/manage/mcsfile.c +++ b/src/manage/mcsfile.c @@ -151,6 +151,9 @@ int g1m_prepare_mcsfile_heads(g1m_mcshead_t *head, g1m_mcshead_t *heads) void g1m_free_mcsfile(g1m_mcsfile_t *handle) { + /* check if exists */ + if (!handle) return ; + switch (handle->head.type) { /* free the cells */ case g1m_mcstype_mat: case g1m_mcstype_vct: case g1m_mcstype_list: diff --git a/src/utils/buffer.c b/src/utils/buffer.c new file mode 100644 index 0000000..895ec1c --- /dev/null +++ b/src/utils/buffer.c @@ -0,0 +1,126 @@ +/* ***************************************************************************** + * utils/buffer.c -- libg1m custom buffers utilities. + * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey + * + * This file is part of libg1m. + * libg1m is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3.0 of the License, + * or (at your option) any later version. + * + * libg1m is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libg1m; if not, see . + * ************************************************************************** */ +#include + +#ifndef G1M_DISABLED_FILE +/* ************************************************************************** */ +/* FILE buffer */ +/* ************************************************************************** */ +/** + * g1m_filebuffer_read: + * Read from a filebuffer. + * + * @arg vcookie the FILE* (uncasted) + * @arg buf the buffer to fill. + * @arg size the size to read. + * @return the error (if any). + */ + +int g1m_filebuffer_read(void *vcookie, unsigned char *buf, size_t size) +{ + FILE *file = (void*)vcookie; + size_t orig = size; + + while (size) { + size_t read = fread(buf, 1, size, file); + size -= read; + + if (!read || read == (size_t)-1) { + log_error("READING failed: read %" PRIuSIZE "/%" PRIuSIZE + " bytes, %" PRIuSIZE " missing.", orig - size, orig, size); +# if LOGLEVEL <= ll_error + if (size) { + log_info("Got the following:"); + logm_info(buf, orig - size); + } +# endif + return (g1m_error_eof); + } + } + + /* no error */ + return (0); +} + +#endif +/* ************************************************************************** */ +/* Memory buffer */ +/* ************************************************************************** */ +/** + * g1m_membuffer_read: + * Read from a memory buffer. + * + * @arg vcookie the cursor (uncasted) + * @arg dest the destination buffer. + * @arg size the size to read. + * @return the error, if any. + */ + +int g1m_membuffer_read(void *vcookie, unsigned char *dest, size_t size) +{ + g1m_cursor_t *cursor = (void*)vcookie; + + if (size > cursor->left) + return (g1m_error_eof); + memcpy(dest, cursor->p, size); + cursor->p += size; + return (0); +} + +/* ************************************************************************** */ +/* Limited buffer */ +/* ************************************************************************** */ +/** + * g1m_limbuffer_read: + * Read from a filebuffer. + * + * @arg vcookie the FILE* (uncasted) + * @arg buf the buffer to fill. + * @arg size the size to read. + * @return the error (if any). + */ + +int g1m_limbuffer_read(void *vcookie, unsigned char *buf, size_t size) +{ + /* check if the size is okay */ + g1m_limited_t *lim = (void*)vcookie; + if (size > lim->left) return (g1m_error_eof); + g1m_buffer_t *buffer = lim->buffer; + + /* read */ + READ(buf, size) + + /* no error */ + return (0); +} + +/** + * g1m_empty_limbuffer: + * Empty the limit buffer. + * + * @arg limbuf the limbuffer. + */ + +int g1m_empty_limbuffer(g1m_buffer_t *limbuffer) +{ + g1m_limited_t *lim = (void*)limbuffer->cookie; + g1m_buffer_t *buffer = lim->buffer; + SKIP(lim->left) + return (0); +} diff --git a/src/utils/filebuffer.c b/src/utils/filebuffer.c deleted file mode 100644 index 000fd64..0000000 --- a/src/utils/filebuffer.c +++ /dev/null @@ -1,52 +0,0 @@ -/* ***************************************************************************** - * utils/filebuffer.c -- FILE to libg1m buffer utilities. - * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey - * - * This file is part of libg1m. - * libg1m is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3.0 of the License, - * or (at your option) any later version. - * - * libg1m is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with libg1m; if not, see . - * ************************************************************************** */ -#include -#ifndef G1M_DISABLED_FILE - -/** - * g1m_filebuffer_read: - * Read from a filebuffer. - * - * @arg vcookie the FILE* (uncasted) - * @arg buf the buffer to fill. - * @arg size the size to read. - * @return the error (if any). - */ - -int g1m_filebuffer_read(void *vcookie, unsigned char *buf, size_t size) -{ - FILE *file = (void*)vcookie; - size_t orig = size; - - while (size) { - size_t read = fread(buf, 1, size, file); - size -= read; - - if (!read || read == (size_t)-1) { - log_error("READING failed: read %" PRIuSIZE "/%" PRIuSIZE - " bytes, %" PRIuSIZE " missing.", orig - size, orig, size); - return (g1m_error_eof); - } - } - - /* no error */ - return (0); -} - -#endif diff --git a/src/utils/limbuffer.c b/src/utils/limbuffer.c deleted file mode 100644 index 36cd8ca..0000000 --- a/src/utils/limbuffer.c +++ /dev/null @@ -1,58 +0,0 @@ -/* ***************************************************************************** - * utils/limbuffer.c -- limited libg1m buffer utilities. - * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey - * - * This file is part of libg1m. - * libg1m is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3.0 of the License, - * or (at your option) any later version. - * - * libg1m is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with libg1m; if not, see . - * ************************************************************************** */ -#include - -/** - * g1m_limbuffer_read: - * Read from a filebuffer. - * - * @arg vcookie the FILE* (uncasted) - * @arg buf the buffer to fill. - * @arg size the size to read. - * @return the error (if any). - */ - -int g1m_limbuffer_read(void *vcookie, unsigned char *buf, size_t size) -{ - /* check if the size is okay */ - g1m_limited_t *lim = (void*)vcookie; - if (size > lim->left) return (g1m_error_eof); - g1m_buffer_t *buffer = lim->buffer; - - /* read */ - READ(buf, size) - - /* no error */ - return (0); -} - -/** - * g1m_empty_limbuffer: - * Empty the limit buffer. - * - * @arg limbuf the limbuffer. - */ - -int g1m_empty_limbuffer(g1m_buffer_t *limbuffer) -{ - g1m_limited_t *lim = (void*)limbuffer->cookie; - g1m_buffer_t *buffer = lim->buffer; - SKIP(lim->left) - return (0); -} diff --git a/src/utils/membuffer.c b/src/utils/membuffer.c deleted file mode 100644 index a365ed7..0000000 --- a/src/utils/membuffer.c +++ /dev/null @@ -1,41 +0,0 @@ -/* ***************************************************************************** - * utils/membuffer.c -- memory to libg1m buffer utilities. - * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey - * - * This file is part of libg1m. - * libg1m is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3.0 of the License, - * or (at your option) any later version. - * - * libg1m is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with libg1m; if not, see . - * ************************************************************************** */ -#include -#include - -/** - * g1m_membuffer_read: - * Read from a memory buffer. - * - * @arg vcookie the cursor (uncasted) - * @arg dest the destination buffer. - * @arg size the size to read. - * @return the error, if any. - */ - -int g1m_membuffer_read(void *vcookie, unsigned char *dest, size_t size) -{ - g1m_cursor_t *cursor = (void*)vcookie; - - if (size > cursor->left) - return (g1m_error_eof); - memcpy(dest, cursor->p, size); - cursor->p += size; - return (0); -} diff --git a/src/utils/picture.c b/src/utils/picture.c new file mode 100644 index 0000000..e6f0028 --- /dev/null +++ b/src/utils/picture.c @@ -0,0 +1,231 @@ +/* ***************************************************************************** + * utils/picture.c -- libg1m picture utilities. + * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey + * + * This file is part of libg1m. + * libg1m is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3.0 of the License, + * or (at your option) any later version. + * + * libg1m is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libg1m; if not, see . + * ************************************************************************** */ +#include + +/* ************************************************************************** */ +/* Constants */ +/* ************************************************************************** */ +/* The dual 2-bit format colors */ +static uint32_t dual2b_colors[] = {0xFFFFFF, 0xAAAAAA, 0x777777, 0x000000}; + +/* prizm colors */ +static const uint32_t prizm_colors[16] = { + [g1m_color_black] = 0x000000, + [g1m_color_blue] = 0x0000ff, + [g1m_color_green] = 0x00ff00, + [g1m_color_cyan] = 0x00ffff, + [g1m_color_red] = 0xff0000, + [g1m_color_magenta] = 0xff00ff, + [g1m_color_yellow] = 0xffff00, + [g1m_color_white] = 0xffffff, + /* RESERVED */ +}; + +/* ************************************************************************** */ +/* Picture decoding */ +/* ************************************************************************** */ +/** + * g1m_decode_picture: + * Decode a picture. + * + * @arg pixels the pixels to fill. + * @arg format the format to use. + * @arg raw the raw bytes to decode from. + * @arg width the width. + * @arg height the height. + * @return the error code (0 if ok). + */ + +int g1m_decode_picture(uint32_t **pixels, g1m_pictureformat_t format, + const unsigned char *raw, unsigned int width, unsigned int height) +{ + int msk; + + switch (format) { + case g1m_pictureformat_1bit_packed: + msk = 0x80; + for (unsigned int y = 0; y < height; y++) + for (unsigned int x = 0; x < width; x++) { + /* get pixel */ + pixels[y][x] = (*raw & msk) ? 0x000000 : 0xFFFFFF; + + /* go to next */ + raw += msk & 1; + msk = (msk >> 1) | ((msk & 1) << 7); + } + break; + + case g1m_pictureformat_1bit_reverse: + msk = 0x80; + for (unsigned int bx = width - 8; bx != (unsigned int)-8; bx -= 8) + for (unsigned int y = height - 1; y != (unsigned int)-1; y--) { + msk = 0x00; + for (unsigned int x = bx; x < bx + 8; x++) { + /* get pixel */ + pixels[y][x] = (*raw & msk) ? 0x000000 : 0xFFFFFF; + + /* go to next */ + msk >>= 1; + } + + /* go to next byte */ + raw++; + } + break; + + case g1m_pictureformat_2bit_dual: + msk = 0x80; const unsigned char *r2 = &raw[height * width / 8]; + for (unsigned int y = 0; y < height; y++) + for (unsigned int x = 0; x < width; x++) { + /* get pixel */ + uint32_t val = (!!(*raw & msk) << 1) | !!(*r2 & msk); + pixels[y][x] = dual2b_colors[val]; + + /* go to next */ + raw += msk & 1; r2 += msk & 1; + msk = (msk >> 1) | ((msk & 1) << 7); + } + break; + + case g1m_pictureformat_4bit_code: + msk = 0xF0; + for (unsigned int y = 0; y < height; y++) + for (unsigned int x = 0; x < width; x++) { + /* get pixel */ + uint32_t px = *raw & msk; px = px | (px >> 4); + pixels[y][x] = prizm_colors[px & 0x0F]; + + /* go to next */ + raw += msk & 1; + msk = ~msk & 0xFF; + } + break; + + case g1m_pictureformat_4bit_rgb: + msk = 0xF0; + for (unsigned int y = height - 1; y != (unsigned int)-1; y--) + for (unsigned int x = width - 1; x != (unsigned int)-1; x--) { + /* get pixel */ + uint32_t val = *raw & msk; val |= val >> 4; + uint32_t px = 0; + if (px & 8) px |= 0xFF0000; + if (px & 4) px |= 0x00FF00; + if (px & 2) px |= 0x0000FF; + pixels[y][x] = px; + + /* go to next */ + raw += msk & 1; + msk = ~msk & 0xFF; + } + break; + + case g1m_pictureformat_16bit: + for (unsigned int y = 0; y < height; y++) + for (unsigned int x = 0; x < width; x++) { + /* get pixel */ + uint32_t o = raw[0], t = raw[1]; + uint32_t px = (o >> 3) << (16 + 3); + px |= (((o & 7) << 3) | (t >> 5)) << (8 + 2); + px |= (t & 31) << 3; + pixels[y][x] = px; + + /* go to next */ + raw += 2; + } + break; + + default: + /* unknown format! */ + return (g1m_error_op); + } + + /* everything went well :) */ + return (0); +} + +/* ************************************************************************** */ +/* Picture encoding */ +/* ************************************************************************** */ +/** + * g1m_encode_picture: + * Encode the picture. + * + * @arg pixels the pixels to encode. + * @arg format the format. + * @arg raw the destination buffer. + * @arg width the picture width. + * @arg height the picture height. + */ + +int g1m_encode_picture(const uint32_t **pixels, g1m_pictureformat_t format, + unsigned char *raw, unsigned int width, unsigned int height) +{ + int msk; + + switch (format) { + case g1m_pictureformat_1bit_packed: + msk = 0x80; + for (unsigned int y = 0; y < height; y++) + for (unsigned int x = 0; x < width; x++) { + /* set pixel */ + if (pixels[y][x] & 0xFFFFFF) *raw = msk; + + /* go to next */ + raw += msk & 1; + msk = (msk >> 1) | ((msk & 1) << 7); + } + break; + + case g1m_pictureformat_4bit_code: + msk = 0xF0; + for (unsigned int y = 0; y < height; y++) + for (unsigned int x = 0; x < width; x++) { + /* set pixel */ + uint32_t color = 0; + color |= !!(0xFF0000 & pixels[y][x]) << 2; + color |= !!(0x00FF00 & pixels[y][x]) << 1; + color |= !!(0x0000FF & pixels[y][x]); + *raw |= color << (msk & 4); + + /* go to next */ + raw += msk & 1; + msk = ~msk & 0xFF; + } + break; + + case g1m_pictureformat_16bit: + for (unsigned int y = 0; y < height; y++) + for (unsigned int x = 0; x < width; x++) { + /* set pixel */ + uint32_t r = (pixels[y][x] & (0x1F << 19)) >> 19; + uint32_t g = (pixels[y][x] & (0x3F << 10)) >> 10; + uint32_t b = (pixels[y][x] & (0x1F << 3)) >> 3; + *raw++ = (r << 3) | (g >> 5); + *raw++ = (g << 5) | b; + } + break; + + default: + /* unknown format! */ + return (g1m_error_op); + } + + /* everything went well :) */ + return (0); +}