UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
dxt62tga.c
Go to the documentation of this file.
1#include <stdio.h>
2#include <stdlib.h>
3#include <stdint.h>
4
5/* size of TARGA header */
6#define TGA_HEADER_SIZE 18
7
8
9typedef uint64_t u64;
10typedef uint32_t u32;
11typedef uint16_t u16;
12typedef uint8_t u8;
13
14static u8 clamp(const double s) {
15 const int is = (int)(s + 0.5);
16 if(is > 255)
17 return 255;
18 if(is < 0)
19 return 0;
20 return is;
21}
22
23
24static int ycocg_to_bgr(int x, int y, u8 * out, int out_stride, double a, double r, double g, double b) {
25 const double _scale = 1.00000000E+00/(3.18750000E+01*b + 1.00000000E+00);
26 const double _Co = (r - 5.01960814E-01)*_scale;
27 const double _Cg = (g - 5.01960814E-01)*_scale;
28 const double _R = (a + _Co) - _Cg;
29 const double _G = a + _Cg;
30 const double _B = (a - _Co) - _Cg;
31 out += 3 * (x + y * out_stride);
32 out[2] = clamp(_R * 255.0);
33 out[1] = clamp(_G * 255.0);
34 out[0] = clamp(_B * 255.0);
35/* printf("A: %f.\n", a); */
36}
37
38static double alpha_decode(const double a0, const double a1, int alpha_idx) {
39 if(a0 > a1) {
40 switch(alpha_idx) {
41 case 0: return a0;
42 case 1: return a1;
43 case 2: return (6.0 * a0 + 1.0 * a1) / 7.0;
44 case 3: return (5.0 * a0 + 2.0 * a1) / 7.0;
45 case 4: return (4.0 * a0 + 3.0 * a1) / 7.0;
46 case 5: return (3.0 * a0 + 4.0 * a1) / 7.0;
47 case 6: return (2.0 * a0 + 5.0 * a1) / 7.0;
48 case 7: return (1.0 * a0 + 6.0 * a1) / 7.0;
49 }
50 } else {
51 switch(alpha_idx) {
52 case 0: return a0;
53 case 1: return a1;
54 case 2: return (4.0 * a0 + 1.0 * a1) / 5.0;
55 case 3: return (3.0 * a0 + 2.0 * a1) / 5.0;
56 case 4: return (2.0 * a0 + 3.0 * a1) / 5.0;
57 case 5: return (1.0 * a0 + 4.0 * a1) / 5.0;
58 case 6: return 0.0;
59 case 7: return 1.0;
60 }
61 }
62}
63
64static int dxt5ycocg_block_to_bgr(int x_offset, int y_offset, u8 * out, int out_stride, u64 alpha_code, u64 rgb_code) {
65 int x, y, rgb_idx;
66 double a, r[4], g[4], b[4];
67 const double alpha_max = (alpha_code & 0xFF) / 255.0;
68 const double alpha_min = ((alpha_code >> 8) & 0xFF) / 255.0;
69
70 b[0] = (rgb_code & 0x1F) / 31.0;
71 g[0] = ((rgb_code >> 5) & 0x3F) / 63.0;
72 r[0] = ((rgb_code >> 11) & 0x1F) / 31.0;
73 b[1] = ((rgb_code >> 16) & 0x1F) / 31.0;
74 g[1] = ((rgb_code >> 21) & 0x3F) / 63.0;
75 r[1] = ((rgb_code >> 27) & 0x1F) / 31.0;
76 b[2] = (2.0 * b[0] + 1.0 * b[1]) / 3.0;
77 g[2] = (2.0 * g[0] + 1.0 * g[1]) / 3.0;
78 r[2] = (2.0 * r[0] + 1.0 * r[1]) / 3.0;
79 b[3] = (1.0 * b[0] + 2.0 * b[1]) / 3.0;
80 g[3] = (1.0 * g[0] + 2.0 * g[1]) / 3.0;
81 r[3] = (1.0 * r[0] + 2.0 * r[1]) / 3.0;
82
83 alpha_code >>= 16;
84 rgb_code >>= 32;
85 for(y = 0; y < 4; y++) {
86 for(x = 0; x < 4; x++) {
87 a = alpha_decode(alpha_max, alpha_min, alpha_code & 7);
88 rgb_idx = rgb_code & 3;
89 alpha_code >>= 3;
90 rgb_code >>= 2;
91 ycocg_to_bgr(x_offset + x, y_offset + y, out, out_stride,
92 a, r[rgb_idx], g[rgb_idx], b[rgb_idx]);
93 }
94 }
95}
96
97
98static int dxt5ycocg_to_bgr(const u64 * in, u8 * out, int size_x, int size_y) {
99 int x, y;
100
101 for(y = 0; y < size_y; y += 4) {
102 for(x = 0; x < size_x; x += 4) {
103 dxt5ycocg_block_to_bgr(x, y, out, size_x, in[0], in[1]);
104 in += 2;
105 }
106 }
107
108 /* nothing checked in this implementation */
109 return 0;
110}
111
112
113
114static void usage(const char * const name, const char * const message) {
115 printf("ERROR: %s\n", message);
116 printf("Usage: %s width height input.yog output.tga\n", name);
117}
118
119
120int main(int argc, char** argv) {
121 FILE *in_file, *tga_file;
122 size_t in_size, tga_size;
123 int size_x, size_y;
124 u8 * tga_header;
125 void * tga = 0, * in = 0;
126
127 /* check arguments */
128 if(5 != argc) {
129 usage(argv[0], "Incorrect argument count.");
130 return -1;
131 }
132
133 /* get image size */
134 size_x = atoi(argv[1]);
135 size_y = atoi(argv[2]);
136 if(size_x <= 0 || (size_x & 3) || (size_y <= 0) || (size_y & 3)) {
137 usage(argv[0], "Image sizes must be positive numbers divisible by 4.");
138 return -1;
139 }
140
141 /* allocate buffers */
142 in_size = size_x * size_y;
143 tga_size = in_size * 3 + TGA_HEADER_SIZE;
144 in = malloc(in_size);
145 tga = malloc(tga_size);
146 if(!in || !tga) {
147 usage(argv[0], "Cannot allocate buffers.\n");
148 return -1;
149 }
150
151 /* open input file */
152 in_file = fopen(argv[3], "r");
153 if(!in_file) {
154 usage(argv[0], "Could not open input file.");
155 return -1;
156 }
157
158 /* load data */
159 if(1 != fread(in, in_size, 1, in_file)) {
160 usage(argv[0], "Could not read from input file.");
161 return -1;
162 }
163 fclose(in_file);
164
165 /* decompress */
166 if(dxt5ycocg_to_bgr((u64*)in, (u8*)tga + TGA_HEADER_SIZE, size_x, size_y)) {
167 usage(argv[0], "DXT6 decompression error.");
168 return -1;
169 }
170
171 /* add the TARGA header for 3 component RGB image */
172 tga_header = (u8*)tga;
173 *(tga_header + 0) = 0; /* no ID field */
174 *(tga_header + 1) = 0; /* no color map */
175 *(tga_header + 2) = 2; /* uncompressed RGB */
176 *(tga_header + 3) = 0; /* ignored if no color map */
177 *(tga_header + 4) = 0; /* ignored if no color map */
178 *(tga_header + 5) = 0; /* ignored if no color map */
179 *(tga_header + 6) = 0; /* ignored if no color map */
180 *(tga_header + 7) = 0; /* ignored if no color map */
181 *((u16*)(tga_header + 8)) = 0; /* image origin X */
182 *((u16*)(tga_header + 10)) = 0; /* image origin Y */
183 *((u16*)(tga_header + 12)) = size_x; /* image width */
184 *((u16*)(tga_header + 14)) = size_y; /* image height */
185 *(tga_header + 16) = 24; /* 24 bits per pixel */
186 *(tga_header + 17) = 1 << 5; /* origin in top-left corner */
187
188 /* open output file */
189 tga_file = fopen(argv[4], "w");
190 if(!tga_file) {
191 usage(argv[0], "Could not open output file for writing.");
192 return -1;
193 }
194
195 /* write output into the file */
196 if(1 != fwrite(tga, tga_size, 1, tga_file)) {
197 usage(argv[0], "Could not write into output file.");
198 return -1;
199 }
200 fclose(tga_file);
201
202 /* free buffers */
203 free(in);
204 free(tga);
205
206 /* indicate success */
207 return 0;
208}
209
static int dxt5ycocg_to_bgr(const u64 *in, u8 *out, int size_x, int size_y)
Definition dxt62tga.c:98
uint64_t u64
Definition dxt62tga.c:9
static double alpha_decode(const double a0, const double a1, int alpha_idx)
Definition dxt62tga.c:38
#define TGA_HEADER_SIZE
Definition dxt62tga.c:6
static int ycocg_to_bgr(int x, int y, u8 *out, int out_stride, double a, double r, double g, double b)
Definition dxt62tga.c:24
uint8_t u8
Definition dxt62tga.c:12
static u8 clamp(const double s)
Definition dxt62tga.c:14
uint16_t u16
Definition dxt62tga.c:11
static int dxt5ycocg_block_to_bgr(int x_offset, int y_offset, u8 *out, int out_stride, u64 alpha_code, u64 rgb_code)
Definition dxt62tga.c:64
uint32_t u32
Definition dxt62tga.c:10
void usage()
Definition main.cpp:28
const char * name
Definition settings.cpp:193