Add facility to read frames in RGB & RGBA format
[imageviewer.git] / rawIOv210.cpp
blob01e8c8e2490182adf4b50426a235f323a253c710
1 /* ***** BEGIN LICENSE BLOCK *****
3 * $Id$
5 * The MIT License
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
25 * THE SOFTWARE.
27 * ***** END LICENSE BLOCK ***** */
29 #include <assert.h>
30 #include "rawIOv210.h"
32 typedef unsigned int uint_t;
33 typedef unsigned char uint8_t;
35 //read the first 10 bit sample from the least significant bits of the 4 bytes pointed to by 'data'
36 inline uint_t readv210sample_pos2of3(uint8_t* data)
38 const uint_t lsb = (data[2] & 0xf0) >> 4;
39 const uint_t msb = (data[3] & 0x3f) << 4;
40 return msb | lsb;
43 //read the second 10 bit sample from the middle bits of the 4 bytes pointed to by 'data'
44 inline uint_t readv210sample_pos1of3(uint8_t* data)
46 const uint_t lsb = (data[1] & 0xfc) >> 2;
47 const uint_t msb = (data[2] & 0x0f) << 6;
48 return msb | lsb;
51 //read the third 10 bit sample from the more significant bits of the 4 bytes pointed to by 'data'
52 inline uint_t readv210sample_pos0of3(uint8_t* data)
54 const uint_t lsb = (data[0] & 0xff);
55 const uint_t msb = (data[1] & 0x03) << 8;
56 return msb | lsb;
59 void unpackv210line(uint8_t *data, const int y, RawFrame &dst)
61 uint8_t* ptr;
62 int x;
64 /* unpack luma */
65 const int num_firstpass_samples_luma = (dst.luma.width()/3)*3; //actual (not padded) number of sets of 3 luma samples in line
66 ptr = data;
67 for (x = 0; x < num_firstpass_samples_luma; ptr += 8) {
68 dst.luma[y][x++] = readv210sample_pos1of3(ptr + 0);
69 dst.luma[y][x++] = readv210sample_pos0of3(ptr + 4);
70 dst.luma[y][x++] = readv210sample_pos2of3(ptr + 4);
73 if (x<dst.luma.width()) {
74 dst.luma[y][x] = readv210sample_pos1of3(ptr + 0);
75 x++;
78 if (x<dst.luma.width()) {
79 dst.luma[y][x] = readv210sample_pos0of3(ptr + 4);
82 /* unpack choma */
83 const int num_firstpass_samples_chroma = (dst.luma.width()/2/3)*3;
84 ptr = data;
85 for (x = 0; x < num_firstpass_samples_chroma; ptr += 16) {
86 dst.cb[y][x] = readv210sample_pos0of3(ptr + 0);
87 dst.cr[y][x] = readv210sample_pos2of3(ptr + 0);
88 x++;
90 dst.cb[y][x] = readv210sample_pos1of3(ptr + 4);
91 dst.cr[y][x] = readv210sample_pos0of3(ptr + 8);
92 x++;
94 dst.cb[y][x] = readv210sample_pos2of3(ptr + 8);
95 dst.cr[y][x] = readv210sample_pos1of3(ptr + 12);
96 x++;
99 if (x<dst.luma.width()/2) {
100 dst.cb[y][x] = readv210sample_pos0of3(ptr + 0);
101 dst.cr[y][x] = readv210sample_pos2of3(ptr + 0);
102 x++;
105 if (x<dst.luma.width()/2) {
106 dst.cb[y][x] = readv210sample_pos1of3(ptr + 4);
107 dst.cr[y][x] = readv210sample_pos0of3(ptr + 8);
112 RawFrame& RawReaderv210::read(RawFrame &f)
114 //there must be an even number of luma samples because v210 is 4:2:2
115 assert((f.luma.width() & 1) == 0);
116 assert(f.chroma == RawFrame::Cr422);
118 /* pad with to a multiple of 48 luma samples */
119 /* nb, 48 luma samples becomes 128 bytes */
120 const uint_t padded_w = ((f.luma.width() + 47)/48) * 48; //number of luma samples, padded
121 const uint_t padded_line_length = (2*padded_w*4) / 3; //number of bytes on each line in the file, includin padding data
123 uint8_t *data = new uint8_t[padded_line_length];
124 size_t linesRead;
126 for (int y=0; y<f.luma.height(); y++) {
128 linesRead = fread(data, padded_line_length, 1, infile);
129 if (linesRead < 1)
130 break;
131 unpackv210line(data, y, f);
134 //if (feof (infile))
135 // throw /* some eof/shortread exception */ ;
137 return f;
140 RawFrame& RawReaderv210::read()
142 throw /* unknown framesize */;
145 void RawWriterv210::write(const RawFrame& f) const
147 //default to 10 bits
148 write(f, 10);
151 void RawWriterv210::write(const RawFrame& f, const int depth) const
153 const int Yoffset = 0; //Y has no offset
154 const int shift = 10 - depth; //no shift for 10 bits, 2 bits shift for 8 bit source
155 const int UVoffset = 0;
157 int v210LineLength = (2 * f.luma.width() * 4) / 3; //there are three components in 4 bytes
158 char *outLine = (char *)calloc(v210LineLength, sizeof(char));
159 assert(f.chroma == RawFrame::Cr422);
161 for (int y = 0; y < f.luma.height(); y++) {
163 /* pack to v210 format */
164 /* do the luminance first */
165 int i=0;
166 for (int x=0; x<v210LineLength; x+=16) {
167 int pix=f.luma[y][i++];
168 pix+=Yoffset;
169 pix <<= shift;
171 outLine[x+1] = (pix << 2) & 0xFC;
172 outLine[x+2] = (pix >> 6) & 0x0F;
174 pix=f.luma[y][i++];
175 pix+=Yoffset;
176 pix <<= shift;
178 outLine[x+4] = pix & 0xFF;
179 outLine[x+5] = (pix >> 8) & 0x03;
181 pix=f.luma[y][i++];
182 pix+=Yoffset;
183 pix <<= shift;
185 outLine[x+6] = (pix << 4) & 0xF0;
186 outLine[x+7] = (pix >> 4) & 0x3F;
188 pix=f.luma[y][i++];
189 pix+=Yoffset;
190 pix <<= shift;
192 outLine[x+9] = (pix << 2) & 0xFC;
193 outLine[x+10] = (pix >> 6) & 0x0F;
195 pix=f.luma[y][i++];
196 pix+=Yoffset;
197 pix <<= shift;
199 outLine[x+12] = pix & 0xFF;
200 outLine[x+13] = (pix >> 8) & 0x03;
202 pix=f.luma[y][i++];
203 pix+=Yoffset;
204 pix <<= shift;
206 outLine[x+14] = (pix << 4) & 0xF0;
207 outLine[x+15] = (pix >> 4) & 0x3F;
210 //do the chroma
211 i=0;
212 for (int x=0; x<v210LineLength; x+=16) {
213 //Cb0
214 int pix=f.cb[y][i];
215 pix+=UVoffset;
216 pix <<= shift;
218 outLine[x] = pix & 0xFF;
219 outLine[x+1] |= (pix >> 8) & 0x03;
221 //Cr0
222 pix=f.cr[y][i++];
223 pix+=UVoffset;
224 pix <<= shift;
226 outLine[x+2] |= (pix << 4) & 0xF0;
227 outLine[x+3] = (pix >> 4) & 0x3F;
229 //Cb1
230 pix=f.cb[y][i];
231 pix+=UVoffset;
232 pix <<= shift;
234 outLine[x+5] |= (pix << 2) & 0xFC;
235 outLine[x+6] |= (pix >> 6) & 0x0F;
237 //Cr1
238 pix=f.cr[y][i++];
239 pix+=UVoffset;
240 pix <<= shift;
242 outLine[x+8] = pix & 0xFF;
243 outLine[x+9] |= (pix >> 8) & 0x03;
245 //Cb2
246 pix=f.cb[y][i];
247 pix+=UVoffset;
248 pix <<= shift;
250 outLine[x+10] |= (pix << 4) & 0xF0;
251 outLine[x+11] = (pix >> 4) & 0x3F;
253 //Cr2
254 pix=f.cr[y][i++];
255 pix+=UVoffset;
256 pix <<= shift;
258 outLine[x+13] |= (pix << 2) & 0xFC;
259 outLine[x+14] |= (pix >> 6) & 0x0F;
262 /* write line out */
263 fwrite(outLine, v210LineLength, 1, outfile);
266 free(outLine);