blob: 558ba28474a24a2e3e0e2284cc5915a66fd8d93c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
/*
* Copyright 2012 Michael Drake <tlsa@netsurf-browser.org>
*
* This file is part of libnsfb, http://www.netsurf-browser.org/
* Licenced under the MIT License,
* http://www.opensource.org/licenses/mit-license.php
*/
/** \file
* Palette (implementation).
*/
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "palette.h"
/** Create an empty palette object. */
bool nsfb_palette_new(struct nsfb_palette_s **palette, int width)
{
*palette = malloc(sizeof(struct nsfb_palette_s));
if (*palette == NULL) {
return false;
}
(*palette)->type = NSFB_PALETTE_EMPTY;
(*palette)->last = 0;
(*palette)->dither = false;
(*palette)->dither_ctx.data_len = width * 3 * sizeof(int);
(*palette)->dither_ctx.data = malloc(width * 3 * sizeof(int));
if ((*palette)->dither_ctx.data == NULL) {
nsfb_palette_free(*palette);
return false;
}
return true;
}
/** Free a palette object. */
void nsfb_palette_free(struct nsfb_palette_s *palette)
{
if (palette != NULL) {
if (palette->dither_ctx.data != NULL) {
free(palette->dither_ctx.data);
}
free(palette);
}
}
/** Init error diffusion for a plot. */
void nsfb_palette_dither_init(struct nsfb_palette_s *palette, int width)
{
width *= 3;
palette->dither = true;
palette->dither_ctx.current = 0;
palette->dither_ctx.width = width;
memset(palette->dither_ctx.data, 0, width * sizeof(int));
}
/** Finalise error diffusion after a plot. */
void nsfb_palette_dither_fini(struct nsfb_palette_s *palette)
{
palette->dither = false;
}
/** Generate libnsfb 8bpp default palette. */
void nsfb_palette_generate_nsfb_8bpp(struct nsfb_palette_s *palette)
{
int rloop, gloop, bloop;
int loop = 0;
uint8_t r, g, b;
/* Build a linear 6-8-5 levels RGB colour cube palette.
* This accounts for 240 colours */
#define RLIM 6
#define GLIM 8
#define BLIM 5
for (rloop = 0; rloop < RLIM; rloop++) {
for (gloop = 0; gloop < GLIM; gloop++) {
for (bloop = 0; bloop < BLIM; bloop++) {
r = ((rloop * 255 * 2) + RLIM - 1) /
(2 * (RLIM - 1));
g = ((gloop * 255 * 2) + GLIM - 1) /
(2 * (GLIM - 1));
b = ((bloop * 255 * 2) + BLIM - 1) /
(2 * (BLIM - 1));
palette->data[loop] = r | g << 8 | b << 16;
loop++;
}
}
}
#undef RLIM
#undef GLIM
#undef BLIM
/* Should have 240 colours set */
assert(loop == 240);
/* Fill index 240 to index 255 with grayscales */
/* Note: already have full black and full white from RGB cube */
for (; loop < 256; loop++) {
int ngray = loop - 240 + 1;
r = ngray * 15; /* 17*15 = 255 */
g = b = r;
palette->data[loop] = r | g << 8 | b << 16;
}
/* Set palette details */
palette->type = NSFB_PALETTE_NSFB_8BPP;
palette->last = 255;
}
|