1 /* === S I N F G =========================================================== */
3 ** \brief Template File
5 ** $Id: trgt_yuv.cpp,v 1.1.1.1 2005/01/04 01:23:14 darco Exp $
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
10 ** This software and associated documentation
11 ** are CONFIDENTIAL and PROPRIETARY property of
12 ** the above-mentioned copyright holder.
14 ** You may not copy, print, publish, or in any
15 ** other way distribute this software without
16 ** a prior written agreement with
17 ** the copyright holder.
20 /* ========================================================================= */
22 /* === H E A D E R S ======================================================= */
34 #include <ETL/stringf>
40 using namespace sinfg;
44 /* === M A C R O S ========================================================= */
48 #define Y_RANGE (Y_CEIL-Y_FLOOR)
52 #define UV_RANGE (UV_CEIL-UV_FLOOR)
54 /* === G L O B A L S ======================================================= */
56 SINFG_TARGET_INIT(yuv);
57 SINFG_TARGET_SET_NAME(yuv,"yuv420p");
58 SINFG_TARGET_SET_EXT(yuv,"yuv");
59 SINFG_TARGET_SET_VERSION(yuv,"0.1");
60 SINFG_TARGET_SET_CVS_ID(yuv,"$Id: trgt_yuv.cpp,v 1.1.1.1 2005/01/04 01:23:14 darco Exp $");
62 /* === M E T H O D S ======================================================= */
64 yuv::yuv(const char *FILENAME):
66 file( (filename=="-")?stdout:fopen(filename.c_str(),"wb") ),
69 // YUV420P doesn't have an alpha channel
78 yuv::set_rend_desc(RendDesc *given_desc)
80 given_desc->clear_flags();
82 // Make sure our width is divisible by two
83 given_desc->set_w(given_desc->get_w()*2/2);
84 given_desc->set_h(given_desc->get_h()*2/2);
89 surface.set_wh(desc.get_w(),desc.get_h());
95 yuv::start_frame(sinfg::ProgressCallback *callback)
97 return static_cast<bool>(file);
101 yuv::start_scanline(int x)
109 return static_cast<bool>(file);
115 const int w=desc.get_w(),h=desc.get_h();
120 // Output Y' channel, adjusting
121 // the gamma as we go
125 Color& c(surface[y][x]);
127 c.set_r(gamma().r_F32_to_F32(c.get_r()));
128 c.set_g(gamma().g_F32_to_F32(c.get_g()));
129 c.set_b(gamma().b_F32_to_F32(c.get_b()));
131 int i(max(min(round_to_int(c.get_y()*Y_RANGE),Y_RANGE),0)+Y_FLOOR);
135 const float er(f-((float)i-Y_FLOOR)/Y_RANGE);
136 const Color error(er,er,er);
138 if(surface.get_h()>y+1)
140 surface[y+1][x-1]+=error * ((float)3/(float)16);
141 surface[y+1][x]+=error * ((float)5/(float)16);
142 if(surface.get_w()>x+1)
143 surface[y+1][x+1]+=error * ((float)1/(float)16);
145 if(surface.get_w()>x+1)
146 surface[y][x+1]+=error * ((float)7/(float)16);
153 // Create new super-sampled surface
154 Surface sm_surface(w/2,h/2);
158 Color c(Color::alpha());
162 c+=surface[y+1][x+1];
164 sm_surface[y/2][x/2]=c;
168 for(y=0;y<sm_surface.get_h();y++)
169 for(x=0;x<sm_surface.get_w();x++)
171 const Color& c(sm_surface[y][x]);
172 const float f(c.get_u());
173 const int i(max(min(round_to_int((f+0.5f)*UV_RANGE),UV_RANGE),0)+UV_FLOOR);
177 const float er(f-((((float)i-UV_FLOOR)/UV_RANGE)-0.5f));
178 const Color error(Color::YUV(0,er,0));
180 if(sm_surface.get_h()>y+1)
182 sm_surface[y+1][x-1]+=error * ((float)3/(float)16);
183 sm_surface[y+1][x]+=error * ((float)5/(float)16);
184 if(sm_surface.get_w()>x+1)
185 sm_surface[y+1][x+1]+=error * ((float)1/(float)16);
187 if(sm_surface.get_w()>x+1)
188 sm_surface[y][x+1]+=error * ((float)7/(float)16);
194 for(y=0;y<sm_surface.get_h();y++)
195 for(x=0;x<sm_surface.get_w();x++)
197 const Color& c(sm_surface[y][x]);
198 const float f(c.get_v());
199 const int i(max(min(round_to_int((f+0.5f)*UV_RANGE),UV_RANGE),0)+UV_FLOOR);
203 const float er(f-((((float)i-UV_FLOOR)/UV_RANGE)-0.5f));
204 const Color error(Color::YUV(0,0,er));
206 if(sm_surface.get_h()>y+1)
208 sm_surface[y+1][x-1]+=error * ((float)3/(float)16);
209 sm_surface[y+1][x]+=error * ((float)5/(float)16);
210 if(sm_surface.get_w()>x+1)
211 sm_surface[y+1][x+1]+=error * ((float)1/(float)16);
213 if(sm_surface.get_w()>x+1)
214 sm_surface[y][x+1]+=error * ((float)7/(float)16);
219 // Flush out the frame