1 // Gmsh - Copyright (C) 1997-2021 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5
6 /*
7 * This code is based on the rgbtoycc.c code from the MPEG-1 Video
8 * Software Encoder (Version 1.5; February 1, 1995), by Lawrence
9 * A. Rowe, Kevin Gong, Eugene Hung, Ketan Patel, Steve Smoot and Dan
10 * Wallach Computer Science Division-EECS, Univ. of Calif. at Berkeley
11 *
12 * Copyright (c) 1995 The Regents of the University of California.
13 * All rights reserved.
14 *
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose, without fee, and without written agreement is
17 * hereby granted, provided that the above copyright notice and the following
18 * two paragraphs appear in all copies of this software.
19 *
20 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
21 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
22 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
23 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
26 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
28 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
29 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
30 */
31
32 #include "MallocUtils.h"
33 #include "gl2yuv.h"
34
create_yuv(FILE * outfile,PixelBuffer * buffer)35 void create_yuv(FILE *outfile, PixelBuffer *buffer)
36 {
37 if(buffer->getFormat() != GL_RGB || buffer->getType() != GL_UNSIGNED_BYTE) {
38 Msg::Error("YUV only implemented for GL_RGB and GL_UNSIGNED_BYTE");
39 return;
40 }
41
42 int x, y;
43 unsigned char *dy0, *dy1;
44 unsigned char *dcr, *dcb;
45 unsigned char *src0, *src1;
46 int cdivisor;
47
48 static int first = 1;
49 static float mult299[1024], mult587[1024], mult114[1024];
50 static float mult16874[1024], mult33126[1024], mult5[1024];
51 static float mult41869[1024], mult08131[1024];
52
53 unsigned char **orig_y, **orig_cr, **orig_cb;
54
55 if(first) {
56 int index;
57 int maxValue;
58
59 maxValue = 255;
60
61 for(index = 0; index <= maxValue; index++) {
62 mult299[index] = index * 0.29900F;
63 mult587[index] = index * 0.58700F;
64 mult114[index] = index * 0.11400F;
65 mult16874[index] = -0.16874F * index;
66 mult33126[index] = -0.33126F * index;
67 mult5[index] = index * 0.50000F;
68 mult41869[index] = -0.41869F * index;
69 mult08131[index] = -0.08131F * index;
70 }
71
72 first = 0;
73 }
74
75 int width = buffer->getWidth();
76 int height = buffer->getHeight();
77 unsigned char *pixels = (unsigned char *)buffer->getPixels();
78
79 // yuv format assumes even number of rows and columns
80 height -= height % 2;
81 width -= width % 2;
82
83 int row_stride = width * 3;
84
85 orig_y = (unsigned char **)Malloc(sizeof(unsigned char *) * height);
86 for(y = 0; y < height; y++) {
87 orig_y[y] = (unsigned char *)Malloc(sizeof(unsigned char) * width);
88 }
89
90 orig_cr = (unsigned char **)Malloc(sizeof(char *) * height / 2);
91 for(y = 0; y < height / 2; y++) {
92 orig_cr[y] = (unsigned char *)Malloc(sizeof(char) * width / 2);
93 }
94
95 orig_cb = (unsigned char **)Malloc(sizeof(char *) * height / 2);
96 for(y = 0; y < height / 2; y++) {
97 orig_cb[y] = (unsigned char *)Malloc(sizeof(char) * width / 2);
98 }
99
100 // assume ydivisor = 1, so cdivisor = 4
101 cdivisor = 4;
102
103 for(y = 0; y < height; y += 2) {
104 src0 = &(pixels[y * row_stride]);
105 src1 = &(pixels[(y + 1) * row_stride]);
106 dy0 = orig_y[y];
107 dy1 = orig_y[y + 1];
108 dcr = orig_cr[y / 2];
109 dcb = orig_cb[y / 2];
110
111 for(x = 0; x < width;
112 x += 2, dy0 += 2, dy1 += 2, dcr++, dcb++, src0 += 6, src1 += 6) {
113 *dy0 =
114 (unsigned char)(mult299[*src0] + mult587[src0[1]] + mult114[src0[2]]);
115
116 *dy1 =
117 (unsigned char)(mult299[*src1] + mult587[src1[1]] + mult114[src1[2]]);
118
119 dy0[1] =
120 (unsigned char)(mult299[src0[3]] + mult587[src0[4]] + mult114[src0[5]]);
121
122 dy1[1] =
123 (unsigned char)(mult299[src1[3]] + mult587[src1[4]] + mult114[src1[5]]);
124
125 *dcb = (unsigned char)((mult16874[*src0] + mult33126[src0[1]] +
126 mult5[src0[2]] + mult16874[*src1] +
127 mult33126[src1[1]] + mult5[src1[2]] +
128 mult16874[src0[3]] + mult33126[src0[4]] +
129 mult5[src0[5]] + mult16874[src1[3]] +
130 mult33126[src1[4]] + mult5[src1[5]]) /
131 cdivisor) +
132 128;
133
134 *dcr = (unsigned char)((mult5[*src0] + mult41869[src0[1]] +
135 mult08131[src0[2]] + mult5[*src1] +
136 mult41869[src1[1]] + mult08131[src1[2]] +
137 mult5[src0[3]] + mult41869[src0[4]] +
138 mult08131[src0[5]] + mult5[src1[3]] +
139 mult41869[src1[4]] + mult08131[src1[5]]) /
140 cdivisor) +
141 128;
142 }
143 }
144
145 // Y
146 for(y = height - 1; y >= 0; y--) fwrite(orig_y[y], 1, width, outfile);
147
148 // U
149 for(y = height / 2 - 1; y >= 0; y--)
150 fwrite(orig_cb[y], 1, width / 2, outfile);
151
152 // V
153 for(y = height / 2 - 1; y >= 0; y--)
154 fwrite(orig_cr[y], 1, width / 2, outfile);
155
156 for(y = 0; y < height; y++) Free(orig_y[y]);
157 Free(orig_y);
158
159 for(y = 0; y < height / 2; y++) Free(orig_cr[y]);
160 Free(orig_cr);
161
162 for(y = 0; y < height / 2; y++) Free(orig_cb[y]);
163 Free(orig_cb);
164 }
165