summaryrefslogtreecommitdiff
path: root/include/palette.h
blob: 845c1bc7448afe2b90dfe8131909665bdc24ead8 (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
/*
 * 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
 *
 * This is the *internal* interface for the cursor. 
 */

#ifndef PALETTE_H
#define PALETTE_H 1

#include <stdint.h>
#include <limits.h>

#include "libnsfb.h"
#include "libnsfb_plot.h"

enum nsfb_palette_type_e {
	NSFB_PALETTE_EMPTY,     /**< empty palette object */
	NSFB_PALETTE_NSFB_8BPP, /**< libnsfb's own 8bpp palette */
	NSFB_PALETTE_OTHER      /**< any other palette  */
};

struct nsfb_palette_s {
	enum nsfb_palette_type_e type; /**< Palette type */
	uint8_t last; /**< Last used palette index */
	nsfb_colour_t data[256]; /**< Palette for index modes */
};

/** Create an empty palette object. */
bool nsfb_palette_new(struct nsfb_palette_s **palette);

/** Free a palette object. */
void nsfb_palette_free(struct nsfb_palette_s *palette);

/** Generate libnsfb 8bpp default palette. */
void nsfb_palette_generate_nsfb_8bpp(struct nsfb_palette_s *palette);


static inline uint8_t nsfb_palette_best_match(
		const struct nsfb_palette_s *palette,
		nsfb_colour_t c)
{
	uint8_t best_col = 0;

	nsfb_colour_t palent;
	int col;
	int dr, dg, db; /* delta red, green blue values */

	int cur_distance;
	int best_distance = INT_MAX;

	switch (palette->type) {
	case NSFB_PALETTE_NSFB_8BPP:
		/* Index into colour cube part */
		dr = ((( c        & 0xFF) * 5) + 128) / 256;
		dg = ((((c >>  8) & 0xFF) * 7) + 128) / 256;
		db = ((((c >> 16) & 0xFF) * 4) + 128) / 256;
		col = 40 * dr + 5 * dg + db;

		palent = palette->data[col];
		dr = ( c        & 0xFF) - ( palent        & 0xFF);
		dg = ((c >>  8) & 0xFF) - ((palent >> 8 ) & 0xFF);
		db = ((c >> 16) & 0xFF) - ((palent >> 16) & 0xFF);
		cur_distance = (dr * dr) + (dg * dg) + (db * db);

		best_col = col;
		best_distance = cur_distance;

		/* Index into grayscale part */
		col = (( c        & 0xFF) +
		       ((c >>  8) & 0xFF) +
		       ((c >> 16) & 0xFF) + (45 / 2)) / (15 * 3) - 1 + 240;
		palent = palette->data[col];

		dr = ( c        & 0xFF) - ( palent        & 0xFF);
		dg = ((c >>  8) & 0xFF) - ((palent >>  8) & 0xFF);
		db = ((c >> 16) & 0xFF) - ((palent >> 16) & 0xFF);
		cur_distance = (dr * dr) + (dg * dg) + (db * db);
		if (cur_distance < best_distance) {
			best_distance = cur_distance;
			best_col = col;
		}
		break;

	case NSFB_PALETTE_OTHER:
		/* Try all colours in palette */
		for (col = 0; col <= palette->last; col++) {
			palent = palette->data[col];

			dr = ( c        & 0xFF) - ( palent        & 0xFF);
			dg = ((c >>  8) & 0xFF) - ((palent >>  8) & 0xFF);
			db = ((c >> 16) & 0xFF) - ((palent >> 16) & 0xFF);
			cur_distance = (dr * dr) + (dg * dg) + (db * db);
			if (cur_distance < best_distance) {
				best_distance = cur_distance;
				best_col = col;
			}
		}
		break;

	default:
		break;
	}

        return best_col;
}

#endif /* PALETTE_H */