cake
/
libg1m
Archived
1
0
Fork 0

Nocturnal mods.

This commit is contained in:
Thomas Touhey 2017-03-11 02:05:34 +01:00
parent a3d708c766
commit 3797c67f18
17 changed files with 429 additions and 433 deletions

View File

@ -30,6 +30,7 @@
# include <libg1m/config.h>
# include <libg1m/buffer.h>
# include <libg1m/handle.h>
# include <libg1m/picture.h>
# include <libfontcharacter.h>
# include <stdio.h>
# include <stdint.h>

View File

@ -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 */

View File

@ -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 */
/* ************************************************************************** */

51
include/libg1m/picture.h Normal file
View File

@ -0,0 +1,51 @@
/* *****************************************************************************
* libg1m/picture.h -- libg1m picture formats.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* 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 <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#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 */

View File

@ -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);

View File

@ -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 */

View File

@ -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);
}

View File

@ -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);

View File

@ -1,81 +0,0 @@
/* *****************************************************************************
* image/16bits.c -- encode and decode from 16-bits encoded image.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* 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 <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/**
* 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;
}
}

View File

@ -1,77 +0,0 @@
/* *****************************************************************************
* image/packed1bit.c -- encode and decode from packed monochrome encoded image.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* 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 <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/**
* 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);
}
}

View File

@ -1,97 +0,0 @@
/* *****************************************************************************
* image/packed4bits.c -- encode and decode from packed 4-bits encoded image.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* 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 <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/* 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;
}
}

View File

@ -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:

126
src/utils/buffer.c Normal file
View File

@ -0,0 +1,126 @@
/* *****************************************************************************
* utils/buffer.c -- libg1m custom buffers utilities.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* 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 <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
#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);
}

View File

@ -1,52 +0,0 @@
/* *****************************************************************************
* utils/filebuffer.c -- FILE to libg1m buffer utilities.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* 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 <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
#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

View File

@ -1,58 +0,0 @@
/* *****************************************************************************
* utils/limbuffer.c -- limited libg1m buffer utilities.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* 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 <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/**
* 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);
}

View File

@ -1,41 +0,0 @@
/* *****************************************************************************
* utils/membuffer.c -- memory to libg1m buffer utilities.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* 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 <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
#include <string.h>
/**
* 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);
}

231
src/utils/picture.c Normal file
View File

@ -0,0 +1,231 @@
/* *****************************************************************************
* utils/picture.c -- libg1m picture utilities.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* 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 <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/* ************************************************************************** */
/* 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);
}