1 /* ***** BEGIN LICENSE BLOCK *****
7 * Copyright (c) 2008 BBC Research
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * ***** END LICENSE BLOCK ***** */
34 /* convert one line of 422 chroma to 444 */
35 void RawWriterppm::chroma422to444(const Array2d
<int>& in
, const int line
,
36 Array1d
<int>& out
) const
38 Array1d
<int> ChromaLine((in
.width()*2) + 2);
41 /* generate zero stuffed chroma */
42 for (int x
=0; x
<in
.width()*2; x
+=2) {
43 ChromaLine
[x
+1] = in
[line
][x
/2]; //offset ChromaLine by 1 to get pixel at x=-1
47 for (int x
=0; x
<in
.width()*2; x
++) {
49 /* 1/2, 1/2 filter *///note the odd indexing to the array
50 int C
= ChromaLine
[x
]; //tap at 'x-1'
51 C
+= ChromaLine
[x
+1] * 2; //tap at 'x'
52 C
+= ChromaLine
[x
+2]; //tap at 'x+1'
62 /* convert a line of YUV to RGB */
63 void RawWriterppm::yuv2rgb(const Array2d
<int>& Y
, const int lineNum
,
64 const Array1d
<int>& ULine
, const Array1d
<int>& VLine
,
65 Array1d
<int>& RLine
, Array1d
<int>& GLine
,
66 Array1d
<int>& BLine
, int depth
) const
68 int maxVal
= (1 << depth
) - 1;
69 //int yOffset = 1 << (depth - 4);
71 for (int x
=0; x
<ULine
.length(); x
++) {
73 //int L = Y[lineNum][x] - yOffset;
74 int L
= Y
[lineNum
][x
];
78 //Matrix YUV to RGB - Tims, scales output 0-255
79 //int R = ((298*L + 409*V + 128)>>8);
80 //int G = ((298*L - 100*U - 208*V + 128)>>8);
81 //int B = ((298*L + 516*U + 128)>>8);
83 // Jons - leaves output at same range as input
84 int R
= ((256*L
+ 394*V
+ 128)>>8);
85 int G
= ((256*L
- 46*U
- 117*V
+ 128)>>8);
86 int B
= ((256*L
+ 464*U
+ 128)>>8);
88 //printf("Y=%d U=%d V=%d R=%d G=%d B=%d\n", L, U, V, R, G, B);
91 RLine
[x
] = (R
< 0) ? 0 : ((R
> maxVal
) ? maxVal
: R
);
92 GLine
[x
] = (G
< 0) ? 0 : ((G
> maxVal
) ? maxVal
: G
);
93 BLine
[x
] = (B
< 0) ? 0 : ((B
> maxVal
) ? maxVal
: B
);
95 //printf("Clipped Y=%d U=%d V=%d R=%d G=%d B=%d\n", L, U, V, RLine[x], GLine[x], BLine[x]);
99 void RawWriterppm::writeCr422(const RawFrame
& f
) const
101 int maxVal
= (1 << depth
) - 1;
103 fprintf(outfile
, "P6 %d %d %d\n", f
.luma
.width(), f
.luma
.height(), maxVal
);
105 int mask
= (1 << (depth
- 8)) - 1;
107 for (int y
=0; y
< f
.luma
.height(); y
++) {
109 Array1d
<int> ULine(f
.luma
.width());
110 Array1d
<int> VLine(f
.luma
.width());
112 Array1d
<int> RLine(f
.luma
.width());
113 Array1d
<int> GLine(f
.luma
.width());
114 Array1d
<int> BLine(f
.luma
.width());
116 /* upconvert a line of chroma */
117 chroma422to444(f
.cb
, y
, ULine
);
118 chroma422to444(f
.cr
, y
, VLine
);
121 yuv2rgb(f
.luma
, y
, ULine
, VLine
, RLine
, GLine
, BLine
, depth
);
123 for (int x
=0; x
<f
.luma
.width(); x
++) {
128 fputc((RLine
[x
] >> 8) & mask
, outfile
);
129 fputc((RLine
[x
] & 0xff), outfile
);
131 fputc((GLine
[x
] >> 8) & mask
, outfile
);
132 fputc((GLine
[x
] & 0xff), outfile
);
134 fputc((BLine
[x
] >> 8) & mask
, outfile
);
135 fputc((BLine
[x
] & 0xff), outfile
);
138 fputc((RLine
[x
] & 0xff), outfile
);
139 fputc((GLine
[x
] & 0xff), outfile
);
140 fputc((BLine
[x
] & 0xff), outfile
);
146 void RawWriterppm::writeYOnly(const RawFrame
& f
) const
150 assert(f
.chroma
== RawFrame::YOnly
);
152 fprintf(outfile
, "P6 %d %d %d\n", f
.luma
.width(), f
.luma
.height(), (1
156 int mask
= (1 << (depth
- 8)) - 1;
157 for (int y
= 0; y
< f
.luma
.height(); y
++)
158 for (int x
= 0; x
< f
.luma
.width(); x
++) {
161 fputc((f
.luma
[y
][x
] >> 8) & mask
, outfile
);
162 fputc((f
.luma
[y
][x
] & 0xff), outfile
);
164 fputc((f
.luma
[y
][x
] >> 8) & mask
, outfile
);
165 fputc((f
.luma
[y
][x
] & 0xff), outfile
);
167 fputc((f
.luma
[y
][x
] >> 8) & mask
, outfile
);
168 fputc((f
.luma
[y
][x
] & 0xff), outfile
);
172 for (int y
= 0; y
< f
.luma
.height(); y
++)
173 for (int x
= 0; x
< f
.luma
.width(); x
++) {
176 fputc((f
.luma
[y
][x
] & 0xff), outfile
);
178 fputc((f
.luma
[y
][x
] & 0xff), outfile
);
180 fputc((f
.luma
[y
][x
] & 0xff), outfile
);
185 void RawReaderppm::readHeader()
187 // This works for our files, but is not generalised:
188 fscanf(infile
, "P6 %d %d %d\n", &_width
, &_height
, &_maxval
);
190 _depth
= (int)ceil(log((double)_maxval
) / log(2.0));
194 RawFrame
& RawReaderppm::read(RawFrame
&f
)
196 assert(f
.chroma
== RawFrame::CrRGB
);
202 lineLen
= f
.luma
.width() * 3 * 2;
203 unsigned char *inLine
= new unsigned char[lineLen
];
205 for (int y
= 0; y
< _height
; y
++) {
207 linesRead
= fread(inLine
, lineLen
, 1, infile
);
209 for (int in
=0, x
=0; x
< _width
; x
++, in
+=6) {
210 f
.r
[y
][x
]=inLine
[in
+0]*256 + inLine
[in
+1];
211 f
.g
[y
][x
]=inLine
[in
+2]*256 + inLine
[in
+3];
212 f
.b
[y
][x
]=inLine
[in
+4]*256 + inLine
[in
+5];
221 lineLen
= f
.luma
.width() * 3;
222 unsigned char *inLine
= new unsigned char[lineLen
];
224 for (int y
= 0; y
< _height
; y
++) {
226 linesRead
= fread(inLine
, lineLen
, 1, infile
);
228 for (int in
=0, x
=0; x
< _width
; x
++, in
+=3) {
229 f
.r
[y
][x
]=inLine
[in
];
230 f
.g
[y
][x
]=inLine
[in
+1];
231 f
.b
[y
][x
]=inLine
[in
+2];
243 RawFrame
& RawReaderppm::read()