2
2
#include <stddef.h>
3
3
#include <stdio.h>
4
4
#include <stdlib.h>
5
+ #include <string.h>
5
6
/**************************************/
6
7
#include "Bitmap.h"
7
8
#include "Colourspace.h"
8
9
#include "Qualetize.h"
9
10
#include "Tiles.h"
10
11
/**************************************/
11
- #define TILE_W 8
12
- #define TILE_H 8
13
- #define PALUNUSED 1 //! These will be filled with {0,0,0,0} but still be used for matching
14
- #define BITRANGE (const struct BGRA8_t){0x1F,0x1F,0x1F,0x01} //! None of these may be 0
15
12
16
- //! Default dither mode
17
- #define DITHER_TYPE DITHER_ORDERED(3)
13
+ //! When not zero, the PSNR for each channel will be displayed
14
+ #define MEASURE_PSNR 1
18
15
19
16
/**************************************/
20
17
21
- //! When not zero, the PSNR for each channel will be displayed
22
- #define MEASURE_PSNR 1
18
+ //! strcmp() implementation that ACTUALLY returns the difference between
19
+ //! characters instead of just the signs. Blame the C standard -_-
20
+ static int mystrcmp (const char * s1 , const char * s2 ) {
21
+ while (* s1 && * s1 == * s2 ) s1 ++ , s2 ++ ;
22
+ return * s1 - * s2 ;
23
+ }
23
24
24
25
/**************************************/
25
26
26
27
int main (int argc , const char * argv []) {
27
28
//! Check arguments
28
- if (argc != 5 ) {
29
+ if (argc < 3 ) {
29
30
printf (
30
31
"tilequant - Tiled colour-quantization tool\n"
31
- "Usage: tilequant Input.bmp Output.bmp (no. of palettes) (entries/palette)\n"
32
+ "Usage:\n"
33
+ " tilequant Input.bmp Output.bmp [options]\n"
34
+ "Options:\n"
35
+ " -np:16 - Set number of palettes available\n"
36
+ " -ps:16 - Set number of colours per palette\n"
37
+ " -tw:8 - Set tile width\n"
38
+ " -th:8 - Set tile height\n"
39
+ " -bgra:5551 - Set BGRA bit depth\n"
40
+ " -dither:floyd,1.0 - Set dither mode, level\n"
41
+ "Dither modes available (and default level):\n"
42
+ " -dither:none - No dithering\n"
43
+ " -dither:floyd,1.0 - Floyd-Steinberg\n"
44
+ " -dither:ord2,0.5 - 2x2 ordered dithering\n"
45
+ " -dither:ord4,0.5 - 4x4 ordered dithering\n"
46
+ " -dither:ord8,0.5 - 8x8 ordered dithering\n"
47
+ " -dither:ord16,0.5 - 16x16 ordered dithering\n"
48
+ " -dither:ord32,0.5 - 32x32 ordered dithering\n"
49
+ " -dither:ord64,0.5 - 64x64 ordered dithering\n"
32
50
);
33
51
return 1 ;
34
52
}
35
53
36
54
//! Parse arguments
37
- int MaxTilePals = atoi (argv [3 ]);
38
- int MaxPalSize = atoi (argv [4 ]);
55
+ int nPalettes = 16 ;
56
+ int nColoursPerPalette = 16 ;
57
+ int nUnusedColoursPerPalette = 1 ;
58
+ int TileW = 8 ;
59
+ int TileH = 8 ;
60
+ uint8_t BitRange [4 ] = {0x1F ,0x1F ,0x1F ,0x01 };
61
+ int DitherMode = DITHER_FLOYDSTEINBERG ;
62
+ float DitherLevel = 1.0f ; {
63
+ int argi ;
64
+ for (argi = 3 ;argi < argc ;argi ++ ) {
65
+ int ArgOk = 0 ;
66
+
67
+ const char * ArgStr ;
68
+ #define ARGMATCH (Input , Target ) \
69
+ ArgStr = Input + strlen(Target); \
70
+ if(!memcmp(Input, Target, strlen(Target)))
71
+ //! nPalettes
72
+ ARGMATCH (argv [argi ], "-np:" ) ArgOk = 1 , nPalettes = atoi (ArgStr );
73
+
74
+ //! nColoursPerPalette
75
+ ARGMATCH (argv [argi ], "-ps:" ) ArgOk = 1 , nColoursPerPalette = atoi (ArgStr );
76
+
77
+ //! nUnusedColoursPerPalette
78
+
79
+ //! TileW
80
+ ARGMATCH (argv [argi ], "-tw:" ) ArgOk = 1 , TileW = atoi (ArgStr );
81
+
82
+ //! TileH
83
+ ARGMATCH (argv [argi ], "-th:" ) ArgOk = 1 , TileH = atoi (ArgStr );
84
+
85
+ //! BitRange
86
+ ARGMATCH (argv [argi ], "-bgra:" ) {
87
+ ArgOk = 1 ;
88
+ BitRange [0 ] = (1 << (* ArgStr ++ - '0' )) - 1 ;
89
+ BitRange [1 ] = (1 << (* ArgStr ++ - '0' )) - 1 ;
90
+ BitRange [2 ] = (1 << (* ArgStr ++ - '0' )) - 1 ;
91
+ BitRange [3 ] = (1 << (* ArgStr ++ - '0' )) - 1 ;
92
+ }
93
+
94
+ //! DitherMode,DitherLevel
95
+ ARGMATCH (argv [argi ], "-dither:" ) {
96
+ int d ;
97
+ #define DITHERMODE_MATCH (Input , Target , ModeValue , DefaultLevel ) \
98
+ d = mystrcmp(Input, Target); \
99
+ if(!d || d == ',') { \
100
+ ArgOk = 1; \
101
+ DitherMode = ModeValue; \
102
+ DitherLevel = !d ? DefaultLevel : atof(strchr(Input, ',')+1); \
103
+ }
104
+ DITHERMODE_MATCH (ArgStr , "none" , DITHER_NONE , 0.0f );
105
+ DITHERMODE_MATCH (ArgStr , "floyd" , DITHER_FLOYDSTEINBERG , 1.0f );
106
+ DITHERMODE_MATCH (ArgStr , "ord2" , DITHER_ORDERED (1 ), 0.5f );
107
+ DITHERMODE_MATCH (ArgStr , "ord4" , DITHER_ORDERED (2 ), 0.5f );
108
+ DITHERMODE_MATCH (ArgStr , "ord8" , DITHER_ORDERED (3 ), 0.5f );
109
+ DITHERMODE_MATCH (ArgStr , "ord16" , DITHER_ORDERED (4 ), 0.5f );
110
+ DITHERMODE_MATCH (ArgStr , "ord32" , DITHER_ORDERED (5 ), 0.5f );
111
+ DITHERMODE_MATCH (ArgStr , "ord64" , DITHER_ORDERED (6 ), 0.5f );
112
+ #undef DITHERMODE_MATCH
113
+ if (!ArgOk ) printf ("Unrecognized dither mode: %s\n" , ArgStr );
114
+ ArgOk = 1 ;
115
+ }
116
+ #undef ARGMATCH
117
+
118
+ //! Unrecognized?
119
+ if (!ArgOk ) printf ("Unrecognized argument: %s\n" , ArgStr );
120
+ }
121
+ }
39
122
40
123
//! Get input image
41
124
struct BmpCtx_t Image ;
42
125
if (!BmpCtx_FromFile (& Image , argv [1 ])) {
43
126
printf ("Unable to read input file\n" );
44
127
return -1 ;
45
128
}
46
- if (Image .Width %TILE_W || Image .Height %TILE_H ) {
47
- printf ("Image not a multiple of tile size (%dx%d)\n" , TILE_W , TILE_H );
129
+ if (Image .Width %TileW || Image .Height %TileH ) {
130
+ printf ("Image not a multiple of tile size (%dx%d)\n" , TileW , TileH );
48
131
BmpCtx_Destroy (& Image );
49
132
return -1 ;
50
133
}
51
134
52
135
//! Perform processing
53
136
//! NOTE: PxData and Palette will be assigned to image; do NOT destroy
54
- struct TilesData_t * TilesData = TilesData_FromBitmap (& Image , TILE_W , TILE_H );
137
+ struct TilesData_t * TilesData = TilesData_FromBitmap (& Image , TileW , TileH );
55
138
uint8_t * PxData = malloc (Image .Width * Image .Height * sizeof (uint8_t ));
56
139
struct BGRAf_t * Palette = calloc (BMP_PALETTE_COLOURS , sizeof (struct BGRAf_t ));
57
140
if (!TilesData || !PxData || !Palette ) {
@@ -63,7 +146,7 @@ int main(int argc, const char *argv[]) {
63
146
return -1 ;
64
147
}
65
148
struct BGRAf_t RMSE = Qualetize (
66
- & Image , TilesData , PxData , Palette , MaxTilePals , MaxPalSize , PALUNUSED , & BITRANGE , DITHER_TYPE , 1
149
+ & Image , TilesData , PxData , Palette , nPalettes , nColoursPerPalette , nUnusedColoursPerPalette , BitRange , DitherMode , DitherLevel , 1
67
150
);
68
151
free (TilesData );
69
152
0 commit comments