head 1.425; access; symbols; locks; strict; comment @ * @; 1.425 date 2009.06.19.21.38.38; author dcoffin; state Exp; branches; next 1.424; 1.424 date 2009.06.09.05.43.45; author dcoffin; state Exp; branches; next 1.423; 1.423 date 2009.05.15.03.35.39; author dcoffin; state Exp; branches; next 1.422; 1.422 date 2009.05.14.19.59.33; author dcoffin; state Exp; branches; next 1.421; 1.421 date 2009.03.10.00.53.36; author dcoffin; state Exp; branches; next 1.420; 1.420 date 2009.03.03.18.58.23; author dcoffin; state Exp; branches; next 1.419; 1.419 date 2009.02.12.18.25.44; author dcoffin; state Exp; branches; next 1.418; 1.418 date 2009.02.03.04.42.52; author dcoffin; state Exp; branches; next 1.417; 1.417 date 2009.01.21.01.19.45; author dcoffin; state Exp; branches; next 1.416; 1.416 date 2009.01.15.22.10.18; author dcoffin; state Exp; branches; next 1.415; 1.415 date 2009.01.14.17.46.50; author dcoffin; state Exp; branches; next 1.414; 1.414 date 2009.01.14.03.23.23; author dcoffin; state Exp; branches; next 1.413; 1.413 date 2009.01.10.23.37.51; author dcoffin; state Exp; branches; next 1.412; 1.412 date 2009.01.08.19.39.07; author dcoffin; state Exp; branches; next 1.411; 1.411 date 2009.01.04.20.19.22; author dcoffin; state Exp; branches; next 1.410; 1.410 date 2009.01.01.09.10.46; author dcoffin; state Exp; branches; next 1.409; 1.409 date 2008.12.11.06.56.09; author dcoffin; state Exp; branches; next 1.408; 1.408 date 2008.12.06.23.35.55; author dcoffin; state Exp; branches; next 1.407; 1.407 date 2008.12.02.01.50.56; author dcoffin; state Exp; branches; next 1.406; 1.406 date 2008.11.26.08.39.39; author dcoffin; state Exp; branches; next 1.405; 1.405 date 2008.09.15.22.29.19; author dcoffin; state Exp; branches; next 1.404; 1.404 date 2008.08.12.19.39.17; author dcoffin; state Exp; branches; next 1.403; 1.403 date 2008.04.29.18.18.53; author dcoffin; state Exp; branches; next 1.402; 1.402 date 2008.04.20.08.09.37; author dcoffin; state Exp; branches; next 1.401; 1.401 date 2008.04.07.19.25.08; author dcoffin; state Exp; branches; next 1.400; 1.400 date 2008.04.06.01.18.43; author dcoffin; state Exp; branches; next 1.399; 1.399 date 2008.03.05.01.29.34; author dcoffin; state Exp; branches; next 1.398; 1.398 date 2008.02.06.21.29.13; author dcoffin; state Exp; branches; next 1.397; 1.397 date 2007.12.10.07.43.31; author dcoffin; state Exp; branches; next 1.396; 1.396 date 2007.11.16.15.24.52; author dcoffin; state Exp; branches; next 1.395; 1.395 date 2007.11.12.20.28.32; author dcoffin; state Exp; branches; next 1.394; 1.394 date 2007.11.04.02.18.54; author dcoffin; state Exp; branches; next 1.393; 1.393 date 2007.10.30.06.23.29; author dcoffin; state Exp; branches; next 1.392; 1.392 date 2007.08.10.21.09.34; author dcoffin; state Exp; branches; next 1.391; 1.391 date 2007.08.08.21.28.17; author dcoffin; state Exp; branches; next 1.390; 1.390 date 2007.08.01.17.39.28; author dcoffin; state Exp; branches; next 1.389; 1.389 date 2007.07.28.23.39.53; author dcoffin; state Exp; branches; next 1.388; 1.388 date 2007.07.23.06.52.52; author dcoffin; state Exp; branches; next 1.387; 1.387 date 2007.06.24.00.18.52; author dcoffin; state Exp; branches; next 1.386; 1.386 date 2007.06.13.22.42.15; author dcoffin; state Exp; branches; next 1.385; 1.385 date 2007.06.13.06.40.04; author dcoffin; state Exp; branches; next 1.384; 1.384 date 2007.06.08.21.29.34; author dcoffin; state Exp; branches; next 1.383; 1.383 date 2007.06.04.01.19.23; author dcoffin; state Exp; branches; next 1.382; 1.382 date 2007.06.02.04.18.22; author dcoffin; state Exp; branches; next 1.381; 1.381 date 2007.05.09.17.19.29; author dcoffin; state Exp; branches; next 1.380; 1.380 date 2007.05.06.23.05.56; author dcoffin; state Exp; branches; next 1.379; 1.379 date 2007.05.03.06.15.16; author dcoffin; state Exp; branches; next 1.378; 1.378 date 2007.04.29.19.01.29; author dcoffin; state Exp; branches; next 1.377; 1.377 date 2007.03.25.22.56.19; author dcoffin; state Exp; branches; next 1.376; 1.376 date 2007.03.19.21.09.00; author dcoffin; state Exp; branches; next 1.375; 1.375 date 2007.03.17.05.18.22; author dcoffin; state Exp; branches; next 1.374; 1.374 date 2007.03.15.05.19.10; author dcoffin; state Exp; branches; next 1.373; 1.373 date 2007.03.14.20.30.19; author dcoffin; state Exp; branches; next 1.372; 1.372 date 2007.03.13.05.04.22; author dcoffin; state Exp; branches; next 1.371; 1.371 date 2007.03.07.23.37.58; author dcoffin; state Exp; branches; next 1.370; 1.370 date 2007.03.02.17.40.15; author dcoffin; state Exp; branches; next 1.369; 1.369 date 2007.02.27.02.11.06; author dcoffin; state Exp; branches; next 1.368; 1.368 date 2007.02.25.03.09.54; author dcoffin; state Exp; branches; next 1.367; 1.367 date 2007.02.24.22.10.59; author dcoffin; state Exp; branches; next 1.366; 1.366 date 2007.02.22.16.50.08; author dcoffin; state Exp; branches; next 1.365; 1.365 date 2007.02.12.22.55.47; author dcoffin; state Exp; branches; next 1.364; 1.364 date 2007.01.21.00.41.17; author dcoffin; state Exp; branches; next 1.363; 1.363 date 2007.01.18.23.57.32; author dcoffin; state Exp; branches; next 1.362; 1.362 date 2007.01.09.02.06.51; author dcoffin; state Exp; branches; next 1.361; 1.361 date 2007.01.02.03.51.27; author dcoffin; state Exp; branches; next 1.360; 1.360 date 2006.12.22.03.56.43; author dcoffin; state Exp; branches; next 1.359; 1.359 date 2006.12.14.15.40.47; author dcoffin; state Exp; branches; next 1.358; 1.358 date 2006.12.04.03.10.46; author dcoffin; state Exp; branches; next 1.357; 1.357 date 2006.11.28.04.18.50; author dcoffin; state Exp; branches; next 1.356; 1.356 date 2006.11.21.16.32.10; author dcoffin; state Exp; branches; next 1.355; 1.355 date 2006.11.04.15.55.41; author dcoffin; state Exp; branches; next 1.354; 1.354 date 2006.10.25.22.35.03; author dcoffin; state Exp; branches; next 1.353; 1.353 date 2006.10.10.04.46.02; author dcoffin; state Exp; branches; next 1.352; 1.352 date 2006.10.06.16.35.50; author dcoffin; state Exp; branches; next 1.351; 1.351 date 2006.09.22.04.59.09; author dcoffin; state Exp; branches; next 1.350; 1.350 date 2006.09.19.20.50.11; author dcoffin; state Exp; branches; next 1.349; 1.349 date 2006.09.12.08.38.59; author dcoffin; state Exp; branches; next 1.348; 1.348 date 2006.09.08.14.52.39; author dcoffin; state Exp; branches; next 1.347; 1.347 date 2006.09.06.18.44.58; author dcoffin; state Exp; branches; next 1.346; 1.346 date 2006.09.03.16.37.49; author dcoffin; state Exp; branches; next 1.345; 1.345 date 2006.09.02.14.56.28; author dcoffin; state Exp; branches; next 1.344; 1.344 date 2006.08.31.18.43.44; author dcoffin; state Exp; branches; next 1.343; 1.343 date 2006.08.24.20.24.51; author dcoffin; state Exp; branches; next 1.342; 1.342 date 2006.08.20.05.14.23; author dcoffin; state Exp; branches; next 1.341; 1.341 date 2006.08.18.02.52.47; author dcoffin; state Exp; branches; next 1.340; 1.340 date 2006.08.08.15.06.13; author dcoffin; state Exp; branches; next 1.339; 1.339 date 2006.08.06.20.28.43; author dcoffin; state Exp; branches; next 1.338; 1.338 date 2006.07.31.21.34.50; author dcoffin; state Exp; branches; next 1.337; 1.337 date 2006.07.30.19.52.37; author dcoffin; state Exp; branches; next 1.336; 1.336 date 2006.07.27.20.04.06; author dcoffin; state Exp; branches; next 1.335; 1.335 date 2006.07.26.18.02.50; author dcoffin; state Exp; branches; next 1.334; 1.334 date 2006.07.21.14.48.23; author dcoffin; state Exp; branches; next 1.333; 1.333 date 2006.07.18.06.30.03; author dcoffin; state Exp; branches; next 1.332; 1.332 date 2006.06.23.07.36.10; author dcoffin; state Exp; branches; next 1.331; 1.331 date 2006.06.21.20.00.07; author dcoffin; state Exp; branches; next 1.330; 1.330 date 2006.05.29.18.54.35; author dcoffin; state Exp; branches; next 1.329; 1.329 date 2006.05.28.05.07.49; author dcoffin; state Exp; branches; next 1.328; 1.328 date 2006.05.21.20.04.39; author dcoffin; state Exp; branches; next 1.327; 1.327 date 2006.05.21.19.44.03; author dcoffin; state Exp; branches; next 1.326; 1.326 date 2006.05.18.06.34.26; author dcoffin; state Exp; branches; next 1.325; 1.325 date 2006.05.14.05.08.10; author dcoffin; state Exp; branches; next 1.324; 1.324 date 2006.05.04.22.45.45; author dcoffin; state Exp; branches; next 1.323; 1.323 date 2006.04.09.02.40.56; author dcoffin; state Exp; branches; next 1.322; 1.322 date 2006.04.06.18.51.37; author dcoffin; state Exp; branches; next 1.321; 1.321 date 2006.03.31.21.54.29; author dcoffin; state Exp; branches; next 1.320; 1.320 date 2006.03.29.02.44.05; author dcoffin; state Exp; branches; next 1.319; 1.319 date 2006.03.24.07.03.04; author dcoffin; state Exp; branches; next 1.318; 1.318 date 2006.03.21.20.47.06; author dcoffin; state Exp; branches; next 1.317; 1.317 date 2006.03.21.02.28.23; author dcoffin; state Exp; branches; next 1.316; 1.316 date 2006.03.20.21.50.28; author dcoffin; state Exp; branches; next 1.315; 1.315 date 2006.02.09.05.23.08; author dcoffin; state Exp; branches; next 1.314; 1.314 date 2006.02.07.06.56.51; author dcoffin; state Exp; branches; next 1.313; 1.313 date 2006.01.24.16.51.53; author dcoffin; state Exp; branches; next 1.312; 1.312 date 2006.01.24.08.47.38; author dcoffin; state Exp; branches; next 1.311; 1.311 date 2006.01.23.09.31.52; author dcoffin; state Exp; branches; next 1.310; 1.310 date 2006.01.21.10.41.56; author dcoffin; state Exp; branches; next 1.309; 1.309 date 2005.12.18.21.02.19; author dcoffin; state Exp; branches; next 1.308; 1.308 date 2005.12.11.01.07.33; author dcoffin; state Exp; branches; next 1.307; 1.307 date 2005.12.09.03.05.18; author dcoffin; state Exp; branches; next 1.306; 1.306 date 2005.12.08.01.42.17; author dcoffin; state Exp; branches; next 1.305; 1.305 date 2005.12.06.08.18.35; author dcoffin; state Exp; branches; next 1.304; 1.304 date 2005.11.29.18.59.01; author dcoffin; state Exp; branches; next 1.303; 1.303 date 2005.11.29.08.36.52; author dcoffin; state Exp; branches; next 1.302; 1.302 date 2005.11.24.01.42.35; author dcoffin; state Exp; branches; next 1.301; 1.301 date 2005.11.23.08.07.55; author dcoffin; state Exp; branches; next 1.300; 1.300 date 2005.11.13.01.46.57; author dcoffin; state Exp; branches; next 1.299; 1.299 date 2005.11.12.01.20.27; author dcoffin; state Exp; branches; next 1.298; 1.298 date 2005.11.11.01.39.54; author dcoffin; state Exp; branches; next 1.297; 1.297 date 2005.11.06.04.17.59; author dcoffin; state Exp; branches; next 1.296; 1.296 date 2005.11.04.07.11.14; author dcoffin; state Exp; branches; next 1.295; 1.295 date 2005.10.26.22.36.53; author dcoffin; state Exp; branches; next 1.294; 1.294 date 2005.10.26.07.22.16; author dcoffin; state Exp; branches; next 1.293; 1.293 date 2005.10.21.02.01.00; author dcoffin; state Exp; branches; next 1.292; 1.292 date 2005.10.19.21.55.29; author dcoffin; state Exp; branches; next 1.291; 1.291 date 2005.10.18.07.43.44; author dcoffin; state Exp; branches; next 1.290; 1.290 date 2005.10.12.03.50.10; author dcoffin; state Exp; branches; next 1.289; 1.289 date 2005.10.08.04.03.17; author dcoffin; state Exp; branches; next 1.288; 1.288 date 2005.10.03.05.31.46; author dcoffin; state Exp; branches; next 1.287; 1.287 date 2005.10.01.04.55.11; author dcoffin; state Exp; branches; next 1.286; 1.286 date 2005.09.25.22.26.03; author dcoffin; state Exp; branches; next 1.285; 1.285 date 2005.09.13.01.03.22; author dcoffin; state Exp; branches; next 1.284; 1.284 date 2005.09.08.04.31.20; author dcoffin; state Exp; branches; next 1.283; 1.283 date 2005.09.07.06.01.08; author dcoffin; state Exp; branches; next 1.282; 1.282 date 2005.09.06.19.17.07; author dcoffin; state Exp; branches; next 1.281; 1.281 date 2005.09.01.00.29.22; author dcoffin; state Exp; branches; next 1.280; 1.280 date 2005.08.30.22.53.17; author dcoffin; state Exp; branches; next 1.279; 1.279 date 2005.08.25.05.59.23; author dcoffin; state Exp; branches; next 1.278; 1.278 date 2005.08.24.20.02.34; author dcoffin; state Exp; branches; next 1.277; 1.277 date 2005.08.22.06.13.13; author dcoffin; state Exp; branches; next 1.276; 1.276 date 2005.08.16.08.48.10; author dcoffin; state Exp; branches; next 1.275; 1.275 date 2005.08.12.21.03.34; author dcoffin; state Exp; branches; next 1.274; 1.274 date 2005.08.06.01.04.30; author dcoffin; state Exp; branches; next 1.273; 1.273 date 2005.08.01.06.28.03; author dcoffin; state Exp; branches; next 1.272; 1.272 date 2005.07.31.02.51.11; author dcoffin; state Exp; branches; next 1.271; 1.271 date 2005.07.29.04.06.08; author dcoffin; state Exp; branches; next 1.270; 1.270 date 2005.07.20.22.41.33; author dcoffin; state Exp; branches; next 1.269; 1.269 date 2005.07.14.02.13.45; author dcoffin; state Exp; branches; next 1.268; 1.268 date 2005.07.13.07.25.45; author dcoffin; state Exp; branches; next 1.267; 1.267 date 2005.07.07.03.40.57; author dcoffin; state Exp; branches; next 1.266; 1.266 date 2005.07.06.05.44.34; author dcoffin; state Exp; branches; next 1.265; 1.265 date 2005.06.27.20.22.12; author dcoffin; state Exp; branches; next 1.264; 1.264 date 2005.06.27.05.12.08; author dcoffin; state Exp; branches; next 1.263; 1.263 date 2005.06.06.05.32.07; author dcoffin; state Exp; branches; next 1.262; 1.262 date 2005.05.27.01.39.38; author dcoffin; state Exp; branches; next 1.261; 1.261 date 2005.05.21.01.54.47; author dcoffin; state Exp; branches; next 1.260; 1.260 date 2005.05.20.06.18.43; author dcoffin; state Exp; branches; next 1.259; 1.259 date 2005.05.10.20.57.07; author dcoffin; state Exp; branches; next 1.258; 1.258 date 2005.05.05.06.35.59; author dcoffin; state Exp; branches; next 1.257; 1.257 date 2005.05.03.18.50.30; author dcoffin; state Exp; branches; next 1.256; 1.256 date 2005.05.03.04.16.09; author dcoffin; state Exp; branches; next 1.255; 1.255 date 2005.04.29.16.38.16; author dcoffin; state Exp; branches; next 1.254; 1.254 date 2005.04.27.20.10.40; author dcoffin; state Exp; branches; next 1.253; 1.253 date 2005.04.26.00.46.33; author dcoffin; state Exp; branches; next 1.252; 1.252 date 2005.04.22.16.03.53; author dcoffin; state Exp; branches; next 1.251; 1.251 date 2005.04.19.16.00.41; author dcoffin; state Exp; branches; next 1.250; 1.250 date 2005.04.18.03.18.57; author dcoffin; state Exp; branches; next 1.249; 1.249 date 2005.04.05.07.21.29; author dcoffin; state Exp; branches; next 1.248; 1.248 date 2005.03.31.19.42.59; author dcoffin; state Exp; branches; next 1.247; 1.247 date 2005.03.29.06.33.18; author dcoffin; state Exp; branches; next 1.246; 1.246 date 2005.03.28.19.32.13; author dcoffin; state Exp; branches; next 1.245; 1.245 date 2005.03.28.04.56.02; author dcoffin; state Exp; branches; next 1.244; 1.244 date 2005.03.25.19.39.58; author dcoffin; state Exp; branches; next 1.243; 1.243 date 2005.03.23.23.00.33; author dcoffin; state Exp; branches; next 1.242; 1.242 date 2005.03.23.17.52.43; author dcoffin; state Exp; branches; next 1.241; 1.241 date 2005.03.19.01.40.04; author dcoffin; state Exp; branches; next 1.240; 1.240 date 2005.03.18.22.15.37; author dcoffin; state Exp; branches; next 1.239; 1.239 date 2005.03.11.18.47.13; author dcoffin; state Exp; branches; next 1.238; 1.238 date 2005.03.11.00.50.22; author dcoffin; state Exp; branches; next 1.237; 1.237 date 2005.03.10.03.48.40; author dcoffin; state Exp; branches; next 1.236; 1.236 date 2005.02.27.03.26.37; author dcoffin; state Exp; branches; next 1.235; 1.235 date 2005.02.16.06.11.39; author dcoffin; state Exp; branches; next 1.234; 1.234 date 2005.02.02.22.29.22; author dcoffin; state Exp; branches; next 1.233; 1.233 date 2005.01.25.20.31.18; author dcoffin; state Exp; branches; next 1.232; 1.232 date 2005.01.25.17.31.10; author dcoffin; state Exp; branches; next 1.231; 1.231 date 2005.01.25.02.29.44; author dcoffin; state Exp; branches; next 1.230; 1.230 date 2005.01.24.05.43.59; author dcoffin; state Exp; branches; next 1.229; 1.229 date 2005.01.21.06.48.13; author dcoffin; state Exp; branches; next 1.228; 1.228 date 2005.01.19.08.50.44; author dcoffin; state Exp; branches; next 1.227; 1.227 date 2005.01.14.00.01.30; author dcoffin; state Exp; branches; next 1.226; 1.226 date 2005.01.10.07.04.46; author dcoffin; state Exp; branches; next 1.225; 1.225 date 2005.01.08.05.26.49; author dcoffin; state Exp; branches; next 1.224; 1.224 date 2005.01.04.23.08.52; author dcoffin; state Exp; branches; next 1.223; 1.223 date 2004.12.31.09.07.44; author dcoffin; state Exp; branches; next 1.222; 1.222 date 2004.12.22.20.48.54; author dcoffin; state Exp; branches; next 1.221; 1.221 date 2004.12.17.07.31.32; author dcoffin; state Exp; branches; next 1.220; 1.220 date 2004.12.08.23.50.03; author dcoffin; state Exp; branches; next 1.219; 1.219 date 2004.12.04.05.42.44; author dcoffin; state Exp; branches; next 1.218; 1.218 date 2004.12.01.21.54.52; author dcoffin; state Exp; branches; next 1.217; 1.217 date 2004.11.28.02.27.04; author dcoffin; state Exp; branches; next 1.216; 1.216 date 2004.11.22.02.34.41; author dcoffin; state Exp; branches; next 1.215; 1.215 date 2004.11.05.06.48.50; author dcoffin; state Exp; branches; next 1.214; 1.214 date 2004.10.26.02.28.46; author dcoffin; state Exp; branches; next 1.213; 1.213 date 2004.10.24.23.27.22; author dcoffin; state Exp; branches; next 1.212; 1.212 date 2004.10.23.04.40.54; author dcoffin; state Exp; branches; next 1.211; 1.211 date 2004.10.13.01.13.53; author dcoffin; state Exp; branches; next 1.210; 1.210 date 2004.10.08.02.34.46; author dcoffin; state Exp; branches; next 1.209; 1.209 date 2004.10.07.01.11.51; author dcoffin; state Exp; branches; next 1.208; 1.208 date 2004.10.04.20.33.44; author dcoffin; state Exp; branches; next 1.207; 1.207 date 2004.10.02.21.59.44; author dcoffin; state Exp; branches; next 1.206; 1.206 date 2004.09.19.05.00.32; author dcoffin; state Exp; branches; next 1.205; 1.205 date 2004.09.16.20.29.15; author dcoffin; state Exp; branches; next 1.204; 1.204 date 2004.09.14.00.35.12; author dcoffin; state Exp; branches; next 1.203; 1.203 date 2004.09.07.17.25.15; author dcoffin; state Exp; branches; next 1.202; 1.202 date 2004.09.06.05.50.09; author dcoffin; state Exp; branches; next 1.201; 1.201 date 2004.09.01.21.28.04; author dcoffin; state Exp; branches; next 1.200; 1.200 date 2004.08.04.18.40.25; author dcoffin; state Exp; branches; next 1.199; 1.199 date 2004.07.28.04.25.31; author dcoffin; state Exp; branches; next 1.198; 1.198 date 2004.07.06.18.36.13; author dcoffin; state Exp; branches; next 1.197; 1.197 date 2004.06.29.22.56.42; author dcoffin; state Exp; branches; next 1.196; 1.196 date 2004.06.29.02.23.39; author dcoffin; state Exp; branches; next 1.195; 1.195 date 2004.06.16.17.19.36; author dcoffin; state Exp; branches; next 1.194; 1.194 date 2004.05.22.15.41.31; author dcoffin; state Exp; branches; next 1.193; 1.193 date 2004.05.14.21.26.40; author dcoffin; state Exp; branches; next 1.192; 1.192 date 2004.05.11.19.09.02; author dcoffin; state Exp; branches; next 1.191; 1.191 date 2004.05.11.04.38.40; author dcoffin; state Exp; branches; next 1.190; 1.190 date 2004.05.05.17.20.10; author dcoffin; state Exp; branches; next 1.189; 1.189 date 2004.05.02.19.14.54; author dcoffin; state Exp; branches; next 1.188; 1.188 date 2004.04.29.19.11.08; author dcoffin; state Exp; branches; next 1.187; 1.187 date 2004.04.28.14.35.07; author dcoffin; state Exp; branches; next 1.186; 1.186 date 2004.04.25.20.19.33; author dcoffin; state Exp; branches; next 1.185; 1.185 date 2004.04.25.04.54.14; author dcoffin; state Exp; branches; next 1.184; 1.184 date 2004.04.22.16.53.47; author dcoffin; state Exp; branches; next 1.183; 1.183 date 2004.04.22.01.01.56; author dcoffin; state Exp; branches; next 1.182; 1.182 date 2004.04.19.22.58.46; author dcoffin; state Exp; branches; next 1.181; 1.181 date 2004.04.14.19.19.12; author dcoffin; state Exp; branches; next 1.180; 1.180 date 2004.04.01.18.17.04; author dcoffin; state Exp; branches; next 1.179; 1.179 date 2004.03.29.19.53.10; author dcoffin; state Exp; branches 1.179.1.1; next 1.178; 1.178 date 2004.03.07.02.06.59; author dcoffin; state Exp; branches; next 1.177; 1.177 date 2004.03.05.17.25.30; author dcoffin; state Exp; branches; next 1.176; 1.176 date 2004.03.01.15.17.47; author dcoffin; state Exp; branches; next 1.175; 1.175 date 2004.02.24.04.56.12; author dcoffin; state Exp; branches; next 1.174; 1.174 date 2004.02.23.00.18.33; author dcoffin; state Exp; branches; next 1.173; 1.173 date 2004.02.22.19.28.03; author dcoffin; state Exp; branches; next 1.172; 1.172 date 2004.02.22.04.02.44; author dcoffin; state Exp; branches; next 1.171; 1.171 date 2004.02.21.23.35.56; author dcoffin; state Exp; branches; next 1.170; 1.170 date 2004.02.20.18.37.17; author dcoffin; state Exp; branches; next 1.169; 1.169 date 2004.02.20.04.22.08; author dcoffin; state Exp; branches; next 1.168; 1.168 date 2004.02.18.20.29.52; author dcoffin; state Exp; branches; next 1.167; 1.167 date 2004.02.16.01.01.44; author dcoffin; state Exp; branches; next 1.166; 1.166 date 2004.02.13.16.29.33; author dcoffin; state Exp; branches; next 1.165; 1.165 date 2004.02.13.14.20.06; author dcoffin; state Exp; branches; next 1.164; 1.164 date 2004.02.12.03.44.30; author dcoffin; state Exp; branches; next 1.163; 1.163 date 2004.02.10.18.29.09; author dcoffin; state Exp; branches; next 1.162; 1.162 date 2004.02.07.13.36.34; author dcoffin; state Exp; branches; next 1.161; 1.161 date 2004.01.04.09.21.49; author dcoffin; state Exp; branches; next 1.160; 1.160 date 2004.01.04.08.09.05; author dcoffin; state Exp; branches; next 1.159; 1.159 date 2003.12.24.18.29.49; author dcoffin; state Exp; branches; next 1.158; 1.158 date 2003.12.23.04.30.39; author dcoffin; state Exp; branches; next 1.157; 1.157 date 2003.12.19.05.07.31; author dcoffin; state Exp; branches; next 1.156; 1.156 date 2003.12.17.05.08.01; author dcoffin; state Exp; branches; next 1.155; 1.155 date 2003.12.09.20.35.40; author dcoffin; state Exp; branches; next 1.154; 1.154 date 2003.12.08.07.09.16; author dcoffin; state Exp; branches; next 1.153; 1.153 date 2003.12.04.01.23.06; author dcoffin; state Exp; branches; next 1.152; 1.152 date 2003.11.25.02.25.27; author dcoffin; state Exp; branches; next 1.151; 1.151 date 2003.11.16.08.39.38; author dcoffin; state Exp; branches; next 1.150; 1.150 date 2003.11.14.23.42.33; author dcoffin; state Exp; branches; next 1.149; 1.149 date 2003.11.14.15.53.47; author dcoffin; state Exp; branches; next 1.148; 1.148 date 2003.11.09.00.44.50; author dcoffin; state Exp; branches; next 1.147; 1.147 date 2003.11.06.00.58.27; author dcoffin; state Exp; branches; next 1.146; 1.146 date 2003.11.05.18.10.17; author dcoffin; state Exp; branches; next 1.145; 1.145 date 2003.10.28.00.20.01; author dcoffin; state Exp; branches; next 1.144; 1.144 date 2003.10.20.18.35.01; author dcoffin; state Exp; branches; next 1.143; 1.143 date 2003.10.16.19.38.02; author dcoffin; state Exp; branches; next 1.142; 1.142 date 2003.10.14.20.36.32; author dcoffin; state Exp; branches; next 1.141; 1.141 date 2003.10.14.01.16.41; author dcoffin; state Exp; branches; next 1.140; 1.140 date 2003.10.13.21.21.00; author dcoffin; state Exp; branches; next 1.139; 1.139 date 2003.10.07.07.27.24; author dcoffin; state Exp; branches; next 1.138; 1.138 date 2003.10.04.19.17.37; author dcoffin; state Exp; branches; next 1.137; 1.137 date 2003.10.01.21.59.51; author dcoffin; state Exp; branches; next 1.136; 1.136 date 2003.09.23.00.38.14; author dcoffin; state Exp; branches; next 1.135; 1.135 date 2003.09.21.19.31.42; author dcoffin; state Exp; branches; next 1.134; 1.134 date 2003.09.20.01.51.39; author dcoffin; state Exp; branches; next 1.133; 1.133 date 2003.09.19.04.02.26; author dcoffin; state Exp; branches; next 1.132; 1.132 date 2003.09.18.02.21.21; author dcoffin; state Exp; branches; next 1.131; 1.131 date 2003.09.17.18.33.30; author dcoffin; state Exp; branches; next 1.130; 1.130 date 2003.09.15.03.12.54; author dcoffin; state Exp; branches; next 1.129; 1.129 date 2003.09.11.20.35.53; author dcoffin; state Exp; branches; next 1.128; 1.128 date 2003.07.17.19.06.11; author dcoffin; state Exp; branches; next 1.127; 1.127 date 2003.07.03.02.53.00; author dcoffin; state Exp; branches; next 1.126; 1.126 date 2003.07.02.04.36.23; author dcoffin; state Exp; branches; next 1.125; 1.125 date 2003.06.27.17.12.37; author dcoffin; state Exp; branches; next 1.124; 1.124 date 2003.06.24.15.07.14; author dcoffin; state Exp; branches; next 1.123; 1.123 date 2003.06.22.17.01.02; author dcoffin; state Exp; branches; next 1.122; 1.122 date 2003.06.21.02.06.35; author dcoffin; state Exp; branches; next 1.121; 1.121 date 2003.06.21.00.16.57; author dcoffin; state Exp; branches; next 1.120; 1.120 date 2003.06.12.23.13.36; author dcoffin; state Exp; branches; next 1.119; 1.119 date 2003.06.06.16.25.41; author dcoffin; state Exp; branches; next 1.118; 1.118 date 2003.06.06.15.45.57; author dcoffin; state Exp; branches; next 1.117; 1.117 date 2003.06.03.19.06.14; author dcoffin; state Exp; branches; next 1.116; 1.116 date 2003.06.02.14.49.38; author dcoffin; state Exp; branches; next 1.115; 1.115 date 2003.05.30.03.42.18; author dcoffin; state Exp; branches; next 1.114; 1.114 date 2003.05.30.02.19.44; author dcoffin; state Exp; branches; next 1.113; 1.113 date 2003.05.29.22.34.18; author dcoffin; state Exp; branches; next 1.112; 1.112 date 2003.05.28.14.10.08; author dcoffin; state Exp; branches; next 1.111; 1.111 date 2003.05.27.18.17.16; author dcoffin; state Exp; branches; next 1.110; 1.110 date 2003.04.25.17.48.05; author dcoffin; state Exp; branches; next 1.109; 1.109 date 2003.04.25.00.46.29; author dcoffin; state Exp; branches; next 1.108; 1.108 date 2003.04.12.15.31.58; author dcoffin; state Exp; branches; next 1.107; 1.107 date 2003.03.29.23.22.37; author dcoffin; state Exp; branches; next 1.106; 1.106 date 2003.03.23.02.49.33; author dcoffin; state Exp; branches; next 1.105; 1.105 date 2003.03.17.19.34.10; author dcoffin; state Exp; branches; next 1.104; 1.104 date 2003.03.14.16.43.26; author dcoffin; state Exp; branches; next 1.103; 1.103 date 2003.03.12.05.22.20; author dcoffin; state Exp; branches; next 1.102; 1.102 date 2003.03.08.02.28.12; author dcoffin; state Exp; branches; next 1.101; 1.101 date 2003.03.07.00.58.29; author dcoffin; state Exp; branches; next 1.100; 1.100 date 2003.02.25.00.41.11; author dcoffin; state Exp; branches; next 1.99; 1.99 date 2003.02.23.16.34.58; author dcoffin; state Exp; branches; next 1.98; 1.98 date 2003.02.22.20.44.54; author dcoffin; state Exp; branches; next 1.97; 1.97 date 2003.02.17.04.23.32; author dcoffin; state Exp; branches; next 1.96; 1.96 date 2003.02.16.05.01.06; author dcoffin; state Exp; branches; next 1.95; 1.95 date 2003.01.30.19.45.42; author dcoffin; state Exp; branches; next 1.94; 1.94 date 2003.01.28.06.19.40; author dcoffin; state Exp; branches; next 1.93; 1.93 date 2003.01.27.02.55.01; author dcoffin; state Exp; branches; next 1.92; 1.92 date 2003.01.13.21.54.22; author dcoffin; state Exp; branches; next 1.91; 1.91 date 2003.01.09.05.07.39; author dcoffin; state Exp; branches; next 1.90; 1.90 date 2003.01.02.23.24.00; author dcoffin; state Exp; branches; next 1.89; 1.89 date 2002.12.31.23.23.33; author dcoffin; state Exp; branches; next 1.88; 1.88 date 2002.12.19.16.33.15; author dcoffin; state Exp; branches; next 1.87; 1.87 date 2002.12.19.03.13.42; author dcoffin; state Exp; branches; next 1.86; 1.86 date 2002.12.18.03.43.08; author dcoffin; state Exp; branches; next 1.85; 1.85 date 2002.12.17.19.52.52; author dcoffin; state Exp; branches; next 1.84; 1.84 date 2002.12.17.01.45.16; author dcoffin; state Exp; branches; next 1.83; 1.83 date 2002.12.16.06.23.49; author dcoffin; state Exp; branches; next 1.82; 1.82 date 2002.12.13.02.48.35; author dcoffin; state Exp; branches; next 1.81; 1.81 date 2002.12.12.18.14.52; author dcoffin; state Exp; branches; next 1.80; 1.80 date 2002.12.12.06.31.37; author dcoffin; state Exp; branches; next 1.79; 1.79 date 2002.12.04.03.28.49; author dcoffin; state Exp; branches; next 1.78; 1.78 date 2002.12.01.04.34.57; author dcoffin; state Exp; branches; next 1.77; 1.77 date 2002.11.25.04.36.23; author dcoffin; state Exp; branches; next 1.76; 1.76 date 2002.11.24.15.00.57; author dcoffin; state Exp; branches; next 1.75; 1.75 date 2002.11.13.17.37.41; author dcoffin; state Exp; branches; next 1.74; 1.74 date 2002.11.11.02.26.53; author dcoffin; state Exp; branches; next 1.73; 1.73 date 2002.11.09.05.31.58; author dcoffin; state Exp; branches; next 1.72; 1.72 date 2002.10.27.23.55.19; author dcoffin; state Exp; branches; next 1.71; 1.71 date 2002.10.27.18.50.40; author dcoffin; state Exp; branches; next 1.70; 1.70 date 2002.10.20.19.47.30; author dcoffin; state Exp; branches; next 1.69; 1.69 date 2002.10.16.01.09.16; author dcoffin; state Exp; branches; next 1.68; 1.68 date 2002.10.15.01.28.32; author dcoffin; state Exp; branches; next 1.67; 1.67 date 2002.08.15.17.22.53; author dcoffin; state Exp; branches; next 1.66; 1.66 date 2002.08.08.13.12.37; author dcoffin; state Exp; branches; next 1.65; 1.65 date 2002.08.07.23.28.31; author dcoffin; state Exp; branches; next 1.64; 1.64 date 2002.08.07.22.50.13; author dcoffin; state Exp; branches; next 1.63; 1.63 date 2002.06.28.03.55.09; author dcoffin; state Exp; branches; next 1.62; 1.62 date 2002.06.24.14.58.04; author dcoffin; state Exp; branches; next 1.61; 1.61 date 2002.06.23.20.39.42; author dcoffin; state Exp; branches; next 1.60; 1.60 date 2002.06.20.20.32.08; author dcoffin; state Exp; branches; next 1.59; 1.59 date 2002.05.28.17.18.51; author dcoffin; state Exp; branches; next 1.58; 1.58 date 2002.05.23.16.26.47; author dcoffin; state Exp; branches; next 1.57; 1.57 date 2002.05.06.04.11.13; author dcoffin; state Exp; branches; next 1.56; 1.56 date 2002.05.05.20.35.28; author dcoffin; state Exp; branches; next 1.55; 1.55 date 2002.05.05.04.52.02; author dcoffin; state Exp; branches; next 1.54; 1.54 date 2002.05.02.19.44.17; author dcoffin; state Exp; branches; next 1.53; 1.53 date 2002.04.26.03.29.48; author dcoffin; state Exp; branches; next 1.52; 1.52 date 2002.04.17.21.29.10; author dcoffin; state Exp; branches; next 1.51; 1.51 date 2002.04.16.23.32.41; author dcoffin; state Exp; branches; next 1.50; 1.50 date 2002.04.07.19.09.14; author dcoffin; state Exp; branches; next 1.49; 1.49 date 2002.04.04.01.44.38; author dcoffin; state Exp; branches; next 1.48; 1.48 date 2002.04.02.13.44.26; author dcoffin; state Exp; branches; next 1.47; 1.47 date 2002.03.29.02.23.51; author dcoffin; state Exp; branches; next 1.46; 1.46 date 2002.03.28.01.05.30; author dcoffin; state Exp; branches; next 1.45; 1.45 date 2002.03.25.03.52.38; author dcoffin; state Exp; branches; next 1.44; 1.44 date 2002.03.24.19.29.10; author dcoffin; state Exp; branches; next 1.43; 1.43 date 2002.03.24.17.34.52; author dcoffin; state Exp; branches; next 1.42; 1.42 date 2002.02.05.22.40.25; author dcoffin; state Exp; branches; next 1.41; 1.41 date 2002.01.29.20.53.56; author dcoffin; state Exp; branches; next 1.40; 1.40 date 2002.01.13.18.05.57; author dcoffin; state Exp; branches; next 1.39; 1.39 date 2001.12.08.22.59.44; author dcoffin; state Exp; branches; next 1.38; 1.38 date 2001.12.06.04.18.11; author dcoffin; state Exp; branches; next 1.37; 1.37 date 2001.11.25.21.39.22; author dcoffin; state Exp; branches; next 1.36; 1.36 date 2001.11.22.17.13.19; author dcoffin; state Exp; branches; next 1.35; 1.35 date 2001.11.06.00.16.04; author dcoffin; state Exp; branches; next 1.34; 1.34 date 2001.10.28.01.00.19; author dcoffin; state Exp; branches; next 1.33; 1.33 date 2001.10.24.17.56.06; author dcoffin; state Exp; branches; next 1.32; 1.32 date 2001.10.23.13.45.51; author dcoffin; state Exp; branches; next 1.31; 1.31 date 2001.10.19.23.01.31; author dcoffin; state Exp; branches; next 1.30; 1.30 date 2001.10.19.20.14.37; author dcoffin; state Exp; branches; next 1.29; 1.29 date 2001.10.15.04.28.53; author dcoffin; state Exp; branches; next 1.28; 1.28 date 2001.10.14.20.46.29; author dcoffin; state Exp; branches; next 1.27; 1.27 date 2001.09.30.15.30.42; author dcoffin; state Exp; branches; next 1.26; 1.26 date 2001.09.30.00.04.43; author dcoffin; state Exp; branches; next 1.25; 1.25 date 2001.09.24.22.41.06; author dcoffin; state Exp; branches; next 1.24; 1.24 date 2000.06.23.20.19.09; author dcoffin; state Exp; branches; next 1.23; 1.23 date 2000.06.19.06.56.27; author dcoffin; state Exp; branches; next 1.22; 1.22 date 2000.05.20.20.31.28; author dcoffin; state Exp; branches; next 1.21; 1.21 date 2000.05.07.04.26.08; author dcoffin; state Exp; branches; next 1.20; 1.20 date 2000.05.06.20.28.57; author dcoffin; state Exp; branches; next 1.19; 1.19 date 2000.05.05.13.48.25; author dcoffin; state Exp; branches; next 1.18; 1.18 date 2000.05.05.04.21.40; author dcoffin; state Exp; branches; next 1.17; 1.17 date 2000.05.02.13.45.14; author dcoffin; state Exp; branches; next 1.16; 1.16 date 2000.05.02.12.18.24; author dcoffin; state Exp; branches; next 1.15; 1.15 date 2000.05.01.07.06.04; author dcoffin; state Exp; branches; next 1.14; 1.14 date 99.05.07.00.10.38; author dcoffin; state Exp; branches; next 1.13; 1.13 date 99.04.15.21.20.26; author dcoffin; state Exp; branches; next 1.12; 1.12 date 99.04.15.19.57.55; author dcoffin; state Exp; branches; next 1.11; 1.11 date 99.04.12.22.57.06; author dcoffin; state Exp; branches 1.11.1.1; next 1.10; 1.10 date 99.04.12.19.36.36; author dcoffin; state Exp; branches; next 1.9; 1.9 date 99.01.01.20.56.22; author dcoffin; state Exp; branches; next 1.8; 1.8 date 97.08.31.02.09.41; author dcoffin; state Exp; branches; next 1.7; 1.7 date 97.08.24.04.06.03; author dcoffin; state Exp; branches; next 1.6; 1.6 date 97.08.23.19.36.52; author dcoffin; state Exp; branches; next 1.5; 1.5 date 97.03.25.02.49.34; author dcoffin; state Exp; branches; next 1.4; 1.4 date 97.02.25.04.12.42; author dcoffin; state Exp; branches; next 1.3; 1.3 date 97.02.24.02.04.30; author dcoffin; state Exp; branches; next 1.2; 1.2 date 97.02.23.02.17.04; author dcoffin; state Exp; branches; next 1.1; 1.1 date 97.02.23.01.20.29; author dcoffin; state Exp; branches; next ; 1.11.1.1 date 99.04.12.23.00.06; author dcoffin; state Exp; branches; next 1.11.1.2; 1.11.1.2 date 99.04.15.19.17.17; author dcoffin; state Exp; branches; next 1.11.1.3; 1.11.1.3 date 99.04.15.19.57.17; author dcoffin; state Exp; branches; next ; 1.179.1.1 date 2004.04.07.07.22.56; author dcoffin; state Exp; branches; next ; desc @Command-line tool to decode raw photos from all digital cameras @ 1.425 log @Support the Phase One P45+. @ text @/* dcraw.c -- Dave Coffin's raw photo decoder Copyright 1997-2009 by Dave Coffin, dcoffin a cybercom o net This is a command-line ANSI C program to convert raw photos from any digital camera on any computer running any operating system. No license is required to download and use dcraw.c. However, to lawfully redistribute dcraw, you must either (a) offer, at no extra charge, full source code* for all executable files containing RESTRICTED functions, (b) distribute this code under the GPL Version 2 or later, (c) remove all RESTRICTED functions, re-implement them, or copy them from an earlier, unrestricted Revision of dcraw.c, or (d) purchase a license from the author. The functions that process Foveon images have been RESTRICTED since Revision 1.237. All other code remains free for all uses. *If you have not modified dcraw.c in any way, a link to my homepage qualifies as "full source code". $Revision$ $Date$ */ #define VERSION "8.95" #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #define _USE_MATH_DEFINES #include #include #include #include #include #include #include #include #include #include #include #include /* NO_JPEG disables decoding of compressed Kodak DC120 files. NO_LCMS disables the "-p" option. */ #ifndef NO_JPEG #include #endif #ifndef NO_LCMS #include #endif #ifdef LOCALEDIR #include #define _(String) gettext(String) #else #define _(String) (String) #endif #ifdef DJGPP #define fseeko fseek #define ftello ftell #else #define fgetc getc_unlocked #endif #ifdef __CYGWIN__ #include #endif #ifdef WIN32 #include #include #pragma comment(lib, "ws2_32.lib") #define snprintf _snprintf #define strcasecmp stricmp #define strncasecmp strnicmp typedef __int64 INT64; typedef unsigned __int64 UINT64; #else #include #include #include typedef long long INT64; typedef unsigned long long UINT64; #endif #ifdef LJPEG_DECODE #error Please compile dcraw.c by itself. #error Do not link it with ljpeg_decode. #endif #ifndef LONG_BIT #define LONG_BIT (8 * sizeof (long)) #endif #define ushort UshORt typedef unsigned char uchar; typedef unsigned short ushort; /* All global variables are defined here, and all functions that access them are prefixed with "CLASS". Note that a thread-safe C++ class cannot have non-const static local variables. */ FILE *ifp, *ofp; short order; const char *ifname; char *meta_data; char cdesc[5], desc[512], make[64], model[64], model2[64], artist[64]; float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len; time_t timestamp; unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id; off_t strip_offset, data_offset; off_t thumb_offset, meta_offset, profile_offset; unsigned thumb_length, meta_length, profile_length; unsigned thumb_misc, *oprof, fuji_layout, shot_select=0, multi_out=0; unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress; unsigned black, maximum, mix_green, raw_color, zero_is_bad; unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error; unsigned tile_width, tile_length, gpsdata[32], load_flags; ushort raw_height, raw_width, height, width, top_margin, left_margin; ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; int flip, tiff_flip, colors; double pixel_aspect, aber[4]={1,1,1,1}, gamm[6]={ 0.45,4.5,0,0,0,0 }; ushort (*image)[4], white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4]; float bright=1, user_mul[4]={0,0,0,0}, threshold=0; int half_size=0, four_color_rgb=0, document_mode=0, highlight=0; int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=-1; int output_color=1, output_bps=8, output_tiff=0, med_passes=0; int no_auto_bright=0; unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX }; float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4]; const double xyz_rgb[3][3] = { /* XYZ from RGB */ { 0.412453, 0.357580, 0.180423 }, { 0.212671, 0.715160, 0.072169 }, { 0.019334, 0.119193, 0.950227 } }; const float d65_white[3] = { 0.950456, 1, 1.088754 }; int histogram[4][0x2000]; void (*write_thumb)(), (*write_fun)(); void (*load_raw)(), (*thumb_load_raw)(); jmp_buf failure; struct decode { struct decode *branch[2]; int leaf; } first_decode[2048], *second_decode, *free_decode; struct tiff_ifd { int width, height, bps, comp, phint, offset, flip, samples, bytes; } tiff_ifd[10]; struct ph1 { int format, key_off, black, black_off, split_col, tag_21a; float tag_210; } ph1; #define CLASS #define FORC(cnt) for (c=0; c < cnt; c++) #define FORC3 FORC(3) #define FORC4 FORC(4) #define FORCC FORC(colors) #define SQR(x) ((x)*(x)) #define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define LIM(x,min,max) MAX(min,MIN(x,max)) #define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y)) #define CLIP(x) LIM(x,0,65535) #define SWAP(a,b) { a ^= b; a ^= (b ^= a); } /* In order to inline this calculation, I make the risky assumption that all filter patterns can be described by a repeating pattern of eight rows and two columns Do not use the FC or BAYER macros with the Leaf CatchLight, because its pattern is 16x16, not 2x8. Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2 PowerShot 600 PowerShot A50 PowerShot Pro70 Pro90 & G1 0xe1e4e1e4: 0x1b4e4b1e: 0x1e4b4e1b: 0xb4b4b4b4: 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 G M G M G M 0 C Y C Y C Y 0 Y C Y C Y C 0 G M G M G M 1 C Y C Y C Y 1 M G M G M G 1 M G M G M G 1 Y C Y C Y C 2 M G M G M G 2 Y C Y C Y C 2 C Y C Y C Y 3 C Y C Y C Y 3 G M G M G M 3 G M G M G M 4 C Y C Y C Y 4 Y C Y C Y C PowerShot A5 5 G M G M G M 5 G M G M G M 0x1e4e1e4e: 6 Y C Y C Y C 6 C Y C Y C Y 7 M G M G M G 7 M G M G M G 0 1 2 3 4 5 0 C Y C Y C Y 1 G M G M G M 2 C Y C Y C Y 3 M G M G M G All RGB cameras use one of these Bayer grids: 0x16161616: 0x61616161: 0x49494949: 0x94949494: 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 B G B G B G 0 G R G R G R 0 G B G B G B 0 R G R G R G 1 G R G R G R 1 B G B G B G 1 R G R G R G 1 G B G B G B 2 B G B G B G 2 G R G R G R 2 G B G B G B 2 R G R G R G 3 G R G R G R 3 B G B G B G 3 R G R G R G 3 G B G B G B */ #define FC(row,col) \ (filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) #define BAYER(row,col) \ image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)] #define BAYER2(row,col) \ image[((row) >> shrink)*iwidth + ((col) >> shrink)][fc(row,col)] int CLASS fc (int row, int col) { static const char filter[16][16] = { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 }, { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 }, { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 }, { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 }, { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 }, { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 }, { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 }, { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 }, { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 }, { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 }, { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 }, { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 }, { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 }, { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 }, { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 }, { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } }; if (filters != 1) return FC(row,col); return filter[(row+top_margin) & 15][(col+left_margin) & 15]; } #ifndef __GLIBC__ char *my_memmem (char *haystack, size_t haystacklen, char *needle, size_t needlelen) { char *c; for (c = haystack; c <= haystack + haystacklen - needlelen; c++) if (!memcmp (c, needle, needlelen)) return c; return 0; } #define memmem my_memmem #endif void CLASS merror (void *ptr, const char *where) { if (ptr) return; fprintf (stderr,_("%s: Out of memory in %s\n"), ifname, where); longjmp (failure, 1); } void CLASS derror() { if (!data_error) { fprintf (stderr, "%s: ", ifname); if (feof(ifp)) fprintf (stderr,_("Unexpected end of file\n")); else fprintf (stderr,_("Corrupt data near 0x%llx\n"), (INT64) ftello(ifp)); } data_error = 1; } ushort CLASS sget2 (uchar *s) { if (order == 0x4949) /* "II" means little-endian */ return s[0] | s[1] << 8; else /* "MM" means big-endian */ return s[0] << 8 | s[1]; } ushort CLASS get2() { uchar str[2] = { 0xff,0xff }; fread (str, 1, 2, ifp); return sget2(str); } unsigned CLASS sget4 (uchar *s) { if (order == 0x4949) return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; else return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; } #define sget4(s) sget4((uchar *)s) unsigned CLASS get4() { uchar str[4] = { 0xff,0xff,0xff,0xff }; fread (str, 1, 4, ifp); return sget4(str); } unsigned CLASS getint (int type) { return type == 3 ? get2() : get4(); } float CLASS int_to_float (int i) { union { int i; float f; } u; u.i = i; return u.f; } double CLASS getreal (int type) { union { char c[8]; double d; } u; int i, rev; switch (type) { case 3: return (unsigned short) get2(); case 4: return (unsigned int) get4(); case 5: u.d = (unsigned int) get4(); return u.d / (unsigned int) get4(); case 8: return (signed short) get2(); case 9: return (signed int) get4(); case 10: u.d = (signed int) get4(); return u.d / (signed int) get4(); case 11: return int_to_float (get4()); case 12: rev = 7 * ((order == 0x4949) == (ntohs(0x1234) == 0x1234)); for (i=0; i < 8; i++) u.c[i ^ rev] = fgetc(ifp); return u.d; default: return fgetc(ifp); } } void CLASS read_shorts (ushort *pixel, int count) { if (fread (pixel, 2, count, ifp) < count) derror(); if ((order == 0x4949) == (ntohs(0x1234) == 0x1234)) swab (pixel, pixel, count*2); } void CLASS canon_black (double dark[2], int nblack) { int c, diff, row, col; if (!nblack) return; FORC(2) dark[c] /= nblack >> 1; if ((diff = dark[0] - dark[1])) for (row=0; row < height; row++) for (col=1; col < width; col+=2) BAYER(row,col) += diff; dark[1] += diff; black = (dark[0] + dark[1] + 1) / 2; } void CLASS canon_600_fixed_wb (int temp) { static const short mul[4][5] = { { 667, 358,397,565,452 }, { 731, 390,367,499,517 }, { 1119, 396,348,448,537 }, { 1399, 485,431,508,688 } }; int lo, hi, i; float frac=0; for (lo=4; --lo; ) if (*mul[lo] <= temp) break; for (hi=0; hi < 3; hi++) if (*mul[hi] >= temp) break; if (lo != hi) frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]); for (i=1; i < 5; i++) pre_mul[i-1] = 1 / (frac * mul[hi][i] + (1-frac) * mul[lo][i]); } /* Return values: 0 = white 1 = near white 2 = not white */ int CLASS canon_600_color (int ratio[2], int mar) { int clipped=0, target, miss; if (flash_used) { if (ratio[1] < -104) { ratio[1] = -104; clipped = 1; } if (ratio[1] > 12) { ratio[1] = 12; clipped = 1; } } else { if (ratio[1] < -264 || ratio[1] > 461) return 2; if (ratio[1] < -50) { ratio[1] = -50; clipped = 1; } if (ratio[1] > 307) { ratio[1] = 307; clipped = 1; } } target = flash_used || ratio[1] < 197 ? -38 - (398 * ratio[1] >> 10) : -123 + (48 * ratio[1] >> 10); if (target - mar <= ratio[0] && target + 20 >= ratio[0] && !clipped) return 0; miss = target - ratio[0]; if (abs(miss) >= mar*4) return 2; if (miss < -20) miss = -20; if (miss > mar) miss = mar; ratio[0] = target - miss; return 1; } void CLASS canon_600_auto_wb() { int mar, row, col, i, j, st, count[] = { 0,0 }; int test[8], total[2][8], ratio[2][2], stat[2]; memset (&total, 0, sizeof total); i = canon_ev + 0.5; if (i < 10) mar = 150; else if (i > 12) mar = 20; else mar = 280 - 20 * i; if (flash_used) mar = 80; for (row=14; row < height-14; row+=4) for (col=10; col < width; col+=2) { for (i=0; i < 8; i++) test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] = BAYER(row+(i >> 1),col+(i & 1)); for (i=0; i < 8; i++) if (test[i] < 150 || test[i] > 1500) goto next; for (i=0; i < 4; i++) if (abs(test[i] - test[i+4]) > 50) goto next; for (i=0; i < 2; i++) { for (j=0; j < 4; j+=2) ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j]; stat[i] = canon_600_color (ratio[i], mar); } if ((st = stat[0] | stat[1]) > 1) goto next; for (i=0; i < 2; i++) if (stat[i]) for (j=0; j < 2; j++) test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10; for (i=0; i < 8; i++) total[st][i] += test[i]; count[st]++; next: ; } if (count[0] | count[1]) { st = count[0]*200 < count[1]; for (i=0; i < 4; i++) pre_mul[i] = 1.0 / (total[st][i] + total[st][i+4]); } } void CLASS canon_600_coeff() { static const short table[6][12] = { { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 }, { -1203,1715,-1136,1648, 1388,-876,267,245, -1641,2153,3921,-3409 }, { -615,1127,-1563,2075, 1437,-925,509,3, -756,1268,2519,-2007 }, { -190,702,-1886,2398, 2153,-1641,763,-251, -452,964,3040,-2528 }, { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 }, { -807,1319,-1785,2297, 1388,-876,769,-257, -230,742,2067,-1555 } }; int t=0, i, c; float mc, yc; mc = pre_mul[1] / pre_mul[2]; yc = pre_mul[3] / pre_mul[2]; if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1; if (mc > 1.28 && mc <= 2) { if (yc < 0.8789) t=3; else if (yc <= 2) t=4; } if (flash_used) t=5; for (raw_color = i=0; i < 3; i++) FORCC rgb_cam[i][c] = table[t][i*4 + c] / 1024.0; } void CLASS canon_600_load_raw() { uchar data[1120], *dp; ushort pixel[896], *pix; int irow, row, col, val; static const short mul[4][2] = { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } }; for (irow=row=0; irow < height; irow++) { if (fread (data, 1, raw_width*5/4, ifp) < raw_width*5/4) derror(); for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8) { pix[0] = (dp[0] << 2) + (dp[1] >> 6 ); pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3); pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3); pix[3] = (dp[4] << 2) + (dp[1] & 3); pix[4] = (dp[5] << 2) + (dp[9] & 3); pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3); pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3); pix[7] = (dp[8] << 2) + (dp[9] >> 6 ); } for (col=0; col < width; col++) BAYER(row,col) = pixel[col]; for (col=width; col < raw_width; col++) black += pixel[col]; if ((row+=2) > height) row = 1; } if (raw_width > width) black = black / ((raw_width - width) * height) - 4; for (row=0; row < height; row++) for (col=0; col < width; col++) { if ((val = BAYER(row,col) - black) < 0) val = 0; val = val * mul[row & 3][col & 1] >> 9; BAYER(row,col) = val; } canon_600_fixed_wb(1311); canon_600_auto_wb(); canon_600_coeff(); maximum = (0x3ff - black) * 1109 >> 9; black = 0; } void CLASS remove_zeroes() { unsigned row, col, tot, n, r, c; for (row=0; row < height; row++) for (col=0; col < width; col++) if (BAYER(row,col) == 0) { tot = n = 0; for (r = row-2; r <= row+2; r++) for (c = col-2; c <= col+2; c++) if (r < height && c < width && FC(r,c) == FC(row,col) && BAYER(r,c)) tot += (n++,BAYER(r,c)); if (n) BAYER(row,col) = tot/n; } } int CLASS canon_s2is() { unsigned row; for (row=0; row < 100; row++) { fseek (ifp, row*3340 + 3284, SEEK_SET); if (getc(ifp) > 15) return 1; } return 0; } void CLASS canon_a5_load_raw() { ushort data[2565], *dp, pixel; int vbits=0, buf=0, row, col, bc=0; order = 0x4949; for (row=-top_margin; row < raw_height-top_margin; row++) { read_shorts (dp=data, raw_width * 10 / 16); for (col=-left_margin; col < raw_width-left_margin; col++) { if ((vbits -= 10) < 0) buf = (vbits += 16, (buf << 16) + *dp++); pixel = buf >> vbits & 0x3ff; if ((unsigned) row < height && (unsigned) col < width) BAYER(row,col) = pixel; else if (col > 1-left_margin && col != width) black += (bc++,pixel); } } if (bc) black /= bc; maximum = 0x3ff; if (raw_width > 1600) remove_zeroes(); } /* getbits(-1) initializes the buffer getbits(n) where 0 <= n <= 25 returns an n-bit integer */ unsigned CLASS getbithuff (int nbits, ushort *huff) { static unsigned bitbuf=0; static int vbits=0, reset=0; unsigned c; if (nbits == -1) return bitbuf = vbits = reset = 0; if (nbits == 0 || vbits < 0) return 0; while (!reset && vbits < nbits && (c = fgetc(ifp)) != EOF && !(reset = zero_after_ff && c == 0xff && fgetc(ifp))) { bitbuf = (bitbuf << 8) + (uchar) c; vbits += 8; } c = bitbuf << (32-vbits) >> (32-nbits); if (huff) { vbits -= huff[c] >> 8; c = (uchar) huff[c]; } else vbits -= nbits; if (vbits < 0) derror(); return c; } #define getbits(n) getbithuff(n,0) #define gethuff(h) getbithuff(*h,h+1) /* Construct a decode tree according the specification in *source. The first 16 bytes specify how many codes should be 1-bit, 2-bit 3-bit, etc. Bytes after that are the leaf values. For example, if the source is { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff }, then the code is 00 0x04 010 0x03 011 0x05 100 0x06 101 0x02 1100 0x07 1101 0x01 11100 0x08 11101 0x09 11110 0x00 111110 0x0a 1111110 0x0b 1111111 0xff */ ushort * CLASS make_decoder_ref (const uchar **source) { int max, len, h, i, j; const uchar *count; ushort *huff; count = (*source += 16) - 17; for (max=16; max && !count[max]; max--); huff = (ushort *) calloc (1 + (1 << max), sizeof *huff); merror (huff, "make_decoder()"); huff[0] = max; for (h=len=1; len <= max; len++) for (i=0; i < count[len]; i++, ++*source) for (j=0; j < 1 << (max-len); j++) if (h <= 1 << max) huff[h++] = len << 8 | **source; return huff; } ushort * CLASS make_decoder (const uchar *source) { return make_decoder_ref (&source); } void CLASS crw_init_tables (unsigned table, ushort *huff[2]) { static const uchar first_tree[3][29] = { { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff }, { 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0, 0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff }, { 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0, 0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff }, }; static const uchar second_tree[3][180] = { { 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139, 0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08, 0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0, 0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42, 0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57, 0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9, 0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98, 0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6, 0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4, 0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7, 0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1, 0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64, 0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba, 0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4, 0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff }, { 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140, 0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06, 0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32, 0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51, 0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26, 0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59, 0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9, 0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99, 0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85, 0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8, 0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a, 0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9, 0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8, 0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8, 0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff }, { 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117, 0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08, 0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22, 0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34, 0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41, 0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48, 0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69, 0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8, 0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94, 0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a, 0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6, 0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62, 0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5, 0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3, 0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff } }; if (table > 2) table = 2; huff[0] = make_decoder ( first_tree[table]); huff[1] = make_decoder (second_tree[table]); } /* Return 0 if the image starts with compressed data, 1 if it starts with uncompressed low-order bits. In Canon compressed data, 0xff is always followed by 0x00. */ int CLASS canon_has_lowbits() { uchar test[0x4000]; int ret=1, i; fseek (ifp, 0, SEEK_SET); fread (test, 1, sizeof test, ifp); for (i=540; i < sizeof test - 1; i++) if (test[i] == 0xff) { if (test[i+1]) return 1; ret=0; } return ret; } void CLASS canon_compressed_load_raw() { ushort *pixel, *prow, *huff[2]; int nblocks, lowbits, i, c, row, r, col, save, val, nblack=0; unsigned irow, icol; int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2]; double dark[2] = { 0,0 }; crw_init_tables (tiff_compress, huff); pixel = (ushort *) calloc (raw_width*8, sizeof *pixel); merror (pixel, "canon_compressed_load_raw()"); lowbits = canon_has_lowbits(); if (!lowbits) maximum = 0x3ff; fseek (ifp, 540 + lowbits*raw_height*raw_width/4, SEEK_SET); zero_after_ff = 1; getbits(-1); for (row=0; row < raw_height; row+=8) { nblocks = MIN (8, raw_height-row) * raw_width >> 6; for (block=0; block < nblocks; block++) { memset (diffbuf, 0, sizeof diffbuf); for (i=0; i < 64; i++ ) { leaf = gethuff(huff[i > 0]); if (leaf == 0 && i) break; if (leaf == 0xff) continue; i += leaf >> 4; len = leaf & 15; if (len == 0) continue; diff = getbits(len); if ((diff & (1 << (len-1))) == 0) diff -= (1 << len) - 1; if (i < 64) diffbuf[i] = diff; } diffbuf[0] += carry; carry = diffbuf[0]; for (i=0; i < 64; i++ ) { if (pnum++ % raw_width == 0) base[0] = base[1] = 512; if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10) derror(); } } if (lowbits) { save = ftell(ifp); fseek (ifp, 26 + row*raw_width/4, SEEK_SET); for (prow=pixel, i=0; i < raw_width*2; i++) { c = fgetc(ifp); for (r=0; r < 8; r+=2, prow++) { val = (*prow << 2) + ((c >> r) & 3); if (raw_width == 2672 && val < 512) val += 2; *prow = val; } } fseek (ifp, save, SEEK_SET); } for (r=0; r < 8; r++) { irow = row - top_margin + r; if (irow >= height) continue; for (col=0; col < raw_width; col++) { icol = col - left_margin; if (icol < width) BAYER(irow,icol) = pixel[r*raw_width+col]; else if (col > 1 && (unsigned) (col-left_margin+2) > width+3) dark[icol & 1] += (nblack++,pixel[r*raw_width+col]); } } } free (pixel); FORC(2) free (huff[c]); canon_black (dark, nblack); } /* Not a full implementation of Lossless JPEG, just enough to decode Canon, Kodak and Adobe DNG images. */ struct jhead { int bits, high, wide, clrs, sraw, psv, restart, vpred[6]; ushort *huff[6], *free[4], *row; }; int CLASS ljpeg_start (struct jhead *jh, int info_only) { int c, tag, len; uchar data[0x10000]; const uchar *dp; memset (jh, 0, sizeof *jh); jh->restart = INT_MAX; fread (data, 2, 1, ifp); if (data[1] != 0xd8) return 0; do { fread (data, 2, 2, ifp); tag = data[0] << 8 | data[1]; len = (data[2] << 8 | data[3]) - 2; if (tag <= 0xff00) return 0; fread (data, 1, len, ifp); switch (tag) { case 0xffc3: jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3; case 0xffc0: jh->bits = data[0]; jh->high = data[1] << 8 | data[2]; jh->wide = data[3] << 8 | data[4]; jh->clrs = data[5] + jh->sraw; if (len == 9 && !dng_version) getc(ifp); break; case 0xffc4: if (info_only) break; for (dp = data; dp < data+len && (c = *dp++) < 4; ) jh->free[c] = jh->huff[c] = make_decoder_ref (&dp); break; case 0xffda: jh->psv = data[1+data[0]*2]; jh->bits -= data[3+data[0]*2] & 15; break; case 0xffdd: jh->restart = data[0] << 8 | data[1]; } } while (tag != 0xffda); if (info_only) return 1; FORC(5) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c]; if (jh->sraw) { FORC(4) jh->huff[2+c] = jh->huff[1]; FORC(jh->sraw) jh->huff[1+c] = jh->huff[0]; } jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4); merror (jh->row, "ljpeg_start()"); return zero_after_ff = 1; } void CLASS ljpeg_end (struct jhead *jh) { int c; FORC4 if (jh->free[c]) free (jh->free[c]); free (jh->row); } int CLASS ljpeg_diff (ushort *huff) { int len, diff; len = gethuff(huff); if (len == 16 && (!dng_version || dng_version >= 0x1010000)) return -32768; diff = getbits(len); if ((diff & (1 << (len-1))) == 0) diff -= (1 << len) - 1; return diff; } ushort * CLASS ljpeg_row (int jrow, struct jhead *jh) { int col, c, diff, pred, spred=0; ushort mark=0, *row[3]; if (jrow * jh->wide % jh->restart == 0) { FORC(6) jh->vpred[c] = 1 << (jh->bits-1); if (jrow) { fseek (ifp, -2, SEEK_CUR); do mark = (mark << 8) + (c = fgetc(ifp)); while (c != EOF && mark >> 4 != 0xffd); } getbits(-1); } FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1); for (col=0; col < jh->wide; col++) FORC(jh->clrs) { diff = ljpeg_diff (jh->huff[c]); if (jh->sraw && c <= jh->sraw && (col | c)) pred = spred; else if (col) pred = row[0][-jh->clrs]; else pred = (jh->vpred[c] += diff) - diff; if (jrow && col) switch (jh->psv) { case 1: break; case 2: pred = row[1][0]; break; case 3: pred = row[1][-jh->clrs]; break; case 4: pred = pred + row[1][0] - row[1][-jh->clrs]; break; case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1); break; case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1); break; case 7: pred = (pred + row[1][0]) >> 1; break; default: pred = 0; } if ((**row = pred + diff) >> jh->bits) derror(); if (c <= jh->sraw) spred = **row; row[0]++; row[1]++; } return row[2]; } void CLASS lossless_jpeg_load_raw() { int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0, nblack=0; double dark[2] = { 0,0 }; struct jhead jh; int min=INT_MAX; ushort *rp; if (!ljpeg_start (&jh, 0)) return; jwide = jh.wide * jh.clrs; for (jrow=0; jrow < jh.high; jrow++) { rp = ljpeg_row (jrow, &jh); for (jcol=0; jcol < jwide; jcol++) { val = *rp++; if (jh.bits <= 12) val = curve[val & 0xfff]; if (cr2_slice[0]) { jidx = jrow*jwide + jcol; i = jidx / (cr2_slice[1]*jh.high); if ((j = i >= cr2_slice[0])) i = cr2_slice[0]; jidx -= i * (cr2_slice[1]*jh.high); row = jidx / cr2_slice[1+j]; col = jidx % cr2_slice[1+j] + i*cr2_slice[1]; } if (raw_width == 3984 && (col -= 2) < 0) col += (row--,raw_width); if ((unsigned) (row-top_margin) < height) { if ((unsigned) (col-left_margin) < width) { BAYER(row-top_margin,col-left_margin) = val; if (min > val) min = val; } else if (col > 1 && (unsigned) (col-left_margin+2) > width+3) dark[(col-left_margin) & 1] += (nblack++,val); } if (++col >= raw_width) col = (row++,0); } } ljpeg_end (&jh); canon_black (dark, nblack); if (!strcasecmp(make,"KODAK")) black = min; } void CLASS canon_sraw_load_raw() { struct jhead jh; short *rp=0, (*ip)[4]; int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c; int v[3]={0,0,0}, ver, hue; char *cp; if (!ljpeg_start (&jh, 0)) return; jwide = (jh.wide >>= 1) * jh.clrs; for (ecol=slice=0; slice <= cr2_slice[0]; slice++) { scol = ecol; ecol += cr2_slice[1] * 2 / jh.clrs; if (!cr2_slice[0] || ecol > raw_width-1) ecol = raw_width & -2; for (row=0; row < height; row += (jh.clrs >> 1) - 1) { ip = (short (*)[4]) image + row*width; for (col=scol; col < ecol; col+=2, jcol+=jh.clrs) { if ((jcol %= jwide) == 0) rp = (short *) ljpeg_row (jrow++, &jh); if (col >= width) continue; FORC (jh.clrs-2) ip[col + (c >> 1)*width + (c & 1)][0] = rp[jcol+c]; ip[col][1] = rp[jcol+jh.clrs-2] - 16384; ip[col][2] = rp[jcol+jh.clrs-1] - 16384; } } } for (cp=model2; *cp && !isdigit(*cp); cp++); sscanf (cp, "%d.%d.%d", v, v+1, v+2); ver = (v[0]*1000 + v[1])*1000 + v[2]; hue = (jh.sraw+1) << 2; if (unique_id == 0x80000218 && ver > 1000006 && ver < 3000000) hue = jh.sraw << 1; ip = (short (*)[4]) image; rp = ip[0]; for (row=0; row < height; row++, ip+=width) { if (row & (jh.sraw >> 1)) for (col=0; col < width; col+=2) for (c=1; c < 3; c++) if (row == height-1) ip[col][c] = ip[col-width][c]; else ip[col][c] = (ip[col-width][c] + ip[col+width][c] + 1) >> 1; for (col=1; col < width; col+=2) for (c=1; c < 3; c++) if (col == width-1) ip[col][c] = ip[col-1][c]; else ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1; } for ( ; rp < ip[0]; rp+=4) { if (unique_id < 0x80000200) { pix[0] = rp[0] + rp[2] - 512; pix[2] = rp[0] + rp[1] - 512; pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12) - 512; } else { rp[1] = (rp[1] << 2) + hue; rp[2] = (rp[2] << 2) + hue; pix[0] = rp[0] + (( 200*rp[1] + 22929*rp[2]) >> 14); pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14); pix[2] = rp[0] + ((29040*rp[1] - 101*rp[2]) >> 14); } FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10); } ljpeg_end (&jh); maximum = 0x3fff; } void CLASS adobe_copy_pixel (int row, int col, ushort **rp) { unsigned r, c; r = row -= top_margin; c = col -= left_margin; if (is_raw == 2 && shot_select) (*rp)++; if (filters) { if (fuji_width) { r = row + fuji_width - 1 - (col >> 1); c = row + ((col+1) >> 1); } if (r < height && c < width) BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp; *rp += is_raw; } else { if (r < height && c < width) FORC(tiff_samples) image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c]; *rp += tiff_samples; } if (is_raw == 2 && shot_select) (*rp)--; } void CLASS adobe_dng_load_raw_lj() { unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col; struct jhead jh; ushort *rp; while (trow < raw_height) { save = ftell(ifp); if (tile_length < INT_MAX) fseek (ifp, get4(), SEEK_SET); if (!ljpeg_start (&jh, 0)) break; jwide = jh.wide; if (filters) jwide *= jh.clrs; jwide /= is_raw; for (row=col=jrow=0; jrow < jh.high; jrow++) { rp = ljpeg_row (jrow, &jh); for (jcol=0; jcol < jwide; jcol++) { adobe_copy_pixel (trow+row, tcol+col, &rp); if (++col >= tile_width || col >= raw_width) row += 1 + (col = 0); } } fseek (ifp, save+4, SEEK_SET); if ((tcol += tile_width) >= raw_width) trow += tile_length + (tcol = 0); ljpeg_end (&jh); } } void CLASS adobe_dng_load_raw_nc() { ushort *pixel, *rp; int row, col; pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel); merror (pixel, "adobe_dng_load_raw_nc()"); for (row=0; row < raw_height; row++) { if (tiff_bps == 16) read_shorts (pixel, raw_width * tiff_samples); else { getbits(-1); for (col=0; col < raw_width * tiff_samples; col++) pixel[col] = getbits(tiff_bps); } for (rp=pixel, col=0; col < raw_width; col++) adobe_copy_pixel (row, col, &rp); } free (pixel); } void CLASS pentax_k10_load_raw() { ushort bit[2][13], huff[4097]; int row, col, diff, c, i; ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2]; fseek (ifp, meta_offset, SEEK_SET); FORC(13) bit[0][c] = get2(); FORC(13) bit[1][c] = fgetc(ifp); FORC(13) for (i=bit[0][c]; i <= ((bit[0][c]+(4096 >> bit[1][c])-1) & 4095); ) huff[++i] = bit[1][c] << 8 | c; huff[0] = 12; fseek (ifp, data_offset, SEEK_SET); getbits(-1); for (row=0; row < height; row++) for (col=0; col < raw_width; col++) { diff = ljpeg_diff (huff); if (col < 2) hpred[col] = vpred[row & 1][col] += diff; else hpred[col & 1] += diff; if (col < width) BAYER(row,col) = hpred[col & 1]; if (hpred[col & 1] >> 12) derror(); } } void CLASS nikon_compressed_load_raw() { static const uchar nikon_tree[][32] = { { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy */ 5,4,3,6,2,7,1,0,8,9,11,10,12 }, { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy after split */ 0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 }, { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, /* 12-bit lossless */ 5,4,6,3,7,2,8,1,9,0,10,11,12 }, { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0, /* 14-bit lossy */ 5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 }, { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0, /* 14-bit lossy after split */ 8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 }, { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0, /* 14-bit lossless */ 7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } }; ushort *huff, ver0, ver1, vpred[2][2], hpred[2], csize; int i, min, max, step=0, tree=0, split=0, row, col, len, shl, diff; fseek (ifp, meta_offset, SEEK_SET); ver0 = fgetc(ifp); ver1 = fgetc(ifp); if (ver0 == 0x49 || ver1 == 0x58) fseek (ifp, 2110, SEEK_CUR); if (ver0 == 0x46) tree = 2; if (tiff_bps == 14) tree += 3; read_shorts (vpred[0], 4); max = 1 << tiff_bps & 0x7fff; if ((csize = get2()) > 1) step = max / (csize-1); if (ver0 == 0x44 && ver1 == 0x20 && step > 0) { for (i=0; i < csize; i++) curve[i*step] = get2(); for (i=0; i < max; i++) curve[i] = ( curve[i-i%step]*(step-i%step) + curve[i-i%step+step]*(i%step) ) / step; fseek (ifp, meta_offset+562, SEEK_SET); split = get2(); } else if (ver0 != 0x46 && csize <= 0x4001) read_shorts (curve, max=csize); while (curve[max-2] == curve[max-1]) max--; huff = make_decoder (nikon_tree[tree]); fseek (ifp, data_offset, SEEK_SET); getbits(-1); for (min=row=0; row < height; row++) { if (split && row == split) { free (huff); huff = make_decoder (nikon_tree[tree+1]); max += (min = 16) << 1; } for (col=0; col < raw_width; col++) { i = gethuff(huff); len = i & 15; shl = i >> 4; diff = ((getbits(len-shl) << 1) + 1) << shl >> 1; if ((diff & (1 << (len-1))) == 0) diff -= (1 << len) - !shl; if (col < 2) hpred[col] = vpred[row & 1][col] += diff; else hpred[col & 1] += diff; if ((ushort)(hpred[col & 1] + min) >= max) derror(); if ((unsigned) (col-left_margin) < width) BAYER(row,col-left_margin) = curve[LIM((short)hpred[col & 1],0,0x3fff)]; } } free (huff); } /* Figure out if a NEF file is compressed. These fancy heuristics are only needed for the D100, thanks to a bug in some cameras that tags all images as "compressed". */ int CLASS nikon_is_compressed() { uchar test[256]; int i; fseek (ifp, data_offset, SEEK_SET); fread (test, 1, 256, ifp); for (i=15; i < 256; i+=16) if (test[i]) return 1; return 0; } /* Returns 1 for a Coolpix 995, 0 for anything else. */ int CLASS nikon_e995() { int i, histo[256]; const uchar often[] = { 0x00, 0x55, 0xaa, 0xff }; memset (histo, 0, sizeof histo); fseek (ifp, -2000, SEEK_END); for (i=0; i < 2000; i++) histo[fgetc(ifp)]++; for (i=0; i < 4; i++) if (histo[often[i]] < 200) return 0; return 1; } /* Returns 1 for a Coolpix 2100, 0 for anything else. */ int CLASS nikon_e2100() { uchar t[12]; int i; fseek (ifp, 0, SEEK_SET); for (i=0; i < 1024; i++) { fread (t, 1, 12, ifp); if (((t[2] & t[4] & t[7] & t[9]) >> 4 & t[1] & t[6] & t[8] & t[11] & 3) != 3) return 0; } return 1; } void CLASS nikon_3700() { int bits, i; uchar dp[24]; static const struct { int bits; char make[12], model[15]; } table[] = { { 0x00, "PENTAX", "Optio 33WR" }, { 0x03, "NIKON", "E3200" }, { 0x32, "NIKON", "E3700" }, { 0x33, "OLYMPUS", "C740UZ" } }; fseek (ifp, 3072, SEEK_SET); fread (dp, 1, 24, ifp); bits = (dp[8] & 3) << 4 | (dp[20] & 3); for (i=0; i < sizeof table / sizeof *table; i++) if (bits == table[i].bits) { strcpy (make, table[i].make ); strcpy (model, table[i].model); } } /* Separates a Minolta DiMAGE Z2 from a Nikon E4300. */ int CLASS minolta_z2() { int i, nz; char tail[424]; fseek (ifp, -sizeof tail, SEEK_END); fread (tail, 1, sizeof tail, ifp); for (nz=i=0; i < sizeof tail; i++) if (tail[i]) nz++; return nz > 20; } /* Here raw_width is in bytes, not pixels. */ void CLASS nikon_e900_load_raw() { int offset=0, irow, row, col; for (irow=0; irow < height; irow++) { row = irow * 2 % height; if (row == 1) offset = - (-offset & -4096); fseek (ifp, offset, SEEK_SET); offset += raw_width; getbits(-1); for (col=0; col < width; col++) BAYER(row,col) = getbits(10); } } /* The Fuji Super CCD is just a Bayer grid rotated 45 degrees. */ void CLASS fuji_load_raw() { ushort *pixel; int wide, row, col, r, c; fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR); wide = fuji_width << !fuji_layout; pixel = (ushort *) calloc (wide, sizeof *pixel); merror (pixel, "fuji_load_raw()"); for (row=0; row < raw_height; row++) { read_shorts (pixel, wide); fseek (ifp, 2*(raw_width - wide), SEEK_CUR); for (col=0; col < wide; col++) { if (fuji_layout) { r = fuji_width - 1 - col + (row >> 1); c = col + ((row+1) >> 1); } else { r = fuji_width - 1 + row - (col >> 1); c = row + ((col+1) >> 1); } BAYER(r,c) = pixel[col]; } } free (pixel); } void CLASS jpeg_thumb(); void CLASS ppm_thumb() { char *thumb; thumb_length = thumb_width*thumb_height*3; thumb = (char *) malloc (thumb_length); merror (thumb, "ppm_thumb()"); fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height); fread (thumb, 1, thumb_length, ifp); fwrite (thumb, 1, thumb_length, ofp); free (thumb); } void CLASS layer_thumb() { int i, c; char *thumb, map[][4] = { "012","102" }; colors = thumb_misc >> 5 & 7; thumb_length = thumb_width*thumb_height; thumb = (char *) calloc (colors, thumb_length); merror (thumb, "layer_thumb()"); fprintf (ofp, "P%d\n%d %d\n255\n", 5 + (colors >> 1), thumb_width, thumb_height); fread (thumb, thumb_length, colors, ifp); for (i=0; i < thumb_length; i++) FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], ofp); free (thumb); } void CLASS rollei_thumb() { unsigned i; ushort *thumb; thumb_length = thumb_width * thumb_height; thumb = (ushort *) calloc (thumb_length, 2); merror (thumb, "rollei_thumb()"); fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height); read_shorts (thumb, thumb_length); for (i=0; i < thumb_length; i++) { putc (thumb[i] << 3, ofp); putc (thumb[i] >> 5 << 2, ofp); putc (thumb[i] >> 11 << 3, ofp); } free (thumb); } void CLASS rollei_load_raw() { uchar pixel[10]; unsigned iten=0, isix, i, buffer=0, row, col, todo[16]; isix = raw_width * raw_height * 5 / 8; while (fread (pixel, 1, 10, ifp) == 10) { for (i=0; i < 10; i+=2) { todo[i] = iten++; todo[i+1] = pixel[i] << 8 | pixel[i+1]; buffer = pixel[i] >> 2 | buffer << 6; } for ( ; i < 16; i+=2) { todo[i] = isix++; todo[i+1] = buffer >> (14-i)*5; } for (i=0; i < 16; i+=2) { row = todo[i] / raw_width - top_margin; col = todo[i] % raw_width - left_margin; if (row < height && col < width) BAYER(row,col) = (todo[i+1] & 0x3ff); } } maximum = 0x3ff; } int CLASS bayer (unsigned row, unsigned col) { return (row < height && col < width) ? BAYER(row,col) : 0; } void CLASS phase_one_flat_field (int is_float, int nc) { ushort head[8]; unsigned wide, y, x, c, rend, cend, row, col; float *mrow, num, mult[4]; read_shorts (head, 8); wide = head[2] / head[4]; mrow = (float *) calloc (nc*wide, sizeof *mrow); merror (mrow, "phase_one_flat_field()"); for (y=0; y < head[3] / head[5]; y++) { for (x=0; x < wide; x++) for (c=0; c < nc; c+=2) { num = is_float ? getreal(11) : get2()/32768.0; if (y==0) mrow[c*wide+x] = num; else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5]; } if (y==0) continue; rend = head[1]-top_margin + y*head[5]; for (row = rend-head[5]; row < height && row < rend; row++) { for (x=1; x < wide; x++) { for (c=0; c < nc; c+=2) { mult[c] = mrow[c*wide+x-1]; mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4]; } cend = head[0]-left_margin + x*head[4]; for (col = cend-head[4]; col < width && col < cend; col++) { c = nc > 2 ? FC(row,col) : 0; if (!(c & 1)) { c = BAYER(row,col) * mult[c]; BAYER(row,col) = LIM(c,0,65535); } for (c=0; c < nc; c+=2) mult[c] += mult[c+1]; } } for (x=0; x < wide; x++) for (c=0; c < nc; c+=2) mrow[c*wide+x] += mrow[(c+1)*wide+x]; } } free (mrow); } void CLASS phase_one_correct() { unsigned entries, tag, data, save, col, row, type; int len, i, j, k, cip, val[4], dev[4], sum, max; int head[9], diff, mindiff=INT_MAX, off_412=0; static const signed char dir[12][2] = { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0}, {-2,-2}, {-2,2}, {2,-2}, {2,2} }; float poly[8], num, cfrac, frac, mult[2], *yval[2]; ushort *xval[2]; if (half_size || !meta_length) return; if (verbose) fprintf (stderr,_("Phase One correction...\n")); fseek (ifp, meta_offset, SEEK_SET); order = get2(); fseek (ifp, 6, SEEK_CUR); fseek (ifp, meta_offset+get4(), SEEK_SET); entries = get4(); get4(); while (entries--) { tag = get4(); len = get4(); data = get4(); save = ftell(ifp); fseek (ifp, meta_offset+data, SEEK_SET); if (tag == 0x419) { /* Polynomial curve */ for (get4(), i=0; i < 8; i++) poly[i] = getreal(11); poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1; for (i=0; i < 0x10000; i++) { num = (poly[5]*i + poly[3])*i + poly[1]; curve[i] = LIM(num,0,65535); } goto apply; /* apply to right half */ } else if (tag == 0x41a) { /* Polynomial curve */ for (i=0; i < 4; i++) poly[i] = getreal(11); for (i=0; i < 0x10000; i++) { for (num=0, j=4; j--; ) num = num * i + poly[j]; curve[i] = LIM(num+i,0,65535); } apply: /* apply to whole image */ for (row=0; row < height; row++) for (col = (tag & 1)*ph1.split_col; col < width; col++) BAYER(row,col) = curve[BAYER(row,col)]; } else if (tag == 0x400) { /* Sensor defects */ while ((len -= 8) >= 0) { col = get2() - left_margin; row = get2() - top_margin; type = get2(); get2(); if (col >= width) continue; if (type == 131) /* Bad column */ for (row=0; row < height; row++) if (FC(row,col) == 1) { for (sum=i=0; i < 4; i++) sum += val[i] = bayer (row+dir[i][0], col+dir[i][1]); for (max=i=0; i < 4; i++) { dev[i] = abs((val[i] << 2) - sum); if (dev[max] < dev[i]) max = i; } BAYER(row,col) = (sum - val[max])/3.0 + 0.5; } else { for (sum=0, i=8; i < 12; i++) sum += bayer (row+dir[i][0], col+dir[i][1]); BAYER(row,col) = 0.5 + sum * 0.0732233 + (bayer(row,col-2) + bayer(row,col+2)) * 0.3535534; } else if (type == 129) { /* Bad pixel */ if (row >= height) continue; j = (FC(row,col) != 1) * 4; for (sum=0, i=j; i < j+8; i++) sum += bayer (row+dir[i][0], col+dir[i][1]); BAYER(row,col) = (sum + 4) >> 3; } } } else if (tag == 0x401) { /* All-color flat fields */ phase_one_flat_field (1, 2); } else if (tag == 0x416 || tag == 0x410) { phase_one_flat_field (0, 2); } else if (tag == 0x40b) { /* Red+blue flat field */ phase_one_flat_field (0, 4); } else if (tag == 0x412) { fseek (ifp, 36, SEEK_CUR); diff = abs (get2() - ph1.tag_21a); if (mindiff > diff) { mindiff = diff; off_412 = ftell(ifp) - 38; } } fseek (ifp, save, SEEK_SET); } if (off_412) { fseek (ifp, off_412, SEEK_SET); for (i=0; i < 9; i++) head[i] = get4() & 0x7fff; yval[0] = (float *) calloc (head[1]*head[3] + head[2]*head[4], 6); merror (yval[0], "phase_one_correct()"); yval[1] = (float *) (yval[0] + head[1]*head[3]); xval[0] = (ushort *) (yval[1] + head[2]*head[4]); xval[1] = (ushort *) (xval[0] + head[1]*head[3]); get2(); for (i=0; i < 2; i++) for (j=0; j < head[i+1]*head[i+3]; j++) yval[i][j] = getreal(11); for (i=0; i < 2; i++) for (j=0; j < head[i+1]*head[i+3]; j++) xval[i][j] = get2(); for (row=0; row < height; row++) for (col=0; col < width; col++) { cfrac = (float) col * head[3] / raw_width; cfrac -= cip = cfrac; num = BAYER(row,col) * 0.5; for (i=cip; i < cip+2; i++) { for (k=j=0; j < head[1]; j++) if (num < xval[0][k = head[1]*i+j]) break; frac = (j == 0 || j == head[1]) ? 0 : (xval[0][k] - num) / (xval[0][k] - xval[0][k-1]); mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac); } i = ((mult[0] * (1-cfrac) + mult[1] * cfrac) * (row + top_margin) + num) * 2; BAYER(row,col) = LIM(i,0,65535); } free (yval[0]); } } void CLASS phase_one_load_raw() { int row, col, a, b; ushort *pixel, akey, bkey, mask; fseek (ifp, ph1.key_off, SEEK_SET); akey = get2(); bkey = get2(); mask = ph1.format == 1 ? 0x5555:0x1354; fseek (ifp, data_offset + top_margin*raw_width*2, SEEK_SET); pixel = (ushort *) calloc (raw_width, sizeof *pixel); merror (pixel, "phase_one_load_raw()"); for (row=0; row < height; row++) { read_shorts (pixel, raw_width); for (col=0; col < raw_width; col+=2) { a = pixel[col+0] ^ akey; b = pixel[col+1] ^ bkey; pixel[col+0] = (a & mask) | (b & ~mask); pixel[col+1] = (b & mask) | (a & ~mask); } for (col=0; col < width; col++) BAYER(row,col) = pixel[col+left_margin]; } free (pixel); phase_one_correct(); } unsigned CLASS ph1_bithuff (int nbits, ushort *huff) { static UINT64 bitbuf=0; static int vbits=0; unsigned c; if (nbits == -1) return bitbuf = vbits = 0; if (nbits == 0) return 0; if (vbits < nbits) { bitbuf = bitbuf << 32 | get4(); vbits += 32; } c = bitbuf << (64-vbits) >> (64-nbits); if (huff) { vbits -= huff[c] >> 8; return (uchar) huff[c]; } vbits -= nbits; return c; } #define ph1_bits(n) ph1_bithuff(n,0) #define ph1_huff(h) ph1_bithuff(*h,h+1) void CLASS phase_one_load_raw_c() { static const int length[] = { 8,7,6,9,11,10,5,12,14,13 }; int *offset, len[2], pred[2], row, col, i, j; ushort *pixel; short (*black)[2]; pixel = (ushort *) calloc (raw_width + raw_height*4, 2); merror (pixel, "phase_one_load_raw_c()"); offset = (int *) (pixel + raw_width); fseek (ifp, strip_offset, SEEK_SET); for (row=0; row < raw_height; row++) offset[row] = get4(); black = (short (*)[2]) offset + raw_height; fseek (ifp, ph1.black_off, SEEK_SET); if (ph1.black_off) read_shorts ((ushort *) black[0], raw_height*2); for (i=0; i < 256; i++) curve[i] = i*i / 3.969 + 0.5; for (row=0; row < raw_height; row++) { fseek (ifp, data_offset + offset[row], SEEK_SET); ph1_bits(-1); pred[0] = pred[1] = 0; for (col=0; col < raw_width; col++) { if (col >= (raw_width & -8)) len[0] = len[1] = 14; else if ((col & 7) == 0) for (i=0; i < 2; i++) { for (j=0; j < 5 && !ph1_bits(1); j++); if (j--) len[i] = length[j*2 + ph1_bits(1)]; } if ((i = len[col & 1]) == 14) pixel[col] = pred[col & 1] = ph1_bits(16); else pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1)); if (pred[col & 1] >> 16) derror(); if (ph1.format == 5 && pixel[col] < 256) pixel[col] = curve[pixel[col]]; } if ((unsigned) (row-top_margin) < height) for (col=0; col < width; col++) { i = (pixel[col+left_margin] << 2) - ph1.black + black[row][col >= ph1.split_col]; if (i > 0) BAYER(row-top_margin,col) = i; } } free (pixel); phase_one_correct(); maximum = 0xfffc - ph1.black; } void CLASS hasselblad_load_raw() { struct jhead jh; int row, col, pred[2], len[2], diff, c; if (!ljpeg_start (&jh, 0)) return; order = 0x4949; ph1_bits(-1); for (row=-top_margin; row < height; row++) { pred[0] = pred[1] = 0x8000; for (col=-left_margin; col < raw_width-left_margin; col+=2) { FORC(2) len[c] = ph1_huff(jh.huff[0]); FORC(2) { diff = ph1_bits(len[c]); if ((diff & (1 << (len[c]-1))) == 0) diff -= (1 << len[c]) - 1; if (diff == 65535) diff = -32768; pred[c] += diff; if (row >= 0 && (unsigned)(col+c) < width) BAYER(row,col+c) = pred[c]; } } } ljpeg_end (&jh); maximum = 0xffff; } void CLASS leaf_hdr_load_raw() { ushort *pixel; unsigned tile=0, r, c, row, col; pixel = (ushort *) calloc (raw_width, sizeof *pixel); merror (pixel, "leaf_hdr_load_raw()"); FORC(tiff_samples) for (r=0; r < raw_height; r++) { if (r % tile_length == 0) { fseek (ifp, data_offset + 4*tile++, SEEK_SET); fseek (ifp, get4() + 2*left_margin, SEEK_SET); } if (filters && c != shot_select) continue; read_shorts (pixel, raw_width); if ((row = r - top_margin) >= height) continue; for (col=0; col < width; col++) if (filters) BAYER(row,col) = pixel[col]; else image[row*width+col][c] = pixel[col]; } free (pixel); if (!filters) { maximum = 0xffff; raw_color = 1; } } void CLASS unpacked_load_raw(); void CLASS sinar_4shot_load_raw() { ushort *pixel; unsigned shot, row, col, r, c; if ((shot = shot_select) || half_size) { if (shot) shot--; if (shot > 3) shot = 3; fseek (ifp, data_offset + shot*4, SEEK_SET); fseek (ifp, get4(), SEEK_SET); unpacked_load_raw(); return; } free (image); image = (ushort (*)[4]) calloc ((iheight=height)*(iwidth=width), sizeof *image); merror (image, "sinar_4shot_load_raw()"); pixel = (ushort *) calloc (raw_width, sizeof *pixel); merror (pixel, "sinar_4shot_load_raw()"); for (shot=0; shot < 4; shot++) { fseek (ifp, data_offset + shot*4, SEEK_SET); fseek (ifp, get4(), SEEK_SET); for (row=0; row < raw_height; row++) { read_shorts (pixel, raw_width); if ((r = row-top_margin - (shot >> 1 & 1)) >= height) continue; for (col=0; col < raw_width; col++) { if ((c = col-left_margin - (shot & 1)) >= width) continue; image[r*width+c][FC(row,col)] = pixel[col]; } } } free (pixel); shrink = filters = 0; } void CLASS imacon_full_load_raw() { int row, col; for (row=0; row < height; row++) for (col=0; col < width; col++) read_shorts (image[row*width+col], 3); } void CLASS packed_12_load_raw() { int vbits=0, rbits=0, bwide, bite, irow, row, col, val, i; UINT64 bitbuf=0; if (raw_width * 2 >= width * 3) { /* If raw_width is in bytes, */ rbits = (bwide = raw_width) * 8; raw_width = raw_width * 2 / 3; /* convert it to pixels and */ rbits -= raw_width * 12; /* save the remainder. */ } else bwide = raw_width * 3 / 2; if (load_flags & 1) bwide = bwide * 16 / 15; fseek (ifp, top_margin*bwide, SEEK_CUR); bite = 8 + (load_flags & 24); for (irow=0; irow < height; irow++) { row = irow; if (load_flags & 2 && (row = irow * 2 % height + irow / (height/2)) == 1 && load_flags & 4) { if (vbits=0, tiff_compress) fseek (ifp, data_offset - (-width*height*3/4 & -2048), SEEK_SET); else { fseek (ifp, 0, SEEK_END); fseek (ifp, ftell(ifp)/2, SEEK_SET); } } for (col=0; col < raw_width; col++) { for (vbits -= 12; vbits < 0; vbits += bite) { bitbuf <<= bite; for (i=0; i < bite; i+=8) bitbuf |= (unsigned) (fgetc(ifp) << i); } val = bitbuf << (52-vbits) >> 52; i = (col ^ (bite == 24)) - left_margin; if ((unsigned) i < width) BAYER(row,i) = val << (load_flags >> 6); else if (load_flags & 32) black += val; if (load_flags & 1 && (col % 10) == 9 && fgetc(ifp) && col < width+left_margin) derror(); } vbits -= rbits; } if (load_flags & 32 && raw_width > width) black /= (raw_width - width) * height; } void CLASS unpacked_load_raw() { ushort *pixel; int row, col, bits=0; while (1 << ++bits < maximum); fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR); pixel = (ushort *) calloc (width, sizeof *pixel); merror (pixel, "unpacked_load_raw()"); for (row=0; row < height; row++) { read_shorts (pixel, width); fseek (ifp, 2*(raw_width - width), SEEK_CUR); for (col=0; col < width; col++) if ((BAYER2(row,col) = pixel[col]) >> bits) derror(); } free (pixel); } void CLASS nokia_load_raw() { uchar *data, *dp; ushort *pixel, *pix; int dwide, row, c; dwide = raw_width * 5 / 4; data = (uchar *) malloc (dwide + raw_width*2); merror (data, "nokia_load_raw()"); pixel = (ushort *) (data + dwide); for (row=0; row < raw_height; row++) { if (fread (data, 1, dwide, ifp) < dwide) derror(); for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=5, pix+=4) FORC4 pix[c] = (dp[c] << 2) | (dp[4] >> (c << 1) & 3); if (row < top_margin) FORC(width) black += pixel[c]; else FORC(width) BAYER(row-top_margin,c) = pixel[c]; } free (data); if (top_margin) black /= top_margin * width; maximum = 0x3ff; } unsigned CLASS pana_bits (int nbits) { static uchar buf[0x4000]; static int vbits; int byte; if (!nbits) return vbits=0; if (!vbits) { fread (buf+load_flags, 1, 0x4000-load_flags, ifp); fread (buf, 1, load_flags, ifp); } vbits = (vbits - nbits) & 0x1ffff; byte = vbits >> 3 ^ 0x3ff0; return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits); } void CLASS panasonic_load_raw() { int row, col, i, j, sh=0, pred[2], nonz[2]; pana_bits(0); for (row=0; row < height; row++) for (col=0; col < raw_width; col++) { if ((i = col % 14) == 0) pred[0] = pred[1] = nonz[0] = nonz[1] = 0; if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2)); if (nonz[i & 1]) { if ((j = pana_bits(8))) { if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4) pred[i & 1] &= ~(-1 << sh); pred[i & 1] += j << sh; } } else if ((nonz[i & 1] = pana_bits(8)) || i > 11) pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4); if (col < width) if ((BAYER(row,col) = pred[col & 1]) > 4098) derror(); } } void CLASS olympus_e410_load_raw() { ushort huff[4096]; int row, col, nbits, sign, low, high, i, c, w, n, nw; int acarry[2][3], *carry, pred, diff; huff[n=0] = 0xc0c; for (i=12; i--; ) FORC(2048 >> i) huff[++n] = (i+1) << 8 | i; fseek (ifp, 7, SEEK_CUR); getbits(-1); for (row=0; row < height; row++) { memset (acarry, 0, sizeof acarry); for (col=0; col < raw_width; col++) { carry = acarry[col & 1]; i = 2 * (carry[2] < 3); for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++); low = (sign = getbits(3)) & 3; sign = sign << 29 >> 31; if ((high = getbithuff(12,huff)) == 12) high = getbits(16-nbits) >> 1; carry[0] = (high << nbits) | getbits(nbits); diff = (carry[0] ^ sign) + carry[1]; carry[1] = (diff*3 + carry[1]) >> 5; carry[2] = carry[0] > 16 ? 0 : carry[2]+1; if (col >= width) continue; if (row < 2 && col < 2) pred = 0; else if (row < 2) pred = BAYER(row,col-2); else if (col < 2) pred = BAYER(row-2,col); else { w = BAYER(row,col-2); n = BAYER(row-2,col); nw = BAYER(row-2,col-2); if ((w < nw && nw < n) || (n < nw && nw < w)) { if (ABS(w-nw) > 32 || ABS(n-nw) > 32) pred = w + n - nw; else pred = (w + n) >> 1; } else pred = ABS(w-nw) > ABS(n-nw) ? w : n; } if ((BAYER(row,col) = pred + ((diff << 2) | low)) >> 12) derror(); } } } void CLASS minolta_rd175_load_raw() { uchar pixel[768]; unsigned irow, box, row, col; for (irow=0; irow < 1481; irow++) { if (fread (pixel, 1, 768, ifp) < 768) derror(); box = irow / 82; row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box-12)*2); switch (irow) { case 1477: case 1479: continue; case 1476: row = 984; break; case 1480: row = 985; break; case 1478: row = 985; box = 1; } if ((box < 12) && (box & 1)) { for (col=0; col < 1533; col++, row ^= 1) if (col != 1) BAYER(row,col) = (col+1) & 2 ? pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1; BAYER(row,1) = pixel[1] << 1; BAYER(row,1533) = pixel[765] << 1; } else for (col=row & 1; col < 1534; col+=2) BAYER(row,col) = pixel[col/2] << 1; } maximum = 0xff << 1; } void CLASS casio_qv5700_load_raw() { uchar data[3232], *dp; ushort pixel[2576], *pix; int row, col; for (row=0; row < height; row++) { fread (data, 1, 3232, ifp); for (dp=data, pix=pixel; dp < data+3220; dp+=5, pix+=4) { pix[0] = (dp[0] << 2) + (dp[1] >> 6); pix[1] = (dp[1] << 4) + (dp[2] >> 4); pix[2] = (dp[2] << 6) + (dp[3] >> 2); pix[3] = (dp[3] << 8) + (dp[4] ); } for (col=0; col < width; col++) BAYER(row,col) = (pixel[col] & 0x3ff); } maximum = 0x3fc; } void CLASS quicktake_100_load_raw() { uchar pixel[484][644]; static const short gstep[16] = { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 }; static const short rstep[6][4] = { { -3,-1,1,3 }, { -5,-1,1,5 }, { -8,-2,2,8 }, { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } }; static const short curve[256] = { 0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27, 28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,53, 54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78, 79,80,81,82,83,84,86,88,90,92,94,97,99,101,103,105,107,110,112,114,116, 118,120,123,125,127,129,131,134,136,138,140,142,144,147,149,151,153,155, 158,160,162,164,166,168,171,173,175,177,179,181,184,186,188,190,192,195, 197,199,201,203,205,208,210,212,214,216,218,221,223,226,230,235,239,244, 248,252,257,261,265,270,274,278,283,287,291,296,300,305,309,313,318,322, 326,331,335,339,344,348,352,357,361,365,370,374,379,383,387,392,396,400, 405,409,413,418,422,426,431,435,440,444,448,453,457,461,466,470,474,479, 483,487,492,496,500,508,519,531,542,553,564,575,587,598,609,620,631,643, 654,665,676,687,698,710,721,732,743,754,766,777,788,799,810,822,833,844, 855,866,878,889,900,911,922,933,945,956,967,978,989,1001,1012,1023 }; int rb, row, col, sharp, val=0; getbits(-1); memset (pixel, 0x80, sizeof pixel); for (row=2; row < height+2; row++) { for (col=2+(row & 1); col < width+2; col+=2) { val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] + pixel[row][col-2]) >> 2) + gstep[getbits(4)]; pixel[row][col] = val = LIM(val,0,255); if (col < 4) pixel[row][col-2] = pixel[row+1][~row & 1] = val; if (row == 2) pixel[row-1][col+1] = pixel[row-1][col+3] = val; } pixel[row][col] = val; } for (rb=0; rb < 2; rb++) for (row=2+rb; row < height+2; row+=2) for (col=3-(row & 1); col < width+2; col+=2) { if (row < 4 || col < 4) sharp = 2; else { val = ABS(pixel[row-2][col] - pixel[row][col-2]) + ABS(pixel[row-2][col] - pixel[row-2][col-2]) + ABS(pixel[row][col-2] - pixel[row-2][col-2]); sharp = val < 4 ? 0 : val < 8 ? 1 : val < 16 ? 2 : val < 32 ? 3 : val < 48 ? 4 : 5; } val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1) + rstep[sharp][getbits(2)]; pixel[row][col] = val = LIM(val,0,255); if (row < 4) pixel[row-2][col+2] = val; if (col < 4) pixel[row+2][col-2] = val; } for (row=2; row < height+2; row++) for (col=3-(row & 1); col < width+2; col+=2) { val = ((pixel[row][col-1] + (pixel[row][col] << 2) + pixel[row][col+1]) >> 1) - 0x100; pixel[row][col] = LIM(val,0,255); } for (row=0; row < height; row++) for (col=0; col < width; col++) BAYER(row,col) = curve[pixel[row+2][col+2]]; maximum = 0x3ff; } #define radc_token(tree) ((signed char) getbithuff(8,huff[tree])) #define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--) #define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \ : (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4) void CLASS kodak_radc_load_raw() { static const char src[] = { 1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8, 1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8, 2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8, 2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8, 2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8, 2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8, 2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8, 2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8, 2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4, 2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8, 1,0, 2,2, 2,-2, 1,-3, 1,3, 2,-17, 2,-5, 2,5, 2,17, 2,-7, 2,2, 2,9, 2,18, 2,-18, 2,-9, 2,-2, 2,7, 2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79, 2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76, 2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37 }; ushort huff[19][256]; int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val; short last[3] = { 16,16,16 }, mul[3], buf[3][3][386]; static const ushort pt[] = { 0,0, 1280,1344, 2320,3616, 3328,8000, 4095,16383, 65535,16383 }; for (i=2; i < 12; i+=2) for (c=pt[i-2]; c <= pt[i]; c++) curve[c] = (float) (c-pt[i-2]) / (pt[i]-pt[i-2]) * (pt[i+1]-pt[i-1]) + pt[i-1] + 0.5; for (s=i=0; i < sizeof src; i+=2) FORC(256 >> src[i]) huff[0][s++] = src[i] << 8 | (uchar) src[i+1]; s = kodak_cbpp == 243 ? 2 : 3; FORC(256) huff[18][c] = (8-s) << 8 | c >> s << s | 1 << (s-1); getbits(-1); for (i=0; i < sizeof(buf)/sizeof(short); i++) buf[0][0][i] = 2048; for (row=0; row < height; row+=4) { FORC3 mul[c] = getbits(6); FORC3 { val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c]; s = val > 65564 ? 10:12; x = ~(-1 << (s-1)); val <<= 12-s; for (i=0; i < sizeof(buf[0])/sizeof(short); i++) buf[c][0][i] = (buf[c][0][i] * val + x) >> s; last[c] = mul[c]; for (r=0; r <= !c; r++) { buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7; for (tree=1, col=width/2; col > 0; ) { if ((tree = radc_token(tree))) { col -= 2; if (tree == 8) FORYX buf[c][y][x] = (uchar) radc_token(18) * mul[c]; else FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR; } else do { nreps = (col > 2) ? radc_token(9) + 1 : 1; for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) { col -= 2; FORYX buf[c][y][x] = PREDICTOR; if (rep & 1) { step = radc_token(10) << 4; FORYX buf[c][y][x] += step; } } } while (nreps == 9); } for (y=0; y < 2; y++) for (x=0; x < width/2; x++) { val = (buf[c][y+1][x] << 4) / mul[c]; if (val < 0) val = 0; if (c) BAYER(row+y*2+c-1,x*2+2-c) = val; else BAYER(row+r*2+y,x*2+y) = val; } memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c); } } for (y=row; y < row+4; y++) for (x=0; x < width; x++) if ((x+y) & 1) { r = x ? x-1 : x+1; s = x+1 < width ? x+1 : x-1; val = (BAYER(y,x)-2048)*2 + (BAYER(y,r)+BAYER(y,s))/2; if (val < 0) val = 0; BAYER(y,x) = val; } } for (i=0; i < iheight*iwidth*4; i++) image[0][i] = curve[image[0][i]]; maximum = 0x3fff; } #undef FORYX #undef PREDICTOR #ifdef NO_JPEG void CLASS kodak_jpeg_load_raw() {} #else METHODDEF(boolean) fill_input_buffer (j_decompress_ptr cinfo) { static uchar jpeg_buffer[4096]; size_t nbytes; nbytes = fread (jpeg_buffer, 1, 4096, ifp); swab (jpeg_buffer, jpeg_buffer, nbytes); cinfo->src->next_input_byte = jpeg_buffer; cinfo->src->bytes_in_buffer = nbytes; return TRUE; } void CLASS kodak_jpeg_load_raw() { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPARRAY buf; JSAMPLE (*pixel)[3]; int row, col; cinfo.err = jpeg_std_error (&jerr); jpeg_create_decompress (&cinfo); jpeg_stdio_src (&cinfo, ifp); cinfo.src->fill_input_buffer = fill_input_buffer; jpeg_read_header (&cinfo, TRUE); jpeg_start_decompress (&cinfo); if ((cinfo.output_width != width ) || (cinfo.output_height*2 != height ) || (cinfo.output_components != 3 )) { fprintf (stderr,_("%s: incorrect JPEG dimensions\n"), ifname); jpeg_destroy_decompress (&cinfo); longjmp (failure, 3); } buf = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, width*3, 1); while (cinfo.output_scanline < cinfo.output_height) { row = cinfo.output_scanline * 2; jpeg_read_scanlines (&cinfo, buf, 1); pixel = (JSAMPLE (*)[3]) buf[0]; for (col=0; col < width; col+=2) { BAYER(row+0,col+0) = pixel[col+0][1] << 1; BAYER(row+1,col+1) = pixel[col+1][1] << 1; BAYER(row+0,col+1) = pixel[col][0] + pixel[col+1][0]; BAYER(row+1,col+0) = pixel[col][2] + pixel[col+1][2]; } } jpeg_finish_decompress (&cinfo); jpeg_destroy_decompress (&cinfo); maximum = 0xff << 1; } #endif void CLASS kodak_dc120_load_raw() { static const int mul[4] = { 162, 192, 187, 92 }; static const int add[4] = { 0, 636, 424, 212 }; uchar pixel[848]; int row, shift, col; for (row=0; row < height; row++) { if (fread (pixel, 1, 848, ifp) < 848) derror(); shift = row * mul[row & 3] + add[row & 3]; for (col=0; col < width; col++) BAYER(row,col) = (ushort) pixel[(col + shift) % 848]; } maximum = 0xff; } void CLASS eight_bit_load_raw() { uchar *pixel; unsigned row, col, val, lblack=0; pixel = (uchar *) calloc (raw_width, sizeof *pixel); merror (pixel, "eight_bit_load_raw()"); fseek (ifp, top_margin*raw_width, SEEK_CUR); for (row=0; row < height; row++) { if (fread (pixel, 1, raw_width, ifp) < raw_width) derror(); for (col=0; col < raw_width; col++) { val = curve[pixel[col]]; if ((unsigned) (col-left_margin) < width) BAYER(row,col-left_margin) = val; else lblack += val; } } free (pixel); if (raw_width > width+1) black = lblack / ((raw_width - width) * height); if (!strncmp(model,"DC2",3)) black = 0; maximum = curve[0xff]; } void CLASS kodak_yrgb_load_raw() { uchar *pixel; int row, col, y, cb, cr, rgb[3], c; pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel); merror (pixel, "kodak_yrgb_load_raw()"); for (row=0; row < height; row++) { if (~row & 1) if (fread (pixel, raw_width, 3, ifp) < 3) derror(); for (col=0; col < raw_width; col++) { y = pixel[width*2*(row & 1) + col]; cb = pixel[width + (col & -2)] - 128; cr = pixel[width + (col & -2)+1] - 128; rgb[1] = y-((cb + cr + 2) >> 2); rgb[2] = rgb[1] + cb; rgb[0] = rgb[1] + cr; FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,255)]; } } free (pixel); maximum = curve[0xff]; } void CLASS kodak_262_load_raw() { static const uchar kodak_tree[2][26] = { { 0,1,5,1,1,2,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 }, { 0,3,1,1,1,1,1,2,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 } }; ushort *huff[2]; uchar *pixel; int *strip, ns, c, row, col, chess, pi=0, pi1, pi2, pred, val; FORC(2) huff[c] = make_decoder (kodak_tree[c]); ns = (raw_height+63) >> 5; pixel = (uchar *) malloc (raw_width*32 + ns*4); merror (pixel, "kodak_262_load_raw()"); strip = (int *) (pixel + raw_width*32); order = 0x4d4d; FORC(ns) strip[c] = get4(); for (row=0; row < raw_height; row++) { if ((row & 31) == 0) { fseek (ifp, strip[row >> 5], SEEK_SET); getbits(-1); pi = 0; } for (col=0; col < raw_width; col++) { chess = (row + col) & 1; pi1 = chess ? pi-2 : pi-raw_width-1; pi2 = chess ? pi-2*raw_width : pi-raw_width+1; if (col <= chess) pi1 = -1; if (pi1 < 0) pi1 = pi2; if (pi2 < 0) pi2 = pi1; if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2; pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1; pixel[pi] = val = pred + ljpeg_diff (huff[chess]); if (val >> 8) derror(); val = curve[pixel[pi++]]; if ((unsigned) (col-left_margin) < width) BAYER(row,col-left_margin) = val; else black += val; } } free (pixel); FORC(2) free (huff[c]); if (raw_width > width) black /= (raw_width - width) * height; } int CLASS kodak_65000_decode (short *out, int bsize) { uchar c, blen[768]; ushort raw[6]; INT64 bitbuf=0; int save, bits=0, i, j, len, diff; save = ftell(ifp); bsize = (bsize + 3) & -4; for (i=0; i < bsize; i+=2) { c = fgetc(ifp); if ((blen[i ] = c & 15) > 12 || (blen[i+1] = c >> 4) > 12 ) { fseek (ifp, save, SEEK_SET); for (i=0; i < bsize; i+=8) { read_shorts (raw, 6); out[i ] = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12; out[i+1] = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12; for (j=0; j < 6; j++) out[i+2+j] = raw[j] & 0xfff; } return 1; } } if ((bsize & 7) == 4) { bitbuf = fgetc(ifp) << 8; bitbuf += fgetc(ifp); bits = 16; } for (i=0; i < bsize; i++) { len = blen[i]; if (bits < len) { for (j=0; j < 32; j+=8) bitbuf += (INT64) fgetc(ifp) << (bits+(j^8)); bits += 32; } diff = bitbuf & (0xffff >> (16-len)); bitbuf >>= len; bits -= len; if ((diff & (1 << (len-1))) == 0) diff -= (1 << len) - 1; out[i] = diff; } return 0; } void CLASS kodak_65000_load_raw() { short buf[256]; int row, col, len, pred[2], ret, i; for (row=0; row < height; row++) for (col=0; col < width; col+=256) { pred[0] = pred[1] = 0; len = MIN (256, width-col); ret = kodak_65000_decode (buf, len); for (i=0; i < len; i++) if ((BAYER(row,col+i) = curve[ret ? buf[i] : (pred[i & 1] += buf[i])]) >> 12) derror(); } } void CLASS kodak_ycbcr_load_raw() { short buf[384], *bp; int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3]; ushort *ip; for (row=0; row < height; row+=2) for (col=0; col < width; col+=128) { len = MIN (128, width-col); kodak_65000_decode (buf, len*3); y[0][1] = y[1][1] = cb = cr = 0; for (bp=buf, i=0; i < len; i+=2, bp+=2) { cb += bp[4]; cr += bp[5]; rgb[1] = -((cb + cr + 2) >> 2); rgb[2] = rgb[1] + cb; rgb[0] = rgb[1] + cr; for (j=0; j < 2; j++) for (k=0; k < 2; k++) { if ((y[j][k] = y[j][k^1] + *bp++) >> 10) derror(); ip = image[(row+j)*width + col+i+k]; FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)]; } } } } void CLASS kodak_rgb_load_raw() { short buf[768], *bp; int row, col, len, c, i, rgb[3]; ushort *ip=image[0]; for (row=0; row < height; row++) for (col=0; col < width; col+=256) { len = MIN (256, width-col); kodak_65000_decode (buf, len*3); memset (rgb, 0, sizeof rgb); for (bp=buf, i=0; i < len; i++, ip+=4) FORC3 if ((ip[c] = rgb[c] += *bp++) >> 12) derror(); } } void CLASS kodak_thumb_load_raw() { int row, col; colors = thumb_misc >> 5; for (row=0; row < height; row++) for (col=0; col < width; col++) read_shorts (image[row*width+col], colors); maximum = (1 << (thumb_misc & 31)) - 1; } void CLASS sony_decrypt (unsigned *data, int len, int start, int key) { static unsigned pad[128], p; if (start) { for (p=0; p < 4; p++) pad[p] = key = key * 48828125 + 1; pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31; for (p=4; p < 127; p++) pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31; for (p=0; p < 127; p++) pad[p] = htonl(pad[p]); } while (len--) *data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127]; } void CLASS sony_load_raw() { uchar head[40]; ushort *pixel; unsigned i, key, row, col; fseek (ifp, 200896, SEEK_SET); fseek (ifp, (unsigned) fgetc(ifp)*4 - 1, SEEK_CUR); order = 0x4d4d; key = get4(); fseek (ifp, 164600, SEEK_SET); fread (head, 1, 40, ifp); sony_decrypt ((unsigned int *) head, 10, 1, key); for (i=26; i-- > 22; ) key = key << 8 | head[i]; fseek (ifp, data_offset, SEEK_SET); pixel = (ushort *) calloc (raw_width, sizeof *pixel); merror (pixel, "sony_load_raw()"); for (row=0; row < height; row++) { if (fread (pixel, 2, raw_width, ifp) < raw_width) derror(); sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key); for (col=9; col < left_margin; col++) black += ntohs(pixel[col]); for (col=0; col < width; col++) if ((BAYER(row,col) = ntohs(pixel[col+left_margin])) >> 14) derror(); } free (pixel); if (left_margin > 9) black /= (left_margin-9) * height; maximum = 0x3ff0; } void CLASS sony_arw_load_raw() { ushort huff[32768]; static const ushort tab[18] = { 0xf11,0xf10,0xe0f,0xd0e,0xc0d,0xb0c,0xa0b,0x90a,0x809, 0x708,0x607,0x506,0x405,0x304,0x303,0x300,0x202,0x201 }; int i, c, n, col, row, len, diff, sum=0; for (n=i=0; i < 18; i++) FORC(32768 >> (tab[i] >> 8)) huff[n++] = tab[i]; getbits(-1); for (col = raw_width; col--; ) for (row=0; row < raw_height+1; row+=2) { if (row == raw_height) row = 1; len = getbithuff(15,huff); diff = getbits(len); if ((diff & (1 << (len-1))) == 0) diff -= (1 << len) - 1; if ((sum += diff) >> 12) derror(); if (row < height) BAYER(row,col) = sum; } } void CLASS sony_arw2_load_raw() { uchar *data, *dp; ushort pix[16]; int row, col, val, max, min, imax, imin, sh, bit, i; data = (uchar *) malloc (raw_width); merror (data, "sony_arw2_load_raw()"); for (row=0; row < height; row++) { fread (data, 1, raw_width, ifp); for (dp=data, col=0; col < width-30; dp+=16) { max = 0x7ff & (val = sget4(dp)); min = 0x7ff & val >> 11; imax = 0x0f & val >> 22; imin = 0x0f & val >> 26; for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++); for (bit=30, i=0; i < 16; i++) if (i == imax) pix[i] = max; else if (i == imin) pix[i] = min; else { pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min; if (pix[i] > 0x7ff) pix[i] = 0x7ff; bit += 7; } for (i=0; i < 16; i++, col+=2) BAYER(row,col) = curve[pix[i] << 1] >> 1; col -= col & 1 ? 1:31; } } free (data); } #define HOLE(row) ((holes >> (((row) - raw_height) & 7)) & 1) /* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */ void CLASS smal_decode_segment (unsigned seg[2][2], int holes) { uchar hist[3][13] = { { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 }, { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 }, { 3, 3, 0, 0, 63, 47, 31, 15, 0 } }; int low, high=0xff, carry=0, nbits=8; int s, count, bin, next, i, sym[3]; uchar diff, pred[]={0,0}; ushort data=0, range=0; unsigned pix, row, col; fseek (ifp, seg[0][1]+1, SEEK_SET); getbits(-1); for (pix=seg[0][0]; pix < seg[1][0]; pix++) { for (s=0; s < 3; s++) { data = data << nbits | getbits(nbits); if (carry < 0) carry = (nbits += carry+1) < 1 ? nbits-1 : 0; while (--nbits >= 0) if ((data >> nbits & 0xff) == 0xff) break; if (nbits > 0) data = ((data & ((1 << (nbits-1)) - 1)) << 1) | ((data + (((data & (1 << (nbits-1)))) << 1)) & (-1 << nbits)); if (nbits >= 0) { data += getbits(1); carry = nbits - 8; } count = ((((data-range+1) & 0xffff) << 2) - 1) / (high >> 4); for (bin=0; hist[s][bin+5] > count; bin++); low = hist[s][bin+5] * (high >> 4) >> 2; if (bin) high = hist[s][bin+4] * (high >> 4) >> 2; high -= low; for (nbits=0; high << nbits < 128; nbits++); range = (range+low) << nbits; high <<= nbits; next = hist[s][1]; if (++hist[s][2] > hist[s][3]) { next = (next+1) & hist[s][0]; hist[s][3] = (hist[s][next+4] - hist[s][next+5]) >> 2; hist[s][2] = 1; } if (hist[s][hist[s][1]+4] - hist[s][hist[s][1]+5] > 1) { if (bin < hist[s][1]) for (i=bin; i < hist[s][1]; i++) hist[s][i+5]--; else if (next <= bin) for (i=hist[s][1]; i < bin; i++) hist[s][i+5]++; } hist[s][1] = next; sym[s] = bin; } diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3); if (sym[0] & 4) diff = diff ? -diff : 0x80; if (ftell(ifp) + 12 >= seg[1][1]) diff = 0; pred[pix & 1] += diff; row = pix / raw_width - top_margin; col = pix % raw_width - left_margin; if (row < height && col < width) BAYER(row,col) = pred[pix & 1]; if (!(pix & 1) && HOLE(row)) pix += 2; } maximum = 0xff; } void CLASS smal_v6_load_raw() { unsigned seg[2][2]; fseek (ifp, 16, SEEK_SET); seg[0][0] = 0; seg[0][1] = get2(); seg[1][0] = raw_width * raw_height; seg[1][1] = INT_MAX; smal_decode_segment (seg, 0); } int CLASS median4 (int *p) { int min, max, sum, i; min = max = sum = p[0]; for (i=1; i < 4; i++) { sum += p[i]; if (min > p[i]) min = p[i]; if (max < p[i]) max = p[i]; } return (sum - min - max) >> 1; } void CLASS fill_holes (int holes) { int row, col, val[4]; for (row=2; row < height-2; row++) { if (!HOLE(row)) continue; for (col=1; col < width-1; col+=4) { val[0] = BAYER(row-1,col-1); val[1] = BAYER(row-1,col+1); val[2] = BAYER(row+1,col-1); val[3] = BAYER(row+1,col+1); BAYER(row,col) = median4(val); } for (col=2; col < width-2; col+=4) if (HOLE(row-2) || HOLE(row+2)) BAYER(row,col) = (BAYER(row,col-2) + BAYER(row,col+2)) >> 1; else { val[0] = BAYER(row,col-2); val[1] = BAYER(row,col+2); val[2] = BAYER(row-2,col); val[3] = BAYER(row+2,col); BAYER(row,col) = median4(val); } } } void CLASS smal_v9_load_raw() { unsigned seg[256][2], offset, nseg, holes, i; fseek (ifp, 67, SEEK_SET); offset = get4(); nseg = fgetc(ifp); fseek (ifp, offset, SEEK_SET); for (i=0; i < nseg*2; i++) seg[0][i] = get4() + data_offset*(i & 1); fseek (ifp, 78, SEEK_SET); holes = fgetc(ifp); fseek (ifp, 88, SEEK_SET); seg[nseg][0] = raw_height * raw_width; seg[nseg][1] = get4() + data_offset; for (i=0; i < nseg; i++) smal_decode_segment (seg+i, holes); if (holes) fill_holes (holes); } /* RESTRICTED code starts here */ void CLASS foveon_decoder (unsigned size, unsigned code) { static unsigned huff[1024]; struct decode *cur; int i, len; if (!code) { for (i=0; i < size; i++) huff[i] = get4(); memset (first_decode, 0, sizeof first_decode); free_decode = first_decode; } cur = free_decode++; if (free_decode > first_decode+2048) { fprintf (stderr,_("%s: decoder table overflow\n"), ifname); longjmp (failure, 2); } if (code) for (i=0; i < size; i++) if (huff[i] == code) { cur->leaf = i; return; } if ((len = code >> 27) > 26) return; code = (len+1) << 27 | (code & 0x3ffffff) << 1; cur->branch[0] = free_decode; foveon_decoder (size, code); cur->branch[1] = free_decode; foveon_decoder (size, code+1); } void CLASS foveon_thumb() { unsigned bwide, row, col, bitbuf=0, bit=1, c, i; char *buf; struct decode *dindex; short pred[3]; bwide = get4(); fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height); if (bwide > 0) { if (bwide < thumb_width*3) return; buf = (char *) malloc (bwide); merror (buf, "foveon_thumb()"); for (row=0; row < thumb_height; row++) { fread (buf, 1, bwide, ifp); fwrite (buf, 3, thumb_width, ofp); } free (buf); return; } foveon_decoder (256, 0); for (row=0; row < thumb_height; row++) { memset (pred, 0, sizeof pred); if (!bit) get4(); for (bit=col=0; col < thumb_width; col++) FORC3 { for (dindex=first_decode; dindex->branch[0]; ) { if ((bit = (bit-1) & 31) == 31) for (i=0; i < 4; i++) bitbuf = (bitbuf << 8) + fgetc(ifp); dindex = dindex->branch[bitbuf >> bit & 1]; } pred[c] += dindex->leaf; fputc (pred[c], ofp); } } } void CLASS foveon_load_camf() { unsigned key, i, val; fseek (ifp, meta_offset, SEEK_SET); key = get4(); fread (meta_data, 1, meta_length, ifp); for (i=0; i < meta_length; i++) { key = (key * 1597 + 51749) % 244944; val = key * (INT64) 301593171 >> 24; meta_data[i] ^= ((((key << 8) - val) >> 1) + val) >> 17; } } void CLASS foveon_load_raw() { struct decode *dindex; short diff[1024]; unsigned bitbuf=0; int pred[3], fixed, row, col, bit=-1, c, i; fixed = get4(); read_shorts ((ushort *) diff, 1024); if (!fixed) foveon_decoder (1024, 0); for (row=0; row < height; row++) { memset (pred, 0, sizeof pred); if (!bit && !fixed && atoi(model+2) < 14) get4(); for (col=bit=0; col < width; col++) { if (fixed) { bitbuf = get4(); FORC3 pred[2-c] += diff[bitbuf >> c*10 & 0x3ff]; } else FORC3 { for (dindex=first_decode; dindex->branch[0]; ) { if ((bit = (bit-1) & 31) == 31) for (i=0; i < 4; i++) bitbuf = (bitbuf << 8) + fgetc(ifp); dindex = dindex->branch[bitbuf >> bit & 1]; } pred[c] += diff[dindex->leaf]; if (pred[c] >> 16 && ~pred[c] >> 16) derror(); } FORC3 image[row*width+col][c] = pred[c]; } } if (document_mode) for (i=0; i < height*width*4; i++) if ((short) image[0][i] < 0) image[0][i] = 0; foveon_load_camf(); } const char * CLASS foveon_camf_param (const char *block, const char *param) { unsigned idx, num; char *pos, *cp, *dp; for (idx=0; idx < meta_length; idx += sget4(pos+8)) { pos = meta_data + idx; if (strncmp (pos, "CMb", 3)) break; if (pos[3] != 'P') continue; if (strcmp (block, pos+sget4(pos+12))) continue; cp = pos + sget4(pos+16); num = sget4(cp); dp = pos + sget4(cp+4); while (num--) { cp += 8; if (!strcmp (param, dp+sget4(cp))) return dp+sget4(cp+4); } } return 0; } void * CLASS foveon_camf_matrix (unsigned dim[3], const char *name) { unsigned i, idx, type, ndim, size, *mat; char *pos, *cp, *dp; double dsize; for (idx=0; idx < meta_length; idx += sget4(pos+8)) { pos = meta_data + idx; if (strncmp (pos, "CMb", 3)) break; if (pos[3] != 'M') continue; if (strcmp (name, pos+sget4(pos+12))) continue; dim[0] = dim[1] = dim[2] = 1; cp = pos + sget4(pos+16); type = sget4(cp); if ((ndim = sget4(cp+4)) > 3) break; dp = pos + sget4(cp+8); for (i=ndim; i--; ) { cp += 12; dim[i] = sget4(cp); } if ((dsize = (double) dim[0]*dim[1]*dim[2]) > meta_length/4) break; mat = (unsigned *) malloc ((size = dsize) * 4); merror (mat, "foveon_camf_matrix()"); for (i=0; i < size; i++) if (type && type != 6) mat[i] = sget4(dp + i*4); else mat[i] = sget4(dp + i*2) & 0xffff; return mat; } fprintf (stderr,_("%s: \"%s\" matrix not found!\n"), ifname, name); return 0; } int CLASS foveon_fixed (void *ptr, int size, const char *name) { void *dp; unsigned dim[3]; dp = foveon_camf_matrix (dim, name); if (!dp) return 0; memcpy (ptr, dp, size*4); free (dp); return 1; } float CLASS foveon_avg (short *pix, int range[2], float cfilt) { int i; float val, min=FLT_MAX, max=-FLT_MAX, sum=0; for (i=range[0]; i <= range[1]; i++) { sum += val = pix[i*4] + (pix[i*4]-pix[(i-1)*4]) * cfilt; if (min > val) min = val; if (max < val) max = val; } if (range[1] - range[0] == 1) return sum/2; return (sum - min - max) / (range[1] - range[0] - 1); } short * CLASS foveon_make_curve (double max, double mul, double filt) { short *curve; unsigned i, size; double x; if (!filt) filt = 0.8; size = 4*M_PI*max / filt; if (size == UINT_MAX) size--; curve = (short *) calloc (size+1, sizeof *curve); merror (curve, "foveon_make_curve()"); curve[0] = size; for (i=0; i < size; i++) { x = i*filt/max/4; curve[i+1] = (cos(x)+1)/2 * tanh(i*filt/mul) * mul + 0.5; } return curve; } void CLASS foveon_make_curves (short **curvep, float dq[3], float div[3], float filt) { double mul[3], max=0; int c; FORC3 mul[c] = dq[c]/div[c]; FORC3 if (max < mul[c]) max = mul[c]; FORC3 curvep[c] = foveon_make_curve (max, mul[c], filt); } int CLASS foveon_apply_curve (short *curve, int i) { if (abs(i) >= curve[0]) return 0; return i < 0 ? -curve[1-i] : curve[1+i]; } #define image ((short (*)[4]) image) void CLASS foveon_interpolate() { static const short hood[] = { -1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1 }; short *pix, prev[3], *curve[8], (*shrink)[3]; float cfilt=0, ddft[3][3][2], ppm[3][3][3]; float cam_xyz[3][3], correct[3][3], last[3][3], trans[3][3]; float chroma_dq[3], color_dq[3], diag[3][3], div[3]; float (*black)[3], (*sgain)[3], (*sgrow)[3]; float fsum[3], val, frow, num; int row, col, c, i, j, diff, sgx, irow, sum, min, max, limit; int dscr[2][2], dstb[4], (*smrow[7])[3], total[4], ipix[3]; int work[3][3], smlast, smred, smred_p=0, dev[3]; int satlev[3], keep[4], active[4]; unsigned dim[3], *badpix; double dsum=0, trsum[3]; char str[128]; const char* cp; if (verbose) fprintf (stderr,_("Foveon interpolation...\n")); foveon_fixed (dscr, 4, "DarkShieldColRange"); foveon_fixed (ppm[0][0], 27, "PostPolyMatrix"); foveon_fixed (satlev, 3, "SaturationLevel"); foveon_fixed (keep, 4, "KeepImageArea"); foveon_fixed (active, 4, "ActiveImageArea"); foveon_fixed (chroma_dq, 3, "ChromaDQ"); foveon_fixed (color_dq, 3, foveon_camf_param ("IncludeBlocks", "ColorDQ") ? "ColorDQ" : "ColorDQCamRGB"); if (foveon_camf_param ("IncludeBlocks", "ColumnFilter")) foveon_fixed (&cfilt, 1, "ColumnFilter"); memset (ddft, 0, sizeof ddft); if (!foveon_camf_param ("IncludeBlocks", "DarkDrift") || !foveon_fixed (ddft[1][0], 12, "DarkDrift")) for (i=0; i < 2; i++) { foveon_fixed (dstb, 4, i ? "DarkShieldBottom":"DarkShieldTop"); for (row = dstb[1]; row <= dstb[3]; row++) for (col = dstb[0]; col <= dstb[2]; col++) FORC3 ddft[i+1][c][1] += (short) image[row*width+col][c]; FORC3 ddft[i+1][c][1] /= (dstb[3]-dstb[1]+1) * (dstb[2]-dstb[0]+1); } if (!(cp = foveon_camf_param ("WhiteBalanceIlluminants", model2))) { fprintf (stderr,_("%s: Invalid white balance \"%s\"\n"), ifname, model2); return; } foveon_fixed (cam_xyz, 9, cp); foveon_fixed (correct, 9, foveon_camf_param ("WhiteBalanceCorrections", model2)); memset (last, 0, sizeof last); for (i=0; i < 3; i++) for (j=0; j < 3; j++) FORC3 last[i][j] += correct[i][c] * cam_xyz[c][j]; #define LAST(x,y) last[(i+x)%3][(c+y)%3] for (i=0; i < 3; i++) FORC3 diag[c][i] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1); #undef LAST FORC3 div[c] = diag[c][0]*0.3127 + diag[c][1]*0.329 + diag[c][2]*0.3583; sprintf (str, "%sRGBNeutral", model2); if (foveon_camf_param ("IncludeBlocks", str)) foveon_fixed (div, 3, str); num = 0; FORC3 if (num < div[c]) num = div[c]; FORC3 div[c] /= num; memset (trans, 0, sizeof trans); for (i=0; i < 3; i++) for (j=0; j < 3; j++) FORC3 trans[i][j] += rgb_cam[i][c] * last[c][j] * div[j]; FORC3 trsum[c] = trans[c][0] + trans[c][1] + trans[c][2]; dsum = (6*trsum[0] + 11*trsum[1] + 3*trsum[2]) / 20; for (i=0; i < 3; i++) FORC3 last[i][c] = trans[i][c] * dsum / trsum[i]; memset (trans, 0, sizeof trans); for (i=0; i < 3; i++) for (j=0; j < 3; j++) FORC3 trans[i][j] += (i==c ? 32 : -1) * last[c][j] / 30; foveon_make_curves (curve, color_dq, div, cfilt); FORC3 chroma_dq[c] /= 3; foveon_make_curves (curve+3, chroma_dq, div, cfilt); FORC3 dsum += chroma_dq[c] / div[c]; curve[6] = foveon_make_curve (dsum, dsum, cfilt); curve[7] = foveon_make_curve (dsum*2, dsum*2, cfilt); sgain = (float (*)[3]) foveon_camf_matrix (dim, "SpatialGain"); if (!sgain) return; sgrow = (float (*)[3]) calloc (dim[1], sizeof *sgrow); sgx = (width + dim[1]-2) / (dim[1]-1); black = (float (*)[3]) calloc (height, sizeof *black); for (row=0; row < height; row++) { for (i=0; i < 6; i++) ddft[0][0][i] = ddft[1][0][i] + row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]); FORC3 black[row][c] = ( foveon_avg (image[row*width]+c, dscr[0], cfilt) + foveon_avg (image[row*width]+c, dscr[1], cfilt) * 3 - ddft[0][c][0] ) / 4 - ddft[0][c][1]; } memcpy (black, black+8, sizeof *black*8); memcpy (black+height-11, black+height-22, 11*sizeof *black); memcpy (last, black, sizeof last); for (row=1; row < height-1; row++) { FORC3 if (last[1][c] > last[0][c]) { if (last[1][c] > last[2][c]) black[row][c] = (last[0][c] > last[2][c]) ? last[0][c]:last[2][c]; } else if (last[1][c] < last[2][c]) black[row][c] = (last[0][c] < last[2][c]) ? last[0][c]:last[2][c]; memmove (last, last+1, 2*sizeof last[0]); memcpy (last[2], black[row+1], sizeof last[2]); } FORC3 black[row][c] = (last[0][c] + last[1][c])/2; FORC3 black[0][c] = (black[1][c] + black[3][c])/2; val = 1 - exp(-1/24.0); memcpy (fsum, black, sizeof fsum); for (row=1; row < height; row++) FORC3 fsum[c] += black[row][c] = (black[row][c] - black[row-1][c])*val + black[row-1][c]; memcpy (last[0], black[height-1], sizeof last[0]); FORC3 fsum[c] /= height; for (row = height; row--; ) FORC3 last[0][c] = black[row][c] = (black[row][c] - fsum[c] - last[0][c])*val + last[0][c]; memset (total, 0, sizeof total); for (row=2; row < height; row+=4) for (col=2; col < width; col+=4) { FORC3 total[c] += (short) image[row*width+col][c]; total[3]++; } for (row=0; row < height; row++) FORC3 black[row][c] += fsum[c]/2 + total[c]/(total[3]*100.0); for (row=0; row < height; row++) { for (i=0; i < 6; i++) ddft[0][0][i] = ddft[1][0][i] + row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]); pix = image[row*width]; memcpy (prev, pix, sizeof prev); frow = row / (height-1.0) * (dim[2]-1); if ((irow = frow) == dim[2]-1) irow--; frow -= irow; for (i=0; i < dim[1]; i++) FORC3 sgrow[i][c] = sgain[ irow *dim[1]+i][c] * (1-frow) + sgain[(irow+1)*dim[1]+i][c] * frow; for (col=0; col < width; col++) { FORC3 { diff = pix[c] - prev[c]; prev[c] = pix[c]; ipix[c] = pix[c] + floor ((diff + (diff*diff >> 14)) * cfilt - ddft[0][c][1] - ddft[0][c][0] * ((float) col/width - 0.5) - black[row][c] ); } FORC3 { work[0][c] = ipix[c] * ipix[c] >> 14; work[2][c] = ipix[c] * work[0][c] >> 14; work[1][2-c] = ipix[(c+1) % 3] * ipix[(c+2) % 3] >> 14; } FORC3 { for (val=i=0; i < 3; i++) for ( j=0; j < 3; j++) val += ppm[c][i][j] * work[i][j]; ipix[c] = floor ((ipix[c] + floor(val)) * ( sgrow[col/sgx ][c] * (sgx - col%sgx) + sgrow[col/sgx+1][c] * (col%sgx) ) / sgx / div[c]); if (ipix[c] > 32000) ipix[c] = 32000; pix[c] = ipix[c]; } pix += 4; } } free (black); free (sgrow); free (sgain); if ((badpix = (unsigned int *) foveon_camf_matrix (dim, "BadPixels"))) { for (i=0; i < dim[0]; i++) { col = (badpix[i] >> 8 & 0xfff) - keep[0]; row = (badpix[i] >> 20 ) - keep[1]; if ((unsigned)(row-1) > height-3 || (unsigned)(col-1) > width-3) continue; memset (fsum, 0, sizeof fsum); for (sum=j=0; j < 8; j++) if (badpix[i] & (1 << j)) { FORC3 fsum[c] += (short) image[(row+hood[j*2])*width+col+hood[j*2+1]][c]; sum++; } if (sum) FORC3 image[row*width+col][c] = fsum[c]/sum; } free (badpix); } /* Array for 5x5 Gaussian averaging of red values */ smrow[6] = (int (*)[3]) calloc (width*5, sizeof **smrow); merror (smrow[6], "foveon_interpolate()"); for (i=0; i < 5; i++) smrow[i] = smrow[6] + i*width; /* Sharpen the reds against these Gaussian averages */ for (smlast=-1, row=2; row < height-2; row++) { while (smlast < row+2) { for (i=0; i < 6; i++) smrow[(i+5) % 6] = smrow[i]; pix = image[++smlast*width+2]; for (col=2; col < width-2; col++) { smrow[4][col][0] = (pix[0]*6 + (pix[-4]+pix[4])*4 + pix[-8]+pix[8] + 8) >> 4; pix += 4; } } pix = image[row*width+2]; for (col=2; col < width-2; col++) { smred = ( 6 * smrow[2][col][0] + 4 * (smrow[1][col][0] + smrow[3][col][0]) + smrow[0][col][0] + smrow[4][col][0] + 8 ) >> 4; if (col == 2) smred_p = smred; i = pix[0] + ((pix[0] - ((smred*7 + smred_p) >> 3)) >> 3); if (i > 32000) i = 32000; pix[0] = i; smred_p = smred; pix += 4; } } /* Adjust the brighter pixels for better linearity */ min = 0xffff; FORC3 { i = satlev[c] / div[c]; if (min > i) min = i; } limit = min * 9 >> 4; for (pix=image[0]; pix < image[height*width]; pix+=4) { if (pix[0] <= limit || pix[1] <= limit || pix[2] <= limit) continue; min = max = pix[0]; for (c=1; c < 3; c++) { if (min > pix[c]) min = pix[c]; if (max < pix[c]) max = pix[c]; } if (min >= limit*2) { pix[0] = pix[1] = pix[2] = max; } else { i = 0x4000 - ((min - limit) << 14) / limit; i = 0x4000 - (i*i >> 14); i = i*i >> 14; FORC3 pix[c] += (max - pix[c]) * i >> 14; } } /* Because photons that miss one detector often hit another, the sum R+G+B is much less noisy than the individual colors. So smooth the hues without smoothing the total. */ for (smlast=-1, row=2; row < height-2; row++) { while (smlast < row+2) { for (i=0; i < 6; i++) smrow[(i+5) % 6] = smrow[i]; pix = image[++smlast*width+2]; for (col=2; col < width-2; col++) { FORC3 smrow[4][col][c] = (pix[c-4]+2*pix[c]+pix[c+4]+2) >> 2; pix += 4; } } pix = image[row*width+2]; for (col=2; col < width-2; col++) { FORC3 dev[c] = -foveon_apply_curve (curve[7], pix[c] - ((smrow[1][col][c] + 2*smrow[2][col][c] + smrow[3][col][c]) >> 2)); sum = (dev[0] + dev[1] + dev[2]) >> 3; FORC3 pix[c] += dev[c] - sum; pix += 4; } } for (smlast=-1, row=2; row < height-2; row++) { while (smlast < row+2) { for (i=0; i < 6; i++) smrow[(i+5) % 6] = smrow[i]; pix = image[++smlast*width+2]; for (col=2; col < width-2; col++) { FORC3 smrow[4][col][c] = (pix[c-8]+pix[c-4]+pix[c]+pix[c+4]+pix[c+8]+2) >> 2; pix += 4; } } pix = image[row*width+2]; for (col=2; col < width-2; col++) { for (total[3]=375, sum=60, c=0; c < 3; c++) { for (total[c]=i=0; i < 5; i++) total[c] += smrow[i][col][c]; total[3] += total[c]; sum += pix[c]; } if (sum < 0) sum = 0; j = total[3] > 375 ? (sum << 16) / total[3] : sum * 174; FORC3 pix[c] += foveon_apply_curve (curve[6], ((j*total[c] + 0x8000) >> 16) - pix[c]); pix += 4; } } /* Transform the image to a different colorspace */ for (pix=image[0]; pix < image[height*width]; pix+=4) { FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]); sum = (pix[0]+pix[1]+pix[1]+pix[2]) >> 2; FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]-sum); FORC3 { for (dsum=i=0; i < 3; i++) dsum += trans[c][i] * pix[i]; if (dsum < 0) dsum = 0; if (dsum > 24000) dsum = 24000; ipix[c] = dsum + 0.5; } FORC3 pix[c] = ipix[c]; } /* Smooth the image bottom-to-top and save at 1/4 scale */ shrink = (short (*)[3]) calloc ((width/4) * (height/4), sizeof *shrink); merror (shrink, "foveon_interpolate()"); for (row = height/4; row--; ) for (col=0; col < width/4; col++) { ipix[0] = ipix[1] = ipix[2] = 0; for (i=0; i < 4; i++) for (j=0; j < 4; j++) FORC3 ipix[c] += image[(row*4+i)*width+col*4+j][c]; FORC3 if (row+2 > height/4) shrink[row*(width/4)+col][c] = ipix[c] >> 4; else shrink[row*(width/4)+col][c] = (shrink[(row+1)*(width/4)+col][c]*1840 + ipix[c]*141 + 2048) >> 12; } /* From the 1/4-scale image, smooth right-to-left */ for (row=0; row < (height & ~3); row++) { ipix[0] = ipix[1] = ipix[2] = 0; if ((row & 3) == 0) for (col = width & ~3 ; col--; ) FORC3 smrow[0][col][c] = ipix[c] = (shrink[(row/4)*(width/4)+col/4][c]*1485 + ipix[c]*6707 + 4096) >> 13; /* Then smooth left-to-right */ ipix[0] = ipix[1] = ipix[2] = 0; for (col=0; col < (width & ~3); col++) FORC3 smrow[1][col][c] = ipix[c] = (smrow[0][col][c]*1485 + ipix[c]*6707 + 4096) >> 13; /* Smooth top-to-bottom */ if (row == 0) memcpy (smrow[2], smrow[1], sizeof **smrow * width); else for (col=0; col < (width & ~3); col++) FORC3 smrow[2][col][c] = (smrow[2][col][c]*6707 + smrow[1][col][c]*1485 + 4096) >> 13; /* Adjust the chroma toward the smooth values */ for (col=0; col < (width & ~3); col++) { for (i=j=30, c=0; c < 3; c++) { i += smrow[2][col][c]; j += image[row*width+col][c]; } j = (j << 16) / i; for (sum=c=0; c < 3; c++) { ipix[c] = foveon_apply_curve (curve[c+3], ((smrow[2][col][c] * j + 0x8000) >> 16) - image[row*width+col][c]); sum += ipix[c]; } sum >>= 3; FORC3 { i = image[row*width+col][c] + ipix[c] - sum; if (i < 0) i = 0; image[row*width+col][c] = i; } } } free (shrink); free (smrow[6]); for (i=0; i < 8; i++) free (curve[i]); /* Trim off the black border */ active[1] -= keep[1]; active[3] -= 2; i = active[2] - active[0]; for (row=0; row < active[3]-active[1]; row++) memcpy (image[row*i], image[(row+active[1])*width+active[0]], i * sizeof *image); width = i; height = row; } #undef image /* RESTRICTED code ends here */ /* Seach from the current directory up to the root looking for a ".badpixels" file, and fix those pixels now. */ void CLASS bad_pixels (const char *cfname) { FILE *fp=0; char *fname, *cp, line[128]; int len, time, row, col, r, c, rad, tot, n, fixed=0; if (!filters) return; if (cfname) fp = fopen (cfname, "r"); else { for (len=32 ; ; len *= 2) { fname = (char *) malloc (len); if (!fname) return; if (getcwd (fname, len-16)) break; free (fname); if (errno != ERANGE) return; } #if defined(WIN32) || defined(DJGPP) if (fname[1] == ':') memmove (fname, fname+2, len-2); for (cp=fname; *cp; cp++) if (*cp == '\\') *cp = '/'; #endif cp = fname + strlen(fname); if (cp[-1] == '/') cp--; while (*fname == '/') { strcpy (cp, "/.badpixels"); if ((fp = fopen (fname, "r"))) break; if (cp == fname) break; while (*--cp != '/'); } free (fname); } if (!fp) return; while (fgets (line, 128, fp)) { cp = strchr (line, '#'); if (cp) *cp = 0; if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue; if ((unsigned) col >= width || (unsigned) row >= height) continue; if (time > timestamp) continue; for (tot=n=0, rad=1; rad < 3 && n==0; rad++) for (r = row-rad; r <= row+rad; r++) for (c = col-rad; c <= col+rad; c++) if ((unsigned) r < height && (unsigned) c < width && (r != row || c != col) && fc(r,c) == fc(row,col)) { tot += BAYER2(r,c); n++; } BAYER2(row,col) = tot/n; if (verbose) { if (!fixed++) fprintf (stderr,_("Fixed dead pixels at:")); fprintf (stderr, " %d,%d", col, row); } } if (fixed) fputc ('\n', stderr); fclose (fp); } void CLASS subtract (const char *fname) { FILE *fp; int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col; ushort *pixel; if (!(fp = fopen (fname, "rb"))) { perror (fname); return; } if (fgetc(fp) != 'P' || fgetc(fp) != '5') error = 1; while (!error && nd < 3 && (c = fgetc(fp)) != EOF) { if (c == '#') comment = 1; if (c == '\n') comment = 0; if (comment) continue; if (isdigit(c)) number = 1; if (number) { if (isdigit(c)) dim[nd] = dim[nd]*10 + c -'0'; else if (isspace(c)) { number = 0; nd++; } else error = 1; } } if (error || nd < 3) { fprintf (stderr,_("%s is not a valid PGM file!\n"), fname); fclose (fp); return; } else if (dim[0] != width || dim[1] != height || dim[2] != 65535) { fprintf (stderr,_("%s has the wrong dimensions!\n"), fname); fclose (fp); return; } pixel = (ushort *) calloc (width, sizeof *pixel); merror (pixel, "subtract()"); for (row=0; row < height; row++) { fread (pixel, 2, width, fp); for (col=0; col < width; col++) BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0); } free (pixel); black = 0; } void CLASS gamma_curve (double pwr, double ts, int mode, int imax) { int i; double g[6], bnd[2]={0,0}, r; g[0] = pwr; g[1] = ts; g[2] = g[3] = g[4] = 0; bnd[g[1] >= 1] = 1; if (g[1] && (g[1]-1)*(g[0]-1) <= 0) { for (i=0; i < 48; i++) { g[2] = (bnd[0] + bnd[1])/2; if (g[0]) bnd[(pow(g[2]/g[1],-g[0]) - 1)/g[0] - 1/g[2] > -1] = g[2]; else bnd[g[2]/exp(1-1/g[2]) < g[1]] = g[2]; } g[3] = g[2] / g[1]; if (g[0]) g[4] = g[2] * (1/g[0] - 1); } if (g[0]) g[5] = 1 / (g[1]*SQR(g[3])/2 - g[4]*(1 - g[3]) + (1 - pow(g[3],1+g[0]))*(1 + g[4])/(1 + g[0])) - 1; else g[5] = 1 / (g[1]*SQR(g[3])/2 + 1 - g[2] - g[3] - g[2]*g[3]*(log(g[3]) - 1)) - 1; if (!mode--) { memcpy (gamm, g, sizeof gamm); return; } for (i=0; i < 0x10000; i++) { curve[i] = 0xffff; if ((r = (double) i / imax) < 1) curve[i] = 0x10000 * ( mode ? (r < g[3] ? r*g[1] : (g[0] ? pow( r,g[0])*(1+g[4])-g[4] : log(r)*g[2]+1)) : (r < g[2] ? r/g[1] : (g[0] ? pow((r+g[4])/(1+g[4]),1/g[0]) : exp((r-1)/g[2])))); } } void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size) { double work[3][6], num; int i, j, k; for (i=0; i < 3; i++) { for (j=0; j < 6; j++) work[i][j] = j == i+3; for (j=0; j < 3; j++) for (k=0; k < size; k++) work[i][j] += in[k][i] * in[k][j]; } for (i=0; i < 3; i++) { num = work[i][i]; for (j=0; j < 6; j++) work[i][j] /= num; for (k=0; k < 3; k++) { if (k==i) continue; num = work[k][i]; for (j=0; j < 6; j++) work[k][j] -= work[i][j] * num; } } for (i=0; i < size; i++) for (j=0; j < 3; j++) for (out[i][j]=k=0; k < 3; k++) out[i][j] += work[j][k+3] * in[i][k]; } void CLASS cam_xyz_coeff (double cam_xyz[4][3]) { double cam_rgb[4][3], inverse[4][3], num; int i, j, k; for (i=0; i < colors; i++) /* Multiply out XYZ colorspace */ for (j=0; j < 3; j++) for (cam_rgb[i][j] = k=0; k < 3; k++) cam_rgb[i][j] += cam_xyz[i][k] * xyz_rgb[k][j]; for (i=0; i < colors; i++) { /* Normalize cam_rgb so that */ for (num=j=0; j < 3; j++) /* cam_rgb * (1,1,1) is (1,1,1,1) */ num += cam_rgb[i][j]; for (j=0; j < 3; j++) cam_rgb[i][j] /= num; pre_mul[i] = 1 / num; } pseudoinverse (cam_rgb, inverse, colors); for (raw_color = i=0; i < 3; i++) for (j=0; j < colors; j++) rgb_cam[i][j] = inverse[j][i]; } #ifdef COLORCHECK void CLASS colorcheck() { #define NSQ 24 // Coordinates of the GretagMacbeth ColorChecker squares // width, height, 1st_column, 1st_row int cut[NSQ][4]; // you must set these // ColorChecker Chart under 6500-kelvin illumination static const double gmb_xyY[NSQ][3] = { { 0.400, 0.350, 10.1 }, // Dark Skin { 0.377, 0.345, 35.8 }, // Light Skin { 0.247, 0.251, 19.3 }, // Blue Sky { 0.337, 0.422, 13.3 }, // Foliage { 0.265, 0.240, 24.3 }, // Blue Flower { 0.261, 0.343, 43.1 }, // Bluish Green { 0.506, 0.407, 30.1 }, // Orange { 0.211, 0.175, 12.0 }, // Purplish Blue { 0.453, 0.306, 19.8 }, // Moderate Red { 0.285, 0.202, 6.6 }, // Purple { 0.380, 0.489, 44.3 }, // Yellow Green { 0.473, 0.438, 43.1 }, // Orange Yellow { 0.187, 0.129, 6.1 }, // Blue { 0.305, 0.478, 23.4 }, // Green { 0.539, 0.313, 12.0 }, // Red { 0.448, 0.470, 59.1 }, // Yellow { 0.364, 0.233, 19.8 }, // Magenta { 0.196, 0.252, 19.8 }, // Cyan { 0.310, 0.316, 90.0 }, // White { 0.310, 0.316, 59.1 }, // Neutral 8 { 0.310, 0.316, 36.2 }, // Neutral 6.5 { 0.310, 0.316, 19.8 }, // Neutral 5 { 0.310, 0.316, 9.0 }, // Neutral 3.5 { 0.310, 0.316, 3.1 } }; // Black double gmb_cam[NSQ][4], gmb_xyz[NSQ][3]; double inverse[NSQ][3], cam_xyz[4][3], num; int c, i, j, k, sq, row, col, count[4]; memset (gmb_cam, 0, sizeof gmb_cam); for (sq=0; sq < NSQ; sq++) { FORCC count[c] = 0; for (row=cut[sq][3]; row < cut[sq][3]+cut[sq][1]; row++) for (col=cut[sq][2]; col < cut[sq][2]+cut[sq][0]; col++) { c = FC(row,col); if (c >= colors) c -= 2; gmb_cam[sq][c] += BAYER(row,col); count[c]++; } FORCC gmb_cam[sq][c] = gmb_cam[sq][c]/count[c] - black; gmb_xyz[sq][0] = gmb_xyY[sq][2] * gmb_xyY[sq][0] / gmb_xyY[sq][1]; gmb_xyz[sq][1] = gmb_xyY[sq][2]; gmb_xyz[sq][2] = gmb_xyY[sq][2] * (1 - gmb_xyY[sq][0] - gmb_xyY[sq][1]) / gmb_xyY[sq][1]; } pseudoinverse (gmb_xyz, inverse, NSQ); for (i=0; i < colors; i++) for (j=0; j < 3; j++) for (cam_xyz[i][j] = k=0; k < NSQ; k++) cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j]; cam_xyz_coeff (cam_xyz); if (verbose) { printf (" { \"%s %s\", %d,\n\t{", make, model, black); num = 10000 / (cam_xyz[1][0] + cam_xyz[1][1] + cam_xyz[1][2]); FORCC for (j=0; j < 3; j++) printf ("%c%d", (c | j) ? ',':' ', (int) (cam_xyz[c][j] * num + 0.5)); puts (" } },"); } #undef NSQ } #endif void CLASS hat_transform (float *temp, float *base, int st, int size, int sc) { int i; for (i=0; i < sc; i++) temp[i] = 2*base[st*i] + base[st*(sc-i)] + base[st*(i+sc)]; for (; i+sc < size; i++) temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(i+sc)]; for (; i < size; i++) temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(2*size-2-(i+sc))]; } void CLASS wavelet_denoise() { float *fimg=0, *temp, thold, mul[2], avg, diff; int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast; ushort *window[4]; static const float noise[] = { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 }; if (verbose) fprintf (stderr,_("Wavelet denoising...\n")); while (maximum << scale < 0x10000) scale++; maximum <<= --scale; black <<= scale; if ((size = iheight*iwidth) < 0x15550000) fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg); merror (fimg, "wavelet_denoise()"); temp = fimg + size*3; if ((nc = colors) == 3 && filters) nc++; FORC(nc) { /* denoise R,G1,B,G3 individually */ for (i=0; i < size; i++) fimg[i] = 256 * sqrt(image[i][c] << scale); for (hpass=lev=0; lev < 5; lev++) { lpass = size*((lev & 1)+1); for (row=0; row < iheight; row++) { hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev); for (col=0; col < iwidth; col++) fimg[lpass + row*iwidth + col] = temp[col] * 0.25; } for (col=0; col < iwidth; col++) { hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev); for (row=0; row < iheight; row++) fimg[lpass + row*iwidth + col] = temp[row] * 0.25; } thold = threshold * noise[lev]; for (i=0; i < size; i++) { fimg[hpass+i] -= fimg[lpass+i]; if (fimg[hpass+i] < -thold) fimg[hpass+i] += thold; else if (fimg[hpass+i] > thold) fimg[hpass+i] -= thold; else fimg[hpass+i] = 0; if (hpass) fimg[i] += fimg[hpass+i]; } hpass = lpass; } for (i=0; i < size; i++) image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000); } if (filters && colors == 3) { /* pull G1 and G3 closer together */ for (row=0; row < 2; row++) mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1]; for (i=0; i < 4; i++) window[i] = (ushort *) fimg + width*i; for (wlast=-1, row=1; row < height-1; row++) { while (wlast < row+1) { for (wlast++, i=0; i < 4; i++) window[(i+3) & 3] = window[i]; for (col = FC(wlast,1) & 1; col < width; col+=2) window[2][col] = BAYER(wlast,col); } thold = threshold/512; for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) { avg = ( window[0][col-1] + window[0][col+1] + window[2][col-1] + window[2][col+1] - black*4 ) * mul[row & 1] + (window[1][col] - black) * 0.5 + black; avg = avg < 0 ? 0 : sqrt(avg); diff = sqrt(BAYER(row,col)) - avg; if (diff < -thold) diff += thold; else if (diff > thold) diff -= thold; else diff = 0; BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5); } } } free (fimg); } void CLASS scale_colors() { unsigned bottom, right, size, row, col, ur, uc, i, x, y, c, sum[8]; int val, dark, sat; double dsum[8], dmin, dmax; float scale_mul[4], fr, fc; ushort *img=0, *pix; if (user_mul[0]) memcpy (pre_mul, user_mul, sizeof pre_mul); if (use_auto_wb || (use_camera_wb && cam_mul[0] == -1)) { memset (dsum, 0, sizeof dsum); bottom = MIN (greybox[1]+greybox[3], height); right = MIN (greybox[0]+greybox[2], width); for (row=greybox[1]; row < bottom; row += 8) for (col=greybox[0]; col < right; col += 8) { memset (sum, 0, sizeof sum); for (y=row; y < row+8 && y < bottom; y++) for (x=col; x < col+8 && x < right; x++) FORC4 { if (filters) { c = FC(y,x); val = BAYER(y,x); } else val = image[y*width+x][c]; if (val > maximum-25) goto skip_block; if ((val -= black) < 0) val = 0; sum[c] += val; sum[c+4]++; if (filters) break; } FORC(8) dsum[c] += sum[c]; skip_block: ; } FORC4 if (dsum[c]) pre_mul[c] = dsum[c+4] / dsum[c]; } if (use_camera_wb && cam_mul[0] != -1) { memset (sum, 0, sizeof sum); for (row=0; row < 8; row++) for (col=0; col < 8; col++) { c = FC(row,col); if ((val = white[row][col] - black) > 0) sum[c] += val; sum[c+4]++; } if (sum[0] && sum[1] && sum[2] && sum[3]) FORC4 pre_mul[c] = (float) sum[c+4] / sum[c]; else if (cam_mul[0] && cam_mul[2]) memcpy (pre_mul, cam_mul, sizeof pre_mul); else fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname); } if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1; dark = black; sat = maximum; if (threshold) wavelet_denoise(); maximum -= black; for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) { if (dmin > pre_mul[c]) dmin = pre_mul[c]; if (dmax < pre_mul[c]) dmax = pre_mul[c]; } if (!highlight) dmax = dmin; FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum; if (verbose) { fprintf (stderr, _("Scaling with darkness %d, saturation %d, and\nmultipliers"), dark, sat); FORC4 fprintf (stderr, " %f", pre_mul[c]); fputc ('\n', stderr); } size = iheight*iwidth; for (i=0; i < size*4; i++) { val = image[0][i]; if (!val) continue; val -= black; val *= scale_mul[i & 3]; image[0][i] = CLIP(val); } if ((aber[0] != 1 || aber[2] != 1) && colors == 3) { if (verbose) fprintf (stderr,_("Correcting chromatic aberration...\n")); for (c=0; c < 4; c+=2) { if (aber[c] == 1) continue; img = (ushort *) malloc (size * sizeof *img); merror (img, "scale_colors()"); for (i=0; i < size; i++) img[i] = image[i][c]; for (row=0; row < iheight; row++) { ur = fr = (row - iheight*0.5) * aber[c] + iheight*0.5; if (ur > iheight-2) continue; fr -= ur; for (col=0; col < iwidth; col++) { uc = fc = (col - iwidth*0.5) * aber[c] + iwidth*0.5; if (uc > iwidth-2) continue; fc -= uc; pix = img + ur*iwidth + uc; image[row*iwidth+col][c] = (pix[ 0]*(1-fc) + pix[ 1]*fc) * (1-fr) + (pix[iwidth]*(1-fc) + pix[iwidth+1]*fc) * fr; } } free(img); } } } void CLASS pre_interpolate() { ushort (*img)[4]; int row, col, c; if (shrink) { if (half_size) { height = iheight; width = iwidth; } else { img = (ushort (*)[4]) calloc (height*width, sizeof *img); merror (img, "pre_interpolate()"); for (row=0; row < height; row++) for (col=0; col < width; col++) { c = fc(row,col); img[row*width+col][c] = image[(row >> 1)*iwidth+(col >> 1)][c]; } free (image); image = img; shrink = 0; } } if (filters && colors == 3) { if ((mix_green = four_color_rgb)) colors++; else { for (row = FC(1,0) >> 1; row < height; row+=2) for (col = FC(row,1) & 1; col < width; col+=2) image[row*width+col][1] = image[row*width+col][3]; filters &= ~((filters & 0x55555555) << 1); } } if (half_size) filters = 0; } void CLASS border_interpolate (int border) { unsigned row, col, y, x, f, c, sum[8]; for (row=0; row < height; row++) for (col=0; col < width; col++) { if (col==border && row >= border && row < height-border) col = width-border; memset (sum, 0, sizeof sum); for (y=row-1; y != row+2; y++) for (x=col-1; x != col+2; x++) if (y < height && x < width) { f = fc(y,x); sum[f] += image[y*width+x][f]; sum[f+4]++; } f = fc(row,col); FORCC if (c != f && sum[c+4]) image[row*width+col][c] = sum[c] / sum[c+4]; } } void CLASS lin_interpolate() { int code[16][16][32], *ip, sum[4]; int c, i, x, y, row, col, shift, color; ushort *pix; if (verbose) fprintf (stderr,_("Bilinear interpolation...\n")); border_interpolate(1); for (row=0; row < 16; row++) for (col=0; col < 16; col++) { ip = code[row][col]; memset (sum, 0, sizeof sum); for (y=-1; y <= 1; y++) for (x=-1; x <= 1; x++) { shift = (y==0) + (x==0); if (shift == 2) continue; color = fc(row+y,col+x); *ip++ = (width*y + x)*4 + color; *ip++ = shift; *ip++ = color; sum[color] += 1 << shift; } FORCC if (c != fc(row,col)) { *ip++ = c; *ip++ = 256 / sum[c]; } } for (row=1; row < height-1; row++) for (col=1; col < width-1; col++) { pix = image[row*width+col]; ip = code[row & 15][col & 15]; memset (sum, 0, sizeof sum); for (i=8; i--; ip+=3) sum[ip[2]] += pix[ip[0]] << ip[1]; for (i=colors; --i; ip+=2) pix[ip[0]] = sum[ip[0]] * ip[1] >> 8; } } /* This algorithm is officially called: "Interpolation using a Threshold-based variable number of gradients" described in http://scien.stanford.edu/class/psych221/projects/99/tingchen/algodep/vargra.html I've extended the basic idea to work with non-Bayer filter arrays. Gradients are numbered clockwise from NW=0 to W=7. */ void CLASS vng_interpolate() { static const signed char *cp, terms[] = { -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01, -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01, -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03, -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06, -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04, -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01, -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40, -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11, -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11, -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22, -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44, -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10, -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04, +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40, +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20, +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08, +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20, +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44, +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60, +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80, +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40, +1,+0,+2,+1,0,0x10 }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 }; ushort (*brow[5])[4], *pix; int prow=7, pcol=1, *ip, *code[16][16], gval[8], gmin, gmax, sum[4]; int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag; int g, diff, thold, num, c; lin_interpolate(); if (verbose) fprintf (stderr,_("VNG interpolation...\n")); if (filters == 1) prow = pcol = 15; ip = (int *) calloc ((prow+1)*(pcol+1), 1280); merror (ip, "vng_interpolate()"); for (row=0; row <= prow; row++) /* Precalculate for VNG */ for (col=0; col <= pcol; col++) { code[row][col] = ip; for (cp=terms, t=0; t < 64; t++) { y1 = *cp++; x1 = *cp++; y2 = *cp++; x2 = *cp++; weight = *cp++; grads = *cp++; color = fc(row+y1,col+x1); if (fc(row+y2,col+x2) != color) continue; diag = (fc(row,col+1) == color && fc(row+1,col) == color) ? 2:1; if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue; *ip++ = (y1*width + x1)*4 + color; *ip++ = (y2*width + x2)*4 + color; *ip++ = weight; for (g=0; g < 8; g++) if (grads & 1< gval[g]) gmin = gval[g]; if (gmax < gval[g]) gmax = gval[g]; } if (gmax == 0) { memcpy (brow[2][col], pix, sizeof *image); continue; } thold = gmin + (gmax >> 1); memset (sum, 0, sizeof sum); color = fc(row,col); for (num=g=0; g < 8; g++,ip+=2) { /* Average the neighbors */ if (gval[g] <= thold) { FORCC if (c == color && ip[1]) sum[c] += (pix[c] + pix[ip[1]]) >> 1; else sum[c] += pix[ip[0] + c]; num++; } } FORCC { /* Save to buffer */ t = pix[color]; if (c != color) t += (sum[c] - sum[color]) / num; brow[2][col][c] = CLIP(t); } } if (row > 3) /* Write buffer to image */ memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image); for (g=0; g < 4; g++) brow[(g-1) & 3] = brow[g]; } memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image); memcpy (image[(row-1)*width+2], brow[1]+2, (width-4)*sizeof *image); free (brow[4]); free (code[0][0]); } /* Patterned Pixel Grouping Interpolation by Alain Desbiolles */ void CLASS ppg_interpolate() { int dir[5] = { 1, width, -1, -width, 1 }; int row, col, diff[2], guess[2], c, d, i; ushort (*pix)[4]; border_interpolate(3); if (verbose) fprintf (stderr,_("PPG interpolation...\n")); /* Fill in the green layer with gradients and pattern recognition: */ for (row=3; row < height-3; row++) for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) { pix = image + row*width+col; for (i=0; (d=dir[i]) > 0; i++) { guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2 - pix[-2*d][c] - pix[2*d][c]; diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) + ABS(pix[ 2*d][c] - pix[ 0][c]) + ABS(pix[ -d][1] - pix[ d][1]) ) * 3 + ( ABS(pix[ 3*d][1] - pix[ d][1]) + ABS(pix[-3*d][1] - pix[-d][1]) ) * 2; } d = dir[i = diff[0] > diff[1]]; pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]); } /* Calculate red and blue for each green pixel: */ for (row=1; row < height-1; row++) for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) { pix = image + row*width+col; for (i=0; (d=dir[i]) > 0; c=2-c, i++) pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1] - pix[-d][1] - pix[d][1]) >> 1); } /* Calculate blue for red pixels and vice versa: */ for (row=1; row < height-1; row++) for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) { pix = image + row*width+col; for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) { diff[i] = ABS(pix[-d][c] - pix[d][c]) + ABS(pix[-d][1] - pix[0][1]) + ABS(pix[ d][1] - pix[0][1]); guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1] - pix[-d][1] - pix[d][1]; } if (diff[0] != diff[1]) pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1); else pix[0][c] = CLIP((guess[0]+guess[1]) >> 2); } } /* Adaptive Homogeneity-Directed interpolation is based on the work of Keigo Hirakawa, Thomas Parks, and Paul Lee. */ #define TS 256 /* Tile Size */ void CLASS ahd_interpolate() { int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2]; ushort (*pix)[4], (*rix)[3]; static const int dir[4] = { -1, 1, -TS, TS }; unsigned ldiff[2][4], abdiff[2][4], leps, abeps; float r, cbrt[0x10000], xyz[3], xyz_cam[3][4]; ushort (*rgb)[TS][TS][3]; short (*lab)[TS][TS][3], (*lix)[3]; char (*homo)[TS][TS], *buffer; if (verbose) fprintf (stderr,_("AHD interpolation...\n")); for (i=0; i < 0x10000; i++) { r = i / 65535.0; cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0; } for (i=0; i < 3; i++) for (j=0; j < colors; j++) for (xyz_cam[i][j] = k=0; k < 3; k++) xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i]; border_interpolate(5); buffer = (char *) malloc (26*TS*TS); /* 1664 kB */ merror (buffer, "ahd_interpolate()"); rgb = (ushort(*)[TS][TS][3]) buffer; lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS); homo = (char (*)[TS][TS]) (buffer + 24*TS*TS); for (top=2; top < height-5; top += TS-6) for (left=2; left < width-5; left += TS-6) { /* Interpolate green horizontally and vertically: */ for (row = top; row < top+TS && row < height-2; row++) { col = left + (FC(row,left) & 1); for (c = FC(row,col); col < left+TS && col < width-2; col+=2) { pix = image + row*width+col; val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2 - pix[-2][c] - pix[2][c]) >> 2; rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]); val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2 - pix[-2*width][c] - pix[2*width][c]) >> 2; rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]); } } /* Interpolate red and blue, and convert to CIELab: */ for (d=0; d < 2; d++) for (row=top+1; row < top+TS-1 && row < height-3; row++) for (col=left+1; col < left+TS-1 && col < width-3; col++) { pix = image + row*width+col; rix = &rgb[d][row-top][col-left]; lix = &lab[d][row-top][col-left]; if ((c = 2 - FC(row,col)) == 1) { c = FC(row+1,col); val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c] - rix[-1][1] - rix[1][1] ) >> 1); rix[0][2-c] = CLIP(val); val = pix[0][1] + (( pix[-width][c] + pix[width][c] - rix[-TS][1] - rix[TS][1] ) >> 1); } else val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c] + pix[+width-1][c] + pix[+width+1][c] - rix[-TS-1][1] - rix[-TS+1][1] - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2); rix[0][c] = CLIP(val); c = FC(row,col); rix[0][c] = pix[0][c]; xyz[0] = xyz[1] = xyz[2] = 0.5; FORCC { xyz[0] += xyz_cam[0][c] * rix[0][c]; xyz[1] += xyz_cam[1][c] * rix[0][c]; xyz[2] += xyz_cam[2][c] * rix[0][c]; } xyz[0] = cbrt[CLIP((int) xyz[0])]; xyz[1] = cbrt[CLIP((int) xyz[1])]; xyz[2] = cbrt[CLIP((int) xyz[2])]; lix[0][0] = 64 * (116 * xyz[1] - 16); lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]); lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]); } /* Build homogeneity maps from the CIELab images: */ memset (homo, 0, 2*TS*TS); for (row=top+2; row < top+TS-2 && row < height-4; row++) { tr = row-top; for (col=left+2; col < left+TS-2 && col < width-4; col++) { tc = col-left; for (d=0; d < 2; d++) { lix = &lab[d][tr][tc]; for (i=0; i < 4; i++) { ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]); abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1]) + SQR(lix[0][2]-lix[dir[i]][2]); } } leps = MIN(MAX(ldiff[0][0],ldiff[0][1]), MAX(ldiff[1][2],ldiff[1][3])); abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]), MAX(abdiff[1][2],abdiff[1][3])); for (d=0; d < 2; d++) for (i=0; i < 4; i++) if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps) homo[d][tr][tc]++; } } /* Combine the most homogenous pixels for the final result: */ for (row=top+3; row < top+TS-3 && row < height-5; row++) { tr = row-top; for (col=left+3; col < left+TS-3 && col < width-5; col++) { tc = col-left; for (d=0; d < 2; d++) for (hm[d]=0, i=tr-1; i <= tr+1; i++) for (j=tc-1; j <= tc+1; j++) hm[d] += homo[d][i][j]; if (hm[0] != hm[1]) FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c]; else FORC3 image[row*width+col][c] = (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1; } } } free (buffer); } #undef TS void CLASS median_filter() { ushort (*pix)[4]; int pass, c, i, j, k, med[9]; static const uchar opt[] = /* Optimal 9-element median search */ { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8, 0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 }; for (pass=1; pass <= med_passes; pass++) { if (verbose) fprintf (stderr,_("Median filter pass %d...\n"), pass); for (c=0; c < 3; c+=2) { for (pix = image; pix < image+width*height; pix++) pix[0][3] = pix[0][c]; for (pix = image+width; pix < image+width*(height-1); pix++) { if ((pix-image+1) % width < 2) continue; for (k=0, i = -width; i <= width; i += width) for (j = i-1; j <= i+1; j++) med[k++] = pix[j][3] - pix[j][1]; for (i=0; i < sizeof opt; i+=2) if (med[opt[i]] > med[opt[i+1]]) SWAP (med[opt[i]] , med[opt[i+1]]); pix[0][c] = CLIP(med[4] + pix[0][1]); } } } } void CLASS blend_highlights() { int clip=INT_MAX, row, col, c, i, j; static const float trans[2][4][4] = { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } }, { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } }; static const float itrans[2][4][4] = { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } }, { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } }; float cam[2][4], lab[2][4], sum[2], chratio; if ((unsigned) (colors-3) > 1) return; if (verbose) fprintf (stderr,_("Blending highlights...\n")); FORCC if (clip > (i = 65535*pre_mul[c])) clip = i; for (row=0; row < height; row++) for (col=0; col < width; col++) { FORCC if (image[row*width+col][c] > clip) break; if (c == colors) continue; FORCC { cam[0][c] = image[row*width+col][c]; cam[1][c] = MIN(cam[0][c],clip); } for (i=0; i < 2; i++) { FORCC for (lab[i][c]=j=0; j < colors; j++) lab[i][c] += trans[colors-3][c][j] * cam[i][j]; for (sum[i]=0,c=1; c < colors; c++) sum[i] += SQR(lab[i][c]); } chratio = sqrt(sum[1]/sum[0]); for (c=1; c < colors; c++) lab[0][c] *= chratio; FORCC for (cam[0][c]=j=0; j < colors; j++) cam[0][c] += itrans[colors-3][c][j] * lab[0][j]; FORCC image[row*width+col][c] = cam[0][c] / colors; } } #define SCALE (4 >> shrink) void CLASS recover_highlights() { float *map, sum, wgt, grow; int hsat[4], count, spread, change, val, i; unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x; ushort *pixel; static const signed char dir[8][2] = { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} }; if (verbose) fprintf (stderr,_("Rebuilding highlights...\n")); grow = pow (2, 4-highlight); FORCC hsat[c] = 32000 * pre_mul[c]; for (kc=0, c=1; c < colors; c++) if (pre_mul[kc] < pre_mul[c]) kc = c; high = height / SCALE; wide = width / SCALE; map = (float *) calloc (high*wide, sizeof *map); merror (map, "recover_highlights()"); FORCC if (c != kc) { memset (map, 0, high*wide*sizeof *map); for (mrow=0; mrow < high; mrow++) for (mcol=0; mcol < wide; mcol++) { sum = wgt = count = 0; for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) { pixel = image[row*width+col]; if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) { sum += pixel[c]; wgt += pixel[kc]; count++; } } if (count == SCALE*SCALE) map[mrow*wide+mcol] = sum / wgt; } for (spread = 32/grow; spread--; ) { for (mrow=0; mrow < high; mrow++) for (mcol=0; mcol < wide; mcol++) { if (map[mrow*wide+mcol]) continue; sum = count = 0; for (d=0; d < 8; d++) { y = mrow + dir[d][0]; x = mcol + dir[d][1]; if (y < high && x < wide && map[y*wide+x] > 0) { sum += (1 + (d & 1)) * map[y*wide+x]; count += 1 + (d & 1); } } if (count > 3) map[mrow*wide+mcol] = - (sum+grow) / (count+grow); } for (change=i=0; i < high*wide; i++) if (map[i] < 0) { map[i] = -map[i]; change = 1; } if (!change) break; } for (i=0; i < high*wide; i++) if (map[i] == 0) map[i] = 1; for (mrow=0; mrow < high; mrow++) for (mcol=0; mcol < wide; mcol++) { for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) { pixel = image[row*width+col]; if (pixel[c] / hsat[c] > 1) { val = pixel[kc] * map[mrow*wide+mcol]; if (pixel[c] < val) pixel[c] = CLIP(val); } } } } free (map); } #undef SCALE void CLASS tiff_get (unsigned base, unsigned *tag, unsigned *type, unsigned *len, unsigned *save) { *tag = get2(); *type = get2(); *len = get4(); *save = ftell(ifp) + 4; if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4) fseek (ifp, get4()+base, SEEK_SET); } void CLASS parse_thumb_note (int base, unsigned toff, unsigned tlen) { unsigned entries, tag, type, len, save; entries = get2(); while (entries--) { tiff_get (base, &tag, &type, &len, &save); if (tag == toff) thumb_offset = get4()+base; if (tag == tlen) thumb_length = get4(); fseek (ifp, save, SEEK_SET); } } int CLASS parse_tiff_ifd (int base); void CLASS parse_makernote (int base, int uptag) { static const uchar xlat[2][256] = { { 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d, 0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d, 0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f, 0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f, 0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1, 0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17, 0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89, 0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f, 0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b, 0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb, 0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3, 0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f, 0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35, 0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43, 0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5, 0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 }, { 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c, 0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34, 0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad, 0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05, 0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee, 0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d, 0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b, 0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b, 0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc, 0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33, 0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8, 0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6, 0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c, 0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49, 0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb, 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f } }; unsigned offset=0, entries, tag, type, len, save, c; unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0}; uchar buf97[324], ci, cj, ck; short sorder=order; char buf[10]; /* The MakerNote might have its own TIFF header (possibly with its own byte-order!), or it might just be a table. */ fread (buf, 1, 10, ifp); if (!strncmp (buf,"KDK" ,3) || /* these aren't TIFF tables */ !strncmp (buf,"VER" ,3) || !strncmp (buf,"IIII",4) || !strncmp (buf,"MMMM",4)) return; if (!strncmp (buf,"KC" ,2) || /* Konica KD-400Z, KD-510Z */ !strncmp (buf,"MLY" ,3)) { /* Minolta DiMAGE G series */ order = 0x4d4d; while ((i=ftell(ifp)) < data_offset && i < 16384) { wb[0] = wb[2]; wb[2] = wb[1]; wb[1] = wb[3]; wb[3] = get2(); if (wb[1] == 256 && wb[3] == 256 && wb[0] > 256 && wb[0] < 640 && wb[2] > 256 && wb[2] < 640) FORC4 cam_mul[c] = wb[c]; } goto quit; } if (!strcmp (buf,"Nikon")) { base = ftell(ifp); order = get2(); if (get2() != 42) goto quit; offset = get4(); fseek (ifp, offset-8, SEEK_CUR); } else if (!strcmp (buf,"OLYMPUS")) { base = ftell(ifp)-10; fseek (ifp, -2, SEEK_CUR); order = get2(); get2(); } else if (!strncmp (buf,"FUJIFILM",8) || !strncmp (buf,"SONY",4) || !strcmp (buf,"Panasonic")) { order = 0x4949; fseek (ifp, 2, SEEK_CUR); } else if (!strcmp (buf,"OLYMP") || !strcmp (buf,"LEICA") || !strcmp (buf,"Ricoh") || !strcmp (buf,"EPSON")) fseek (ifp, -2, SEEK_CUR); else if (!strcmp (buf,"AOC") || !strcmp (buf,"QVC")) fseek (ifp, -4, SEEK_CUR); else fseek (ifp, -10, SEEK_CUR); entries = get2(); if (entries > 1000) return; while (entries--) { tiff_get (base, &tag, &type, &len, &save); tag |= uptag << 16; if (tag == 2 && strstr(make,"NIKON")) iso_speed = (get2(),get2()); if (tag == 4 && len > 26 && len < 35) { if ((i=(get4(),get2())) != 0x7fff && !iso_speed) iso_speed = 50 * pow (2, i/32.0 - 4); if ((i=(get2(),get2())) != 0x7fff && !aperture) aperture = pow (2, i/64.0); if ((i=get2()) != 0xffff && !shutter) shutter = pow (2, (short) i/-32.0); wbi = (get2(),get2()); shot_order = (get2(),get2()); } if (tag == 7 && type == 2 && len > 20) fgets (model2, 64, ifp); if (tag == 8 && type == 4) shot_order = get4(); if (tag == 9 && !strcmp(make,"Canon")) fread (artist, 64, 1, ifp); if (tag == 0xc && len == 4) { cam_mul[0] = getreal(type); cam_mul[2] = getreal(type); } if (tag == 0x10 && type == 4) unique_id = get4(); if (tag == 0x11 && is_raw && !strncmp(make,"NIKON",5)) { fseek (ifp, get4()+base, SEEK_SET); parse_tiff_ifd (base); } if (tag == 0x14 && len == 2560 && type == 7) { fseek (ifp, 1248, SEEK_CUR); goto get2_256; } if (tag == 0x15 && type == 2 && is_raw) fread (model, 64, 1, ifp); if (strstr(make,"PENTAX")) { if (tag == 0x1b) tag = 0x1018; if (tag == 0x1c) tag = 0x1017; } if (tag == 0x1d) while ((c = fgetc(ifp)) && c != EOF) serial = serial*10 + (isdigit(c) ? c - '0' : c % 10); if (tag == 0x81 && type == 4) { data_offset = get4(); fseek (ifp, data_offset + 41, SEEK_SET); raw_height = get2() * 2; raw_width = get2(); filters = 0x61616161; } if (tag == 0x29 && type == 1) { c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0; fseek (ifp, 8 + c*32, SEEK_CUR); FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4(); } if ((tag == 0x81 && type == 7) || (tag == 0x100 && type == 7) || (tag == 0x280 && type == 1)) { thumb_offset = ftell(ifp); thumb_length = len; } if (tag == 0x88 && type == 4 && (thumb_offset = get4())) thumb_offset += base; if (tag == 0x89 && type == 4) thumb_length = get4(); if (tag == 0x8c || tag == 0x96) meta_offset = ftell(ifp); if (tag == 0x97) { for (i=0; i < 4; i++) ver97 = ver97 * 10 + fgetc(ifp)-'0'; switch (ver97) { case 100: fseek (ifp, 68, SEEK_CUR); FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2(); break; case 102: fseek (ifp, 6, SEEK_CUR); goto get2_rggb; case 103: fseek (ifp, 16, SEEK_CUR); FORC4 cam_mul[c] = get2(); } if (ver97 >= 200) { if (ver97 != 205) fseek (ifp, 280, SEEK_CUR); fread (buf97, 324, 1, ifp); } } if (tag == 0xa4 && type == 3) { fseek (ifp, wbi*48, SEEK_CUR); FORC3 cam_mul[c] = get2(); } if (tag == 0xa7 && (unsigned) (ver97-200) < 12 && !cam_mul[0]) { ci = xlat[0][serial & 0xff]; cj = xlat[1][fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp)]; ck = 0x60; for (i=0; i < 324; i++) buf97[i] ^= (cj += ci * ck++); i = "66666>666;6A"[ver97-200] - '0'; FORC4 cam_mul[c ^ (c >> 1) ^ (i & 1)] = sget2 (buf97 + (i & -2) + c*2); } if (tag == 0x200 && len == 3) shot_order = (get4(),get4()); if (tag == 0x200 && len == 4) black = (get2()+get2()+get2()+get2())/4; if (tag == 0x201 && len == 4) goto get2_rggb; if (tag == 0x220 && len == 53) meta_offset = ftell(ifp) + 14; if (tag == 0x401 && len == 4) { black = (get4()+get4()+get4()+get4())/4; } if (tag == 0xe01) { /* Nikon Capture Note */ type = order; order = 0x4949; fseek (ifp, 22, SEEK_CUR); for (offset=22; offset+22 < len; offset += 22+i) { tag = get4(); fseek (ifp, 14, SEEK_CUR); i = get4()-4; if (tag == 0x76a43207) flip = get2(); else fseek (ifp, i, SEEK_CUR); } order = type; } if (tag == 0xe80 && len == 256 && type == 7) { fseek (ifp, 48, SEEK_CUR); cam_mul[0] = get2() * 508 * 1.078 / 0x10000; cam_mul[2] = get2() * 382 * 1.173 / 0x10000; } if (tag == 0xf00 && type == 7) { if (len == 614) fseek (ifp, 176, SEEK_CUR); else if (len == 734 || len == 1502) fseek (ifp, 148, SEEK_CUR); else goto next; goto get2_256; } if ((tag == 0x1011 && len == 9) || tag == 0x20400200) for (i=0; i < 3; i++) FORC3 cmatrix[i][c] = ((short) get2()) / 256.0; if ((tag == 0x1012 || tag == 0x20400600) && len == 4) for (black = i=0; i < 4; i++) black += get2() << 2; if (tag == 0x1017 || tag == 0x20400100) cam_mul[0] = get2() / 256.0; if (tag == 0x1018 || tag == 0x20400100) cam_mul[2] = get2() / 256.0; if (tag == 0x2011 && len == 2) { get2_256: order = 0x4d4d; cam_mul[0] = get2() / 256.0; cam_mul[2] = get2() / 256.0; } if ((tag | 0x70) == 0x2070 && type == 4) fseek (ifp, get4()+base, SEEK_SET); if (tag == 0x2010 && type != 7) load_raw = &CLASS olympus_e410_load_raw; if (tag == 0x2020) parse_thumb_note (base, 257, 258); if (tag == 0x2040) parse_makernote (base, 0x2040); if (tag == 0xb028) { fseek (ifp, get4(), SEEK_SET); parse_thumb_note (base, 136, 137); } if (tag == 0x4001 && len > 500) { i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126; fseek (ifp, i, SEEK_CUR); get2_rggb: FORC4 cam_mul[c ^ (c >> 1)] = get2(); fseek (ifp, 22, SEEK_CUR); FORC4 sraw_mul[c ^ (c >> 1)] = get2(); } next: fseek (ifp, save, SEEK_SET); } quit: order = sorder; } /* Since the TIFF DateTime string has no timezone information, assume that the camera's clock was set to Universal Time. */ void CLASS get_timestamp (int reversed) { struct tm t; char str[20]; int i; str[19] = 0; if (reversed) for (i=19; i--; ) str[i] = fgetc(ifp); else fread (str, 19, 1, ifp); memset (&t, 0, sizeof t); if (sscanf (str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6) return; t.tm_year -= 1900; t.tm_mon -= 1; if (mktime(&t) > 0) timestamp = mktime(&t); } void CLASS parse_exif (int base) { unsigned kodak, entries, tag, type, len, save, c; double expo; kodak = !strncmp(make,"EASTMAN",7); entries = get2(); while (entries--) { tiff_get (base, &tag, &type, &len, &save); switch (tag) { case 33434: shutter = getreal(type); break; case 33437: aperture = getreal(type); break; case 34855: iso_speed = get2(); break; case 36867: case 36868: get_timestamp(0); break; case 37377: if ((expo = -getreal(type)) < 128) shutter = pow (2, expo); break; case 37378: aperture = pow (2, getreal(type)/2); break; case 37386: focal_len = getreal(type); break; case 37500: parse_makernote (base, 0); break; case 40962: if (kodak) raw_width = get4(); break; case 40963: if (kodak) raw_height = get4(); break; case 41730: if (get4() == 0x20002) for (exif_cfa=c=0; c < 8; c+=2) exif_cfa |= fgetc(ifp) * 0x01010101 << c; } fseek (ifp, save, SEEK_SET); } } void CLASS parse_gps (int base) { unsigned entries, tag, type, len, save, c; entries = get2(); while (entries--) { tiff_get (base, &tag, &type, &len, &save); switch (tag) { case 1: case 3: case 5: gpsdata[29+tag/2] = getc(ifp); break; case 2: case 4: case 7: FORC(6) gpsdata[tag/3*6+c] = get4(); break; case 6: FORC(2) gpsdata[18+c] = get4(); break; case 18: case 29: fgets ((char *) (gpsdata+14+tag/3), MIN(len,12), ifp); } fseek (ifp, save, SEEK_SET); } } void CLASS romm_coeff (float romm_cam[3][3]) { static const float rgb_romm[3][3] = /* ROMM == Kodak ProPhoto */ { { 2.034193, -0.727420, -0.306766 }, { -0.228811, 1.231729, -0.002922 }, { -0.008565, -0.153273, 1.161839 } }; int i, j, k; for (i=0; i < 3; i++) for (j=0; j < 3; j++) for (cmatrix[i][j] = k=0; k < 3; k++) cmatrix[i][j] += rgb_romm[i][k] * romm_cam[k][j]; } void CLASS parse_mos (int offset) { char data[40]; int skip, from, i, c, neut[4], planes=0, frot=0; static const char *mod[] = { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22", "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65", "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7" }; float romm_cam[3][3]; fseek (ifp, offset, SEEK_SET); while (1) { if (get4() != 0x504b5453) break; get4(); fread (data, 1, 40, ifp); skip = get4(); from = ftell(ifp); if (!strcmp(data,"JPEG_preview_data")) { thumb_offset = from; thumb_length = skip; } if (!strcmp(data,"icc_camera_profile")) { profile_offset = from; profile_length = skip; } if (!strcmp(data,"ShootObj_back_type")) { fscanf (ifp, "%d", &i); if ((unsigned) i < sizeof mod / sizeof (*mod)) strcpy (model, mod[i]); } if (!strcmp(data,"icc_camera_to_tone_matrix")) { for (i=0; i < 9; i++) romm_cam[0][i] = int_to_float(get4()); romm_coeff (romm_cam); } if (!strcmp(data,"CaptProf_color_matrix")) { for (i=0; i < 9; i++) fscanf (ifp, "%f", &romm_cam[0][i]); romm_coeff (romm_cam); } if (!strcmp(data,"CaptProf_number_of_planes")) fscanf (ifp, "%d", &planes); if (!strcmp(data,"CaptProf_raw_data_rotation")) fscanf (ifp, "%d", &flip); if (!strcmp(data,"CaptProf_mosaic_pattern")) FORC4 { fscanf (ifp, "%d", &i); if (i == 1) frot = c ^ (c >> 1); } if (!strcmp(data,"ImgProf_rotation_angle")) { fscanf (ifp, "%d", &i); flip = i - flip; } if (!strcmp(data,"NeutObj_neutrals") && !cam_mul[0]) { FORC4 fscanf (ifp, "%d", neut+c); FORC3 cam_mul[c] = (float) neut[0] / neut[c+1]; } parse_mos (from); fseek (ifp, skip+from, SEEK_SET); } if (planes) filters = (planes == 1) * 0x01010101 * (uchar) "\x94\x61\x16\x49"[(flip/90 + frot) & 3]; } void CLASS linear_table (unsigned len) { int i; if (len > 0x1000) len = 0x1000; read_shorts (curve, len); for (i=len; i < 0x1000; i++) curve[i] = curve[i-1]; maximum = curve[0xfff]; } void CLASS parse_kodak_ifd (int base) { unsigned entries, tag, type, len, save; int i, c, wbi=-2, wbtemp=6500; float mul[3], num; entries = get2(); if (entries > 1024) return; while (entries--) { tiff_get (base, &tag, &type, &len, &save); if (tag == 1020) wbi = getint(type); if (tag == 1021 && len == 72) { /* WB set in software */ fseek (ifp, 40, SEEK_CUR); FORC3 cam_mul[c] = 2048.0 / get2(); wbi = -2; } if (tag == 2118) wbtemp = getint(type); if (tag == 2130 + wbi) FORC3 mul[c] = getreal(type); if (tag == 2140 + wbi && wbi >= 0) FORC3 { for (num=i=0; i < 4; i++) num += getreal(type) * pow (wbtemp/100.0, i); cam_mul[c] = 2048 / (num * mul[c]); } if (tag == 2317) linear_table (len); if (tag == 6020) iso_speed = getint(type); fseek (ifp, save, SEEK_SET); } } void CLASS parse_minolta (int base); int CLASS parse_tiff_ifd (int base) { unsigned entries, tag, type, len, plen=16, save; int ifd, use_cm=0, cfa, i, j, c, ima_len=0; char software[64], *cbuf, *cp; uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256]; double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num; double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 }; unsigned sony_curve[] = { 0,0,0,0,0,4095 }; unsigned *buf, sony_offset=0, sony_length=0, sony_key=0; struct jhead jh; FILE *sfp; if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0]) return 1; ifd = tiff_nifds++; for (j=0; j < 4; j++) for (i=0; i < 4; i++) cc[j][i] = i == j; entries = get2(); if (entries > 512) return 1; while (entries--) { tiff_get (base, &tag, &type, &len, &save); switch (tag) { case 17: case 18: if (type == 3 && len == 1) cam_mul[(tag-17)*2] = get2() / 256.0; break; case 23: if (type == 3) iso_speed = get2(); break; case 36: case 37: case 38: cam_mul[tag-0x24] = get2(); break; case 39: if (len < 50 || cam_mul[0]) break; fseek (ifp, 12, SEEK_CUR); FORC3 cam_mul[c] = get2(); break; case 46: if (type != 7 || fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) break; thumb_offset = ftell(ifp) - 2; thumb_length = len; break; case 2: case 256: /* ImageWidth */ tiff_ifd[ifd].width = getint(type); break; case 3: case 257: /* ImageHeight */ tiff_ifd[ifd].height = getint(type); break; case 258: /* BitsPerSample */ tiff_ifd[ifd].samples = len & 7; tiff_ifd[ifd].bps = get2(); break; case 259: /* Compression */ tiff_ifd[ifd].comp = get2(); break; case 262: /* PhotometricInterpretation */ tiff_ifd[ifd].phint = get2(); break; case 270: /* ImageDescription */ fread (desc, 512, 1, ifp); break; case 271: /* Make */ fgets (make, 64, ifp); break; case 272: /* Model */ fgets (model, 64, ifp); break; case 280: /* Panasonic RW2 offset */ if (type != 4) break; load_raw = &CLASS panasonic_load_raw; load_flags = 0x2008; case 273: /* StripOffset */ case 513: tiff_ifd[ifd].offset = get4()+base; if (!tiff_ifd[ifd].bps) { fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET); if (ljpeg_start (&jh, 1)) { tiff_ifd[ifd].comp = 6; tiff_ifd[ifd].width = jh.wide << (jh.clrs == 2); tiff_ifd[ifd].height = jh.high; tiff_ifd[ifd].bps = jh.bits; tiff_ifd[ifd].samples = jh.clrs; } } break; case 274: /* Orientation */ tiff_ifd[ifd].flip = "50132467"[get2() & 7]-'0'; break; case 277: /* SamplesPerPixel */ tiff_ifd[ifd].samples = getint(type) & 7; break; case 279: /* StripByteCounts */ case 514: tiff_ifd[ifd].bytes = get4(); break; case 305: case 11: /* Software */ fgets (software, 64, ifp); if (!strncmp(software,"Adobe",5) || !strncmp(software,"dcraw",5) || !strncmp(software,"UFRaw",5) || !strncmp(software,"Bibble",6) || !strncmp(software,"Nikon Scan",10) || !strcmp (software,"Digital Photo Professional")) is_raw = 0; break; case 306: /* DateTime */ get_timestamp(0); break; case 315: /* Artist */ fread (artist, 64, 1, ifp); break; case 322: /* TileWidth */ tile_width = getint(type); break; case 323: /* TileLength */ tile_length = getint(type); break; case 324: /* TileOffsets */ tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4(); if (len == 4) { load_raw = &CLASS sinar_4shot_load_raw; is_raw = 5; } break; case 330: /* SubIFDs */ if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].width == 3872) { load_raw = &CLASS sony_arw_load_raw; data_offset = get4()+base; ifd++; break; } while (len--) { i = ftell(ifp); fseek (ifp, get4()+base, SEEK_SET); if (parse_tiff_ifd (base)) break; fseek (ifp, i+4, SEEK_SET); } break; case 400: strcpy (make, "Sarnoff"); maximum = 0xfff; break; case 28688: FORC4 sony_curve[c+1] = get2() >> 2 & 0xfff; for (i=0; i < 5; i++) for (j = sony_curve[i]+1; j <= sony_curve[i+1]; j++) curve[j] = curve[j-1] + (1 << i); break; case 29184: sony_offset = get4(); break; case 29185: sony_length = get4(); break; case 29217: sony_key = get4(); break; case 29264: parse_minolta (ftell(ifp)); raw_width = 0; break; case 29443: FORC4 cam_mul[c ^ (c < 2)] = get2(); break; case 29459: FORC4 cam_mul[c ^ (c >> 1)] = get2(); break; case 33405: /* Model2 */ fgets (model2, 64, ifp); break; case 33422: /* CFAPattern */ case 64777: /* Kodak P-series */ if ((plen=len) > 16) plen = 16; fread (cfa_pat, 1, plen, ifp); for (colors=cfa=i=0; i < plen; i++) { colors += !(cfa & (1 << cfa_pat[i])); cfa |= 1 << cfa_pat[i]; } if (cfa == 070) memcpy (cfa_pc,"\003\004\005",3); /* CMY */ if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4); /* GMCY */ goto guess_cfa_pc; case 33424: fseek (ifp, get4()+base, SEEK_SET); parse_kodak_ifd (base); break; case 33434: /* ExposureTime */ shutter = getreal(type); break; case 33437: /* FNumber */ aperture = getreal(type); break; case 34306: /* Leaf white balance */ FORC4 cam_mul[c ^ 1] = 4096.0 / get2(); break; case 34307: /* Leaf CatchLight color matrix */ fread (software, 1, 7, ifp); if (strncmp(software,"MATRIX",6)) break; colors = 4; for (raw_color = i=0; i < 3; i++) { FORC4 fscanf (ifp, "%f", &rgb_cam[i][c^1]); if (!use_camera_wb) continue; num = 0; FORC4 num += rgb_cam[i][c]; FORC4 rgb_cam[i][c] /= num; } break; case 34310: /* Leaf metadata */ parse_mos (ftell(ifp)); case 34303: strcpy (make, "Leaf"); break; case 34665: /* EXIF tag */ fseek (ifp, get4()+base, SEEK_SET); parse_exif (base); break; case 34853: /* GPSInfo tag */ fseek (ifp, get4()+base, SEEK_SET); parse_gps (base); break; case 34675: /* InterColorProfile */ case 50831: /* AsShotICCProfile */ profile_offset = ftell(ifp); profile_length = len; break; case 37122: /* CompressedBitsPerPixel */ kodak_cbpp = get4(); break; case 37386: /* FocalLength */ focal_len = getreal(type); break; case 37393: /* ImageNumber */ shot_order = getint(type); break; case 37400: /* old Kodak KDC tag */ for (raw_color = i=0; i < 3; i++) { getreal(type); FORC3 rgb_cam[i][c] = getreal(type); } break; case 46275: /* Imacon tags */ strcpy (make, "Imacon"); data_offset = ftell(ifp); ima_len = len; break; case 46279: if (!ima_len) break; fseek (ifp, 78, SEEK_CUR); raw_width = get4(); raw_height = get4(); left_margin = get4() & 7; width = raw_width - left_margin - (get4() & 7); top_margin = get4() & 7; height = raw_height - top_margin - (get4() & 7); if (raw_width == 7262) { height = 5444; width = 7244; left_margin = 7; } fseek (ifp, 52, SEEK_CUR); FORC3 cam_mul[c] = getreal(11); fseek (ifp, 114, SEEK_CUR); flip = (get2() >> 7) * 90; if (width * height * 6 == ima_len) { if (flip % 180 == 90) SWAP(width,height); filters = flip = 0; } sprintf (model, "Ixpress %d-Mp", height*width/1000000); load_raw = &CLASS imacon_full_load_raw; if (filters) { if (left_margin & 1) filters = 0x61616161; load_raw = &CLASS unpacked_load_raw; } maximum = 0xffff; break; case 50454: /* Sinar tag */ case 50455: if (!(cbuf = (char *) malloc(len))) break; fread (cbuf, 1, len, ifp); for (cp = cbuf-1; cp && cp < cbuf+len; cp = strchr(cp,'\n')) if (!strncmp (++cp,"Neutral ",8)) sscanf (cp+8, "%f %f %f", cam_mul, cam_mul+1, cam_mul+2); free (cbuf); break; case 50458: if (!make[0]) strcpy (make, "Hasselblad"); break; case 50459: /* Hasselblad tag */ i = order; j = ftell(ifp); c = tiff_nifds; order = get2(); fseek (ifp, j+(get2(),get4()), SEEK_SET); parse_tiff_ifd (j); maximum = 0xffff; tiff_nifds = c; order = i; break; case 50706: /* DNGVersion */ FORC4 dng_version = (dng_version << 8) + fgetc(ifp); if (!make[0]) strcpy (make, "DNG"); is_raw = 1; break; case 50710: /* CFAPlaneColor */ if (len > 4) len = 4; colors = len; fread (cfa_pc, 1, colors, ifp); guess_cfa_pc: FORCC tab[cfa_pc[c]] = c; cdesc[c] = 0; for (i=16; i--; ) filters = filters << 2 | tab[cfa_pat[i % plen]]; break; case 50711: /* CFALayout */ if (get2() == 2) { fuji_width = 1; filters = 0x49494949; } break; case 291: case 50712: /* LinearizationTable */ linear_table (len); break; case 50714: /* BlackLevel */ case 50715: /* BlackLevelDeltaH */ case 50716: /* BlackLevelDeltaV */ for (dblack=i=0; i < len; i++) dblack += getreal(type); black += dblack/len + 0.5; break; case 50717: /* WhiteLevel */ maximum = getint(type); break; case 50718: /* DefaultScale */ pixel_aspect = getreal(type); pixel_aspect /= getreal(type); break; case 50721: /* ColorMatrix1 */ case 50722: /* ColorMatrix2 */ FORCC for (j=0; j < 3; j++) cm[c][j] = getreal(type); use_cm = 1; break; case 50723: /* CameraCalibration1 */ case 50724: /* CameraCalibration2 */ for (i=0; i < colors; i++) FORCC cc[i][c] = getreal(type); case 50727: /* AnalogBalance */ FORCC ab[c] = getreal(type); break; case 50728: /* AsShotNeutral */ FORCC asn[c] = getreal(type); break; case 50729: /* AsShotWhiteXY */ xyz[0] = getreal(type); xyz[1] = getreal(type); xyz[2] = 1 - xyz[0] - xyz[1]; FORC3 xyz[c] /= d65_white[c]; break; case 50740: /* DNGPrivateData */ if (dng_version) break; parse_minolta (j = get4()+base); fseek (ifp, j, SEEK_SET); parse_tiff_ifd (base); break; case 50752: read_shorts (cr2_slice, 3); break; case 50829: /* ActiveArea */ top_margin = getint(type); left_margin = getint(type); height = getint(type) - top_margin; width = getint(type) - left_margin; break; case 64772: /* Kodak P-series */ if (len < 13) break; fseek (ifp, 16, SEEK_CUR); data_offset = get4(); fseek (ifp, 28, SEEK_CUR); data_offset += get4(); load_raw = &CLASS packed_12_load_raw; break; case 65026: if (type == 2) fgets (model2, 64, ifp); } fseek (ifp, save, SEEK_SET); } if (sony_length && (buf = (unsigned *) malloc(sony_length))) { fseek (ifp, sony_offset, SEEK_SET); fread (buf, sony_length, 1, ifp); sony_decrypt (buf, sony_length/4, 1, sony_key); sfp = ifp; if ((ifp = tmpfile())) { fwrite (buf, sony_length, 1, ifp); fseek (ifp, 0, SEEK_SET); parse_tiff_ifd (-sony_offset); fclose (ifp); } ifp = sfp; free (buf); } for (i=0; i < colors; i++) FORCC cc[i][c] *= ab[i]; if (use_cm) { FORCC for (i=0; i < 3; i++) for (cam_xyz[c][i]=j=0; j < colors; j++) cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i]; cam_xyz_coeff (cam_xyz); } if (asn[0]) { cam_mul[3] = 0; FORCC cam_mul[c] = 1 / asn[c]; } if (!use_cm) FORCC pre_mul[c] /= cc[c][c]; return 0; } void CLASS parse_tiff (int base) { int doff, max_samp=0, raw=-1, thm=-1, i; struct jhead jh; fseek (ifp, base, SEEK_SET); order = get2(); if (order != 0x4949 && order != 0x4d4d) return; get2(); memset (tiff_ifd, 0, sizeof tiff_ifd); tiff_nifds = 0; while ((doff = get4())) { fseek (ifp, doff+base, SEEK_SET); if (parse_tiff_ifd (base)) break; } thumb_misc = 16; if (thumb_offset) { fseek (ifp, thumb_offset, SEEK_SET); if (ljpeg_start (&jh, 1)) { thumb_misc = jh.bits; thumb_width = jh.wide; thumb_height = jh.high; } } for (i=0; i < tiff_nifds; i++) { if (max_samp < tiff_ifd[i].samples) max_samp = tiff_ifd[i].samples; if (max_samp > 3) max_samp = 3; if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) && (tiff_ifd[i].width | tiff_ifd[i].height) < 0x10000 && tiff_ifd[i].width*tiff_ifd[i].height > raw_width*raw_height) { raw_width = tiff_ifd[i].width; raw_height = tiff_ifd[i].height; tiff_bps = tiff_ifd[i].bps; tiff_compress = tiff_ifd[i].comp; data_offset = tiff_ifd[i].offset; tiff_flip = tiff_ifd[i].flip; tiff_samples = tiff_ifd[i].samples; raw = i; } } fuji_width *= (raw_width+1)/2; if (tiff_ifd[0].flip) tiff_flip = tiff_ifd[0].flip; if (raw >= 0 && !load_raw) switch (tiff_compress) { case 0: case 1: switch (tiff_bps) { case 8: load_raw = &CLASS eight_bit_load_raw; break; case 12: load_raw = &CLASS packed_12_load_raw; if (tiff_ifd[raw].phint == 2) load_flags = 6; if (strncmp(make,"PENTAX",6)) break; case 14: case 16: load_raw = &CLASS unpacked_load_raw; break; } if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) { load_raw = &CLASS packed_12_load_raw; load_flags = 273; } break; case 6: case 7: case 99: load_raw = &CLASS lossless_jpeg_load_raw; break; case 262: load_raw = &CLASS kodak_262_load_raw; break; case 32767: if (tiff_ifd[raw].bytes*8 != raw_width*raw_height*tiff_bps) { raw_height += 8; load_raw = &CLASS sony_arw_load_raw; break; } if (tiff_bps == 8) { tiff_bps = 12; load_raw = &CLASS sony_arw2_load_raw; break; } load_flags = 79; case 32769: load_flags++; case 32773: load_raw = &CLASS packed_12_load_raw; break; case 34713: load_raw = &CLASS nikon_compressed_load_raw; break; case 65535: load_raw = &CLASS pentax_k10_load_raw; break; case 65000: switch (tiff_ifd[raw].phint) { case 2: load_raw = &CLASS kodak_rgb_load_raw; filters = 0; break; case 6: load_raw = &CLASS kodak_ycbcr_load_raw; filters = 0; break; case 32803: load_raw = &CLASS kodak_65000_load_raw; } case 32867: break; default: is_raw = 0; } if (!dng_version) if ( (tiff_samples == 3 && tiff_ifd[raw].bytes && tiff_bps != 14 && tiff_bps != 2048) || (tiff_bps == 8 && !strstr(make,"KODAK") && !strstr(make,"Kodak") && !strstr(model2,"DEBUG RAW"))) is_raw = 0; for (i=0; i < tiff_nifds; i++) if (i != raw && tiff_ifd[i].samples == max_samp && tiff_ifd[i].width * tiff_ifd[i].height / SQR(tiff_ifd[i].bps+1) > thumb_width * thumb_height / SQR(thumb_misc+1)) { thumb_width = tiff_ifd[i].width; thumb_height = tiff_ifd[i].height; thumb_offset = tiff_ifd[i].offset; thumb_length = tiff_ifd[i].bytes; thumb_misc = tiff_ifd[i].bps; thm = i; } if (thm >= 0) { thumb_misc |= tiff_ifd[thm].samples << 5; switch (tiff_ifd[thm].comp) { case 0: write_thumb = &CLASS layer_thumb; break; case 1: if (tiff_ifd[thm].bps > 8) thumb_load_raw = &CLASS kodak_thumb_load_raw; else write_thumb = &CLASS ppm_thumb; break; case 65000: thumb_load_raw = tiff_ifd[thm].phint == 6 ? &CLASS kodak_ycbcr_load_raw : &CLASS kodak_rgb_load_raw; } } } void CLASS parse_minolta (int base) { int save, tag, len, offset, high=0, wide=0, i, c; short sorder=order; fseek (ifp, base, SEEK_SET); if (fgetc(ifp) || fgetc(ifp)-'M' || fgetc(ifp)-'R') return; order = fgetc(ifp) * 0x101; offset = base + get4() + 8; while ((save=ftell(ifp)) < offset) { for (tag=i=0; i < 4; i++) tag = tag << 8 | fgetc(ifp); len = get4(); switch (tag) { case 0x505244: /* PRD */ fseek (ifp, 8, SEEK_CUR); high = get2(); wide = get2(); break; case 0x574247: /* WBG */ get4(); i = strcmp(model,"DiMAGE A200") ? 0:3; FORC4 cam_mul[c ^ (c >> 1) ^ i] = get2(); break; case 0x545457: /* TTW */ parse_tiff (ftell(ifp)); data_offset = offset; } fseek (ifp, save+len+8, SEEK_SET); } raw_height = high; raw_width = wide; order = sorder; } /* Many cameras have a "debug mode" that writes JPEG and raw at the same time. The raw file has no header, so try to to open the matching JPEG file and read its metadata. */ void CLASS parse_external_jpeg() { const char *file, *ext; char *jname, *jfile, *jext; FILE *save=ifp; ext = strrchr (ifname, '.'); file = strrchr (ifname, '/'); if (!file) file = strrchr (ifname, '\\'); if (!file) file = ifname-1; file++; if (!ext || strlen(ext) != 4 || ext-file != 8) return; jname = (char *) malloc (strlen(ifname) + 1); merror (jname, "parse_external_jpeg()"); strcpy (jname, ifname); jfile = file - ifname + jname; jext = ext - ifname + jname; if (strcasecmp (ext, ".jpg")) { strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg"); if (isdigit(*file)) { memcpy (jfile, file+4, 4); memcpy (jfile+4, file, 4); } } else while (isdigit(*--jext)) { if (*jext != '9') { (*jext)++; break; } *jext = '0'; } if (strcmp (jname, ifname)) { if ((ifp = fopen (jname, "rb"))) { if (verbose) fprintf (stderr,_("Reading metadata from %s ...\n"), jname); parse_tiff (12); thumb_offset = 0; is_raw = 1; fclose (ifp); } } if (!timestamp) fprintf (stderr,_("Failed to read metadata from %s\n"), jname); free (jname); ifp = save; } /* CIFF block 0x1030 contains an 8x8 white sample. Load this into white[][] for use in scale_colors(). */ void CLASS ciff_block_1030() { static const ushort key[] = { 0x410, 0x45f3 }; int i, bpp, row, col, vbits=0; unsigned long bitbuf=0; if ((get2(),get4()) != 0x80008 || !get4()) return; bpp = get2(); if (bpp != 10 && bpp != 12) return; for (i=row=0; row < 8; row++) for (col=0; col < 8; col++) { if (vbits < bpp) { bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]); vbits += 16; } white[row][col] = bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp); vbits -= bpp; } } /* Parse a CIFF file, better known as Canon CRW format. */ void CLASS parse_ciff (int offset, int length) { int tboff, nrecs, c, type, len, save, wbi=-1; ushort key[] = { 0x410, 0x45f3 }; fseek (ifp, offset+length-4, SEEK_SET); tboff = get4() + offset; fseek (ifp, tboff, SEEK_SET); nrecs = get2(); if (nrecs > 100) return; while (nrecs--) { type = get2(); len = get4(); save = ftell(ifp) + 4; fseek (ifp, offset+get4(), SEEK_SET); if ((((type >> 8) + 8) | 8) == 0x38) parse_ciff (ftell(ifp), len); /* Parse a sub-table */ if (type == 0x0810) fread (artist, 64, 1, ifp); if (type == 0x080a) { fread (make, 64, 1, ifp); fseek (ifp, strlen(make) - 63, SEEK_CUR); fread (model, 64, 1, ifp); } if (type == 0x1810) { fseek (ifp, 12, SEEK_CUR); flip = get4(); } if (type == 0x1835) /* Get the decoder table */ tiff_compress = get4(); if (type == 0x2007) { thumb_offset = ftell(ifp); thumb_length = len; } if (type == 0x1818) { shutter = pow (2, -int_to_float((get4(),get4()))); aperture = pow (2, int_to_float(get4())/2); } if (type == 0x102a) { iso_speed = pow (2, (get4(),get2())/32.0 - 4) * 50; aperture = pow (2, (get2(),(short)get2())/64.0); shutter = pow (2,-((short)get2())/32.0); wbi = (get2(),get2()); if (wbi > 17) wbi = 0; fseek (ifp, 32, SEEK_CUR); if (shutter > 1e6) shutter = get2()/10.0; } if (type == 0x102c) { if (get2() > 512) { /* Pro90, G1 */ fseek (ifp, 118, SEEK_CUR); FORC4 cam_mul[c ^ 2] = get2(); } else { /* G2, S30, S40 */ fseek (ifp, 98, SEEK_CUR); FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2(); } } if (type == 0x0032) { if (len == 768) { /* EOS D30 */ fseek (ifp, 72, SEEK_CUR); FORC4 cam_mul[c ^ (c >> 1)] = 1024.0 / get2(); if (!wbi) cam_mul[0] = -1; /* use my auto white balance */ } else if (!cam_mul[0]) { if (get2() == key[0]) /* Pro1, G6, S60, S70 */ c = (strstr(model,"Pro1") ? "012346000000000000":"01345:000000006008")[wbi]-'0'+ 2; else { /* G3, G5, S45, S50 */ c = "023457000000006000"[wbi]-'0'; key[0] = key[1] = 0; } fseek (ifp, 78 + c*8, SEEK_CUR); FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2() ^ key[c & 1]; if (!wbi) cam_mul[0] = -1; } } if (type == 0x10a9) { /* D60, 10D, 300D, and clones */ if (len > 66) wbi = "0134567028"[wbi]-'0'; fseek (ifp, 2 + wbi*8, SEEK_CUR); FORC4 cam_mul[c ^ (c >> 1)] = get2(); } if (type == 0x1030 && (0x18040 >> wbi & 1)) ciff_block_1030(); /* all that don't have 0x10a9 */ if (type == 0x1031) { raw_width = (get2(),get2()); raw_height = get2(); } if (type == 0x5029) { focal_len = len >> 16; if ((len & 0xffff) == 2) focal_len /= 32; } if (type == 0x5813) flash_used = int_to_float(len); if (type == 0x5814) canon_ev = int_to_float(len); if (type == 0x5817) shot_order = len; if (type == 0x5834) unique_id = len; if (type == 0x580e) timestamp = len; if (type == 0x180e) timestamp = get4(); #ifdef LOCALTIME if ((type | 0x4000) == 0x580e) timestamp = mktime (gmtime (×tamp)); #endif fseek (ifp, save, SEEK_SET); } } void CLASS parse_rollei() { char line[128], *val; struct tm t; fseek (ifp, 0, SEEK_SET); memset (&t, 0, sizeof t); do { fgets (line, 128, ifp); if ((val = strchr(line,'='))) *val++ = 0; else val = line + strlen(line); if (!strcmp(line,"DAT")) sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year); if (!strcmp(line,"TIM")) sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec); if (!strcmp(line,"HDR")) thumb_offset = atoi(val); if (!strcmp(line,"X ")) raw_width = atoi(val); if (!strcmp(line,"Y ")) raw_height = atoi(val); if (!strcmp(line,"TX ")) thumb_width = atoi(val); if (!strcmp(line,"TY ")) thumb_height = atoi(val); } while (strncmp(line,"EOHD",4)); data_offset = thumb_offset + thumb_width * thumb_height * 2; t.tm_year -= 1900; t.tm_mon -= 1; if (mktime(&t) > 0) timestamp = mktime(&t); strcpy (make, "Rollei"); strcpy (model,"d530flex"); write_thumb = &CLASS rollei_thumb; } void CLASS parse_sinar_ia() { int entries, off; char str[8], *cp; order = 0x4949; fseek (ifp, 4, SEEK_SET); entries = get4(); fseek (ifp, get4(), SEEK_SET); while (entries--) { off = get4(); get4(); fread (str, 8, 1, ifp); if (!strcmp(str,"META")) meta_offset = off; if (!strcmp(str,"THUMB")) thumb_offset = off; if (!strcmp(str,"RAW0")) data_offset = off; } fseek (ifp, meta_offset+20, SEEK_SET); fread (make, 64, 1, ifp); make[63] = 0; if ((cp = strchr(make,' '))) { strcpy (model, cp+1); *cp = 0; } raw_width = get2(); raw_height = get2(); load_raw = &CLASS unpacked_load_raw; thumb_width = (get4(),get2()); thumb_height = get2(); write_thumb = &CLASS ppm_thumb; maximum = 0x3fff; } void CLASS parse_phase_one (int base) { unsigned entries, tag, type, len, data, save, i, c; float romm_cam[3][3]; char *cp; memset (&ph1, 0, sizeof ph1); fseek (ifp, base, SEEK_SET); order = get4() & 0xffff; if (get4() >> 8 != 0x526177) return; /* "Raw" */ fseek (ifp, get4()+base, SEEK_SET); entries = get4(); get4(); while (entries--) { tag = get4(); type = get4(); len = get4(); data = get4(); save = ftell(ifp); fseek (ifp, base+data, SEEK_SET); switch (tag) { case 0x100: flip = "0653"[data & 3]-'0'; break; case 0x106: for (i=0; i < 9; i++) romm_cam[0][i] = getreal(11); romm_coeff (romm_cam); break; case 0x107: FORC3 cam_mul[c] = getreal(11); break; case 0x108: raw_width = data; break; case 0x109: raw_height = data; break; case 0x10a: left_margin = data; break; case 0x10b: top_margin = data; break; case 0x10c: width = data; break; case 0x10d: height = data; break; case 0x10e: ph1.format = data; break; case 0x10f: data_offset = data+base; break; case 0x110: meta_offset = data+base; meta_length = len; break; case 0x112: ph1.key_off = save - 4; break; case 0x210: ph1.tag_210 = int_to_float(data); break; case 0x21a: ph1.tag_21a = data; break; case 0x21c: strip_offset = data+base; break; case 0x21d: ph1.black = data; break; case 0x222: ph1.split_col = data - left_margin; break; case 0x223: ph1.black_off = data+base; break; case 0x301: model[63] = 0; fread (model, 1, 63, ifp); if ((cp = strstr(model," camera"))) *cp = 0; } fseek (ifp, save, SEEK_SET); } load_raw = ph1.format < 3 ? &CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c; maximum = 0xffff; strcpy (make, "Phase One"); if (model[0]) return; switch (raw_height) { case 2060: strcpy (model,"LightPhase"); break; case 2682: strcpy (model,"H 10"); break; case 4128: strcpy (model,"H 20"); break; case 5488: strcpy (model,"H 25"); break; } } void CLASS parse_fuji (int offset) { unsigned entries, tag, len, save, c; fseek (ifp, offset, SEEK_SET); entries = get4(); if (entries > 255) return; while (entries--) { tag = get2(); len = get2(); save = ftell(ifp); if (tag == 0x100) { raw_height = get2(); raw_width = get2(); } else if (tag == 0x121) { height = get2(); if ((width = get2()) == 4284) width += 3; } else if (tag == 0x130) fuji_layout = fgetc(ifp) >> 7; if (tag == 0x2ff0) FORC4 cam_mul[c ^ 1] = get2(); fseek (ifp, save+len, SEEK_SET); } height <<= fuji_layout; width >>= fuji_layout; } int CLASS parse_jpeg (int offset) { int len, save, hlen, mark; fseek (ifp, offset, SEEK_SET); if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return 0; while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda) { order = 0x4d4d; len = get2() - 2; save = ftell(ifp); if (mark == 0xc0 || mark == 0xc3) { fgetc(ifp); raw_height = get2(); raw_width = get2(); } order = get2(); hlen = get4(); if (get4() == 0x48454150) /* "HEAP" */ parse_ciff (save+hlen, len-hlen); parse_tiff (save+6); fseek (ifp, save+len, SEEK_SET); } return 1; } void CLASS parse_riff() { unsigned i, size, end; char tag[4], date[64], month[64]; static const char mon[12][4] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" }; struct tm t; order = 0x4949; fread (tag, 4, 1, ifp); size = get4(); end = ftell(ifp) + size; if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) { get4(); while (ftell(ifp)+7 < end) parse_riff(); } else if (!memcmp(tag,"nctg",4)) { while (ftell(ifp)+7 < end) { i = get2(); size = get2(); if ((i+1) >> 1 == 10 && size == 20) get_timestamp(0); else fseek (ifp, size, SEEK_CUR); } } else if (!memcmp(tag,"IDIT",4) && size < 64) { fread (date, 64, 1, ifp); date[size] = 0; memset (&t, 0, sizeof t); if (sscanf (date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) == 6) { for (i=0; i < 12 && strcasecmp(mon[i],month); i++); t.tm_mon = i; t.tm_year -= 1900; if (mktime(&t) > 0) timestamp = mktime(&t); } } else fseek (ifp, size, SEEK_CUR); } void CLASS parse_smal (int offset, int fsize) { int ver; fseek (ifp, offset+2, SEEK_SET); order = 0x4949; ver = fgetc(ifp); if (ver == 6) fseek (ifp, 5, SEEK_CUR); if (get4() != fsize) return; if (ver > 6) data_offset = get4(); raw_height = height = get2(); raw_width = width = get2(); strcpy (make, "SMaL"); sprintf (model, "v%d %dx%d", ver, width, height); if (ver == 6) load_raw = &CLASS smal_v6_load_raw; if (ver == 9) load_raw = &CLASS smal_v9_load_raw; } void CLASS parse_cine() { unsigned off_head, off_setup, off_image, i; order = 0x4949; fseek (ifp, 4, SEEK_SET); is_raw = get2() == 2; fseek (ifp, 14, SEEK_CUR); is_raw *= get4(); off_head = get4(); off_setup = get4(); off_image = get4(); timestamp = get4(); if ((i = get4())) timestamp = i; fseek (ifp, off_head+4, SEEK_SET); raw_width = get4(); raw_height = get4(); switch (get2(),get2()) { case 8: load_raw = &CLASS eight_bit_load_raw; break; case 16: load_raw = &CLASS unpacked_load_raw; } fseek (ifp, off_setup+792, SEEK_SET); strcpy (make, "CINE"); sprintf (model, "%d", get4()); fseek (ifp, 12, SEEK_CUR); switch ((i=get4()) & 0xffffff) { case 3: filters = 0x94949494; break; case 4: filters = 0x49494949; break; default: is_raw = 0; } fseek (ifp, 72, SEEK_CUR); switch ((get4()+3600) % 360) { case 270: flip = 4; break; case 180: flip = 1; break; case 90: flip = 7; break; case 0: flip = 2; } cam_mul[0] = getreal(11); cam_mul[2] = getreal(11); maximum = ~(-1 << get4()); fseek (ifp, 668, SEEK_CUR); shutter = get4()/1000000000.0; fseek (ifp, off_image, SEEK_SET); if (shot_select < is_raw) fseek (ifp, shot_select*8, SEEK_CUR); data_offset = (INT64) get4() + 8; data_offset += (INT64) get4() << 32; } char * CLASS foveon_gets (int offset, char *str, int len) { int i; fseek (ifp, offset, SEEK_SET); for (i=0; i < len-1; i++) if ((str[i] = get2()) == 0) break; str[i] = 0; return str; } void CLASS parse_foveon() { int entries, img=0, off, len, tag, save, i, wide, high, pent, poff[256][2]; char name[64], value[64]; order = 0x4949; /* Little-endian */ fseek (ifp, 36, SEEK_SET); flip = get4(); fseek (ifp, -4, SEEK_END); fseek (ifp, get4(), SEEK_SET); if (get4() != 0x64434553) return; /* SECd */ entries = (get4(),get4()); while (entries--) { off = get4(); len = get4(); tag = get4(); save = ftell(ifp); fseek (ifp, off, SEEK_SET); if (get4() != (0x20434553 | (tag << 24))) return; switch (tag) { case 0x47414d49: /* IMAG */ case 0x32414d49: /* IMA2 */ fseek (ifp, 12, SEEK_CUR); wide = get4(); high = get4(); if (wide > raw_width && high > raw_height) { raw_width = wide; raw_height = high; data_offset = off+24; } fseek (ifp, off+28, SEEK_SET); if (fgetc(ifp) == 0xff && fgetc(ifp) == 0xd8 && thumb_length < len-28) { thumb_offset = off+28; thumb_length = len-28; write_thumb = &CLASS jpeg_thumb; } if (++img == 2 && !thumb_length) { thumb_offset = off+24; thumb_width = wide; thumb_height = high; write_thumb = &CLASS foveon_thumb; } break; case 0x464d4143: /* CAMF */ meta_offset = off+24; meta_length = len-28; if (meta_length > 0x20000) meta_length = 0x20000; break; case 0x504f5250: /* PROP */ pent = (get4(),get4()); fseek (ifp, 12, SEEK_CUR); off += pent*8 + 24; if ((unsigned) pent > 256) pent=256; for (i=0; i < pent*2; i++) poff[0][i] = off + get4()*2; for (i=0; i < pent; i++) { foveon_gets (poff[i][0], name, 64); foveon_gets (poff[i][1], value, 64); if (!strcmp (name, "ISO")) iso_speed = atoi(value); if (!strcmp (name, "CAMMANUF")) strcpy (make, value); if (!strcmp (name, "CAMMODEL")) strcpy (model, value); if (!strcmp (name, "WB_DESC")) strcpy (model2, value); if (!strcmp (name, "TIME")) timestamp = atoi(value); if (!strcmp (name, "EXPTIME")) shutter = atoi(value) / 1000000.0; if (!strcmp (name, "APERTURE")) aperture = atof(value); if (!strcmp (name, "FLENGTH")) focal_len = atof(value); } #ifdef LOCALTIME timestamp = mktime (gmtime (×tamp)); #endif } fseek (ifp, save, SEEK_SET); } is_foveon = 1; } /* Thanks to Adobe for providing these excellent CAM -> XYZ matrices! */ void CLASS adobe_coeff (const char *make, const char *model) { static const struct { const char *prefix; short black, maximum, trans[12]; } table[] = { { "AGFAPHOTO DC-833m", 0, 0, /* DJC */ { 11438,-3762,-1115,-2409,9914,2497,-1227,2295,5300 } }, { "Apple QuickTake", 0, 0, /* DJC */ { 21392,-5653,-3353,2406,8010,-415,7166,1427,2078 } }, { "Canon EOS D2000", 0, 0, { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, { "Canon EOS D6000", 0, 0, { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } }, { "Canon EOS D30", 0, 0, { 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } }, { "Canon EOS D60", 0, 0xfa0, { 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } }, { "Canon EOS 5D Mark II", 0, 0x3cf0, { 4716,603,-830,-7798,15474,2480,-1496,1937,6651 } }, { "Canon EOS 5D", 0, 0xe6c, { 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } }, { "Canon EOS 10D", 0, 0xfa0, { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, { "Canon EOS 20Da", 0, 0, { 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } }, { "Canon EOS 20D", 0, 0xfff, { 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } }, { "Canon EOS 30D", 0, 0, { 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } }, { "Canon EOS 40D", 0, 0x3f60, { 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } }, { "Canon EOS 50D", 0, 0x3d93, { 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } }, { "Canon EOS 300D", 0, 0xfa0, { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, { "Canon EOS 350D", 0, 0xfff, { 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } }, { "Canon EOS 400D", 0, 0xe8e, { 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } }, { "Canon EOS 450D", 0, 0x390d, { 5784,-262,-821,-7539,15064,2672,-1982,2681,7427 } }, { "Canon EOS 1000D", 0, 0xe43, { 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } }, { "Canon EOS-1Ds Mark III", 0, 0x3bb0, { 5859,-211,-930,-8255,16017,2353,-1732,1887,7448 } }, { "Canon EOS-1Ds Mark II", 0, 0xe80, { 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } }, { "Canon EOS-1D Mark II N", 0, 0xe80, { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } }, { "Canon EOS-1D Mark III", 0, 0x3bb0, { 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } }, { "Canon EOS-1D Mark II", 0, 0xe80, { 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } }, { "Canon EOS-1DS", 0, 0xe20, { 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } }, { "Canon EOS-1D", 0, 0xe20, { 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } }, { "Canon EOS", 0, 0, { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, { "Canon PowerShot A50", 0, 0, { -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } }, { "Canon PowerShot A5", 0, 0, { -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } }, { "Canon PowerShot G10", 0, 0, { 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } }, { "Canon PowerShot G1", 0, 0, { -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } }, { "Canon PowerShot G2", 0, 0, { 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } }, { "Canon PowerShot G3", 0, 0, { 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } }, { "Canon PowerShot G5", 0, 0, { 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } }, { "Canon PowerShot G6", 0, 0, { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } }, { "Canon PowerShot G9", 0, 0, { 7368,-2141,-598,-5621,13254,2625,-1418,1696,5743 } }, { "Canon PowerShot Pro1", 0, 0, { 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } }, { "Canon PowerShot Pro70", 34, 0, { -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 } }, { "Canon PowerShot Pro90", 0, 0, { -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577 } }, { "Canon PowerShot S30", 0, 0, { 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 } }, { "Canon PowerShot S40", 0, 0, { 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 } }, { "Canon PowerShot S45", 0, 0, { 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 } }, { "Canon PowerShot S50", 0, 0, { 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 } }, { "Canon PowerShot S60", 0, 0, { 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } }, { "Canon PowerShot S70", 0, 0, { 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } }, { "Canon PowerShot A610", 0, 0, /* DJC */ { 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } }, { "Canon PowerShot A620", 0, 0, /* DJC */ { 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } }, { "Canon PowerShot A630", 0, 0, /* DJC */ { 14201,-5308,-1757,-6087,14472,1617,-2191,3105,5348 } }, { "Canon PowerShot A640", 0, 0, /* DJC */ { 13124,-5329,-1390,-3602,11658,1944,-1612,2863,4885 } }, { "Canon PowerShot A650", 0, 0, /* DJC */ { 9427,-3036,-959,-2581,10671,1911,-1039,1982,4430 } }, { "Canon PowerShot A720", 0, 0, /* DJC */ { 14573,-5482,-1546,-1266,9799,1468,-1040,1912,3810 } }, { "Canon PowerShot S3 IS", 0, 0, /* DJC */ { 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } }, { "Canon PowerShot SX1 IS", 0, 0, /* DJC */ { 10013,-2214,-1111,-3650,11589,2062,342,685,3617 } }, { "Canon PowerShot SX110 IS", 0, 0, /* DJC */ { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } }, { "CASIO EX-S20", 0, 0, /* DJC */ { 11634,-3924,-1128,-4968,12954,2015,-1588,2648,7206 } }, { "CINE 650", 0, 0, { 3390,480,-500,-800,3610,340,-550,2336,1192 } }, { "CINE 660", 0, 0, { 3390,480,-500,-800,3610,340,-550,2336,1192 } }, { "CINE", 0, 0, { 20183,-4295,-423,-3940,15330,3985,-280,4870,9800 } }, { "Contax N Digital", 0, 0xf1e, { 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } }, { "EPSON R-D1", 0, 0, { 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } }, { "FUJIFILM FinePix E550", 0, 0, { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } }, { "FUJIFILM FinePix E900", 0, 0, { 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } }, { "FUJIFILM FinePix F8", 0, 0, { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } }, { "FUJIFILM FinePix F7", 0, 0, { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, { "FUJIFILM FinePix S100FS", 514, 0, { 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } }, { "FUJIFILM FinePix S20Pro", 0, 0, { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, { "FUJIFILM FinePix S2Pro", 128, 0, { 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } }, { "FUJIFILM FinePix S3Pro", 0, 0, { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } }, { "FUJIFILM FinePix S5Pro", 0, 0, { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } }, { "FUJIFILM FinePix S5000", 0, 0, { 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } }, { "FUJIFILM FinePix S5100", 0, 0x3e00, { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } }, { "FUJIFILM FinePix S5500", 0, 0x3e00, { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } }, { "FUJIFILM FinePix S5200", 0, 0, { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } }, { "FUJIFILM FinePix S5600", 0, 0, { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } }, { "FUJIFILM FinePix S6", 0, 0, { 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } }, { "FUJIFILM FinePix S7000", 0, 0, { 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } }, { "FUJIFILM FinePix S9000", 0, 0, { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } }, { "FUJIFILM FinePix S9500", 0, 0, { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } }, { "FUJIFILM FinePix S9100", 0, 0, { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } }, { "FUJIFILM FinePix S9600", 0, 0, { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } }, { "FUJIFILM IS-1", 0, 0, { 21461,-10807,-1441,-2332,10599,1999,289,875,7703 } }, { "FUJIFILM IS Pro", 0, 0, { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } }, { "Imacon Ixpress", 0, 0, /* DJC */ { 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } }, { "KODAK NC2000", 0, 0, { 13891,-6055,-803,-465,9919,642,2121,82,1291 } }, { "Kodak DCS315C", 8, 0, { 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } }, { "Kodak DCS330C", 8, 0, { 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } }, { "KODAK DCS420", 0, 0, { 10868,-1852,-644,-1537,11083,484,2343,628,2216 } }, { "KODAK DCS460", 0, 0, { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } }, { "KODAK EOSDCS1", 0, 0, { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } }, { "KODAK EOSDCS3B", 0, 0, { 9898,-2700,-940,-2478,12219,206,1985,634,1031 } }, { "Kodak DCS520C", 180, 0, { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, { "Kodak DCS560C", 188, 0, { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } }, { "Kodak DCS620C", 180, 0, { 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } }, { "Kodak DCS620X", 185, 0, { 13095,-6231,154,12221,-21,-2137,895,4602,2258 } }, { "Kodak DCS660C", 214, 0, { 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } }, { "Kodak DCS720X", 0, 0, { 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } }, { "Kodak DCS760C", 0, 0, { 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } }, { "Kodak DCS Pro SLR", 0, 0, { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } }, { "Kodak DCS Pro 14nx", 0, 0, { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } }, { "Kodak DCS Pro 14", 0, 0, { 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } }, { "Kodak ProBack645", 0, 0, { 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } }, { "Kodak ProBack", 0, 0, { 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } }, { "KODAK P712", 0, 0, { 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } }, { "KODAK P850", 0, 0xf7c, { 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } }, { "KODAK P880", 0, 0xfff, { 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } }, { "Leaf CMost", 0, 0, { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } }, { "Leaf Valeo 6", 0, 0, { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } }, { "Leaf Aptus 54S", 0, 0, { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } }, { "Leaf Aptus 65", 0, 0, { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, { "Leaf Aptus 75", 0, 0, { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, { "Leaf", 0, 0, { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } }, { "Mamiya ZD", 0, 0, { 7645,2579,-1363,-8689,16717,2015,-3712,5941,5961 } }, { "Micron 2010", 110, 0, /* DJC */ { 16695,-3761,-2151,155,9682,163,3433,951,4904 } }, { "Minolta DiMAGE 5", 0, 0xf7d, { 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } }, { "Minolta DiMAGE 7Hi", 0, 0xf7d, { 11368,-3894,-1242,-6521,14358,2339,-2475,3056,7285 } }, { "Minolta DiMAGE 7", 0, 0xf7d, { 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } }, { "Minolta DiMAGE A1", 0, 0xf8b, { 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } }, { "MINOLTA DiMAGE A200", 0, 0, { 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } }, { "Minolta DiMAGE A2", 0, 0xf8f, { 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } }, { "Minolta DiMAGE Z2", 0, 0, /* DJC */ { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } }, { "MINOLTA DYNAX 5", 0, 0xffb, { 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } }, { "MINOLTA DYNAX 7", 0, 0xffb, { 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } }, { "MOTOROLA PIXL", 0, 0, /* DJC */ { 8898,-989,-1033,-3292,11619,1674,-661,3178,5216 } }, { "NIKON D100", 0, 0, { 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } }, { "NIKON D1H", 0, 0, { 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } }, { "NIKON D1X", 0, 0, { 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } }, { "NIKON D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */ { 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } }, { "NIKON D2H", 0, 0, { 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } }, { "NIKON D2X", 0, 0, { 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } }, { "NIKON D40X", 0, 0, { 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } }, { "NIKON D40", 0, 0, { 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } }, { "NIKON D50", 0, 0, { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, { "NIKON D60", 0, 0, { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } }, { "NIKON D700", 0, 0, { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } }, { "NIKON D70", 0, 0, { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, { "NIKON D80", 0, 0, { 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } }, { "NIKON D90", 0, 0xf00, { 7309,-1403,-519,-8474,16008,2622,-2434,2826,8064 } }, { "NIKON D200", 0, 0xfbc, { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } }, { "NIKON D300", 0, 0, { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } }, { "NIKON D3X", 0, 0, { 7171,-1986,-648,-8085,15555,2718,-2170,2512,7457 } }, { "NIKON D3", 0, 0, { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } }, { "NIKON E950", 0, 0x3dd, /* DJC */ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, { "NIKON E995", 0, 0, /* copied from E5000 */ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, { "NIKON E2100", 0, 0, /* copied from Z2, new white balance */ { 13142,-4152,-1596,-4655,12374,2282,-1769,2696,6711} }, { "NIKON E2500", 0, 0, { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, { "NIKON E4300", 0, 0, /* copied from Minolta DiMAGE Z2 */ { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } }, { "NIKON E4500", 0, 0, { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, { "NIKON E5000", 0, 0, { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, { "NIKON E5400", 0, 0, { 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } }, { "NIKON E5700", 0, 0, { -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } }, { "NIKON E8400", 0, 0, { 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } }, { "NIKON E8700", 0, 0, { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } }, { "NIKON E8800", 0, 0, { 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } }, { "NIKON COOLPIX P6000", 0, 0, { 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } }, { "OLYMPUS C5050", 0, 0, { 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } }, { "OLYMPUS C5060", 0, 0, { 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } }, { "OLYMPUS C7070", 0, 0, { 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 } }, { "OLYMPUS C70", 0, 0, { 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } }, { "OLYMPUS C80", 0, 0, { 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } }, { "OLYMPUS E-10", 0, 0xffc0, { 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } }, { "OLYMPUS E-1", 0, 0xfff0, { 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } }, { "OLYMPUS E-20", 0, 0xffc0, { 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } }, { "OLYMPUS E-300", 0, 0, { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } }, { "OLYMPUS E-330", 0, 0, { 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } }, { "OLYMPUS E-30", 0, 0, { 8144,-1861,-1111,-7763,15894,1929,-1865,2542,7607 } }, { "OLYMPUS E-3", 0, 0xf99, { 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } }, { "OLYMPUS E-400", 0, 0xfff0, { 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } }, { "OLYMPUS E-410", 0, 0xf6a, { 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } }, { "OLYMPUS E-420", 0, 0xfd7, { 8746,-2425,-1095,-7594,15612,2073,-1780,2309,7416 } }, { "OLYMPUS E-500", 0, 0, { 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } }, { "OLYMPUS E-510", 0, 0xf6a, { 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } }, { "OLYMPUS E-520", 0, 0xfd2, { 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } }, { "OLYMPUS SP350", 0, 0, { 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } }, { "OLYMPUS SP3", 0, 0, { 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 } }, { "OLYMPUS SP500UZ", 0, 0xfff, { 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } }, { "OLYMPUS SP510UZ", 0, 0xffe, { 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } }, { "OLYMPUS SP550UZ", 0, 0xffe, { 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } }, { "OLYMPUS SP560UZ", 0, 0xff9, { 10915,-3677,-982,-5587,12986,2911,-1168,1968,6223 } }, { "OLYMPUS SP570UZ", 0, 0, { 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } }, { "PENTAX *ist DL2", 0, 0, { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, { "PENTAX *ist DL", 0, 0, { 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 } }, { "PENTAX *ist DS2", 0, 0, { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, { "PENTAX *ist DS", 0, 0, { 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } }, { "PENTAX *ist D", 0, 0, { 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } }, { "PENTAX K10D", 0, 0, { 9566,-2863,-803,-7170,15172,2112,-818,803,9705 } }, { "PENTAX K1", 0, 0, { 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } }, { "PENTAX K20D", 0, 0, { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } }, { "PENTAX K200D", 0, 0, { 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } }, { "PENTAX K2000", 0, 0, { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } }, { "PENTAX K-m", 0, 0, { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } }, { "Panasonic DMC-FZ8", 0, 0xf7f0, { 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } }, { "Panasonic DMC-FZ18", 0, 0, { 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } }, { "Panasonic DMC-FZ28", 15, 0xfff, { 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } }, { "Panasonic DMC-FZ30", 0, 0xf94c, { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } }, { "Panasonic DMC-FZ50", 0, 0xfff0, /* aka "LEICA V-LUX1" */ { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } }, { "Panasonic DMC-L10", 15, 0xf96, { 8025,-1942,-1050,-7920,15904,2100,-2456,3005,7039 } }, { "Panasonic DMC-L1", 0, 0xf7fc, /* aka "LEICA DIGILUX 3" */ { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } }, { "Panasonic DMC-LC1", 0, 0, /* aka "LEICA DIGILUX 2" */ { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } }, { "Panasonic DMC-LX1", 0, 0xf7f0, /* aka "LEICA D-LUX2" */ { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } }, { "Panasonic DMC-LX2", 0, 0, /* aka "LEICA D-LUX3" */ { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } }, { "Panasonic DMC-LX3", 15, 0xfff, /* aka "LEICA D-LUX4" */ { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } }, { "Panasonic DMC-FX150", 15, 0xfff, { 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } }, { "Panasonic DMC-G1", 15, 0xfff, { 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } }, { "Panasonic DMC-GH1", 15, 0xfff, /* DJC */ { 7808,-2387,-480,-2859,10002,2857,-1001,2012,4915 } }, { "Phase One H 20", 0, 0, /* DJC */ { 1313,1855,-109,-6715,15908,808,-327,1840,6020 } }, { "Phase One P 2", 0, 0, { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } }, { "Phase One P 30", 0, 0, { 4516,-245,-37,-7020,14976,2173,-3206,4671,7087 } }, { "Phase One P 45", 0, 0, { 5053,-24,-117,-5684,14076,1702,-2619,4492,5849 } }, { "Phase One P65", 0, 0, /* DJC */ { 8522,1268,-1916,-7706,16350,1358,-2397,4344,4923 } }, { "SAMSUNG GX-1", 0, 0, { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, { "SAMSUNG S85", 0, 0, /* DJC */ { 11885,-3968,-1473,-4214,12299,1916,-835,1655,5549 } }, { "Sinar", 0, 0, /* DJC */ { 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } }, { "SONY DSC-F828", 491, 0, { 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } }, { "SONY DSC-R1", 512, 0, { 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } }, { "SONY DSC-V3", 0, 0, { 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } }, { "SONY DSLR-A100", 0, 0xfeb, { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } }, { "SONY DSLR-A200", 0, 0, { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } }, { "SONY DSLR-A300", 0, 0, { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } }, { "SONY DSLR-A350", 0, 0xffc, { 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } }, { "SONY DSLR-A700", 254, 0x1ffe, { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } }, { "SONY DSLR-A900", 254, 0x1ffe, { 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } } }; double cam_xyz[4][3]; char name[130]; int i, j; sprintf (name, "%s %s", make, model); for (i=0; i < sizeof table / sizeof *table; i++) if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) { if (table[i].black) black = (ushort) table[i].black; if (table[i].maximum) maximum = (ushort) table[i].maximum; for (j=0; j < 12; j++) cam_xyz[0][j] = table[i].trans[j] / 10000.0; cam_xyz_coeff (cam_xyz); break; } } void CLASS simple_coeff (int index) { static const float table[][12] = { /* index 0 -- all Foveon cameras */ { 1.4032,-0.2231,-0.1016,-0.5263,1.4816,0.017,-0.0112,0.0183,0.9113 }, /* index 1 -- Kodak DC20 and DC25 */ { 2.25,0.75,-1.75,-0.25,-0.25,0.75,0.75,-0.25,-0.25,-1.75,0.75,2.25 }, /* index 2 -- Logitech Fotoman Pixtura */ { 1.893,-0.418,-0.476,-0.495,1.773,-0.278,-1.017,-0.655,2.672 }, /* index 3 -- Nikon E880, E900, and E990 */ { -1.936280, 1.800443, -1.448486, 2.584324, 1.405365, -0.524955, -0.289090, 0.408680, -1.204965, 1.082304, 2.941367, -1.818705 } }; int i, c; for (raw_color = i=0; i < 3; i++) FORCC rgb_cam[i][c] = table[index][i*colors+c]; } short CLASS guess_byte_order (int words) { uchar test[4][2]; int t=2, msb; double diff, sum[2] = {0,0}; fread (test[0], 2, 2, ifp); for (words-=2; words--; ) { fread (test[t], 2, 1, ifp); for (msb=0; msb < 2; msb++) { diff = (test[t^2][msb] << 8 | test[t^2][!msb]) - (test[t ][msb] << 8 | test[t ][!msb]); sum[msb] += diff*diff; } t = (t+1) & 3; } return sum[0] < sum[1] ? 0x4d4d : 0x4949; } /* Identify which camera created this file, and set global variables accordingly. */ void CLASS identify() { char head[32], *cp; unsigned hlen, fsize, i, c, is_canon; struct jhead jh; static const struct { int fsize; char make[12], model[19], withjpeg; } table[] = { { 62464, "Kodak", "DC20" ,0 }, { 124928, "Kodak", "DC20" ,0 }, { 1652736, "Kodak", "DCS200" ,0 }, { 4159302, "Kodak", "C330" ,0 }, { 4162462, "Kodak", "C330" ,0 }, { 460800, "Kodak", "C603v" ,0 }, { 614400, "Kodak", "C603v" ,0 }, { 6163328, "Kodak", "C603" ,0 }, { 6166488, "Kodak", "C603" ,0 }, { 9116448, "Kodak", "C603y" ,0 }, { 311696, "ST Micro", "STV680 VGA" ,0 }, /* SPYz */ { 614400, "Kodak", "KAI-0340" ,0 }, { 787456, "Creative", "PC-CAM 600" ,0 }, { 1138688, "Minolta", "RD175" ,0 }, { 3840000, "Foculus", "531C" ,0 }, { 786432, "AVT", "F-080C" ,0 }, { 1447680, "AVT", "F-145C" ,0 }, { 1920000, "AVT", "F-201C" ,0 }, { 5067304, "AVT", "F-510C" ,0 }, { 10134608, "AVT", "F-510C" ,0 }, { 16157136, "AVT", "F-810C" ,0 }, { 1409024, "Sony", "XCD-SX910CR" ,0 }, { 2818048, "Sony", "XCD-SX910CR" ,0 }, { 3884928, "Micron", "2010" ,0 }, { 6624000, "Pixelink", "A782" ,0 }, { 13248000, "Pixelink", "A782" ,0 }, { 6291456, "RoverShot","3320AF" ,0 }, { 6553440, "Canon", "PowerShot A460" ,0 }, { 6653280, "Canon", "PowerShot A530" ,0 }, { 6573120, "Canon", "PowerShot A610" ,0 }, { 9219600, "Canon", "PowerShot A620" ,0 }, { 10341600, "Canon", "PowerShot A720" ,0 }, { 10383120, "Canon", "PowerShot A630" ,0 }, { 12945240, "Canon", "PowerShot A640" ,0 }, { 15636240, "Canon", "PowerShot A650" ,0 }, { 5298000, "Canon", "PowerShot SD300" ,0 }, { 7710960, "Canon", "PowerShot S3 IS" ,0 }, { 15467760, "Canon", "PowerShot SX110 IS",0 }, { 5939200, "OLYMPUS", "C770UZ" ,0 }, { 1581060, "NIKON", "E900" ,1 }, /* or E900s,E910 */ { 2465792, "NIKON", "E950" ,1 }, /* or E800,E700 */ { 2940928, "NIKON", "E2100" ,1 }, /* or E2500 */ { 4771840, "NIKON", "E990" ,1 }, /* or E995, Oly C3030Z */ { 4775936, "NIKON", "E3700" ,1 }, /* or Optio 33WR */ { 5869568, "NIKON", "E4300" ,1 }, /* or DiMAGE Z2 */ { 5865472, "NIKON", "E4500" ,1 }, { 7438336, "NIKON", "E5000" ,1 }, /* or E5700 */ { 8998912, "NIKON", "COOLPIX S6" ,1 }, { 1976352, "CASIO", "QV-2000UX" ,1 }, { 3217760, "CASIO", "QV-3*00EX" ,1 }, { 6218368, "CASIO", "QV-5700" ,1 }, { 6054400, "CASIO", "QV-R41" ,1 }, { 7530816, "CASIO", "QV-R51" ,1 }, { 7684000, "CASIO", "QV-4000" ,1 }, { 2937856, "CASIO", "EX-S20" ,1 }, { 4948608, "CASIO", "EX-S100" ,1 }, { 7542528, "CASIO", "EX-Z50" ,1 }, { 7753344, "CASIO", "EX-Z55" ,1 }, { 7426656, "CASIO", "EX-P505" ,1 }, { 9313536, "CASIO", "EX-P600" ,1 }, { 10979200, "CASIO", "EX-P700" ,1 }, { 3178560, "PENTAX", "Optio S" ,1 }, { 4841984, "PENTAX", "Optio S" ,1 }, { 6114240, "PENTAX", "Optio S4" ,1 }, /* or S4i, CASIO EX-Z4 */ { 10702848, "PENTAX", "Optio 750Z" ,1 }, { 15980544, "AGFAPHOTO","DC-833m" ,1 }, { 16098048, "SAMSUNG", "S85" ,1 }, { 16215552, "SAMSUNG", "S85" ,1 }, { 12582980, "Sinar", "" ,0 }, { 33292868, "Sinar", "" ,0 }, { 44390468, "Sinar", "" ,0 } }; static const char *corp[] = { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX", "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One", "SAMSUNG", "Mamiya", "MOTOROLA" }; tiff_flip = flip = filters = -1; /* 0 is valid, so -1 is unknown */ raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0; maximum = height = width = top_margin = left_margin = 0; cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0; iso_speed = shutter = aperture = focal_len = unique_id = 0; memset (gpsdata, 0, sizeof gpsdata); memset (white, 0, sizeof white); thumb_offset = thumb_length = thumb_width = thumb_height = 0; load_raw = thumb_load_raw = 0; write_thumb = &CLASS jpeg_thumb; data_offset = meta_length = tiff_bps = tiff_compress = 0; kodak_cbpp = zero_after_ff = dng_version = load_flags = 0; timestamp = shot_order = tiff_samples = black = is_foveon = 0; mix_green = profile_length = data_error = zero_is_bad = 0; pixel_aspect = is_raw = raw_color = 1; tile_width = tile_length = INT_MAX; for (i=0; i < 4; i++) { cam_mul[i] = i == 1; pre_mul[i] = i < 3; FORC3 cmatrix[c][i] = 0; FORC3 rgb_cam[c][i] = c == i; } colors = 3; tiff_bps = 12; for (i=0; i < 0x4000; i++) curve[i] = i; order = get2(); hlen = get4(); fseek (ifp, 0, SEEK_SET); fread (head, 1, 32, ifp); fseek (ifp, 0, SEEK_END); fsize = ftell(ifp); if ((cp = (char *) memmem (head, 32, "MMMM", 4)) || (cp = (char *) memmem (head, 32, "IIII", 4))) { parse_phase_one (cp-head); if (cp-head) parse_tiff(0); } else if (order == 0x4949 || order == 0x4d4d) { if (!memcmp (head+6,"HEAPCCDR",8)) { data_offset = hlen; parse_ciff (hlen, fsize - hlen); } else { parse_tiff(0); } } else if (!memcmp (head,"\xff\xd8\xff\xe1",4) && !memcmp (head+6,"Exif",4)) { fseek (ifp, 4, SEEK_SET); data_offset = 4 + get2(); fseek (ifp, data_offset, SEEK_SET); if (fgetc(ifp) != 0xff) parse_tiff(12); thumb_offset = 0; } else if (!memcmp (head+25,"ARECOYK",7)) { strcpy (make, "Contax"); strcpy (model,"N Digital"); fseek (ifp, 33, SEEK_SET); get_timestamp(1); fseek (ifp, 60, SEEK_SET); FORC4 cam_mul[c ^ (c >> 1)] = get4(); } else if (!strcmp (head, "PXN")) { strcpy (make, "Logitech"); strcpy (model,"Fotoman Pixtura"); } else if (!strcmp (head, "qktk")) { strcpy (make, "Apple"); strcpy (model,"QuickTake 100"); } else if (!strcmp (head, "qktn")) { strcpy (make, "Apple"); strcpy (model,"QuickTake 150"); } else if (!memcmp (head,"FUJIFILM",8)) { fseek (ifp, 84, SEEK_SET); thumb_offset = get4(); thumb_length = get4(); fseek (ifp, 92, SEEK_SET); parse_fuji (get4()); if (thumb_offset > 120) { fseek (ifp, 120, SEEK_SET); is_raw += (i = get4()) && 1; if (is_raw == 2 && shot_select) parse_fuji (i); } fseek (ifp, 100, SEEK_SET); data_offset = get4(); parse_tiff (thumb_offset+12); } else if (!memcmp (head,"RIFF",4)) { fseek (ifp, 0, SEEK_SET); parse_riff(); } else if (!memcmp (head,"\0\001\0\001\0@@",6)) { fseek (ifp, 6, SEEK_SET); fread (make, 1, 8, ifp); fread (model, 1, 8, ifp); fread (model2, 1, 16, ifp); data_offset = get2(); get2(); raw_width = get2(); raw_height = get2(); load_raw = &CLASS nokia_load_raw; filters = 0x61616161; } else if (!memcmp (head,"DSC-Image",9)) parse_rollei(); else if (!memcmp (head,"PWAD",4)) parse_sinar_ia(); else if (!memcmp (head,"\0MRM",4)) parse_minolta(0); else if (!memcmp (head,"FOVb",4)) parse_foveon(); else if (!memcmp (head,"CI",2)) parse_cine(); else for (i=0; i < sizeof table / sizeof *table; i++) if (fsize == table[i].fsize) { strcpy (make, table[i].make ); strcpy (model, table[i].model); if (table[i].withjpeg) parse_external_jpeg(); } if (make[0] == 0) parse_smal (0, fsize); if (make[0] == 0) parse_jpeg (is_raw = 0); for (i=0; i < sizeof corp / sizeof *corp; i++) if (strstr (make, corp[i])) /* Simplify company names */ strcpy (make, corp[i]); if (!strncmp (make,"KODAK",5) && ((cp = strstr(model,"DIGITAL CAMERA")) || (cp = strstr(model,"FILE VERSION")))) *cp = 0; cp = make + strlen(make); /* Remove trailing spaces */ while (*--cp == ' ') *cp = 0; cp = model + strlen(model); while (*--cp == ' ') *cp = 0; i = strlen(make); /* Remove make from model */ if (!strncasecmp (model, make, i) && model[i++] == ' ') memmove (model, model+i, 64-i); if (!strncmp (model,"Digital Camera ",15)) strcpy (model, model+15); desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0; if (!is_raw) goto notraw; if (!maximum) maximum = (1 << tiff_bps) - 1; if (!height) height = raw_height; if (!width) width = raw_width; if (fuji_width) { width = height + fuji_width; height = width - 1; pixel_aspect = 1; } if (height == 2624 && width == 3936) /* Pentax K10D and Samsung GX10 */ { height = 2616; width = 3896; } if (height == 3136 && width == 4864) /* Pentax K20D */ { height = 3124; width = 4688; } if (height == 3014 && width == 4096) /* Ricoh GX200 */ width = 4014; if (dng_version) { if (filters == UINT_MAX) filters = 0; if (filters) is_raw = tiff_samples; else colors = tiff_samples; if (tiff_compress == 1) load_raw = &CLASS adobe_dng_load_raw_nc; if (tiff_compress == 7) load_raw = &CLASS adobe_dng_load_raw_lj; goto dng_skip; } if ((is_canon = !strcmp(make,"Canon"))) load_raw = memcmp (head+6,"HEAPCCDR",8) ? &CLASS lossless_jpeg_load_raw : &CLASS canon_compressed_load_raw; if (!strcmp(make,"NIKON")) { if (!load_raw) load_raw = &CLASS packed_12_load_raw; if (model[0] == 'E') load_flags |= !data_offset << 2 | 2; } if (!strcmp(make,"CASIO")) { load_raw = &CLASS packed_12_load_raw; maximum = 0xf7f; } /* Set parameters based on camera name (for non-DNG files). */ if (is_foveon) { if (height*2 < width) pixel_aspect = 0.5; if (height > width) pixel_aspect = 2; filters = 0; load_raw = &CLASS foveon_load_raw; simple_coeff(0); } else if (is_canon && tiff_bps == 15) { switch (width) { case 3344: width -= 66; case 3872: width -= 6; } filters = 0; load_raw = &CLASS canon_sraw_load_raw; } else if (!strcmp(model,"PowerShot 600")) { height = 613; width = 854; raw_width = 896; pixel_aspect = 607/628.0; colors = 4; filters = 0xe1e4e1e4; load_raw = &CLASS canon_600_load_raw; } else if (!strcmp(model,"PowerShot A5") || !strcmp(model,"PowerShot A5 Zoom")) { height = 773; width = 960; raw_width = 992; pixel_aspect = 256/235.0; colors = 4; filters = 0x1e4e1e4e; load_raw = &CLASS canon_a5_load_raw; } else if (!strcmp(model,"PowerShot A50")) { height = 968; width = 1290; raw_width = 1320; colors = 4; filters = 0x1b4e4b1e; load_raw = &CLASS canon_a5_load_raw; } else if (!strcmp(model,"PowerShot Pro70")) { height = 1024; width = 1552; colors = 4; filters = 0x1e4b4e1b; load_raw = &CLASS canon_a5_load_raw; } else if (!strcmp(model,"PowerShot SD300")) { height = 1752; width = 2344; raw_height = 1766; raw_width = 2400; top_margin = 12; left_margin = 12; load_raw = &CLASS canon_a5_load_raw; } else if (!strcmp(model,"PowerShot A460")) { height = 1960; width = 2616; raw_height = 1968; raw_width = 2664; top_margin = 4; left_margin = 4; load_raw = &CLASS canon_a5_load_raw; } else if (!strcmp(model,"PowerShot A530")) { height = 1984; width = 2620; raw_height = 1992; raw_width = 2672; top_margin = 6; left_margin = 10; load_raw = &CLASS canon_a5_load_raw; raw_color = 0; } else if (!strcmp(model,"PowerShot A610")) { if (canon_s2is()) strcpy (model+10, "S2 IS"); height = 1960; width = 2616; raw_height = 1968; raw_width = 2672; top_margin = 8; left_margin = 12; load_raw = &CLASS canon_a5_load_raw; } else if (!strcmp(model,"PowerShot A620")) { height = 2328; width = 3112; raw_height = 2340; raw_width = 3152; top_margin = 12; left_margin = 36; load_raw = &CLASS canon_a5_load_raw; } else if (!strcmp(model,"PowerShot A720")) { height = 2472; width = 3298; raw_height = 2480; raw_width = 3336; top_margin = 5; left_margin = 6; load_raw = &CLASS canon_a5_load_raw; } else if (!strcmp(model,"PowerShot A630")) { height = 2472; width = 3288; raw_height = 2484; raw_width = 3344; top_margin = 6; left_margin = 12; load_raw = &CLASS canon_a5_load_raw; } else if (!strcmp(model,"PowerShot A640")) { height = 2760; width = 3672; raw_height = 2772; raw_width = 3736; top_margin = 6; left_margin = 12; load_raw = &CLASS canon_a5_load_raw; } else if (!strcmp(model,"PowerShot A650")) { height = 3024; width = 4032; raw_height = 3048; raw_width = 4104; top_margin = 12; left_margin = 48; load_raw = &CLASS canon_a5_load_raw; } else if (!strcmp(model,"PowerShot S3 IS")) { height = 2128; width = 2840; raw_height = 2136; raw_width = 2888; top_margin = 8; left_margin = 44; load_raw = &CLASS canon_a5_load_raw; } else if (!strcmp(model,"PowerShot SX110 IS")) { height = 2760; width = 3684; raw_height = 2772; raw_width = 3720; top_margin = 12; left_margin = 6; load_raw = &CLASS packed_12_load_raw; load_flags = 40; zero_is_bad = 1; } else if (!strcmp(model,"PowerShot Pro90 IS")) { width = 1896; colors = 4; filters = 0xb4b4b4b4; } else if (is_canon && raw_width == 2144) { height = 1550; width = 2088; top_margin = 8; left_margin = 4; if (!strcmp(model,"PowerShot G1")) { colors = 4; filters = 0xb4b4b4b4; } } else if (is_canon && raw_width == 2224) { height = 1448; width = 2176; top_margin = 6; left_margin = 48; } else if (is_canon && raw_width == 2376) { height = 1720; width = 2312; top_margin = 6; left_margin = 12; } else if (is_canon && raw_width == 2672) { height = 1960; width = 2616; top_margin = 6; left_margin = 12; } else if (is_canon && raw_width == 3152) { height = 2056; width = 3088; top_margin = 12; left_margin = 64; if (unique_id == 0x80000170) adobe_coeff ("Canon","EOS 300D"); } else if (is_canon && raw_width == 3160) { height = 2328; width = 3112; top_margin = 12; left_margin = 44; } else if (is_canon && raw_width == 3344) { height = 2472; width = 3288; top_margin = 6; left_margin = 4; } else if (!strcmp(model,"EOS D2000C")) { filters = 0x61616161; black = curve[200]; } else if (is_canon && raw_width == 3516) { top_margin = 14; left_margin = 42; if (unique_id == 0x80000189) adobe_coeff ("Canon","EOS 350D"); goto canon_cr2; } else if (is_canon && raw_width == 3596) { top_margin = 12; left_margin = 74; goto canon_cr2; } else if (is_canon && raw_width == 3944) { height = 2602; width = 3908; top_margin = 18; left_margin = 30; } else if (is_canon && raw_width == 3948) { top_margin = 18; left_margin = 42; height -= 2; if (unique_id == 0x80000236) adobe_coeff ("Canon","EOS 400D"); if (unique_id == 0x80000254) adobe_coeff ("Canon","EOS 1000D"); goto canon_cr2; } else if (is_canon && raw_width == 3984) { top_margin = 20; left_margin = 76; height -= 2; goto canon_cr2; } else if (is_canon && raw_width == 4104) { height = 3024; width = 4032; top_margin = 12; left_margin = 48; } else if (is_canon && raw_width == 4152) { top_margin = 12; left_margin = 192; goto canon_cr2; } else if (is_canon && raw_width == 4312) { top_margin = 18; left_margin = 22; height -= 2; if (unique_id == 0x80000176) adobe_coeff ("Canon","EOS 450D"); goto canon_cr2; } else if (is_canon && raw_width == 4476) { top_margin = 34; left_margin = 90; goto canon_cr2; } else if (is_canon && raw_width == 4480) { height = 3326; width = 4432; top_margin = 10; left_margin = 12; filters = 0x49494949; } else if (is_canon && raw_width == 1208) { top_margin = unique_id == 0x80000261 ? 51:26; left_margin = 62; raw_width = width *= 4; goto canon_cr2; } else if (is_canon && raw_width == 1448) { top_margin = 51; left_margin = 158; raw_width = width *= 4; goto canon_cr2; } else if (is_canon && raw_width == 5108) { top_margin = 13; left_margin = 98; canon_cr2: height -= top_margin; width -= left_margin; } else if (is_canon && raw_width == 5712) { height = 3752; width = 5640; top_margin = 20; left_margin = 62; } else if (!strcmp(model,"D1")) { cam_mul[0] *= 256/527.0; cam_mul[2] *= 256/317.0; } else if (!strcmp(model,"D1X")) { width -= 4; pixel_aspect = 0.5; } else if (!strcmp(model,"D40X") || !strcmp(model,"D60") || !strcmp(model,"D80")) { height -= 3; width -= 4; } else if (!strcmp(model,"D3") || !strcmp(model,"D700")) { width -= 4; left_margin = 2; } else if (!strncmp(model,"D40",3) || !strncmp(model,"D50",3) || !strncmp(model,"D70",3)) { width--; } else if (!strcmp(model,"D90")) { width -= 42; } else if (!strcmp(model,"D100")) { if (tiff_compress == 34713 && !nikon_is_compressed()) { load_raw = &CLASS packed_12_load_raw; load_flags |= 1; raw_width = (width += 3) + 3; } } else if (!strcmp(model,"D200")) { left_margin = 1; width -= 4; filters = 0x94949494; } else if (!strncmp(model,"D2H",3)) { left_margin = 6; width -= 14; } else if (!strncmp(model,"D2X",3)) { if (width == 3264) width -= 32; else width -= 8; } else if (!strcmp(model,"D300")) { width -= 32; } else if (!strcmp(model,"COOLPIX P6000")) { load_flags = 24; filters = 0x94949494; } else if (fsize == 1581060) { height = 963; width = 1287; raw_width = 1632; load_raw = &CLASS nikon_e900_load_raw; maximum = 0x3f4; colors = 4; filters = 0x1e1e1e1e; simple_coeff(3); pre_mul[0] = 1.2085; pre_mul[1] = 1.0943; pre_mul[3] = 1.1103; } else if (fsize == 2465792) { height = 1203; width = 1616; raw_width = 2048; load_raw = &CLASS nikon_e900_load_raw; colors = 4; filters = 0x4b4b4b4b; adobe_coeff ("NIKON","E950"); } else if (fsize == 4771840) { height = 1540; width = 2064; colors = 4; filters = 0xe1e1e1e1; load_raw = &CLASS packed_12_load_raw; load_flags = 6; if (!timestamp && nikon_e995()) strcpy (model, "E995"); if (strcmp(model,"E995")) { filters = 0xb4b4b4b4; simple_coeff(3); pre_mul[0] = 1.196; pre_mul[1] = 1.246; pre_mul[2] = 1.018; } } else if (!strcmp(model,"E2100")) { if (!timestamp && !nikon_e2100()) goto cp_e2500; height = 1206; width = 1616; load_flags = 30; } else if (!strcmp(model,"E2500")) { cp_e2500: strcpy (model, "E2500"); height = 1204; width = 1616; colors = 4; filters = 0x4b4b4b4b; } else if (fsize == 4775936) { height = 1542; width = 2064; load_raw = &CLASS packed_12_load_raw; load_flags = 30; if (!timestamp) nikon_3700(); if (model[0] == 'E' && atoi(model+1) < 3700) filters = 0x49494949; if (!strcmp(model,"Optio 33WR")) { flip = 1; filters = 0x16161616; } } else if (fsize == 5869568) { height = 1710; width = 2288; filters = 0x16161616; if (!timestamp && minolta_z2()) { strcpy (make, "Minolta"); strcpy (model,"DiMAGE Z2"); } load_raw = &CLASS packed_12_load_raw; load_flags = 6 + 24*(make[0] == 'M'); } else if (!strcmp(model,"E4500")) { height = 1708; width = 2288; colors = 4; filters = 0xb4b4b4b4; } else if (fsize == 7438336) { height = 1924; width = 2576; colors = 4; filters = 0xb4b4b4b4; } else if (fsize == 8998912) { height = 2118; width = 2832; maximum = 0xf83; load_raw = &CLASS packed_12_load_raw; load_flags = 30; } else if (!strcmp(model,"FinePix S5100") || !strcmp(model,"FinePix S5500")) { load_raw = &CLASS unpacked_load_raw; } else if (!strcmp(make,"FUJIFILM")) { if (!strcmp(model+7,"S2Pro")) { strcpy (model+7," S2Pro"); height = 2144; width = 2880; flip = 6; } else maximum = 0x3e00; if (is_raw == 2 && shot_select) maximum = 0x2f00; top_margin = (raw_height - height)/2; left_margin = (raw_width - width )/2; if (is_raw == 2) data_offset += (shot_select > 0) * ( fuji_layout ? (raw_width *= 2) : raw_height*raw_width*2 ); fuji_width = width >> !fuji_layout; width = (height >> fuji_layout) + fuji_width; raw_height = height; height = width - 1; load_raw = &CLASS fuji_load_raw; if (!(fuji_width & 1)) filters = 0x49494949; } else if (!strcmp(model,"RD175")) { height = 986; width = 1534; data_offset = 513; filters = 0x61616161; load_raw = &CLASS minolta_rd175_load_raw; } else if (!strcmp(model,"KD-400Z")) { height = 1712; width = 2312; raw_width = 2336; goto konica_400z; } else if (!strcmp(model,"KD-510Z")) { goto konica_510z; } else if (!strcasecmp(make,"MINOLTA")) { load_raw = &CLASS unpacked_load_raw; maximum = 0xfff; if (!strncmp(model,"DiMAGE A",8)) { if (!strcmp(model,"DiMAGE A200")) filters = 0x49494949; load_raw = &CLASS packed_12_load_raw; } else if (!strncmp(model,"ALPHA",5) || !strncmp(model,"DYNAX",5) || !strncmp(model,"MAXXUM",6)) { sprintf (model+20, "DYNAX %-10s", model+6+(model[0]=='M')); adobe_coeff (make, model+20); load_raw = &CLASS packed_12_load_raw; } else if (!strncmp(model,"DiMAGE G",8)) { if (model[8] == '4') { height = 1716; width = 2304; } else if (model[8] == '5') { konica_510z: height = 1956; width = 2607; raw_width = 2624; } else if (model[8] == '6') { height = 2136; width = 2848; } data_offset += 14; filters = 0x61616161; konica_400z: load_raw = &CLASS unpacked_load_raw; maximum = 0x3df; order = 0x4d4d; } } else if (!strcmp(model,"*ist DS")) { height -= 2; } else if (!strcmp(model,"K20D")) { filters = 0x16161616; } else if (!strcmp(model,"Optio S")) { if (fsize == 3178560) { height = 1540; width = 2064; load_raw = &CLASS eight_bit_load_raw; cam_mul[0] *= 4; cam_mul[2] *= 4; } else { height = 1544; width = 2068; raw_width = 3136; load_raw = &CLASS packed_12_load_raw; maximum = 0xf7c; } } else if (fsize == 6114240) { height = 1737; width = 2324; raw_width = 3520; load_raw = &CLASS packed_12_load_raw; maximum = 0xf7a; } else if (!strcmp(model,"Optio 750Z")) { height = 2302; width = 3072; load_raw = &CLASS packed_12_load_raw; load_flags = 30; } else if (!strcmp(model,"DC-833m")) { height = 2448; width = 3264; order = 0x4949; filters = 0x61616161; load_raw = &CLASS unpacked_load_raw; maximum = 0xfc00; } else if (!strncmp(model,"S85",3)) { height = 2448; width = 3264; raw_width = fsize/height/2; order = 0x4d4d; load_raw = &CLASS unpacked_load_raw; maximum = 0xffff; } else if (!strcmp(model,"STV680 VGA")) { height = 484; width = 644; load_raw = &CLASS eight_bit_load_raw; flip = 2; filters = 0x16161616; black = 16; } else if (!strcmp(model,"KAI-0340")) { height = 477; width = 640; order = 0x4949; data_offset = 3840; load_raw = &CLASS unpacked_load_raw; } else if (!strcmp(model,"N95")) { height = raw_height - (top_margin = 2); } else if (!strcmp(model,"531C")) { height = 1200; width = 1600; load_raw = &CLASS unpacked_load_raw; filters = 0x49494949; } else if (!strcmp(model,"F-080C")) { height = 768; width = 1024; load_raw = &CLASS eight_bit_load_raw; } else if (!strcmp(model,"F-145C")) { height = 1040; width = 1392; load_raw = &CLASS eight_bit_load_raw; } else if (!strcmp(model,"F-201C")) { height = 1200; width = 1600; load_raw = &CLASS eight_bit_load_raw; } else if (!strcmp(model,"F-510C")) { height = 1958; width = 2588; load_raw = fsize < 7500000 ? &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw; maximum = 0xfff0; } else if (!strcmp(model,"F-810C")) { height = 2469; width = 3272; load_raw = &CLASS unpacked_load_raw; maximum = 0xfff0; } else if (!strcmp(model,"XCD-SX910CR")) { height = 1024; width = 1375; raw_width = 1376; filters = 0x49494949; maximum = 0x3ff; load_raw = fsize < 2000000 ? &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw; } else if (!strcmp(model,"2010")) { height = 1207; width = 1608; order = 0x4949; filters = 0x16161616; data_offset = 3212; maximum = 0x3ff; load_raw = &CLASS unpacked_load_raw; } else if (!strcmp(model,"A782")) { height = 3000; width = 2208; filters = 0x61616161; load_raw = fsize < 10000000 ? &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw; maximum = 0xffc0; } else if (!strcmp(model,"3320AF")) { height = 1536; raw_width = width = 2048; filters = 0x61616161; load_raw = &CLASS unpacked_load_raw; maximum = 0x3ff; fseek (ifp, 0x300000, SEEK_SET); if ((order = guess_byte_order(0x10000)) == 0x4d4d) { height -= (top_margin = 16); width -= (left_margin = 28); maximum = 0xf5c0; strcpy (make, "ISG"); model[0] = 0; } } else if (!strcmp(make,"Hasselblad")) { if (load_raw == &CLASS lossless_jpeg_load_raw) load_raw = &CLASS hasselblad_load_raw; if (raw_width == 7262) { height = 5444; width = 7248; top_margin = 4; left_margin = 7; filters = 0x61616161; } else if (raw_width == 4090) { strcpy (model, "V96C"); height -= (top_margin = 6); width -= (left_margin = 3) + 7; filters = 0x61616161; } } else if (!strcmp(make,"Sinar")) { if (!memcmp(head,"8BPS",4)) { fseek (ifp, 14, SEEK_SET); height = get4(); width = get4(); filters = 0x61616161; data_offset = 68; } if (!load_raw) load_raw = &CLASS unpacked_load_raw; maximum = 0x3fff; } else if (!strcmp(make,"Leaf")) { maximum = 0x3fff; fseek (ifp, data_offset, SEEK_SET); if (ljpeg_start (&jh, 1) && jh.bits == 15) maximum = 0x1fff; if (tiff_samples > 1) filters = 0; if (tiff_samples > 1 || tile_length < raw_height) load_raw = &CLASS leaf_hdr_load_raw; if ((width | height) == 2048) { if (tiff_samples == 1) { filters = 1; strcpy (cdesc, "RBTG"); strcpy (model, "CatchLight"); top_margin = 8; left_margin = 18; height = 2032; width = 2016; } else { strcpy (model, "DCB2"); top_margin = 10; left_margin = 16; height = 2028; width = 2022; } } else if (width+height == 3144+2060) { if (!model[0]) strcpy (model, "Cantare"); if (width > height) { top_margin = 6; left_margin = 32; height = 2048; width = 3072; filters = 0x61616161; } else { left_margin = 6; top_margin = 32; width = 2048; height = 3072; filters = 0x16161616; } if (!cam_mul[0] || model[0] == 'V') filters = 0; else is_raw = tiff_samples; } else if (width == 2116) { strcpy (model, "Valeo 6"); height -= 2 * (top_margin = 30); width -= 2 * (left_margin = 55); filters = 0x49494949; } else if (width == 3171) { strcpy (model, "Valeo 6"); height -= 2 * (top_margin = 24); width -= 2 * (left_margin = 24); filters = 0x16161616; } } else if (!strcmp(make,"LEICA") || !strcmp(make,"Panasonic")) { maximum = 0xfff0; if ((fsize-data_offset) / (width*8/7) == height) load_raw = &CLASS panasonic_load_raw; if (!load_raw) load_raw = &CLASS unpacked_load_raw; switch (width) { case 2568: adobe_coeff ("Panasonic","DMC-LC1"); break; case 3130: left_margin = -14; case 3170: left_margin += 18; width = 3096; if (height > 2326) { height = 2326; top_margin = 13; filters = 0x49494949; } zero_is_bad = 1; adobe_coeff ("Panasonic","DMC-FZ8"); break; case 3213: width -= 27; case 3177: width -= 10; filters = 0x49494949; zero_is_bad = 1; adobe_coeff ("Panasonic","DMC-L1"); break; case 3304: width -= 17; zero_is_bad = 1; adobe_coeff ("Panasonic","DMC-FZ30"); break; case 3330: width += 43; left_margin = -6; maximum = 0xf7f0; case 3370: width -= 82; left_margin += 15; if (height > 2480) height = 2480 - (top_margin = 10); filters = 0x49494949; zero_is_bad = 1; adobe_coeff ("Panasonic","DMC-FZ18"); break; case 3690: height -= 2; left_margin = -14; maximum = 0xf7f0; case 3770: width = 3672; if (--height == 2798 && (height = 2760)) top_margin = 15; else filters = 0x49494949; left_margin += 17; zero_is_bad = 1; adobe_coeff ("Panasonic","DMC-FZ50"); break; case 3710: width = 3682; filters = 0x49494949; adobe_coeff ("Panasonic","DMC-L10"); break; case 3724: width -= 14; if (height == 2450) height -= 2; case 3836: width -= 42; lx3: filters = 0x16161616; if (make[0] != 'P') adobe_coeff ("Panasonic","DMC-LX3"); break; case 3880: width -= 22; left_margin = 6; zero_is_bad = 1; adobe_coeff ("Panasonic","DMC-LX1"); break; case 4060: if (!strcmp(model,"DMC-GH1")) goto gh1; width = 3982; if (height == 2250) goto lx3; width = 4018; filters = 0x49494949; zero_is_bad = 1; adobe_coeff ("Panasonic","DMC-G1"); break; case 4172: case 4396: gh1: width -= 28; filters = 0x49494949; adobe_coeff ("Panasonic","DMC-GH1"); break; case 4290: height += 38; left_margin = -14; filters = 0x49494949; case 4330: width = 4248; if ((height -= 39) == 2400) top_margin = 15; left_margin += 17; adobe_coeff ("Panasonic","DMC-LX2"); break; case 4508: height -= 6; width = 4429; filters = 0x16161616; adobe_coeff ("Panasonic","DMC-FX150"); break; } } else if (!strcmp(model,"C770UZ")) { height = 1718; width = 2304; filters = 0x16161616; load_raw = &CLASS packed_12_load_raw; load_flags = 30; } else if (!strcmp(make,"OLYMPUS")) { height += height & 1; filters = exif_cfa; if (width == 4100) width -= 4; if (load_raw == &CLASS olympus_e410_load_raw) { black >>= 4; } else if (!strcmp(model,"E-10") || !strncmp(model,"E-20",4)) { black <<= 2; } else if (!strcmp(model,"E-300") || !strcmp(model,"E-500")) { width -= 20; if (load_raw == &CLASS unpacked_load_raw) { maximum = 0xfc30; black = 0; } } else if (!strcmp(model,"E-330")) { width -= 30; if (load_raw == &CLASS unpacked_load_raw) maximum = 0xf790; } else if (!strcmp(model,"SP550UZ")) { thumb_length = fsize - (thumb_offset = 0xa39800); thumb_height = 480; thumb_width = 640; } } else if (!strcmp(model,"N Digital")) { height = 2047; width = 3072; filters = 0x61616161; data_offset = 0x1a00; load_raw = &CLASS packed_12_load_raw; } else if (!strcmp(model,"DSC-F828")) { width = 3288; left_margin = 5; data_offset = 862144; load_raw = &CLASS sony_load_raw; filters = 0x9c9c9c9c; colors = 4; strcpy (cdesc, "RGBE"); } else if (!strcmp(model,"DSC-V3")) { width = 3109; left_margin = 59; data_offset = 787392; load_raw = &CLASS sony_load_raw; } else if (!strcmp(make,"SONY") && raw_width == 3984) { adobe_coeff ("SONY","DSC-R1"); width = 3925; order = 0x4d4d; } else if (!strcmp(model,"DSLR-A100")) { height--; } else if (!strcmp(model,"DSLR-A350")) { height -= 4; } else if (!strcmp(model,"PIXL")) { height -= top_margin = 4; width -= left_margin = 32; gamma_curve (0, 7, 1, 255); } else if (!strcmp(model,"C603v")) { height = 480; width = 640; goto c603v; } else if (!strcmp(model,"C603y")) { height = 2134; width = 2848; c603v: filters = 0; load_raw = &CLASS kodak_yrgb_load_raw; gamma_curve (0, 3.875, 1, 255); } else if (!strcmp(model,"C603")) { raw_height = height = 2152; raw_width = width = 2864; goto c603; } else if (!strcmp(model,"C330")) { height = 1744; width = 2336; raw_height = 1779; raw_width = 2338; top_margin = 33; left_margin = 1; c603: order = 0x4949; if ((data_offset = fsize - raw_height*raw_width)) { fseek (ifp, 168, SEEK_SET); read_shorts (curve, 256); } else gamma_curve (0, 3.875, 1, 255); load_raw = &CLASS eight_bit_load_raw; } else if (!strcmp(model,"EASYSHARE Z1015 IS")) { height = 2742; width = 3664; data_offset = 0x15000; load_raw = &CLASS packed_12_load_raw; } else if (!strcasecmp(make,"KODAK")) { if (filters == UINT_MAX) filters = 0x61616161; if (!strncmp(model,"NC2000",6)) { width -= 4; left_margin = 2; } else if (!strcmp(model,"EOSDCS3B")) { width -= 4; left_margin = 2; } else if (!strcmp(model,"EOSDCS1")) { width -= 4; left_margin = 2; } else if (!strcmp(model,"DCS420")) { width -= 4; left_margin = 2; } else if (!strncmp(model,"DCS460 ",7)) { model[6] = 0; width -= 4; left_margin = 2; } else if (!strcmp(model,"DCS460A")) { width -= 4; left_margin = 2; colors = 1; filters = 0; } else if (!strcmp(model,"DCS660M")) { black = 214; colors = 1; filters = 0; } else if (!strcmp(model,"DCS760M")) { colors = 1; filters = 0; } if (!strcmp(model+4,"20X")) strcpy (cdesc, "MYCY"); if (strstr(model,"DC25")) { strcpy (model, "DC25"); data_offset = 15424; } if (!strncmp(model,"DC2",3)) { height = 242; if (fsize < 100000) { raw_width = 256; width = 249; pixel_aspect = (4.0*height) / (3.0*width); } else { raw_width = 512; width = 501; pixel_aspect = (493.0*height) / (373.0*width); } data_offset += raw_width + 1; colors = 4; filters = 0x8d8d8d8d; simple_coeff(1); pre_mul[1] = 1.179; pre_mul[2] = 1.209; pre_mul[3] = 1.036; load_raw = &CLASS eight_bit_load_raw; } else if (!strcmp(model,"40")) { strcpy (model, "DC40"); height = 512; width = 768; data_offset = 1152; load_raw = &CLASS kodak_radc_load_raw; } else if (strstr(model,"DC50")) { strcpy (model, "DC50"); height = 512; width = 768; data_offset = 19712; load_raw = &CLASS kodak_radc_load_raw; } else if (strstr(model,"DC120")) { strcpy (model, "DC120"); height = 976; width = 848; pixel_aspect = height/0.75/width; load_raw = tiff_compress == 7 ? &CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw; } else if (!strcmp(model,"DCS200")) { thumb_height = 128; thumb_width = 192; thumb_offset = 6144; thumb_misc = 360; write_thumb = &CLASS layer_thumb; height = 1024; width = 1536; data_offset = 79872; load_raw = &CLASS eight_bit_load_raw; black = 17; } } else if (!strcmp(model,"Fotoman Pixtura")) { height = 512; width = 768; data_offset = 3632; load_raw = &CLASS kodak_radc_load_raw; filters = 0x61616161; simple_coeff(2); } else if (!strcmp(model,"QuickTake 100")) { fseek (ifp, 544, SEEK_SET); height = get2(); width = get2(); data_offset = (get4(),get2()) == 30 ? 738:736; if (height > width) { SWAP(height,width); fseek (ifp, data_offset-6, SEEK_SET); flip = ~get2() & 3 ? 5:6; } load_raw = &CLASS quicktake_100_load_raw; filters = 0x61616161; } else if (!strcmp(model,"QuickTake 150")) { data_offset = 738 - head[5]; if (head[5]) strcpy (model+10, "200"); load_raw = &CLASS kodak_radc_load_raw; height = 480; width = 640; filters = 0x61616161; } else if (!strcmp(make,"Rollei") && !load_raw) { switch (raw_width) { case 1316: height = 1030; width = 1300; top_margin = 1; left_margin = 6; break; case 2568: height = 1960; width = 2560; top_margin = 2; left_margin = 8; } filters = 0x16161616; load_raw = &CLASS rollei_load_raw; } else if (!strcmp(model,"PC-CAM 600")) { height = 768; data_offset = width = 1024; filters = 0x49494949; load_raw = &CLASS eight_bit_load_raw; } else if (!strcmp(model,"QV-2000UX")) { height = 1208; width = 1632; data_offset = width * 2; load_raw = &CLASS eight_bit_load_raw; } else if (fsize == 3217760) { height = 1546; width = 2070; raw_width = 2080; load_raw = &CLASS eight_bit_load_raw; } else if (!strcmp(model,"QV-4000")) { height = 1700; width = 2260; load_raw = &CLASS unpacked_load_raw; maximum = 0xffff; } else if (!strcmp(model,"QV-5700")) { height = 1924; width = 2576; load_raw = &CLASS casio_qv5700_load_raw; } else if (!strcmp(model,"QV-R41")) { height = 1720; width = 2312; raw_width = 3520; left_margin = 2; } else if (!strcmp(model,"QV-R51")) { height = 1926; width = 2580; raw_width = 3904; } else if (!strcmp(model,"EX-S20")) { height = 1208; width = 1620; raw_width = 2432; flip = 3; } else if (!strcmp(model,"EX-S100")) { height = 1544; width = 2058; raw_width = 3136; } else if (!strcmp(model,"EX-Z50")) { height = 1931; width = 2570; raw_width = 3904; } else if (!strcmp(model,"EX-Z55")) { height = 1960; width = 2570; raw_width = 3904; } else if (!strcmp(model,"EX-P505")) { height = 1928; width = 2568; raw_width = 3852; maximum = 0xfff; } else if (fsize == 9313536) { /* EX-P600 or QV-R61 */ height = 2142; width = 2844; raw_width = 4288; } else if (!strcmp(model,"EX-P700")) { height = 2318; width = 3082; raw_width = 4672; } if (!model[0]) sprintf (model, "%dx%d", width, height); if (filters == UINT_MAX) filters = 0x94949494; if (raw_color) adobe_coeff (make, model); if (load_raw == &CLASS kodak_radc_load_raw) if (raw_color) adobe_coeff ("Apple","Quicktake"); if (thumb_offset && !thumb_height) { fseek (ifp, thumb_offset, SEEK_SET); if (ljpeg_start (&jh, 1)) { thumb_width = jh.wide; thumb_height = jh.high; } } dng_skip: if (!load_raw || height < 22) is_raw = 0; #ifdef NO_JPEG if (load_raw == &CLASS kodak_jpeg_load_raw) { fprintf (stderr,_("%s: You must link dcraw with libjpeg!!\n"), ifname); is_raw = 0; } #endif if (!cdesc[0]) strcpy (cdesc, colors == 3 ? "RGB":"GMCY"); if (!raw_height) raw_height = height; if (!raw_width ) raw_width = width; if (filters && colors == 3) for (i=0; i < 32; i+=4) { if ((filters >> i & 15) == 9) filters |= 2 << i; if ((filters >> i & 15) == 6) filters |= 8 << i; } notraw: if (flip == -1) flip = tiff_flip; if (flip == -1) flip = 0; } #ifndef NO_LCMS void CLASS apply_profile (const char *input, const char *output) { char *prof; cmsHPROFILE hInProfile=0, hOutProfile=0; cmsHTRANSFORM hTransform; FILE *fp; unsigned size; cmsErrorAction (LCMS_ERROR_SHOW); if (strcmp (input, "embed")) hInProfile = cmsOpenProfileFromFile (input, "r"); else if (profile_length) { prof = (char *) malloc (profile_length); merror (prof, "apply_profile()"); fseek (ifp, profile_offset, SEEK_SET); fread (prof, 1, profile_length, ifp); hInProfile = cmsOpenProfileFromMem (prof, profile_length); free (prof); } else fprintf (stderr,_("%s has no embedded profile.\n"), ifname); if (!hInProfile) return; if (!output) hOutProfile = cmsCreate_sRGBProfile(); else if ((fp = fopen (output, "rb"))) { fread (&size, 4, 1, fp); fseek (fp, 0, SEEK_SET); oprof = (unsigned *) malloc (size = ntohl(size)); merror (oprof, "apply_profile()"); fread (oprof, 1, size, fp); fclose (fp); if (!(hOutProfile = cmsOpenProfileFromMem (oprof, size))) { free (oprof); oprof = 0; } } else fprintf (stderr,_("Cannot open file %s!\n"), output); if (!hOutProfile) goto quit; if (verbose) fprintf (stderr,_("Applying color profile...\n")); hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16, hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0); cmsDoTransform (hTransform, image, image, width*height); raw_color = 1; /* Don't use rgb_cam with a profile */ cmsDeleteTransform (hTransform); cmsCloseProfile (hOutProfile); quit: cmsCloseProfile (hInProfile); } #endif void CLASS convert_to_rgb() { int row, col, c, i, j, k; ushort *img; float out[3], out_cam[3][4]; double num, inverse[3][3]; static const double xyzd50_srgb[3][3] = { { 0.436083, 0.385083, 0.143055 }, { 0.222507, 0.716888, 0.060608 }, { 0.013930, 0.097097, 0.714022 } }; static const double rgb_rgb[3][3] = { { 1,0,0 }, { 0,1,0 }, { 0,0,1 } }; static const double adobe_rgb[3][3] = { { 0.715146, 0.284856, 0.000000 }, { 0.000000, 1.000000, 0.000000 }, { 0.000000, 0.041166, 0.958839 } }; static const double wide_rgb[3][3] = { { 0.593087, 0.404710, 0.002206 }, { 0.095413, 0.843149, 0.061439 }, { 0.011621, 0.069091, 0.919288 } }; static const double prophoto_rgb[3][3] = { { 0.529317, 0.330092, 0.140588 }, { 0.098368, 0.873465, 0.028169 }, { 0.016879, 0.117663, 0.865457 } }; static const double (*out_rgb[])[3] = { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb }; static const char *name[] = { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" }; static const unsigned phead[] = { 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0, 0x61637370, 0, 0, 0x6e6f6e65, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d }; unsigned pbody[] = { 10, 0x63707274, 0, 36, /* cprt */ 0x64657363, 0, 40, /* desc */ 0x77747074, 0, 20, /* wtpt */ 0x626b7074, 0, 20, /* bkpt */ 0x72545243, 0, 14, /* rTRC */ 0x67545243, 0, 14, /* gTRC */ 0x62545243, 0, 14, /* bTRC */ 0x7258595a, 0, 20, /* rXYZ */ 0x6758595a, 0, 20, /* gXYZ */ 0x6258595a, 0, 20 }; /* bXYZ */ static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc }; unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 }; gamma_curve (gamm[0], gamm[1], 0, 0); memcpy (out_cam, rgb_cam, sizeof out_cam); raw_color |= colors == 1 || document_mode || output_color < 1 || output_color > 5; if (!raw_color) { oprof = (unsigned *) calloc (phead[0], 1); merror (oprof, "convert_to_rgb()"); memcpy (oprof, phead, sizeof phead); if (output_color == 5) oprof[4] = oprof[5]; oprof[0] = 132 + 12*pbody[0]; for (i=0; i < pbody[0]; i++) { oprof[oprof[0]/4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874; pbody[i*3+2] = oprof[0]; oprof[0] += (pbody[i*3+3] + 3) & -4; } memcpy (oprof+32, pbody, sizeof pbody); oprof[pbody[5]/4+2] = strlen(name[output_color-1]) + 1; memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof pwhite); pcurve[3] = (short)(256/gamm[5]+0.5) << 16; for (i=4; i < 7; i++) memcpy ((char *)oprof+pbody[i*3+2], pcurve, sizeof pcurve); pseudoinverse ((double (*)[3]) out_rgb[output_color-1], inverse, 3); for (i=0; i < 3; i++) for (j=0; j < 3; j++) { for (num = k=0; k < 3; k++) num += xyzd50_srgb[i][k] * inverse[j][k]; oprof[pbody[j*3+23]/4+i+2] = num * 0x10000 + 0.5; } for (i=0; i < phead[0]/4; i++) oprof[i] = htonl(oprof[i]); strcpy ((char *)oprof+pbody[2]+8, "auto-generated by dcraw"); strcpy ((char *)oprof+pbody[5]+12, name[output_color-1]); for (i=0; i < 3; i++) for (j=0; j < colors; j++) for (out_cam[i][j] = k=0; k < 3; k++) out_cam[i][j] += out_rgb[output_color-1][i][k] * rgb_cam[k][j]; } if (verbose) fprintf (stderr, raw_color ? _("Building histograms...\n") : _("Converting to %s colorspace...\n"), name[output_color-1]); memset (histogram, 0, sizeof histogram); for (img=image[0], row=0; row < height; row++) for (col=0; col < width; col++, img+=4) { if (!raw_color) { out[0] = out[1] = out[2] = 0; FORCC { out[0] += out_cam[0][c] * img[c]; out[1] += out_cam[1][c] * img[c]; out[2] += out_cam[2][c] * img[c]; } FORC3 img[c] = CLIP((int) out[c]); } else if (document_mode) img[0] = img[FC(row,col)]; FORCC histogram[c][img[c] >> 3]++; } if (colors == 4 && output_color) colors = 3; if (document_mode && filters) colors = 1; } void CLASS fuji_rotate() { int i, row, col; double step; float r, c, fr, fc; unsigned ur, uc; ushort wide, high, (*img)[4], (*pix)[4]; if (!fuji_width) return; if (verbose) fprintf (stderr,_("Rotating image 45 degrees...\n")); fuji_width = (fuji_width - 1 + shrink) >> shrink; step = sqrt(0.5); wide = fuji_width / step; high = (height - fuji_width) / step; img = (ushort (*)[4]) calloc (wide*high, sizeof *img); merror (img, "fuji_rotate()"); for (row=0; row < high; row++) for (col=0; col < wide; col++) { ur = r = fuji_width + (row-col)*step; uc = c = (row+col)*step; if (ur > height-2 || uc > width-2) continue; fr = r - ur; fc = c - uc; pix = image + ur*width + uc; for (i=0; i < colors; i++) img[row*wide+col][i] = (pix[ 0][i]*(1-fc) + pix[ 1][i]*fc) * (1-fr) + (pix[width][i]*(1-fc) + pix[width+1][i]*fc) * fr; } free (image); width = wide; height = high; image = img; fuji_width = 0; } void CLASS stretch() { ushort newdim, (*img)[4], *pix0, *pix1; int row, col, c; double rc, frac; if (pixel_aspect == 1) return; if (verbose) fprintf (stderr,_("Stretching the image...\n")); if (pixel_aspect < 1) { newdim = height / pixel_aspect + 0.5; img = (ushort (*)[4]) calloc (width*newdim, sizeof *img); merror (img, "stretch()"); for (rc=row=0; row < newdim; row++, rc+=pixel_aspect) { frac = rc - (c = rc); pix0 = pix1 = image[c*width]; if (c+1 < height) pix1 += width*4; for (col=0; col < width; col++, pix0+=4, pix1+=4) FORCC img[row*width+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5; } height = newdim; } else { newdim = width * pixel_aspect + 0.5; img = (ushort (*)[4]) calloc (height*newdim, sizeof *img); merror (img, "stretch()"); for (rc=col=0; col < newdim; col++, rc+=1/pixel_aspect) { frac = rc - (c = rc); pix0 = pix1 = image[c]; if (c+1 < width) pix1 += 4; for (row=0; row < height; row++, pix0+=width*4, pix1+=width*4) FORCC img[row*newdim+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5; } width = newdim; } free (image); image = img; } int CLASS flip_index (int row, int col) { if (flip & 4) SWAP(row,col); if (flip & 2) row = iheight - 1 - row; if (flip & 1) col = iwidth - 1 - col; return row * iwidth + col; } struct tiff_tag { ushort tag, type; int count; union { char c[4]; short s[2]; int i; } val; }; struct tiff_hdr { ushort order, magic; int ifd; ushort pad, ntag; struct tiff_tag tag[23]; int nextifd; ushort pad2, nexif; struct tiff_tag exif[4]; ushort pad3, ngps; struct tiff_tag gpst[10]; short bps[4]; int rat[10]; unsigned gps[26]; char desc[512], make[64], model[64], soft[32], date[20], artist[64]; }; void CLASS tiff_set (ushort *ntag, ushort tag, ushort type, int count, int val) { struct tiff_tag *tt; int c; tt = (struct tiff_tag *)(ntag+1) + (*ntag)++; tt->tag = tag; tt->type = type; tt->count = count; if (type < 3 && count <= 4) FORC(4) tt->val.c[c] = val >> (c << 3); else if (type == 3 && count <= 2) FORC(2) tt->val.s[c] = val >> (c << 4); else tt->val.i = val; } #define TOFF(ptr) ((char *)(&(ptr)) - (char *)th) void CLASS tiff_head (struct tiff_hdr *th, int full) { int c, psize=0; struct tm *t; memset (th, 0, sizeof *th); th->order = htonl(0x4d4d4949) >> 16; th->magic = 42; th->ifd = 10; if (full) { tiff_set (&th->ntag, 254, 4, 1, 0); tiff_set (&th->ntag, 256, 4, 1, width); tiff_set (&th->ntag, 257, 4, 1, height); tiff_set (&th->ntag, 258, 3, colors, output_bps); if (colors > 2) th->tag[th->ntag-1].val.i = TOFF(th->bps); FORC4 th->bps[c] = output_bps; tiff_set (&th->ntag, 259, 3, 1, 1); tiff_set (&th->ntag, 262, 3, 1, 1 + (colors > 1)); } tiff_set (&th->ntag, 270, 2, 512, TOFF(th->desc)); tiff_set (&th->ntag, 271, 2, 64, TOFF(th->make)); tiff_set (&th->ntag, 272, 2, 64, TOFF(th->model)); if (full) { if (oprof) psize = ntohl(oprof[0]); tiff_set (&th->ntag, 273, 4, 1, sizeof *th + psize); tiff_set (&th->ntag, 277, 3, 1, colors); tiff_set (&th->ntag, 278, 4, 1, height); tiff_set (&th->ntag, 279, 4, 1, height*width*colors*output_bps/8); } else tiff_set (&th->ntag, 274, 3, 1, "12435867"[flip]-'0'); tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0])); tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2])); tiff_set (&th->ntag, 284, 3, 1, 1); tiff_set (&th->ntag, 296, 3, 1, 2); tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft)); tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date)); tiff_set (&th->ntag, 315, 2, 64, TOFF(th->artist)); tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif)); if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th); tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4])); tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6])); tiff_set (&th->nexif, 34855, 3, 1, iso_speed); tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8])); if (gpsdata[1]) { tiff_set (&th->ntag, 34853, 4, 1, TOFF(th->ngps)); tiff_set (&th->ngps, 0, 1, 4, 0x202); tiff_set (&th->ngps, 1, 2, 2, gpsdata[29]); tiff_set (&th->ngps, 2, 5, 3, TOFF(th->gps[0])); tiff_set (&th->ngps, 3, 2, 2, gpsdata[30]); tiff_set (&th->ngps, 4, 5, 3, TOFF(th->gps[6])); tiff_set (&th->ngps, 5, 1, 1, gpsdata[31]); tiff_set (&th->ngps, 6, 5, 1, TOFF(th->gps[18])); tiff_set (&th->ngps, 7, 5, 3, TOFF(th->gps[12])); tiff_set (&th->ngps, 18, 2, 12, TOFF(th->gps[20])); tiff_set (&th->ngps, 29, 2, 12, TOFF(th->gps[23])); memcpy (th->gps, gpsdata, sizeof th->gps); } th->rat[0] = th->rat[2] = 300; th->rat[1] = th->rat[3] = 1; FORC(6) th->rat[4+c] = 1000000; th->rat[4] *= shutter; th->rat[6] *= aperture; th->rat[8] *= focal_len; strncpy (th->desc, desc, 512); strncpy (th->make, make, 64); strncpy (th->model, model, 64); strcpy (th->soft, "dcraw v"VERSION); t = gmtime (×tamp); sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d", t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); strncpy (th->artist, artist, 64); } void CLASS jpeg_thumb() { char *thumb; ushort exif[5]; struct tiff_hdr th; thumb = (char *) malloc (thumb_length); merror (thumb, "jpeg_thumb()"); fread (thumb, 1, thumb_length, ifp); fputc (0xff, ofp); fputc (0xd8, ofp); if (strcmp (thumb+6, "Exif")) { memcpy (exif, "\xff\xe1 Exif\0\0", 10); exif[1] = htons (8 + sizeof th); fwrite (exif, 1, sizeof exif, ofp); tiff_head (&th, 0); fwrite (&th, 1, sizeof th, ofp); } fwrite (thumb+2, 1, thumb_length-2, ofp); free (thumb); } void CLASS write_ppm_tiff() { struct tiff_hdr th; uchar *ppm; ushort *ppm2; int c, row, col, soff, rstep, cstep; int perc, val, total, white=0x2000; perc = width * height * 0.01; /* 99th percentile white level */ if (fuji_width) perc /= 2; if (!((highlight & ~2) || no_auto_bright)) for (white=c=0; c < colors; c++) { for (val=0x2000, total=0; --val > 32; ) if ((total += histogram[c][val]) > perc) break; if (white < val) white = val; } gamma_curve (gamm[0], gamm[1], 2, (white << 3)/bright); iheight = height; iwidth = width; if (flip & 4) SWAP(height,width); ppm = (uchar *) calloc (width, colors*output_bps/8); ppm2 = (ushort *) ppm; merror (ppm, "write_ppm_tiff()"); if (output_tiff) { tiff_head (&th, 1); fwrite (&th, sizeof th, 1, ofp); if (oprof) fwrite (oprof, ntohl(oprof[0]), 1, ofp); } else if (colors > 3) fprintf (ofp, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n", width, height, colors, (1 << output_bps)-1, cdesc); else fprintf (ofp, "P%d\n%d %d\n%d\n", colors/2+5, width, height, (1 << output_bps)-1); soff = flip_index (0, 0); cstep = flip_index (0, 1) - soff; rstep = flip_index (1, 0) - flip_index (0, width); for (row=0; row < height; row++, soff += rstep) { for (col=0; col < width; col++, soff += cstep) if (output_bps == 8) FORCC ppm [col*colors+c] = curve[image[soff][c]] >> 8; else FORCC ppm2[col*colors+c] = curve[image[soff][c]]; if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa) swab (ppm2, ppm2, width*colors*2); fwrite (ppm, colors*output_bps/8, width, ofp); } free (ppm); } int CLASS main (int argc, const char **argv) { int arg, status=0; int timestamp_only=0, thumbnail_only=0, identify_only=0; int user_qual=-1, user_black=-1, user_sat=-1, user_flip=-1; int use_fuji_rotate=1, write_to_stdout=0, quality, i, c; const char *sp, *bpfile=0, *dark_frame=0, *write_ext; char opm, opt, *ofname, *cp; struct utimbuf ut; #ifndef NO_LCMS const char *cam_profile=0, *out_profile=0; #endif #ifndef LOCALTIME putenv ((char *) "TZ=UTC"); #endif #ifdef LOCALEDIR setlocale (LC_CTYPE, ""); setlocale (LC_MESSAGES, ""); bindtextdomain ("dcraw", LOCALEDIR); textdomain ("dcraw"); #endif if (argc == 1) { printf(_("\nRaw photo decoder \"dcraw\" v%s"), VERSION); printf(_("\nby Dave Coffin, dcoffin a cybercom o net\n")); printf(_("\nUsage: %s [OPTION]... [FILE]...\n\n"), argv[0]); puts(_("-v Print verbose messages")); puts(_("-c Write image data to standard output")); puts(_("-e Extract embedded thumbnail image")); puts(_("-i Identify files without decoding them")); puts(_("-i -v Identify files and show metadata")); puts(_("-z Change file dates to camera timestamp")); puts(_("-w Use camera white balance, if possible")); puts(_("-a Average the whole image for white balance")); puts(_("-A Average a grey box for white balance")); puts(_("-r Set custom white balance")); puts(_("+M/-M Use/don't use an embedded color matrix")); puts(_("-C Correct chromatic aberration")); puts(_("-P Fix the dead pixels listed in this file")); puts(_("-K Subtract dark frame (16-bit raw PGM)")); puts(_("-k Set the darkness level")); puts(_("-S Set the saturation level")); puts(_("-n Set threshold for wavelet denoising")); puts(_("-H [0-9] Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)")); puts(_("-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)")); puts(_("-o [0-5] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)")); #ifndef NO_LCMS puts(_("-o Apply output ICC profile from file")); puts(_("-p Apply camera ICC profile from file or \"embed\"")); #endif puts(_("-d Document mode (no color, no interpolation)")); puts(_("-D Document mode without scaling (totally raw)")); puts(_("-j Don't stretch or rotate raw pixels")); puts(_("-W Don't automatically brighten the image")); puts(_("-b Adjust brightness (default = 1.0)")); puts(_("-g

Set custom gamma curve (default = 2.222 4.5)")); puts(_("-q [0-3] Set the interpolation quality")); puts(_("-h Half-size color image (twice as fast as \"-q 0\")")); puts(_("-f Interpolate RGGB as four colors")); puts(_("-m Apply a 3x3 median filter to R-G and B-G")); puts(_("-s [0..N-1] Select one raw image or \"all\" from each file")); puts(_("-6 Write 16-bit instead of 8-bit")); puts(_("-4 Linear 16-bit, same as \"-6 -W -g 1 1\"")); puts(_("-T Write TIFF instead of PPM")); puts(""); return 1; } argv[argc] = ""; for (arg=1; (((opm = argv[arg][0]) - 2) | 2) == '+'; ) { opt = argv[arg++][1]; if ((cp = strchr (sp="nbrkStqmHACg", opt))) for (i=0; i < "114111111422"[cp-sp]-'0'; i++) if (!isdigit(argv[arg+i][0])) { fprintf (stderr,_("Non-numeric argument to \"-%c\"\n"), opt); return 1; } switch (opt) { case 'n': threshold = atof(argv[arg++]); break; case 'b': bright = atof(argv[arg++]); break; case 'r': FORC4 user_mul[c] = atof(argv[arg++]); break; case 'C': aber[0] = 1 / atof(argv[arg++]); aber[2] = 1 / atof(argv[arg++]); break; case 'g': gamm[0] = atof(argv[arg++]); gamm[1] = atof(argv[arg++]); if (gamm[0]) gamm[0] = 1/gamm[0]; break; case 'k': user_black = atoi(argv[arg++]); break; case 'S': user_sat = atoi(argv[arg++]); break; case 't': user_flip = atoi(argv[arg++]); break; case 'q': user_qual = atoi(argv[arg++]); break; case 'm': med_passes = atoi(argv[arg++]); break; case 'H': highlight = atoi(argv[arg++]); break; case 's': shot_select = abs(atoi(argv[arg])); multi_out = !strcmp(argv[arg++],"all"); break; case 'o': if (isdigit(argv[arg][0]) && !argv[arg][1]) output_color = atoi(argv[arg++]); #ifndef NO_LCMS else out_profile = argv[arg++]; break; case 'p': cam_profile = argv[arg++]; #endif break; case 'P': bpfile = argv[arg++]; break; case 'K': dark_frame = argv[arg++]; break; case 'z': timestamp_only = 1; break; case 'e': thumbnail_only = 1; break; case 'i': identify_only = 1; break; case 'c': write_to_stdout = 1; break; case 'v': verbose = 1; break; case 'h': half_size = 1; /* "-h" implies "-f" */ case 'f': four_color_rgb = 1; break; case 'A': FORC4 greybox[c] = atoi(argv[arg++]); case 'a': use_auto_wb = 1; break; case 'w': use_camera_wb = 1; break; case 'M': use_camera_matrix = (opm == '+'); break; case 'D': case 'd': document_mode = 1 + (opt == 'D'); case 'j': use_fuji_rotate = 0; break; case 'W': no_auto_bright = 1; break; case 'T': output_tiff = 1; break; case '4': gamm[0] = gamm[1] = no_auto_bright = 1; case '6': output_bps = 16; break; default: fprintf (stderr,_("Unknown option \"-%c\".\n"), opt); return 1; } } if (use_camera_matrix < 0) use_camera_matrix = use_camera_wb; if (arg == argc) { fprintf (stderr,_("No files to process.\n")); return 1; } if (write_to_stdout) { if (isatty(1)) { fprintf (stderr,_("Will not write an image to the terminal!\n")); return 1; } #if defined(WIN32) || defined(DJGPP) || defined(__CYGWIN__) if (setmode(1,O_BINARY) < 0) { perror ("setmode()"); return 1; } #endif } for ( ; arg < argc; arg++) { status = 1; image = 0; oprof = 0; meta_data = ofname = 0; ofp = stdout; if (setjmp (failure)) { if (fileno(ifp) > 2) fclose(ifp); if (fileno(ofp) > 2) fclose(ofp); status = 1; goto cleanup; } ifname = argv[arg]; if (!(ifp = fopen (ifname, "rb"))) { perror (ifname); continue; } status = (identify(),!is_raw); if (user_flip >= 0) flip = user_flip; switch ((flip+3600) % 360) { case 270: flip = 5; break; case 180: flip = 3; break; case 90: flip = 6; } if (timestamp_only) { if ((status = !timestamp)) fprintf (stderr,_("%s has no timestamp.\n"), ifname); else if (identify_only) printf ("%10ld%10d %s\n", (long) timestamp, shot_order, ifname); else { if (verbose) fprintf (stderr,_("%s time set to %d.\n"), ifname, (int) timestamp); ut.actime = ut.modtime = timestamp; utime (ifname, &ut); } goto next; } write_fun = &CLASS write_ppm_tiff; if (thumbnail_only) { if ((status = !thumb_offset)) { fprintf (stderr,_("%s has no thumbnail.\n"), ifname); goto next; } else if (thumb_load_raw) { load_raw = thumb_load_raw; data_offset = thumb_offset; height = thumb_height; width = thumb_width; filters = 0; } else { fseek (ifp, thumb_offset, SEEK_SET); write_fun = write_thumb; goto thumbnail; } } if (load_raw == &CLASS kodak_ycbcr_load_raw) { height += height & 1; width += width & 1; } if (identify_only && verbose && make[0]) { printf (_("\nFilename: %s\n"), ifname); printf (_("Timestamp: %s"), ctime(×tamp)); printf (_("Camera: %s %s\n"), make, model); if (artist[0]) printf (_("Owner: %s\n"), artist); if (dng_version) { printf (_("DNG Version: ")); for (i=24; i >= 0; i -= 8) printf ("%d%c", dng_version >> i & 255, i ? '.':'\n'); } printf (_("ISO speed: %d\n"), (int) iso_speed); printf (_("Shutter: ")); if (shutter > 0 && shutter < 1) shutter = (printf ("1/"), 1 / shutter); printf (_("%0.1f sec\n"), shutter); printf (_("Aperture: f/%0.1f\n"), aperture); printf (_("Focal length: %0.1f mm\n"), focal_len); printf (_("Embedded ICC profile: %s\n"), profile_length ? _("yes"):_("no")); printf (_("Number of raw images: %d\n"), is_raw); if (pixel_aspect != 1) printf (_("Pixel Aspect Ratio: %0.6f\n"), pixel_aspect); if (thumb_offset) printf (_("Thumb size: %4d x %d\n"), thumb_width, thumb_height); printf (_("Full size: %4d x %d\n"), raw_width, raw_height); } else if (!is_raw) fprintf (stderr,_("Cannot decode file %s\n"), ifname); if (!is_raw) goto next; shrink = filters && (half_size || threshold || aber[0] != 1 || aber[2] != 1); iheight = (height + shrink) >> shrink; iwidth = (width + shrink) >> shrink; if (identify_only) { if (verbose) { if (use_fuji_rotate) { if (fuji_width) { fuji_width = (fuji_width - 1 + shrink) >> shrink; iwidth = fuji_width / sqrt(0.5); iheight = (iheight - fuji_width) / sqrt(0.5); } else { if (pixel_aspect < 1) iheight = iheight / pixel_aspect + 0.5; if (pixel_aspect > 1) iwidth = iwidth * pixel_aspect + 0.5; } } if (flip & 4) SWAP(iheight,iwidth); printf (_("Image size: %4d x %d\n"), width, height); printf (_("Output size: %4d x %d\n"), iwidth, iheight); printf (_("Raw colors: %d"), colors); if (filters) { printf (_("\nFilter pattern: ")); if (!cdesc[3]) cdesc[3] = 'G'; for (i=0; i < 16; i++) putchar (cdesc[fc(i >> 1,i & 1)]); } printf (_("\nDaylight multipliers:")); FORCC printf (" %f", pre_mul[c]); if (cam_mul[0] > 0) { printf (_("\nCamera multipliers:")); FORC4 printf (" %f", cam_mul[c]); } putchar ('\n'); } else printf (_("%s is a %s %s image.\n"), ifname, make, model); next: fclose(ifp); continue; } if (use_camera_matrix && cmatrix[0][0] > 0.25) { memcpy (rgb_cam, cmatrix, sizeof cmatrix); raw_color = 0; } image = (ushort (*)[4]) calloc (iheight*iwidth, sizeof *image); merror (image, "main()"); if (meta_length) { meta_data = (char *) malloc (meta_length); merror (meta_data, "main()"); } if (verbose) fprintf (stderr,_("Loading %s %s image from %s ...\n"), make, model, ifname); if (shot_select >= is_raw) fprintf (stderr,_("%s: \"-s %d\" requests a nonexistent image!\n"), ifname, shot_select); fseeko (ifp, data_offset, SEEK_SET); (*load_raw)(); if (zero_is_bad) remove_zeroes(); bad_pixels (bpfile); if (dark_frame) subtract (dark_frame); quality = 2 + !fuji_width; if (user_qual >= 0) quality = user_qual; if (user_black >= 0) black = user_black; if (user_sat > 0) maximum = user_sat; #ifdef COLORCHECK colorcheck(); #endif if (is_foveon && !document_mode) foveon_interpolate(); if (!is_foveon && document_mode < 2) scale_colors(); pre_interpolate(); if (filters && !document_mode) { if (quality == 0) lin_interpolate(); else if (quality == 1 || colors > 3) vng_interpolate(); else if (quality == 2) ppg_interpolate(); else ahd_interpolate(); } if (mix_green) for (colors=3, i=0; i < height*width; i++) image[i][1] = (image[i][1] + image[i][3]) >> 1; if (!is_foveon && colors == 3) median_filter(); if (!is_foveon && highlight == 2) blend_highlights(); if (!is_foveon && highlight > 2) recover_highlights(); if (use_fuji_rotate) fuji_rotate(); #ifndef NO_LCMS if (cam_profile) apply_profile (cam_profile, out_profile); #endif convert_to_rgb(); if (use_fuji_rotate) stretch(); thumbnail: if (write_fun == &CLASS jpeg_thumb) write_ext = ".jpg"; else if (output_tiff && write_fun == &CLASS write_ppm_tiff) write_ext = ".tiff"; else write_ext = ".pgm\0.ppm\0.ppm\0.pam" + colors*5-5; ofname = (char *) malloc (strlen(ifname) + 64); merror (ofname, "main()"); if (write_to_stdout) strcpy (ofname,_("standard output")); else { strcpy (ofname, ifname); if ((cp = strrchr (ofname, '.'))) *cp = 0; if (multi_out) sprintf (ofname+strlen(ofname), "_%0*d", snprintf(0,0,"%d",is_raw-1), shot_select); if (thumbnail_only) strcat (ofname, ".thumb"); strcat (ofname, write_ext); ofp = fopen (ofname, "wb"); if (!ofp) { status = 1; perror (ofname); goto cleanup; } } if (verbose) fprintf (stderr,_("Writing data to %s ...\n"), ofname); (*write_fun)(); fclose(ifp); if (ofp != stdout) fclose(ofp); cleanup: if (meta_data) free (meta_data); if (ofname) free (ofname); if (oprof) free (oprof); if (image) free (image); if (multi_out) { if (++shot_select < is_raw) arg--; else shot_select = 0; } } return status; } @ 1.424 log @Decode one-byte Huffman tokens by lookup table instead of crawling a tree. Support the Casio EX-S20, the Samsung S850, and the Agfa DC-833m. Removed pre_mul[] settings so users will send me color chart photos. @ text @d5305 1 @ 1.423 log @When sampling dark pixels, don't get too close to the light pixels. Support the Panasonic DMC-GH1. @ text @d26 1 a26 1 #define VERSION "8.94" d576 1 a576 1 unsigned CLASS getbits (int nbits) d584 3 a586 4 if (nbits == 0 || reset) return 0; while (vbits < nbits) { if ((c = fgetc(ifp)) == EOF) derror(); if ((reset = zero_after_ff && c == 0xff && fgetc(ifp))) return 0; d590 8 a597 2 vbits -= nbits; return bitbuf << (32-nbits-vbits) >> (32-nbits); d600 2 a601 5 void CLASS init_decoder() { memset (first_decode, 0, sizeof first_decode); free_decode = first_decode; } d629 1 a629 1 uchar * CLASS make_decoder (const uchar *source, int level) d631 16 a646 3 struct decode *cur; static int leaf; int i, next; d648 3 a650 18 if (level==0) leaf=0; cur = free_decode++; if (free_decode > first_decode+2048) { fprintf (stderr,_("%s: decoder table overflow\n"), ifname); longjmp (failure, 2); } for (i=next=0; i <= leaf && next < 16; ) i += source[next++]; if (i > leaf) { if (level < next) { cur->branch[0] = free_decode; make_decoder (source, level+1); cur->branch[1] = free_decode; make_decoder (source, level+1); } else cur->leaf = source[16 + leaf++]; } return (uchar *) source + 16 + leaf; d653 1 a653 1 void CLASS crw_init_tables (unsigned table) d711 2 a712 4 init_decoder(); make_decoder ( first_tree[table], 0); second_decode = free_decode; make_decoder (second_tree[table], 0); d738 2 a739 2 ushort *pixel, *prow; int nblocks, lowbits, i, row, r, col, save, val, nblack=0; a740 1 struct decode *decode, *dindex; a742 1 uchar c; d744 1 a744 1 crw_init_tables (tiff_compress); a755 1 decode = first_decode; d757 1 a757 4 for (dindex=decode; dindex->branch[0]; ) dindex = dindex->branch[getbits(1)]; leaf = dindex->leaf; decode = second_decode; d803 1 d813 1 a813 2 struct CLASS decode *huff[6]; ushort *row; d819 2 a820 1 uchar data[0x10000], *dp; a821 1 if (!info_only) init_decoder(); a822 1 FORC(6) jh->huff[c] = free_decode; d844 2 a845 4 for (dp = data; dp < data+len && *dp < 4; ) { jh->huff[*dp] = free_decode; dp = make_decoder (++dp, 0); } d856 1 d866 8 a873 1 int CLASS ljpeg_diff (struct decode *dindex) d877 1 a877 3 while (dindex->branch[0]) dindex = dindex->branch[getbits(1)]; len = dindex->leaf; d893 2 a894 1 if (jrow) d897 1 d964 1 a964 1 free (jh.row); d1033 1 a1033 1 free (jh.row); d1086 1 a1086 1 free (jh.row); a1110 20 void CLASS pentax_tree() { ushort bit[2][13]; struct decode *cur; int c, i, j; init_decoder(); FORC(13) bit[0][c] = get2(); FORC(13) bit[1][c] = fgetc(ifp) & 15; FORC(13) { cur = first_decode; for (i=0; i < bit[1][c]; i++) { j = bit[0][c] >> (11-i) & 1; if (!cur->branch[j]) cur->branch[j] = ++free_decode; cur = cur->branch[j]; } cur->leaf = c; } } d1113 2 a1114 1 int row, col, diff; d1117 8 d1128 1 a1128 1 diff = ljpeg_diff (first_decode); d1152 2 a1153 3 struct decode *dindex; ushort ver0, ver1, vpred[2][2], hpred[2], csize; int i, min, max, step=0, huff=0, split=0, row, col, len, shl, diff; d1160 2 a1161 2 if (ver0 == 0x46) huff = 2; if (tiff_bps == 14) huff += 3; d1177 1 a1177 2 init_decoder(); make_decoder (nikon_tree[huff], 0); d1182 2 a1183 2 init_decoder(); make_decoder (nikon_tree[huff+1], 0); d1187 3 a1189 4 for (dindex=first_decode; dindex->branch[0]; ) dindex = dindex->branch[getbits(1)]; len = dindex->leaf & 15; shl = dindex->leaf >> 4; d1200 1 d1615 1 a1615 1 unsigned CLASS ph1_bits (int nbits) d1619 1 d1624 1 a1624 1 if ((vbits -= nbits) < 0) { d1628 7 a1634 1 return bitbuf << (64-nbits-vbits) >> (64-nbits); d1636 2 d1693 1 a1693 2 struct decode *dindex; int row, col, pred[2], len[2], diff, i; a1695 1 free (jh.row); d1701 5 a1705 9 for (i=0; i < 2; i++) { for (dindex=jh.huff[0]; dindex->branch[0]; ) dindex = dindex->branch[ph1_bits(1)]; len[i] = dindex->leaf; } for (i=0; i < 2; i++) { diff = ph1_bits(len[i]); if ((diff & (1 << (len[i]-1))) == 0) diff -= (1 << len[i]) - 1; d1707 3 a1709 3 pred[i] += diff; if (row >= 0 && (unsigned)(col+i) < width) BAYER(row,col+i) = pred[i]; d1713 1 d1919 2 a1920 1 int row, col, nbits, sign, low, high, i, w, n, nw; d1923 3 d1934 3 a1936 5 sign = getbits(1) * -1; low = getbits(2); for (high=0; high < 12; high++) if (getbits(1)) break; if (high == 12) d2076 3 a2078 3 const int * CLASS make_decoder_int (const int *source, int level) { struct decode *cur; d2080 2 a2081 12 cur = free_decode++; if (level < source[0]) { cur->branch[0] = free_decode; source = make_decoder_int (source, level+1); cur->branch[1] = free_decode; source = make_decoder_int (source, level+1); } else { cur->leaf = source[1]; source += 2; } return source; } d2083 1 a2083 1 int CLASS radc_token (int tree) d2085 1 a2085 3 int t; static struct decode *dstart[18], *dindex; static const int *s, source[] = { d2105 1 a2105 24 if (free_decode == first_decode) for (s=source, t=0; t < 18; t++) { dstart[t] = free_decode; s = make_decoder_int (s, 0); } if (tree == 18) { if (kodak_cbpp == 243) return (getbits(6) << 2) + 2; /* most DC50 photos */ else return (getbits(5) << 3) + 4; /* DC40, Fotoman Pixtura */ } for (dindex = dstart[tree]; dindex->branch[0]; ) dindex = dindex->branch[getbits(1)]; return dindex->leaf; } #define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--) #define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \ : (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4) void CLASS kodak_radc_load_raw() { d2115 5 a2119 1 init_decoder(); d2139 1 a2139 1 FORYX buf[c][y][x] = radc_token(tree+10) * mul[c]; d2311 1 a2311 1 struct decode *decode[2]; d2313 1 a2313 1 int *strip, ns, i, row, col, chess, pi=0, pi1, pi2, pred, val; d2315 1 a2315 5 init_decoder(); for (i=0; i < 2; i++) { decode[i] = free_decode; make_decoder (kodak_tree[i], 0); } d2321 1 a2321 2 for (i=0; i < ns; i++) strip[i] = get4(); d2337 1 a2337 1 pixel[pi] = val = pred + ljpeg_diff (decode[chess]); d2346 1 d2518 5 a2522 1 int col, row, len, diff, sum=0; d2524 2 d2530 1 a2530 4 len = 4 - getbits(2); if (len == 3 && getbits(1)) len = 0; if (len == 4) while (len < 17 && !getbits(1)) len++; d2722 2 a2723 1 init_decoder(); d4591 2 a4592 4 if (tag == 0x220 && len == 53) { fseek (ifp, 14, SEEK_CUR); pentax_tree(); } d6024 2 d6132 2 d6440 2 d6444 2 d6589 1 d6600 1 a7140 2 pre_mul[0] = 1.818; pre_mul[2] = 1.618; a7146 2 pre_mul[0] = 1.331; pre_mul[2] = 1.820; a7254 2 pre_mul[0] = 1.391; pre_mul[2] = 1.188; a7260 2 pre_mul[0] = 1.137; pre_mul[2] = 1.453; a7267 2 pre_mul[0] = 1.980; pre_mul[2] = 1.570; d7273 8 a7280 1 } else if (!strcmp(model,"S85")) { a7293 2 pre_mul[0] = 1.097; pre_mul[2] = 1.128; a7299 2 pre_mul[0] = 1.561; pre_mul[2] = 2.454; a7306 1 pre_mul[1] = 1.218; a7358 2 pre_mul[0] = 1.717; pre_mul[2] = 1.138; a7756 2 pre_mul[0] = 1.8; pre_mul[2] = 1.3; a7761 2 pre_mul[0] = 1.14; pre_mul[2] = 2.73; d7790 5 a7794 2 pre_mul[0] = 1.340; pre_mul[2] = 1.672; a7798 2 pre_mul[0] = 1.631; pre_mul[2] = 1.106; a7802 2 pre_mul[0] = 2.529; pre_mul[2] = 1.185; a7806 2 pre_mul[0] = 1.520; pre_mul[2] = 1.316; a7811 2 pre_mul[0] = 2.07; pre_mul[2] = 1.88; a7815 2 pre_mul[0] = 1.797; pre_mul[2] = 1.219; a7819 2 pre_mul[0] = 1.758; pre_mul[2] = 1.504; @ 1.422 log @Use a logarithmic curve when "-g" has zero power and nonzero toe slope. Linearize the Apple Quicktake, Kodak DC40/DC50, and Logitech Fotoman Pixtura. Support the Canon SX1, SX110, and EOS 500D/Rebel T1i/Kiss X3. Support the Motorola PIXL, Kodak Z1015, and Olympus E-30. @ text @d350 1 a350 1 void CLASS canon_black (double dark[2]) d354 2 a355 2 if (raw_width < width+4) return; FORC(2) dark[c] /= (raw_width-width-2) * height >> 1; d741 1 a741 1 int nblocks, lowbits, i, row, r, col, save, val; d805 2 a806 2 else if (col > 1) dark[icol & 1] += pixel[r*raw_width+col]; d811 1 a811 1 canon_black (dark); d930 1 a930 1 int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0; d960 2 a961 2 } else if (col > 1) dark[(col-left_margin) & 1] += val; d968 1 a968 1 canon_black (dark); d6469 2 d7549 1 d7556 5 @ 1.421 log @Pentax K2000/K-m Huffman tree must be read from the MakerNote. The Kodak 620x and 720x use the filter pattern YMCY, not GRBG. @ text @d26 1 a26 1 #define VERSION "8.93" d28 1 d30 1 d104 1 a104 1 FILE *ifp; d106 2 a107 1 char *ifname, *meta_data; d117 1 a117 1 unsigned black, maximum, mix_green, raw_color, use_gamma, zero_is_bad; d123 2 a124 2 double pixel_aspect, aber[4]={1,1,1,1}, gamm[5]={ 0.45,4.5,0,0,0 }; ushort (*image)[4], white[8][8], curve[0x4001], cr2_slice[3], sraw_mul[4]; d138 1 a138 1 void (*write_thumb)(FILE *), (*write_fun)(FILE *); d147 1 a147 1 struct { d151 1 a151 1 struct { d257 1 a257 1 void CLASS merror (void *ptr, char *where) d1356 1 a1356 1 void CLASS jpeg_thumb (FILE *tfp); d1358 1 a1358 1 void CLASS ppm_thumb (FILE *tfp) d1364 1 a1364 1 fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height); d1366 1 a1366 1 fwrite (thumb, 1, thumb_length, tfp); d1370 1 a1370 1 void CLASS layer_thumb (FILE *tfp) d1379 1 a1379 1 fprintf (tfp, "P%d\n%d %d\n255\n", d1383 1 a1383 1 FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], tfp); d1387 1 a1387 1 void CLASS rollei_thumb (FILE *tfp) d1395 1 a1395 1 fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height); d1398 3 a1400 3 putc (thumb[i] << 3, tfp); putc (thumb[i] >> 5 << 2, tfp); putc (thumb[i] >> 11 << 3, tfp); d1489 1 a1489 1 ushort curve[0x10000], *xval[2]; d1804 1 a1804 1 int vbits=0, rbits=0, irow, row, col; d1808 1 a1808 1 rbits = raw_width * 8; d1811 4 a1814 2 } order = load_flags & 1 ? 0x4949 : 0x4d4d; d1828 13 a1840 8 if ((vbits -= 12) < 0) { bitbuf = bitbuf << 32 | get4(); vbits += 32; } if ((unsigned) (col-left_margin) < width) BAYER(row,col-left_margin) = bitbuf << (52-vbits) >> 52; if (load_flags & 8 && (col % 10) == 9) if (vbits=0, bitbuf & 255) derror(); d1844 2 a1845 1 if (!strcmp(make,"OLYMPUS")) black >>= 4; a1928 27 void CLASS olympus_e300_load_raw() { uchar *data, *dp; ushort *pixel, *pix; int dwide, row, col; dwide = raw_width * 16 / 10; fseek (ifp, dwide*top_margin, SEEK_CUR); data = (uchar *) malloc (dwide + raw_width*2); merror (data, "olympus_e300_load_raw()"); pixel = (ushort *) (data + dwide); for (row=0; row < height; row++) { if (fread (data, 1, dwide, ifp) < dwide) derror(); for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=3, pix+=2) { if (((dp-data) & 15) == 15) if (*dp++ && pix < pixel+width+left_margin) derror(); pix[0] = dp[1] << 8 | dp[0]; pix[1] = dp[2] << 4 | dp[1] >> 4; } for (col=0; col < width; col++) BAYER(row,col) = (pixel[col+left_margin] & 0xfff); } free (data); maximum >>= 4; black >>= 4; } d1938 1 a1938 1 for (col=0; col < width; col++) { d1952 1 d2153 2 d2156 4 d2216 3 a2218 2 maximum = 0xfff; use_gamma = 0; d2340 1 a2340 1 FORC3 image[row*width+col][c] = LIM(rgb[c],0,255); d2344 1 a2344 1 use_gamma = 0; d2587 1 a2587 1 data = (uchar *) malloc (raw_width*tiff_bps >> 3); d2590 19 a2608 25 fread (data, 1, raw_width*tiff_bps >> 3, ifp); if (tiff_bps == 8) { for (dp=data, col=0; col < width-30; dp+=16) { max = 0x7ff & (val = sget4(dp)); min = 0x7ff & val >> 11; imax = 0x0f & val >> 22; imin = 0x0f & val >> 26; for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++); for (bit=30, i=0; i < 16; i++) if (i == imax) pix[i] = max; else if (i == imin) pix[i] = min; else { pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min; if (pix[i] > 0x7ff) pix[i] = 0x7ff; bit += 7; } for (i=0; i < 16; i++, col+=2) BAYER(row,col) = curve[pix[i] << 1] >> 1; col -= col & 1 ? 1:31; } } else if (tiff_bps == 12) for (dp=data, col=0; col < width; dp+=3, col+=2) { BAYER(row,col) = ((dp[1] << 8 | dp[0]) & 0xfff) << 1; BAYER(row,col+1) = (dp[2] << 4 | dp[1] >> 4) << 1; } a2691 1 use_gamma = 0; d2786 1 a2786 1 void CLASS foveon_thumb (FILE *tfp) d2794 1 a2794 1 fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height); d2801 1 a2801 1 fwrite (buf, 3, thumb_width, tfp); d2820 1 a2820 1 fputc (pred[c], tfp); d3400 1 a3400 1 void CLASS bad_pixels (char *fname) d3403 1 a3403 1 char *cp, line[128]; d3407 2 a3408 2 if (fname) fp = fopen (fname, "r"); d3459 1 a3459 1 void CLASS subtract (char *fname) d3499 35 d3592 1 a3592 25 static const int cut[NSQ][4] = { { 241, 231, 234, 274 }, { 251, 235, 534, 274 }, { 255, 239, 838, 272 }, { 255, 240, 1146, 274 }, { 251, 237, 1452, 278 }, { 243, 238, 1758, 288 }, { 253, 253, 218, 558 }, { 255, 249, 524, 562 }, { 261, 253, 830, 562 }, { 260, 255, 1144, 564 }, { 261, 255, 1450, 566 }, { 247, 247, 1764, 576 }, { 255, 251, 212, 862 }, { 259, 259, 518, 862 }, { 263, 261, 826, 864 }, { 265, 263, 1138, 866 }, { 265, 257, 1450, 872 }, { 257, 255, 1762, 874 }, { 257, 253, 212, 1164 }, { 262, 251, 516, 1172 }, { 263, 257, 826, 1172 }, { 263, 255, 1136, 1176 }, { 255, 252, 1452, 1182 }, { 257, 253, 1760, 1180 } }; d5276 1 d5282 3 d5373 4 a5376 2 if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) load_raw = &CLASS olympus_e300_load_raw; d5383 9 a5391 5 load_raw = &CLASS sony_arw2_load_raw; if (tiff_ifd[raw].bytes*8 == raw_width*raw_height*tiff_bps) break; raw_height += 8; load_raw = &CLASS sony_arw_load_raw; break; d5393 1 a5393 1 load_flags = 8; d5409 5 a5413 2 if (!dng_version && tiff_samples == 3) if (tiff_ifd[raw].bytes && tiff_bps != 14 && tiff_bps != 2048) a5414 3 if (!dng_version && tiff_bps == 8 && tiff_compress == 1 && tiff_ifd[raw].phint == 1) is_raw = 0; if (tiff_bps == 8 && tiff_samples == 4) is_raw = 0; d5487 2 a5488 1 char *file, *ext, *jname, *jfile, *jext; d6061 1 a6061 1 void CLASS adobe_coeff (char *make, char *model) d6068 1 a6068 1 { 17576,-3191,-3318,5210,6733,-1942,9031,1280,-124 } }, d6169 4 d6307 2 d6341 2 d6391 2 d6605 1 d6640 1 a6640 1 "SAMSUNG", "Mamiya" }; d6656 1 a6656 1 pixel_aspect = is_raw = raw_color = use_gamma = 1; d6762 4 a6765 2 if (!strncmp (make,"KODAK",5)) make[16] = model[16] = 0; d6943 10 d7035 4 d7057 1 a7057 1 top_margin = 51; d7101 1 a7101 1 load_flags |= 8; d7117 1 a7117 1 load_flags = 1; d7159 1 a7159 1 load_flags = 7; d7171 1 a7171 1 load_flags = 7; d7192 1 a7192 1 load_flags = 6 + (make[0] == 'M'); d7208 1 a7208 1 load_flags = 7; d7313 1 a7313 1 load_flags = 7; d7534 1 d7574 1 a7574 1 load_flags = 7; d7578 1 d7627 4 d7641 1 d7658 1 a7658 1 } else use_gamma = 0; d7660 5 d7679 2 a7680 1 } else if (!strcmp(model,"DCS460")) { d7873 2 d7907 1 a7907 1 void CLASS apply_profile (char *input, char *output) d7962 1 a7962 1 double num, inverse[3][3], bnd[2]={0,0}; d8002 1 a8002 12 bnd[gamm[1] >= 1] = 1; if (gamm[1] && (gamm[1]-1)*(gamm[0]-1) <= 0) { for (i=0; i < 36; i++) { gamm[2] = (bnd[0] + bnd[1])/2; bnd[(pow(gamm[2]/gamm[1],-gamm[0])-1)/gamm[0]-1/gamm[2] > -1] = gamm[2]; } gamm[3] = gamm[2]*(1/gamm[0]-1); gamm[2] /= gamm[1]; } gamm[4] = 1 / (gamm[1]/2*SQR(gamm[2]) - gamm[3]*(1-gamm[2]) + (1-pow(gamm[2],1+gamm[0]))*(1+gamm[3])/(1+gamm[0])) - 1; d8020 1 a8020 2 if (output_bps == 8) pcurve[3] = (short)(256/gamm[4]+0.5) << 16; a8145 23 void CLASS gamma_lut (uchar lut[0x10000]) { int perc, c, val, total, i; float white=0, r; perc = width * height * 0.01; /* 99th percentile white level */ if (fuji_width) perc /= 2; if ((highlight & ~2) || no_auto_bright) perc = -1; FORCC { for (val=0x2000, total=0; --val > 32; ) if ((total += histogram[c][val]) > perc) break; if (white < val) white = val; } white *= 8 / bright; for (i=0; i < 0x10000; i++) { r = i / white; val = 256 * ( !use_gamma ? r : r <= gamm[2] ? r*gamm[1] : pow(r,gamm[0])*(1+gamm[3])-gamm[3]); if (val > 255) val = 255; lut[i] = val; } } d8261 1 a8261 1 void CLASS jpeg_thumb (FILE *tfp) d8270 2 a8271 2 fputc (0xff, tfp); fputc (0xd8, tfp); d8275 1 a8275 1 fwrite (exif, 1, sizeof exif, tfp); d8277 1 a8277 1 fwrite (&th, 1, sizeof th, tfp); d8279 1 a8279 1 fwrite (thumb+2, 1, thumb_length-2, tfp); d8283 1 a8283 1 void CLASS write_ppm_tiff (FILE *ofp) d8286 1 a8286 1 uchar *ppm, lut[0x10000]; d8289 1 d8291 9 a8317 2 if (output_bps == 8) gamma_lut (lut); d8324 2 a8325 2 FORCC ppm [col*colors+c] = lut[image[soff][c]]; else FORCC ppm2[col*colors+c] = image[soff][c]; d8333 1 a8333 1 int CLASS main (int argc, char **argv) d8339 2 a8340 2 char opm, opt, *ofname, *sp, *cp, *bpfile=0, *dark_frame=0; const char *write_ext; a8341 1 FILE *ofp; d8343 1 a8343 1 char *cam_profile=0, *out_profile=0; d8347 1 a8347 1 putenv ("TZ=UTC"); d8395 2 a8396 1 puts(_("-4 Write 16-bit linear instead of 8-bit with gamma")); d8417 3 a8419 2 case 'g': gamm[0] = 1 / atof(argv[arg++]); gamm[1] = atof(argv[arg++]); break; d8457 3 a8459 1 case '4': output_bps = 16; break; d8691 1 a8691 1 (*write_fun)(ofp); @ 1.420 log @Added "-g" option for custom gamma curves. Support the Pentax K2000/K-m. Support Firmware 1.0.7 in the Canon EOS 5D Mark II. @ text @d26 1 a26 1 #define VERSION "8.92" d826 1 a826 1 init_decoder(); d1111 20 a1132 3 static const uchar pentax_tree[2][30] = { { 0,2,3,1,1,1,1,1,1,2,0,0,0,0,0,0, 3,4,2,5,1,6,0,7,8,9,10,11,12 }, { 0,2,3,1,1,1,1,1,1,2,0,0,0,0,0,0, 1,2,0,3,4,5,6,7,8,9,10,11,12 } }; a1135 3 init_decoder(); row = !strcmp(model,"K2000") || !strcmp(model,"K-m"); make_decoder (pentax_tree[row], 0); d4636 4 d7649 2 @ 1.419 log @Don't hang when a RIFF file has an extra byte at the end. @ text @d26 1 a26 1 #define VERSION "8.91" d120 1 a120 1 double pixel_aspect, aber[4]={1,1,1,1}; d975 2 d998 6 d1025 5 a1029 5 rp[1] += jh.sraw+1; rp[2] += jh.sraw+1; pix[0] = rp[0] + (( 200*rp[1] + 22929*rp[2]) >> 12); pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 12); pix[2] = rp[0] + ((29040*rp[1] - 101*rp[2]) >> 12); d1113 3 a1115 3 static const uchar pentax_tree[] = { 0,2,3,1,1,1,1,1,1,2,0,0,0,0,0,0, 3,4,2,5,1,6,0,7,8,9,10,11,12 }; d1120 2 a1121 1 make_decoder (pentax_tree, 0); d4529 2 d6406 2 d7893 1 a7893 1 double num, inverse[3][3]; d7933 12 d7963 1 a7963 5 #ifdef SRGB_GAMMA pcurve[3] = 0x2330000; #else pcurve[3] = 0x1f00000; #endif d8106 1 a8106 5 #ifdef SRGB_GAMMA r <= 0.00304 ? r*12.92 : pow(r,2.5/6)*1.055-0.055 ); #else r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099 ); #endif d8348 1 d8362 2 a8363 2 if ((cp = strchr (sp="nbrkStqmHAC", opt))) for (i=0; i < "11411111142"[cp-sp]-'0'; i++) d8375 2 @ 1.418 log @Support the Hasselblad V96C. @ text @d5832 1 a5832 1 while (ftell(ifp) < end) d5835 1 a5835 1 while (ftell(ifp) < end) { @ 1.417 log @Get camera WB from ARW files edited by Sony IDC software. @ text @d3 1 a3 1 Copyright 1997-2008 by Dave Coffin, dcoffin a cybercom o net d26 1 a26 1 #define VERSION "8.90" d5160 3 d7352 5 @ 1.416 log @Fixed an overflow bug in wavelet_denoise(). @ text @d5041 3 @ 1.415 log @Support the Samsung S85 at ISO 800 and higher. @ text @d3668 1 a3668 1 fimg[i] = sqrt((unsigned) (image[i][c] << (scale+16))); @ 1.414 log @Better support the Apple QuickTake 100. @ text @d6578 1 d7246 1 a7246 1 raw_width = 3288; d7249 1 a7249 1 maximum = 0xfef8; @ 1.413 log @Support the Samsung S85. @ text @d7666 9 a7674 1 data_offset = 736; d7676 1 a7676 1 goto qt_common; a7680 1 qt_common: @ 1.412 log @Regardless of the Software tag, a DNG file is always raw. @ text @d26 1 a26 1 #define VERSION "8.89" d5456 1 a5456 1 merror (jname, "parse_external()"); d5462 4 a5465 2 memcpy (jfile, file+4, 4); memcpy (jfile+4, file, 4); d6577 1 d7242 7 @ 1.411 log @Support 3672 x 2486 images from the Panasonic DMC-FZ50. @ text @d5171 1 @ 1.410 log @Support FFF format from the Hasselblad H3D. @ text @d7429 1 a7429 1 height += 36; a7430 1 filters = 0x49494949; d7434 1 a7434 1 if ((height -= 39) == 2760) d7436 1 @ 1.409 log @Correctly handle negative pixels in split NEF files. @ text @d1679 1 d1693 1 d5119 1 @ 1.408 log @Support GPS-tagged ORFs and anonymous DNGs. @ text @d1142 1 a1142 1 int i, max, step=0, huff=0, split=0, row, col, len, shl, diff; d1165 1 d1170 1 a1170 1 for (row=0; row < height; row++) { d1174 1 d1186 1 a1186 1 if (hpred[col & 1] >= max) derror(); d1188 1 a1188 1 BAYER(row,col-left_margin) = curve[hpred[col & 1] & 0x3fff]; @ 1.407 log @Correctly handle edges of Canon sRAW images. @ text @d4652 3 a4654 1 if (tag == 0x2010 && type == 13) d5165 1 @ 1.406 log @Show exposure from Canon MakerNote only if EXIF values are missing. Support the sRAW1 and sRAW2 modes of the Canon EOS 50D and 5D Mark II. Support the Leaf AFi 7, Panasonic FX150 and G1, and Canon PowerShot G10. @ text @d1002 4 a1005 2 ip[col][c] = (ip[col-width][c] + ip[col+width][c] + 1) >> 1; for (col=1; col < width-1; col+=2) d1007 3 a1009 1 ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1; @ 1.405 log @Detect and correct even/odd dark skew in Canon images. Merged three other functions into packed_12_load_raw(). Support the Panasonics LX3 and FZ28, Nikons D90 and P6000, Canon EOS 50D, and Sony A900. @ text @d26 1 a26 1 #define VERSION "8.88" d816 2 a817 2 int bits, high, wide, clrs, sraw, psv, restart, vpred[4]; struct CLASS decode *huff[4]; d823 1 a823 1 int i, tag, len; d828 1 a828 2 for (i=0; i < 4; i++) jh->huff[i] = free_decode; d840 1 a840 1 jh->sraw = data[7] == 0x21; d857 1 d865 2 a866 2 jh->huff[3] = jh->huff[2] = jh->huff[1]; jh->huff[1] = jh->huff[0]; d890 1 a890 1 int col, c, diff, pred; d894 1 a894 1 FORC4 jh->vpred[c] = 1 << (jh->bits-1); d904 2 a905 2 if (jh->sraw && c < 2 && (col | c)) pred = row[0][(c << 1)-3]; d919 1 d973 1 a973 1 short *rp=0, *ip; d977 1 a977 1 jwide = (jh.wide >>= 1) * 4; d981 5 a985 5 ecol += cr2_slice[1] >> 1; if (!cr2_slice[0] || ecol > width-1) ecol = width & -2; for (row=0; row < height; row++) { ip = (short *) image[row*width+scol]; for (col=scol; col < ecol; col+=2, jcol+=4, ip+=8) { d988 5 a992 4 ip[0] = rp[jcol]; ip[4] = rp[jcol+1]; ip[1] = (short) (rp[jcol+2] << 2) >> 2; ip[2] = (short) (rp[jcol+3] << 2) >> 2; d996 22 a1017 13 for (row=0; row < height; row++) { ip = (short *) image[row*width+1]; for (col=1; col < width-1; col+=2, ip+=8) { ip[1] = (ip[-3] + ip[5] + 1) >> 1; ip[2] = (ip[-2] + ip[6] + 1) >> 1; } if (col < width) { ip[1] = ip[-3]; ip[2] = ip[-2]; } ip = (short *) image[row*width]; for (col=0; col < width; col++, ip+=4) { pix[0] = ip[2] + ip[0]; pix[2] = ip[1] + ip[0]; pix[1] = ((ip[0] << 12) - ip[1]*778 - (ip[2] << 11)) >> 12; FORC3 ip[c] = CLIP((pix[c] - 512) * sraw_mul[c] >> 10); d1019 1 d1268 1 a1268 1 int i; d1273 3 a1275 3 for (i=0; i < sizeof tail; i++) if (tail[i]) return 1; return 0; d4503 3 a4505 2 iso_speed = 50 * pow (2, (get4(),get2())/32.0 - 4); if ((i=(get2(),get2())) != 0x7fff) d4507 1 a4507 1 if ((i=get2()) != 0xffff) d4658 2 a4659 2 if (tag == 0x4001 && type == 3) { i = len == 582 ? 50 : len == 653 ? 68 : 126; d4771 1 a4771 1 "Aptus 54S","Aptus 65S","Aptus 75S" }; d4942 1 a4942 1 if (~tiff_ifd[ifd].offset) break; d4969 1 a4969 1 case 305: /* Software */ d4973 1 d5808 1 a5809 1 end = ftell(ifp) + size; d5813 8 d6020 2 d6034 2 d6045 1 a6045 1 { 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } }, d6066 2 d6164 2 d6272 2 a6273 2 { "NIKON D90", 0, 0xf00, /* DJC */ { 9692,-2519,-831,-5396,13053,2344,-1818,2682,7084 } }, d6304 2 d6372 2 d6378 2 d6394 6 d6428 2 a6429 2 { "SONY DSLR-A900", 254, 0x1ffe, /* DJC */ { 6971,-1730,-794,-5763,13529,2236,-1500,2251,6715 } } d6716 2 d6751 4 d6962 6 d6972 5 a6976 1 maximum = 0x3d93; d7335 3 d7401 1 a7401 1 width -= 16; d7405 2 a7406 2 width = 3291; left_margin = 9; a7407 1 goto fz18; d7409 3 a7411 3 width = 3288; left_margin = 15; fz18: if (height > 2480) d7415 1 a7415 1 break; d7431 1 a7431 1 break; d7435 4 a7438 5 width += 36; case 4060: width -= 78; filters = 0x16161616; maximum = 0xfff; d7445 7 d7462 5 @ 1.404 log @Support the Kodak C603, Nikon D700, Canon EOS 1000D, Canon PowerShot SD300, and Olympus E-520. Removed useless code from ppg_interpolate(). @ text @d26 1 a26 1 #define VERSION "8.87" d116 1 a116 1 unsigned tile_width, tile_length, gpsdata[32]; d347 14 d555 1 a555 1 if (vbits < 10) d557 1 a557 1 pixel = buf >> (vbits -= 10) & 0x3ff; d742 1 d802 2 a803 2 else black += pixel[r*raw_width+col]; d808 1 a808 2 if (raw_width > width) black /= (raw_width - width) * height; d927 1 d956 2 a957 1 } else black += val; d964 1 a964 2 if (raw_width > width) black /= (raw_width - width) * height; a1174 25 void CLASS nikon_load_raw() { int irow, row, col, i; getbits(-1); for (irow=0; irow < height; irow++) { row = irow; if (make[0] == 'O' || model[0] == 'E') { row = irow * 2 % height + irow / (height/2); if (row == 1 && data_offset == 0) { fseek (ifp, 0, SEEK_END); fseek (ifp, ftell(ifp)/2, SEEK_SET); getbits(-1); } } for (col=0; col < raw_width; col++) { i = getbits(12); if ((unsigned) (col-left_margin) < width) BAYER(row,col-left_margin) = i; if (tiff_compress > 32768 && (col % 10) == 9) if (getbits(8)) derror(); } } } a1282 28 void CLASS nikon_e2100_load_raw() { uchar data[4608], *dp; ushort pixel[3072], *pix; int row, col; for (row=0; row <= height; row+=2) { if (row == height) { fseek (ifp, 0, SEEK_END); fseek (ifp, ftell(ifp)/2, SEEK_SET); row = 1; } fread (data, 1, width*3/2, ifp); for (dp=data, pix=pixel; pix < pixel+width; dp+=12, pix+=8) { pix[0] = (dp[2] >> 4) + (dp[ 3] << 4); pix[1] = (dp[2] << 8) + dp[ 1]; pix[2] = (dp[7] >> 4) + (dp[ 0] << 4); pix[3] = (dp[7] << 8) + dp[ 6]; pix[4] = (dp[4] >> 4) + (dp[ 5] << 4); pix[5] = (dp[4] << 8) + dp[11]; pix[6] = (dp[9] >> 4) + (dp[10] << 4); pix[7] = (dp[9] << 8) + dp[ 8]; } for (col=0; col < width; col++) BAYER(row,col) = (pixel[col] & 0xfff); } } d1595 1 a1595 1 if (vbits < nbits) { a1598 1 vbits -= nbits; d1758 2 a1759 1 int row, col; d1761 29 a1789 10 if (raw_width * 2 < width * 3) raw_width = raw_width * 3 / 2; /* Convert raw_width to bytes */ getbits(-1); for (row=0; row < height; row++) { for (col=0; col < left_margin; col++) getbits(12); for (col=0; col < width; col++) BAYER(row,col) = getbits(12); for (col = (width+left_margin)*3/2; col < raw_width; col++) if (getbits(8) && raw_width-col < 35 && width != 3896) derror(); d1791 1 d1838 12 a1849 6 static uchar buf[16], vbits=0; if (!vbits && fread (buf, 1, 16, ifp) < 16) derror(); vbits = (vbits - nbits) & 127; return (buf[(vbits >> 3)+1] << 8 | buf[vbits >> 3]) >> (vbits & 7) & ~(-1 << nbits); d1856 1 a1856 1 raw_width = (raw_width+13)/14*14; d1859 4 a1862 4 if ((i = col % 14) < 2) nonz[i] = pred[i] = pana_bits(12); else { if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2)); d1866 1 a1866 2 pred[i & 1] += nonz[i & 1] ? j << sh : j; nonz[i & 1] = 1; d1868 2 a1869 1 } d1871 1 a1871 1 if ((BAYER(row,col) = pred[col & 1]) >> 12) derror(); a1942 16 void CLASS olympus_cseries_load_raw() { int irow, row, col; for (irow=0; irow < height; irow++) { row = irow * 2 % height + irow / (height/2); if (row < 2) { fseek (ifp, data_offset - row*(-width*height*3/4 & -2048), SEEK_SET); getbits(-1); } for (col=0; col < width; col++) BAYER(row,col) = getbits(12); } black >>= 4; } d4552 1 a4552 1 ver97 = (ver97 << 4) + fgetc(ifp)-'0'; d4554 1 a4554 1 case 0x100: d4558 1 a4558 1 case 0x102: d4561 1 a4561 1 case 0x103: d4565 2 a4566 2 if (ver97 >> 8 == 2) { if (ver97 != 0x205) fseek (ifp, 280, SEEK_CUR); d4574 1 a4574 1 if (tag == 0xa7 && ver97 >> 8 == 2) { d4580 3 a4582 5 FORC4 cam_mul[c ^ (c >> 1)] = sget2 (buf97 + (ver97 == 0x205 ? 14:6) + c*2); if (ver97 == 0x209) FORC4 cam_mul[c ^ (c >> 1) ^ 1] = sget2 (buf97 + 10 + c*2); d4928 4 d5305 2 a5306 2 if (!strncmp(make,"NIKON",5)) load_raw = &CLASS nikon_load_raw; a5312 2 if (tiff_bps == 12 && tiff_ifd[raw].phint == 2) load_raw = &CLASS olympus_cseries_load_raw; d5325 1 a5325 1 load_raw = &CLASS nikon_load_raw; break; d5805 1 a5805 1 for (i=0; i < 12 && strcmp(mon[i],month); i++); d6074 2 d6242 2 d6385 3 a6387 1 { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } } d6539 1 a6539 1 kodak_cbpp = zero_after_ff = dng_version = 0; d6687 6 a6692 2 if (!strcmp(make,"NIKON") && !load_raw) load_raw = &CLASS nikon_load_raw; d6706 1 a6706 1 } else if (is_canon && tiff_samples == 4) { d6914 6 d6950 2 d6954 2 a6955 1 load_raw = &CLASS nikon_load_raw; d6970 3 d6998 2 a6999 1 load_raw = &CLASS nikon_load_raw; d7013 1 a7013 1 load_raw = &CLASS nikon_e2100_load_raw; d7024 2 a7025 1 load_raw = &CLASS nikon_e2100_load_raw; d7045 2 a7046 2 if (make[0] == 'M') load_raw = &CLASS nikon_e2100_load_raw; d7061 2 a7062 1 load_raw = &CLASS nikon_e2100_load_raw; d7166 2 a7167 1 load_raw = &CLASS nikon_e2100_load_raw; d7372 9 d7401 2 a7402 1 load_raw = &CLASS nikon_e2100_load_raw; @ 1.403 log @Don't crash on corrupt CR2 files. Extract the largest JPEG from any X3F file. @ text @d26 1 a26 1 #define VERSION "8.86" d2316 24 d3849 1 a3849 1 merror (img, "unshrink()"); d4076 2 a4077 3 int gr[4], dir[5] = { 1, width, -1, -width, 1 }; int row, col, avg, diff[2], guess[2], c, d, i; static const short sort[] = { 0,2,1,3,0,1,2,3 }; a4086 14 for (avg=i=0; i < 4; i++) avg += gr[i] = pix[dir[i]][1] << 2; avg >>= 2; for (i=0; i < 8; i+=2) if (gr[sort[i]] > gr[sort[i+1]]) SWAP(gr[sort[i]],gr[sort[i+1]]) for (d=0; d < 4; d++) { for (i=-2; i < 2; i++) if (pix[i*dir[d] + (i+1)*dir[d+1]][1] <= avg) break; if (i == 2) { pix[0][1] = (gr[1]+gr[2]) >> 3; goto next_pixel; } } a4097 1 next_pixel: ; d6046 2 d6106 2 d6262 2 d6324 2 a6325 2 { "OLYMPUS E-420", 0, 0xfd7, /* copied from above */ { 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } }, d6330 2 d6484 5 d6514 1 d6757 8 d6908 2 d6954 4 a6976 3 } else if (!strcmp(model,"D3")) { width -= 4; left_margin = 2; d7446 14 d7467 1 @ 1.402 log @Added SONY A300 (dcraw's 300th camera!), fixed camera WB on the A200. Set model-specific saturation levels in adobe_coeff(). @ text @d925 1 a925 1 val = curve[val]; d5944 2 a5945 1 if (fgetc(ifp) == 0xff && fgetc(ifp) == 0xd8) { @ 1.401 log @Support the Olympus E-420. @ text @d26 1 a26 1 #define VERSION "8.85" a1884 2 maximum = 0xf96; black = 15; a2585 1 maximum = 0x1fff; d4657 2 d5004 1 d5339 5 a5343 1 load_raw = &CLASS sony_arw2_load_raw; break; d5418 1 a5418 1 i = strstr(model,"A200") ? 3:0; d6005 1 a6005 1 short black, trans[12]; d6007 1 a6007 1 { "Apple QuickTake", 0, /* DJC */ d6009 1 a6009 1 { "Canon EOS D2000", 0, d6011 1 a6011 1 { "Canon EOS D6000", 0, d6013 1 a6013 1 { "Canon EOS D30", 0, d6015 1 a6015 1 { "Canon EOS D60", 0, d6017 1 a6017 1 { "Canon EOS 5D", 0, d6019 3 a6021 1 { "Canon EOS 20Da", 0, d6023 1 a6023 1 { "Canon EOS 20D", 0, d6025 1 a6025 1 { "Canon EOS 30D", 0, d6027 1 a6027 1 { "Canon EOS 40D", 0, d6029 3 a6031 1 { "Canon EOS 350D", 0, d6033 1 a6033 1 { "Canon EOS 400D", 0, d6035 1 a6035 1 { "Canon EOS 450D", 0, d6037 1 a6037 1 { "Canon EOS-1Ds Mark III", 0, d6039 1 a6039 1 { "Canon EOS-1Ds Mark II", 0, d6041 1 a6041 1 { "Canon EOS-1D Mark II N", 0, d6043 1 a6043 1 { "Canon EOS-1D Mark III", 0, d6045 1 a6045 1 { "Canon EOS-1D Mark II", 0, d6047 1 a6047 1 { "Canon EOS-1DS", 0, d6049 1 a6049 1 { "Canon EOS-1D", 0, d6051 1 a6051 1 { "Canon EOS", 0, d6053 1 a6053 1 { "Canon PowerShot A50", 0, d6055 1 a6055 1 { "Canon PowerShot A5", 0, d6057 1 a6057 1 { "Canon PowerShot G1", 0, d6059 1 a6059 1 { "Canon PowerShot G2", 0, d6061 1 a6061 1 { "Canon PowerShot G3", 0, d6063 1 a6063 1 { "Canon PowerShot G5", 0, d6065 1 a6065 1 { "Canon PowerShot G6", 0, d6067 1 a6067 1 { "Canon PowerShot G9", 0, d6069 1 a6069 1 { "Canon PowerShot Pro1", 0, d6071 1 a6071 1 { "Canon PowerShot Pro70", 34, d6073 1 a6073 1 { "Canon PowerShot Pro90", 0, d6075 1 a6075 1 { "Canon PowerShot S30", 0, d6077 1 a6077 1 { "Canon PowerShot S40", 0, d6079 1 a6079 1 { "Canon PowerShot S45", 0, d6081 1 a6081 1 { "Canon PowerShot S50", 0, d6083 1 a6083 1 { "Canon PowerShot S60", 0, d6085 1 a6085 1 { "Canon PowerShot S70", 0, d6087 1 a6087 1 { "Canon PowerShot A610", 0, /* DJC */ d6089 1 a6089 1 { "Canon PowerShot A620", 0, /* DJC */ d6091 1 a6091 1 { "Canon PowerShot A640", 0, /* DJC */ d6093 1 a6093 1 { "Canon PowerShot A650", 0, /* DJC */ d6095 1 a6095 1 { "Canon PowerShot S3 IS", 0, /* DJC */ d6097 1 a6097 1 { "CINE 650", 0, d6099 1 a6099 1 { "CINE 660", 0, d6101 1 a6101 1 { "CINE", 0, d6103 1 a6103 1 { "Contax N Digital", 0, d6105 1 a6105 1 { "EPSON R-D1", 0, d6107 1 a6107 1 { "FUJIFILM FinePix E550", 0, d6109 1 a6109 1 { "FUJIFILM FinePix E900", 0, d6111 1 a6111 1 { "FUJIFILM FinePix F8", 0, d6113 1 a6113 1 { "FUJIFILM FinePix F7", 0, d6115 1 a6115 1 { "FUJIFILM FinePix S100FS", 514, d6117 1 a6117 1 { "FUJIFILM FinePix S20Pro", 0, d6119 1 a6119 1 { "FUJIFILM FinePix S2Pro", 128, d6121 1 a6121 1 { "FUJIFILM FinePix S3Pro", 0, d6123 1 a6123 1 { "FUJIFILM FinePix S5Pro", 0, d6125 1 a6125 1 { "FUJIFILM FinePix S5000", 0, d6127 1 a6127 1 { "FUJIFILM FinePix S5100", 0, d6129 1 a6129 1 { "FUJIFILM FinePix S5500", 0, d6131 1 a6131 1 { "FUJIFILM FinePix S5200", 0, d6133 1 a6133 1 { "FUJIFILM FinePix S5600", 0, d6135 1 a6135 1 { "FUJIFILM FinePix S6", 0, d6137 1 a6137 1 { "FUJIFILM FinePix S7000", 0, d6139 1 a6139 1 { "FUJIFILM FinePix S9000", 0, d6141 1 a6141 1 { "FUJIFILM FinePix S9500", 0, d6143 1 a6143 1 { "FUJIFILM FinePix S9100", 0, d6145 1 a6145 1 { "FUJIFILM FinePix S9600", 0, d6147 1 a6147 1 { "FUJIFILM IS-1", 0, d6149 1 a6149 1 { "Imacon Ixpress", 0, /* DJC */ d6151 1 a6151 1 { "KODAK NC2000", 0, d6153 1 a6153 1 { "Kodak DCS315C", 8, d6155 1 a6155 1 { "Kodak DCS330C", 8, d6157 1 a6157 1 { "KODAK DCS420", 0, d6159 1 a6159 1 { "KODAK DCS460", 0, d6161 1 a6161 1 { "KODAK EOSDCS1", 0, d6163 1 a6163 1 { "KODAK EOSDCS3B", 0, d6165 1 a6165 1 { "Kodak DCS520C", 180, d6167 1 a6167 1 { "Kodak DCS560C", 188, d6169 1 a6169 1 { "Kodak DCS620C", 180, d6171 1 a6171 1 { "Kodak DCS620X", 185, d6173 1 a6173 1 { "Kodak DCS660C", 214, d6175 1 a6175 1 { "Kodak DCS720X", 0, d6177 1 a6177 1 { "Kodak DCS760C", 0, d6179 1 a6179 1 { "Kodak DCS Pro SLR", 0, d6181 1 a6181 1 { "Kodak DCS Pro 14nx", 0, d6183 1 a6183 1 { "Kodak DCS Pro 14", 0, d6185 1 a6185 1 { "Kodak ProBack645", 0, d6187 1 a6187 1 { "Kodak ProBack", 0, d6189 1 a6189 1 { "KODAK P712", 0, d6191 1 a6191 1 { "KODAK P850", 0, d6193 1 a6193 1 { "KODAK P880", 0, d6195 1 a6195 1 { "Leaf CMost", 0, d6197 1 a6197 1 { "Leaf Valeo 6", 0, d6199 1 a6199 1 { "Leaf Aptus 54S", 0, d6201 1 a6201 1 { "Leaf Aptus 65", 0, d6203 1 a6203 1 { "Leaf Aptus 75", 0, d6205 1 a6205 1 { "Leaf", 0, d6207 1 a6207 1 { "Mamiya ZD", 0, d6209 1 a6209 1 { "Micron 2010", 110, /* DJC */ d6211 1 a6211 1 { "Minolta DiMAGE 5", 0, d6213 1 a6213 1 { "Minolta DiMAGE 7Hi", 0, d6215 1 a6215 1 { "Minolta DiMAGE 7", 0, d6217 1 a6217 1 { "Minolta DiMAGE A1", 0, d6219 1 a6219 1 { "MINOLTA DiMAGE A200", 0, d6221 1 a6221 1 { "Minolta DiMAGE A2", 0, d6223 1 a6223 1 { "Minolta DiMAGE Z2", 0, /* DJC */ d6225 1 a6225 1 { "MINOLTA DYNAX 5", 0, d6227 1 a6227 1 { "MINOLTA DYNAX 7", 0, d6229 1 a6229 1 { "NIKON D100", 0, d6231 1 a6231 1 { "NIKON D1H", 0, d6233 1 a6233 1 { "NIKON D1X", 0, d6235 1 a6235 1 { "NIKON D1", 0, /* multiplied by 2.218750, 1.0, 1.148438 */ d6237 1 a6237 1 { "NIKON D2H", 0, d6239 1 a6239 1 { "NIKON D2X", 0, d6241 1 a6241 1 { "NIKON D40X", 0, d6243 1 a6243 1 { "NIKON D40", 0, d6245 1 a6245 1 { "NIKON D50", 0, d6247 1 a6247 1 { "NIKON D60", 0, d6249 1 a6249 1 { "NIKON D70", 0, d6251 1 a6251 1 { "NIKON D80", 0, d6253 1 a6253 1 { "NIKON D200", 0, d6255 1 a6255 1 { "NIKON D300", 0, d6257 1 a6257 1 { "NIKON D3", 0, d6259 1 a6259 1 { "NIKON E950", 0, /* DJC */ d6261 1 a6261 1 { "NIKON E995", 0, /* copied from E5000 */ d6263 1 a6263 1 { "NIKON E2100", 0, /* copied from Z2, new white balance */ d6265 1 a6265 1 { "NIKON E2500", 0, d6267 1 a6267 1 { "NIKON E4300", 0, /* copied from Minolta DiMAGE Z2 */ d6269 1 a6269 1 { "NIKON E4500", 0, d6271 1 a6271 1 { "NIKON E5000", 0, d6273 1 a6273 1 { "NIKON E5400", 0, d6275 1 a6275 1 { "NIKON E5700", 0, d6277 1 a6277 1 { "NIKON E8400", 0, d6279 1 a6279 1 { "NIKON E8700", 0, d6281 1 a6281 1 { "NIKON E8800", 0, d6283 1 a6283 1 { "OLYMPUS C5050", 0, d6285 1 a6285 1 { "OLYMPUS C5060", 0, d6287 1 a6287 1 { "OLYMPUS C7070", 0, d6289 1 a6289 1 { "OLYMPUS C70", 0, d6291 1 a6291 1 { "OLYMPUS C80", 0, d6293 1 a6293 1 { "OLYMPUS E-10", 0, d6295 1 a6295 1 { "OLYMPUS E-1", 0, d6297 1 a6297 1 { "OLYMPUS E-20", 0, d6299 1 a6299 1 { "OLYMPUS E-300", 0, d6301 1 a6301 1 { "OLYMPUS E-330", 0, d6303 1 a6303 1 { "OLYMPUS E-3", 0, d6305 1 a6305 1 { "OLYMPUS E-400", 0, d6307 3 a6309 1 { "OLYMPUS E-410", 0, d6311 1 a6311 1 { "OLYMPUS E-500", 0, d6313 1 a6313 1 { "OLYMPUS E-510", 0, d6315 1 a6315 1 { "OLYMPUS SP350", 0, d6317 1 a6317 1 { "OLYMPUS SP3", 0, d6319 1 a6319 1 { "OLYMPUS SP500UZ", 0, d6321 1 a6321 1 { "OLYMPUS SP510UZ", 0, d6323 1 a6323 1 { "OLYMPUS SP550UZ", 0, d6325 1 a6325 1 { "OLYMPUS SP560UZ", 0, d6327 1 a6327 1 { "OLYMPUS SP570UZ", 0, d6329 1 a6329 1 { "PENTAX *ist DL2", 0, d6331 1 a6331 1 { "PENTAX *ist DL", 0, d6333 1 a6333 1 { "PENTAX *ist DS2", 0, d6335 1 a6335 1 { "PENTAX *ist DS", 0, d6337 1 a6337 1 { "PENTAX *ist D", 0, d6339 1 a6339 1 { "PENTAX K10D", 0, d6341 1 a6341 1 { "PENTAX K1", 0, d6343 1 a6343 1 { "PENTAX K20D", 0, d6345 1 a6345 1 { "PENTAX K200D", 0, d6347 1 a6347 1 { "Panasonic DMC-FZ8", 0, d6349 1 a6349 1 { "Panasonic DMC-FZ18", 0, d6351 1 a6351 1 { "Panasonic DMC-FZ30", 0, d6353 1 a6353 1 { "Panasonic DMC-FZ50", 0, /* aka "LEICA V-LUX1" */ d6355 1 a6355 1 { "Panasonic DMC-L10", 0, d6357 1 a6357 1 { "Panasonic DMC-L1", 0, /* aka "LEICA DIGILUX 3" */ d6359 1 a6359 1 { "Panasonic DMC-LC1", 0, /* aka "LEICA DIGILUX 2" */ d6361 1 a6361 1 { "Panasonic DMC-LX1", 0, /* aka "LEICA D-LUX2" */ d6363 1 a6363 1 { "Panasonic DMC-LX2", 0, /* aka "LEICA D-LUX3" */ d6365 1 a6365 1 { "Phase One H 20", 0, /* DJC */ d6367 1 a6367 1 { "Phase One P 2", 0, d6369 1 a6369 1 { "Phase One P 30", 0, d6371 1 a6371 1 { "Phase One P 45", 0, d6373 1 a6373 1 { "SAMSUNG GX-1", 0, d6375 1 a6375 1 { "Sinar", 0, /* DJC */ d6377 1 a6377 1 { "SONY DSC-F828", 491, d6379 1 a6379 1 { "SONY DSC-R1", 512, d6381 1 a6381 1 { "SONY DSC-V3", 0, d6383 1 a6383 1 { "SONY DSLR-A100", 0, d6385 1 a6385 1 { "SONY DSLR-A200", 0, d6387 3 a6389 1 { "SONY DSLR-A3", 0, d6391 1 a6391 1 { "SONY DSLR-A700", 254, d6401 2 a6402 2 if (table[i].black) black = table[i].black; d6688 4 a6842 1 maximum = 0xfa0; a6870 1 maximum = 0x3f60; a6881 1 maximum = 0x3bb0; a6897 1 maximum = 0xe6c; a6901 1 maximum = 0xe80; a6909 1 maximum = 0x3bb0; a6929 1 maximum = 0xf44; a6932 1 maximum = 0xfbc; a6939 1 maximum = 0xf35; a6961 1 maximum = 0x3dd; a7034 1 maximum = 0x3e00; d7071 1 a7071 1 maximum = 0xf7d; a7075 1 maximum = model[8] == '1' ? 0xf8b : 0xfff; a7081 1 maximum = 0xffb; a7297 1 maximum = 0xf7f0; d7300 2 a7304 1 maximum = 0xf7fc; a7308 1 maximum = 0xf94c; a7342 1 maximum = 0xf7f0; d7364 2 a7365 3 if (!strcmp(model,"E-1") || !strcmp(model,"E-400")) { maximum = 0xfff0; a7367 1 maximum = 0xffc0; a7379 11 } else if (!strcmp(model,"E-3")) { maximum = 0xf99; goto e410; } else if (!strcmp(model,"E-420")) { maximum = 0xfd7; goto e410; } else if (!strcmp(model,"E-410") || !strcmp(model,"E-510")) { maximum = 0xf6a; e410: load_raw = &CLASS olympus_e410_load_raw; black >>= 4; a7390 1 maximum = 0xf1e; a7409 5 load_raw = &CLASS sony_arw_load_raw; maximum = 0xfeb; } else if (!strcmp(model,"DSLR-A200")) { height = raw_height += 8; load_raw = &CLASS sony_arw_load_raw; d7411 1 a7411 5 height = (raw_height += 8) - 4; load_raw = &CLASS sony_arw_load_raw; maximum = 0x1ffe; } else if (!strncmp(model,"P850",4)) { maximum = 0xf7c; a7574 2 load_raw = &CLASS packed_12_load_raw; maximum = 0xf7f; a7578 2 load_raw = &CLASS packed_12_load_raw; maximum = 0xf7f; a7584 1 load_raw = &CLASS packed_12_load_raw; a7590 2 load_raw = &CLASS packed_12_load_raw; maximum = 0xf7f; a7596 2 load_raw = &CLASS packed_12_load_raw; maximum = 0xf7f; d7603 1 a7603 1 load_raw = &CLASS packed_12_load_raw; a7609 2 load_raw = &CLASS packed_12_load_raw; maximum = 0xf7f; a7615 2 load_raw = &CLASS packed_12_load_raw; maximum = 0xf7f; @ 1.400 log @Support the Canon EOS 450D, Nikon D60, and Fuji S100FS. Copied new matrices from Adobe DNG Converter 4.4. sRAW support in 1.393 broke Fuji DNG files, now fixed. @ text @d26 1 a26 1 #define VERSION "8.84" d7384 3 @ 1.399 log @Copy GPS data into thumbnails and TIFF output. Support the Apple QuickTake 200, Fuji IS-1, Sony DSLR-A350, Pentax K20D, Nokia N95, and Canon PowerShots A460, A530, and A650. @ text @d26 1 a26 1 #define VERSION "8.83" d802 1 a802 1 int bits, high, wide, clrs, psv, restart, vpred[4]; a825 1 case 0xffc0: data[7] = 0; d827 2 d832 1 a832 1 jh->clrs = data[5] + (data[7] == 0x21); d850 1 a850 1 if (jh->clrs == 4) { d890 1 a890 1 if (jh->clrs == 4 && c < 2 && (col | c)) d5362 1 d6027 2 d6107 2 d6239 2 d6317 2 d6333 4 d6377 2 a6378 2 { "SONY DSLR-A350", 0, /* copied from above */ { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } }, d6671 1 a6671 1 if ((is_canon = !strcmp(make,"Canon"))) { a6673 2 maximum = 0xfff; } d6875 7 d6907 1 d6929 3 a6931 2 } else if (!strcmp(model,"D2X")) { width -= 8; @ 1.398 log @Added the "-P" and "-S" options. Support the Sony DSLR-A200 and the PowerShots A720 and S5 IS. @ text @d26 1 a26 1 #define VERSION "8.82" a57 1 #define fgetc getc_unlocked d61 2 d116 1 a116 1 unsigned tile_width, tile_length; d155 4 a158 3 #define FORC3 for (c=0; c < 3; c++) #define FORC4 for (c=0; c < 4; c++) #define FORCC for (c=0; c < colors; c++) d534 1 a534 1 ushort data[2335], *dp, pixel; d887 1 a887 1 for (c=0; c < jh->clrs; c++) { d1014 1 a1014 1 for (c=0; c < tiff_samples; c++) d1728 1 a1728 1 for (c=0; c < tiff_samples; c++) { a1740 1 } d1829 24 d3652 1 a3652 1 for (c=0; c < nc; c++) { /* denoise R,G1,B,G3 individually */ d3740 1 a3740 1 for (c=0; c < 8; c++) dsum[c] += sum[c]; d4738 21 d5082 4 d6081 2 d6133 2 d6137 2 a6138 2 { "KODAK NC2000", 0, /* DJC */ { 16475,-6903,-1218,-851,10375,477,2505,-7,1020 } }, d6363 2 d6458 2 d6465 1 d6506 1 d6586 11 d6643 4 a6646 4 if (height == 2624 && width == 3936) { /* Pentax K10D and Samsung GX10 */ height = 2616; width = 3896; } d6706 17 d6764 8 d6887 4 a6894 3 } else if (!strcmp(model,"D80")) { height -= 3; width -= 4; d7009 1 a7009 1 } else if (!strncmp(model,"FinePix",7)) { d7080 2 d7129 2 d7404 4 d7517 2 a7518 1 data_offset = 738; d7939 1 a7939 1 union { short s0, s1; int i0; } val; d7946 1 a7946 1 struct tiff_tag tag[22]; d7950 2 d7954 1 d7962 1 d7968 5 a7972 3 if (type == 3 && count == 1) tt->val.s0 = val; else tt->val.i0 = val; d7992 1 a7992 1 th->tag[th->ntag-1].val.i0 = TOFF(th->bps); d8008 2 a8009 2 tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[6])); tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[8])); d8017 2 a8018 2 tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[0])); tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[2])); d8020 21 a8040 7 tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[4])); for (c=0; c < 6; c++) th->rat[c] = 1000000; th->rat[0] *= shutter; th->rat[2] *= aperture; th->rat[4] *= focal_len; th->rat[6] = th->rat[8] = 300; th->rat[7] = th->rat[9] = 1; @ 1.397 log @Support the Panasonic DMC-L10, added the "-W" option. @ text @d3 1 a3 1 Copyright 1997-2007 by Dave Coffin, dcoffin a cybercom o net d26 1 a26 1 #define VERSION "8.81" d3353 1 a3353 1 void CLASS bad_pixels() d3356 1 a3356 1 char *fname, *cp, line[128]; d3360 10 a3369 7 for (len=32 ; ; len *= 2) { fname = (char *) malloc (len); if (!fname) return; if (getcwd (fname, len-16)) break; free (fname); if (errno != ERANGE) return; } d3371 4 a3374 4 if (fname[1] == ':') memmove (fname, fname+2, len-2); for (cp=fname; *cp; cp++) if (*cp == '\\') *cp = '/'; d3376 9 a3384 7 cp = fname + strlen(fname); if (cp[-1] == '/') cp--; while (*fname == '/') { strcpy (cp, "/.badpixels"); if ((fp = fopen (fname, "r"))) break; if (cp == fname) break; while (*--cp != '/'); a3385 1 free (fname); d3404 1 a3404 1 fprintf (stderr,_("Fixed bad pixels at:")); d3687 1 a3687 1 int val, dblack; d3737 2 a3738 1 dblack = black; d3750 2 a3751 1 fprintf (stderr,_("Scaling with black %d, multipliers"), dblack); d6307 2 d6404 1 d6652 8 d7300 3 d7991 1 a7991 1 int arg, status=0, user_flip=-1, user_black=-1, user_qual=-1; d7993 1 d7995 1 a7995 1 char opm, opt, *ofname, *sp, *cp, *dark_frame=0; d8029 4 a8033 2 puts(_("-k Set the black level")); puts(_("-K Subtract dark frame (16-bit raw PGM)")); d8059 2 a8060 2 if ((cp = strchr (sp="nbrktqmHAC", opt))) for (i=0; i < "1141111142"[cp-sp]-'0'; i++) d8073 1 d8091 2 a8092 2 case 'K': dark_frame = argv[arg++]; break; d8279 1 a8279 1 bad_pixels(); d8284 1 @ 1.396 log @Cropped four columns from the Nikon D3. @ text @d26 1 a26 1 #define VERSION "8.80" d125 1 d1828 35 d5969 2 d6000 1 a6000 1 { 10823,-3042,-1842,-4562,13656,900,-1311,1670,3556 } }, d6247 2 d6271 2 d7140 2 d7195 4 d7788 1 a7788 1 perc = width * height * 0.01; /* 99th percentile white point */ d7790 1 a7790 1 if (highlight && highlight != 2) perc = -1; a8007 1 puts(_("-b Adjust brightness (default = 1.0)")); d8009 1 a8009 1 puts(_("-k Set black point")); d8021 2 d8083 1 @ 1.395 log @Abolished the getrat() macro, support the Hasselblad H3D. @ text @d6756 3 @ 1.394 log @Added the Olympus E-3 and adjusted a few maximums. @ text @d26 1 a26 1 #define VERSION "8.79" a335 1 #define getrat() getreal(10) d1697 1 a1697 1 for (row=0; row < height; row++) { d1699 1 a1699 1 for (col=0; col < width; col+=2) { d1709 3 a1711 1 BAYER(row,col+i) = pred[i] += diff; d4459 2 a4460 2 cam_mul[0] = getrat(); cam_mul[2] = getrat(); d4650 2 a4651 2 case 33434: shutter = getrat(); break; case 33437: aperture = getrat(); break; d4655 1 a4655 1 case 37377: if ((expo = -getrat()) < 128) d4657 2 a4658 2 case 37378: aperture = pow (2, getrat()/2); break; case 37386: focal_len = getrat(); break; d4965 1 a4965 1 shutter = getrat(); d4968 1 a4968 1 aperture = getrat(); d5003 1 a5003 1 focal_len = getrat(); d5010 2 a5011 2 getrat(); FORC3 rgb_cam[i][c] = getrat(); d5102 2 a5103 2 pixel_aspect = getrat(); pixel_aspect /= getrat(); d5108 1 a5108 1 cm[c][j] = getrat(); d5114 1 a5114 1 FORCC cc[i][c] = getrat(); d5116 1 a5116 1 FORCC ab[c] = getrat(); d5122 2 a5123 2 xyz[0] = getrat(); xyz[1] = getrat(); d6149 2 a6798 2 pre_mul[0] = 1.945; pre_mul[2] = 1.040; d7039 7 @ 1.393 log @Support the AVT F-080C, Canon EOS 40D, Canon EOS-1Ds Mark III, Canon PowerShot G9, Nikon Coolpix S6, Nikon D3, Nikon D300, Panasonic DMC-FZ18, and Sony DSLR-A700. Support the new Canon sRAW CR2 format. Added median filtering after interpolation. @ text @d26 1 a26 1 #define VERSION "8.78" d1714 1 d6186 2 d6729 3 a6731 3 } else if (!strncmp(model,"D40",3)) { width--; } else if (!strncmp(model,"D50",3) || !strncmp(model,"D70",3)) { a6732 1 maximum = 0xf53; d6843 1 d7183 3 a7187 1 load_raw = &CLASS olympus_e410_load_raw; d7189 1 @ 1.392 log @Use fseeko() and ftello() only when needed. @ text @d9 6 a14 5 to lawfully redistribute this code, you must either (a) include full source code* for all executable files containing RESTRICTED functions, (b) remove all RESTRICTED functions, re-implement them, or copy them from an earlier, unrestricted Revision of dcraw.c, or (c) purchase a license from the author. d26 1 a26 1 #define VERSION "8.77" d41 1 d59 4 d70 1 d108 1 a108 1 off_t strip_offset, data_offset, curve_offset; d120 1 a120 1 ushort (*image)[4], white[8][8], curve[0x1000], cr2_slice[3]; d124 1 a124 1 int output_color=1, output_bps=8, output_tiff=0; d824 1 a824 1 case 0xffc0: d829 1 a829 1 jh->clrs = data[5]; d847 4 d887 4 a890 2 if (!col) pred = (jh->vpred[c] += diff) - diff; else pred = row[0][-jh->clrs]; d951 44 d1083 2 a1084 4 if (col < 2) hpred[col] = vpred[row & 1][col] += diff; else hpred[col & 1] += diff; d1093 16 a1108 5 static const uchar nikon_tree[] = { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, 5,4,3,6,2,7,1,0,8,9,11,10,12 }; int csize, row, col, diff; ushort vpred[2][2], hpred[2], *curve; d1110 21 d1132 1 a1132 9 make_decoder (nikon_tree, 0); fseek (ifp, curve_offset, SEEK_SET); read_shorts (vpred[0], 4); csize = get2(); curve = (ushort *) calloc (csize, sizeof *curve); merror (curve, "nikon_compressed_load_raw()"); read_shorts (curve, csize); d1135 5 a1139 1 for (row=0; row < height; row++) d1141 12 a1152 8 diff = ljpeg_diff (first_decode); if (col < 2) hpred[col] = vpred[row & 1][col] += diff; else hpred[col & 1] += diff; if ((unsigned) (col-left_margin) >= width) continue; if (hpred[col & 1] >= csize) derror(); else BAYER(row,col-left_margin) = curve[hpred[col & 1]]; d1154 1 a1154 1 free (curve); a1191 4 if (tiff_compress != 34713) return 0; if (strcmp(model,"D100")) return 1; d1848 2 a1849 4 if (!strcmp(make,"OLYMPUS")) { maximum = 0xfff; black >>= 4; } d2488 39 d2767 1 a2767 1 if (!bit && !fixed && width < 2688) get4(); d3829 1 a3829 1 *ip++ = sum[c]; d3840 1 a3840 1 pix[ip[0]] = sum[ip[0]] / ip[1]; d4181 28 d4388 1 a4388 1 short sorder; a4393 1 sorder = order; d4486 5 d4501 2 a4502 4 if (tag == 0x8c) curve_offset = ftell(ifp) + 2112; if (tag == 0x96) curve_offset = ftell(ifp) + 2; d4535 3 d4603 2 d4799 1 d4830 5 d4928 6 d4937 4 a5126 1 i = order; a5127 1 order = i; d5207 1 d5228 2 d5243 2 d5249 2 d5259 1 a5259 1 case 32867: case 34713: break; d5300 1 d5329 1 d5784 1 a5784 4 fseek (ifp, 40, SEEK_CUR); cam_mul[0] = 1/getreal(11); cam_mul[2] = 1/getreal(11); fseek (ifp, 24, SEEK_CUR); d5791 2 a5792 1 fseek (ifp, 8, SEEK_CUR); d5925 2 d5959 2 d6085 2 d6139 4 d6192 1 a6192 1 { 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } }, d6219 2 d6252 3 a6254 1 { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } } d6334 1 d6360 1 d6408 1 a6408 1 for (i=0; i < 0x1000; i++) curve[i] = i; a6528 3 /* We'll try to decode anything from Canon or Nikon. */ d6534 2 a6535 3 if (!strcmp(make,"NIKON")) load_raw = nikon_is_compressed() ? &CLASS nikon_compressed_load_raw : &CLASS nikon_load_raw; d6545 3 d6678 6 d6697 5 d6714 6 d6735 2 a6736 1 if (tiff_compress == 34713 && load_raw == &CLASS nikon_load_raw) d6738 1 d6751 2 d6838 4 d6970 4 d7084 1 a7084 1 load_raw = &CLASS unpacked_load_raw; d7098 1 a7098 2 load_raw = &CLASS olympus_e300_load_raw; maximum = 0xf7f; d7112 13 d7172 4 a7175 2 maximum = 0xfc30; if (load_raw == &CLASS unpacked_load_raw) black = 0; d7178 2 d7183 1 a7183 1 maximum = 0xfff; d7383 1 d7389 1 d7404 1 d7412 1 d7427 1 d7435 1 d7912 1 a7912 1 FILE *ofp = stdout; d7960 1 d7970 2 a7971 2 if ((cp = strchr (sp="nbrktqHAC", opt))) for (i=0; i < "114111142"[cp-sp]-'0'; i++) d7986 1 a8016 1 case 'm': output_color = 0; break; d8047 1 d8208 2 a8209 2 if (mix_green && (colors = 3)) for (i=0; i < height*width; i++) d8211 1 @ 1.391 log @Reject TIFF files with unsupported Compression tags. @ text @a55 1 #ifndef DJGPP a56 2 #define fseek fseeko #endif d258 1 a258 1 fprintf (stderr,_("Corrupt data near 0x%lx\n"), ftell(ifp)); d7941 1 a7941 1 fseek (ifp, data_offset, SEEK_SET); @ 1.390 log @When they differ, use DateTimeOriginal instead of DateTime. @ text @d1092 1 a1092 1 if (tiff_compress == 34713 && (col % 10) == 9) d5074 2 d5086 2 a6628 3 } else if (!strncmp(model,"R-D1",4)) { tiff_compress = 34713; load_raw = &CLASS nikon_load_raw; @ 1.389 log @Added color matrix for the Canon PowerShot A640. @ text @a4470 1 if (timestamp) return; @ 1.388 log @Reject 8-bit grayscale TIFFs. Decode raw CINE files, which may exceed 2GB. Error-check the "-s" option, and enable "-s all". Support camera WB for the Canon EOS-1D and EOS-1DS. Use full output range for "-H 2". @ text @d5803 2 @ 1.387 log @Support all Lossless JPEG predictors. @ text @d25 1 a25 1 #define VERSION "8.76" d58 1 d104 4 a107 3 unsigned profile_offset, profile_length, *oprof; unsigned thumb_offset, thumb_length, thumb_misc; unsigned data_offset, strip_offset, curve_offset, meta_offset, meta_length; a120 1 int fuji_layout, fuji_secondary, shot_select=0; d947 1 a947 1 if (fuji_secondary && shot_select) (*rp)++; d955 1 a955 1 *rp += 1 + fuji_secondary; d962 1 a962 1 if (fuji_secondary && shot_select) (*rp)--; d978 1 a978 1 jwide >>= fuji_secondary; d4241 1 a4241 1 unsigned ver97=0, serial=0, i, wb[4]={0,0,0,0}; d4305 2 a4306 1 shot_order = (get4(),get2(),get2()); d4376 4 d4750 4 a4753 1 if (len == 4) load_raw = &CLASS sinar_4shot_load_raw; a5050 1 fuji_secondary = tiff_samples == 2; d5089 2 d5576 51 d5805 6 d6201 1 a6201 1 kodak_cbpp = zero_after_ff = dng_version = fuji_secondary = 0; d6265 2 a6266 2 fuji_secondary = (i = get4()) && 1; if (fuji_secondary && shot_select) d6283 2 d6327 2 a6328 2 if (!filters) colors = tiff_samples; d6639 1 a6639 1 if (fuji_secondary && shot_select) d6643 1 a6643 1 if (fuji_secondary) d6851 1 d7484 1 a7484 1 if (highlight) perc = -1; d7719 1 a7719 1 puts(_("-s [0-99] Select a different raw image from the same file")); d7728 2 a7729 2 if ((cp = strchr (sp="nbrktqsHAC", opt))) for (i=0; i < "1141111142"[cp-sp]-'0'; i++) a7743 1 case 's': shot_select = atoi(argv[arg++]); break; d7745 4 a7875 1 printf (_("Secondary pixels: %s\n"), fuji_secondary ? _("yes"):_("no")); d7877 1 a7877 1 printf (_("Decodable with dcraw: %s\n"), is_raw ? _("yes"):_("no")); d7937 5 a7941 2 fprintf (stderr, _("Loading %s %s image from %s ...\n"), make, model, ifname); d7983 1 a7983 1 ofname = (char *) malloc (strlen(ifname) + 16); d7990 3 d8013 4 @ 1.386 log @Reports of corruption in 16-bit linear DNGs were false. @ text @d25 1 a25 1 #define VERSION "8.75" d106 1 a106 1 unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress, tile_length; d109 1 d795 1 a795 1 int bits, high, wide, clrs, restart, vpred[4]; d825 1 a825 1 if (len == 9) getc(ifp); d834 3 d842 1 a842 1 jh->row = (ushort *) calloc (jh->wide*jh->clrs, 2); d862 1 a862 1 void CLASS ljpeg_row (int jrow, struct jhead *jh) d864 2 a865 2 int col, c, diff; ushort mark=0, *outp=jh->row; d874 1 d878 14 a891 3 *outp = diff = col ? outp[-jh->clrs]+diff : (jh->vpred[c] += diff); if ((ushort) diff >> jh->bits) derror(); outp++; d893 1 d901 1 d907 1 a907 1 ljpeg_row (jrow, &jh); d909 1 a909 1 val = jh.row[jcol]; d966 1 a966 1 int save, twide, trow=0, tcol=0, jrow, jcol; d970 1 a970 1 while (1) { d975 10 a984 14 if (trow >= raw_height) break; if (jh.high > raw_height-trow) jh.high = raw_height-trow; twide = jh.wide; if (filters) twide *= jh.clrs; else colors = jh.clrs; if (fuji_secondary) twide /= 2; if (twide > raw_width-tcol) twide = raw_width-tcol; for (jrow=0; jrow < jh.high; jrow++) { ljpeg_row (jrow, &jh); for (rp=jh.row, jcol=0; jcol < twide; jcol++) adobe_copy_pixel (trow+jrow, tcol+jcol, &rp); d987 2 a988 4 if ((tcol += twide) >= raw_width) { tcol = 0; trow += jh.high; } d4736 3 d6138 1 a6138 1 tile_length = INT_MAX; @ 1.385 log @Added "+M" option for version 8.75. @ text @d874 1 a874 1 if (diff >> jh->bits) derror(); @ 1.384 log @Added "-M" option and improved PPG interpolation. @ text @d25 1 a25 1 #define VERSION "8.74" d116 1 a116 1 int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=1; d120 1 a120 1 float cam_mul[4], pre_mul[4], rgb_cam[3][4]; /* RGB from camera color */ a3625 1 filters = 0; d3648 1 d4406 1 a4406 2 if (((tag == 0x1011 && len == 9) || tag == 0x20400200) && use_camera_matrix) { d4408 1 a4408 3 FORC3 rgb_cam[i][c] = ((short) get2()) / 256.0; raw_color = rgb_cam[0][0] < 0.25; } d4508 1 a4508 1 for (raw_color = i=0; i < 3; i++) d4510 2 a4511 2 for (rgb_cam[i][j] = k=0; k < 3; k++) rgb_cam[i][j] += rgb_romm[i][k] * romm_cam[k][j]; d4544 6 a4549 1 if (!strcmp(data,"CaptProf_color_matrix") && use_camera_matrix) { a5402 1 if (!use_camera_matrix) break; d6127 1 d7583 1 a7583 1 char opt, *ofname, *sp, *cp, *dark_frame=0; d7615 1 a7615 1 puts(_("-M Don't use an embedded color matrix")); d7641 1 a7641 1 for (arg=1; argv[arg][0] == '-'; ) { d7682 1 a7682 1 case 'M': use_camera_matrix = 0; break; d7694 2 d7839 4 @ 1.383 log @Added "-C" option to the usage message. @ text @d25 1 a25 1 #define VERSION "8.73" d116 1 a116 1 int verbose=0, use_auto_wb=0, use_camera_wb=0; d422 1 a422 1 next: continue; d3544 1 a3544 2 skip_block: continue; d3855 2 a3856 2 int gr[4], dir[4] = { 1, width, -1, -width }; int row, col, avg, pat, diff[2], guess[2], c, d, i; a3869 3 for (pat=i=0; i < 4; i++) pat = pat << 1 | (gr[i] > avg); if (pat & 8) pat ^= 15; d3873 20 a3892 18 if (pat == 0 || pat == 3 || pat == 6) pix[0][1] = (gr[1]+gr[2]) >> 3; else { for (i=0; (d=dir[i]) > 0; i++) { diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) + ABS(pix[ 2*d][c] - pix[ 0][c]) + ABS(pix[ -d][1] - pix[ d][1]) ) * 3 + ( ABS(pix[ 3*d][1] - pix[ d][1]) + ABS(pix[-3*d][1] - pix[-d][1]) ) * 2; guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2 - pix[-2*d][c] - pix[2*d][c]; } d = dir[i = diff[0] > diff[1]]; if (diff[0] != diff[1]) pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]); else pix[0][1] = ULIM((guess[0]+guess[1]) >> 1, gr[1], gr[2]) >> 2; } d3899 2 a3900 2 pix[0][c] = CLIP(((pix[0][1] + pix[-d][c] + pix[d][c]) * 2 - pix[-d][1] - pix[d][1]) >> 2); d3908 4 a3911 3 ABS(pix[-d][1] + pix[d][1] - 2*pix[0][1]); guess[i] = (pix[0][1] + pix[-d][c] + pix[d][c]) * 2 - pix[-d][1] - pix[d][1]; d3914 1 a3914 1 pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 2); d3916 1 a3916 1 pix[0][c] = CLIP((guess[0]+guess[1]) >> 3); d4406 2 a4407 1 if (((tag == 0x1011 && len == 9) || tag == 0x20400200) && use_camera_wb) { d4547 1 a4547 1 if (!strcmp(data,"CaptProf_color_matrix") && use_camera_wb) { d5401 1 a5401 1 if (!use_camera_wb) break; d5655 1 a5655 1 { 17524,-3363,-2877,5519,6087,-1605,9082,1142,-31 } }, d7613 1 d7680 1 @ 1.382 log @Added "-C" option to correct chromatic aberration. Support the Hasselblad CFV, Kodak EasyShare C330, and Nikon D40X. Use a switch statement for Leica and Panasonic models. Output seven new TIFF tags, including ImageDescription and Artist. Generated color matrices for the Apple QuickTake and Phase One H 20. Copied new matrices from Adobe DNG Converter 4.1. @ text @d7613 1 @ 1.381 log @Support 3096x2103 mode for the Panasonic DMC-FZ8. @ text @d25 1 a25 1 #define VERSION "8.72" d98 2 a99 1 char *ifname, make[64], model[64], model2[64], *meta_data, cdesc[5]; d112 1 a112 1 double pixel_aspect; d485 2 a486 2 val = (BAYER(row,col) - black) * mul[row & 3][col & 1] >> 9; if (val < 0) val = 0; d824 1 d1534 1 a1534 1 if (nbits == 0) d1536 1 d1566 1 a1566 1 ph1_bits(0); d1596 27 a1845 16 void CLASS eight_bit_load_raw() { uchar *pixel; int row, col; pixel = (uchar *) calloc (raw_width, sizeof *pixel); merror (pixel, "eight_bit_load_raw()"); for (row=0; row < height; row++) { if (fread (pixel, 1, raw_width, ifp) < raw_width) derror(); for (col=0; col < width; col++) BAYER(row,col) = pixel[col]; } free (pixel); maximum = 0xff; } d2138 1 a2138 1 void CLASS kodak_easy_load_raw() d2141 1 a2141 1 unsigned row, col, val; a2142 2 if (raw_width > width) black = 0; d2144 2 a2145 1 merror (pixel, "kodak_easy_load_raw()"); d2152 1 a2152 1 else black += val; d2156 2 a2157 2 if (raw_width > width) black /= (raw_width - width) * height; d3514 1 a3514 1 unsigned bottom, right, row, col, x, y, c, sum[8]; d3517 2 a3518 1 float scale_mul[4]; d3582 30 a3611 8 for (row=0; row < iheight; row++) for (col=0; col < iwidth; col++) FORC4 { val = image[row*iwidth+col][c]; if (!val) continue; val -= black; val *= scale_mul[c]; image[row*iwidth+col][c] = CLIP(val); d3613 3 d4297 2 d4305 1 a4305 1 if (tag == 0x11 && is_raw) { d4313 2 d4410 1 a4410 1 raw_color = rgb_cam[0][0] < 1; d4674 3 d4719 3 d4832 5 d4845 7 d4862 11 d5222 2 d5401 1 d5407 1 a5407 1 FORC3 cam_mul[c] = pre_mul[c] = getreal(11); d5654 2 d5680 2 d5747 1 a5747 1 { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } }, d5860 2 d5916 2 d5920 2 d5930 2 d5960 8 d6052 2 d6111 1 a6111 1 make[0] = model[0] = model2[0] = cdesc[0] = 0; d6224 1 a6224 1 make[63] = model[63] = model2[63] = 0; d6727 3 a6729 8 } else if (!strcmp(make,"Imacon")) { sprintf (model, "Ixpress %d-Mp", height*width/1000000); load_raw = &CLASS imacon_full_load_raw; if (filters) { if (left_margin & 1) filters = 0x61616161; load_raw = &CLASS unpacked_load_raw; } maximum = 0xffff; d6779 49 a6827 12 if (width == 2568) { adobe_coeff ("Panasonic","DMC-LC1"); } else if (width == 3130) { left_margin = 4; goto fz8_common; } else if (width == 3170) { left_margin = 18; fz8_common: width = 3096; if (height > 2326) { height = 2326; top_margin = 13; d6829 6 a6834 49 } load_raw = &CLASS olympus_e300_load_raw; maximum = 0xf7f; adobe_coeff ("Panasonic","DMC-FZ8"); zero_is_bad = 1; } else if (width == 3177) { maximum = 0xf7fc; width -= 10; filters = 0x49494949; adobe_coeff ("Panasonic","DMC-L1"); zero_is_bad = 1; } else if (width == 3304) { maximum = 0xf94c; width -= 16; adobe_coeff ("Panasonic","DMC-FZ30"); zero_is_bad = 1; } else if (width == 3690) { maximum = 0xf7f0; height -= 3; width = 3672; left_margin = 3; filters = 0x49494949; adobe_coeff ("Panasonic","DMC-FZ50"); zero_is_bad = 1; } else if (width == 3770) { height = 2760; width = 3672; top_margin = 15; left_margin = 17; adobe_coeff ("Panasonic","DMC-FZ50"); zero_is_bad = 1; } else if (width == 3880) { maximum = 0xf7f0; width -= 22; left_margin = 6; adobe_coeff ("Panasonic","DMC-LX1"); zero_is_bad = 1; } else if (width == 4290) { height--; width = 4248; left_margin = 3; filters = 0x49494949; adobe_coeff ("Panasonic","DMC-LX2"); } else if (width == 4330) { height = 2400; width = 4248; top_margin = 15; left_margin = 17; adobe_coeff ("Panasonic","DMC-LX2"); d6898 13 a6940 2 if (load_raw == &CLASS eight_bit_load_raw) load_raw = &CLASS kodak_easy_load_raw; d6961 1 a6961 1 load_raw = &CLASS kodak_easy_load_raw; d7427 1 a7427 1 struct tiff_tag tag[15]; d7432 2 a7433 2 int rat[6]; char make[64], model[64], soft[32], date[20]; d7462 1 d7472 1 d7483 4 d7489 1 d7500 3 d7509 1 d7639 2 a7640 2 if ((cp = strchr (sp="nbrktqsHA", opt))) for (i=0; i < "114111114"[cp-sp]-'0'; i++) d7650 2 d7767 2 d7792 2 a7793 1 shrink = (half_size || threshold) && filters; @ 1.380 log @Added Patterned Pixel Grouping interpolation. @ text @a6692 2 height = 2326; top_margin = 13; a6693 1 filters = 0x49494949; d6696 5 @ 1.379 log @Offer blended highlights with the "-H 2" option. Set "shot_order" for ORF and CR2 files. Support the Pentax Optio 750Z. @ text @d25 1 a25 1 #define VERSION "8.71" d3813 70 d7743 4 a7746 2 else if (quality < 3 || colors > 3) vng_interpolate(); @ 1.378 log @Added "-A" option to select a rectangle for white balance. Protect against overflow attacks on malloc() or calloc(). Nucore raw formats are not used outside Nucore, so drop them. Support the Canon PowerShots A630 and A640, Panasonic DMC-FZ8, Sigma SD14, Apple QuickTake 100 & 150, Mamiya ZD, Casio QV-R41, and Olympus E-410. @ text @d25 1 a25 1 #define VERSION "8.70" d1197 2 a1198 2 uchar data[3456], *dp; ushort pixel[2304], *pix; d1203 2 a1204 1 fseek (ifp, ((width==1616) << 13) - (-ftell(ifp) & -2048), SEEK_SET); d1767 1 a1767 1 BAYER(row,col) = pred + ((diff << 2) | low); d2568 1 d3943 37 d3990 1 a3990 1 if (verbose) fprintf (stderr,_("Highlight recovery...\n")); d4178 1 a4178 1 if (tag == 4 && len == 27) { d4180 5 a4184 2 aperture = (get2(), pow (2, get2()/64.0)); shutter = pow (2, ((short) get2())/-32.0); d4259 2 d5932 1 d6475 4 d6954 1 a6954 1 if (!load_raw || !height) is_raw = 0; d7228 1 a7228 1 if (highlight) perc = 0; d7437 1 a7437 1 puts(_("-H [0-9] Highlight mode (0=clip, 1=no clip, 2+=recover)")); a7676 2 if (!is_foveon && highlight > 1) recover_highlights(); if (use_fuji_rotate) fuji_rotate(); d7680 3 @ 1.377 log @Better detect and reject non-raw TIFFs. @ text @d25 1 a25 1 #define VERSION "8.69" d56 3 a58 1 d67 1 d101 10 a110 9 unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id, *oprof; int profile_offset, profile_length; int thumb_offset, thumb_length, thumb_width, thumb_height, thumb_misc; int data_offset, strip_offset, curve_offset, meta_offset, meta_length; int tiff_nifds, tiff_flip, tiff_bps, tiff_compress, tile_length; int raw_height, raw_width, top_margin, left_margin; int height, width, fuji_width, colors, tiff_samples; int black, maximum, mix_green, raw_color, use_gamma; int iheight, iwidth, shrink, flip; a111 1 int zero_after_ff, is_raw, dng_version, is_foveon, data_error; d118 1 a144 1 #define fgetc getc_unlocked d239 1 a239 1 return NULL; d278 1 a278 1 int CLASS sget4 (uchar *s) d287 1 a287 1 int CLASS get4() d294 1 a294 1 int CLASS getint (int type) d512 11 d525 1 a525 1 ushort data[1970], *dp, pixel; d537 2 a538 1 else black += (bc++,pixel); d804 1 d952 2 a953 1 fseek (ifp, get4(), SEEK_SET); d1005 2 a1006 2 int row, col, diff, i; ushort vpred[4] = {0,0,0,0}, hpred[2]; d1014 3 a1016 5 if (col < 2) { i = 2*(row & 1) + (col & 1); vpred[i] += diff; hpred[col] = vpred[i]; } else d1029 2 a1030 2 int csize, row, col, diff, i; ushort vpred[4], hpred[2], *curve; d1036 1 a1036 1 read_shorts (vpred, 4); d1047 3 a1049 5 if (col < 2) { i = 2*(row & 1) + (col & 1); vpred[i] += diff; hpred[col] = vpred[i]; } else d1272 1 a1272 1 thumb = (char *) malloc (thumb_length*colors); d1284 5 a1288 2 int i, size = thumb_width * thumb_height; ushort *thumb = (ushort *) calloc (size, 2); d1291 2 a1292 2 read_shorts (thumb, size); for (i=0; i < size; i++) { d1466 1 a1466 1 for (i=0; i < 9; i++) head[i] = get4(); d1534 1 a1534 1 bitbuf = bitbuf << 32 | (unsigned) get4(); a1665 1 /* Here raw_width is in bytes, not pixels. */ d1670 2 d1674 2 d1678 2 a1679 2 for (col = width*3/2; col < raw_width; col++) if (getbits(8)) derror(); a1700 6 void CLASS panasonic_load_raw() { unpacked_load_raw(); remove_zeroes(); } d1708 1 d1716 1 a1716 1 if (*dp++) derror(); d1721 1 a1721 1 BAYER(row,col) = (pixel[col] & 0xfff); d1724 45 a1768 2 maximum = 0xfff; black >>= 4; d1851 1 a1851 1 void CLASS nucore_load_raw() d1853 21 a1873 2 ushort *pixel; int irow, row, col; d1875 38 a1912 5 pixel = (ushort *) calloc (width, 2); merror (pixel, "nucore_load_raw()"); for (irow=0; irow < height; irow++) { read_shorts (pixel, width); row = irow/2 + height/2 * (irow & 1); d1914 2 a1915 3 BAYER(row,col) = pixel[col]; } free (pixel); d2035 3 a2037 1 val = (BAYER(y,x)-2048)*2 + (BAYER(y,x-1)+BAYER(y,x+1))/2; d2042 2 a2043 1 maximum = 10000; d2559 1 a2559 1 int bwide, row, col, bit=-1, c, i; a2562 1 unsigned bitbuf=0; d2581 1 a2581 1 for (col=bit=0; col < thumb_width; col++) d2622 1 a2622 1 if (!bit && !fixed) get4(); d2666 1 a2666 1 return NULL; d2669 1 a2669 1 void * CLASS foveon_camf_matrix (int dim[3], const char *name) d2673 1 d2689 2 a2690 2 if ((size = dim[0]*dim[1]*dim[2]) > meta_length/4) break; mat = (unsigned *) malloc (size * 4); d2700 1 a2700 1 return NULL; d2706 1 a2706 1 int dim[3]; d2725 1 d2732 1 a2732 1 int i, size; d2737 1 d2777 1 a2777 1 int dim[3], dscr[2][2], dstb[4], (*smrow[7])[3], total[4], ipix[3]; d2780 1 a2780 1 unsigned *badpix; d3172 1 a3172 1 FILE *fp=NULL; d3424 1 a3424 1 float *fimg, *temp, thold, mul[2], avg, diff; d3435 2 a3436 2 size = iheight*iwidth; fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg); d3499 2 a3500 1 int dblack, row, col, x, y, c, val, sum[8]; d3504 2 d3508 4 a3511 2 for (row=0; row < iheight-7; row += 8) for (col=0; col < iwidth-7; col += 8) { d3513 2 a3514 2 for (y=row; y < row+8; y++) for (x=col; x < col+8; x++) d3516 5 a3520 2 val = image[y*iwidth+x][c]; if (!val) continue; d3522 1 a3522 2 val -= black; if (val < 0) val = 0; d3525 1 a3548 2 if (user_mul[0]) memcpy (pre_mul, user_mul, sizeof pre_mul); d4026 1 a4026 1 if (*len * ("1112481124848"[*type < 13 ? *type:0]-'0') > 4) d4037 1 a4037 1 if (tag == toff) thumb_offset = get4(); d4045 1 a4045 1 void CLASS parse_makernote (int base) d4113 4 d4136 1 d4250 1 a4250 1 if (tag == 0x1011 && len == 9 && use_camera_wb) { d4255 1 a4255 1 if (tag == 0x1012 && len == 4) d4258 1 a4258 1 if (tag == 0x1017) d4260 1 a4260 1 if (tag == 0x1018) d4270 2 d4276 1 a4276 1 if (tag == 0x4001) { d4334 1 a4334 1 case 37500: parse_makernote (base); break; d4508 1 a4508 1 tiff_ifd[ifd].samples = len; d4541 1 a4541 1 tiff_ifd[ifd].samples = getint(type); d4794 4 a4797 2 if (asn[0]) FORCC pre_mul[c] = 1 / asn[c]; d4848 7 a4854 2 load_raw = tiff_bps > 8 ? &CLASS unpacked_load_raw : &CLASS eight_bit_load_raw; d5405 1 d5424 1 a5424 1 if (pent > 256) pent=256; d5633 2 d5745 2 d5861 2 d5876 1 d5894 1 a5894 1 "SAMSUNG" }; d5903 1 a5903 1 load_raw = thumb_load_raw = NULL; d5908 1 a5918 1 mix_green = profile_length = data_error = 0; a5944 23 } else if (!memcmp (head,"BM",2) && head[26] == 1 && head[28] == 16 && head[30] == 0) { data_offset = 0x1000; order = 0x4949; fseek (ifp, 38, SEEK_SET); if (get4() == 2834 && get4() == 2834 && get4() == 0 && get4() == 4096) { strcpy (model, "BMQ"); flip = 3; goto nucore; } } else if (!memcmp (head,"BR",2)) { strcpy (model, "RAW"); nucore: strcpy (make, "Nucore"); order = 0x4949; fseek (ifp, 10, SEEK_SET); data_offset += get4(); raw_width = (get4(),get4()); raw_height = get4(); if (model[0] == 'B' && raw_width == 2597) { raw_width++; data_offset -= 0x1000; } d5955 6 d6008 1 a6008 1 if (!strncmp (model, make, i) && model[i++] == ' ') a6014 2 if ((raw_height | raw_width) < 0) raw_height = raw_width = 0; a6034 1 FORC4 cam_mul[c] = pre_mul[c]; d6088 1 d6104 16 d6570 14 d6589 1 a6589 1 load_raw = &CLASS panasonic_load_raw; d6594 1 a6594 1 load_raw = &CLASS panasonic_load_raw; d6602 1 a6602 1 load_raw = &CLASS panasonic_load_raw; d6609 1 a6609 1 load_raw = &CLASS panasonic_load_raw; d6615 1 a6615 1 load_raw = &CLASS panasonic_load_raw; d6651 5 d6782 11 d6837 6 a6891 8 } else if (!strcmp(make,"Nucore")) { filters = 0x61616161; load_raw = &CLASS unpacked_load_raw; if (width == 2598) { filters = 0x16161616; load_raw = &CLASS nucore_load_raw; flip = 2; } d6932 1 a6932 1 cmsHPROFILE hInProfile=NULL, hOutProfile=NULL; d6961 1 a6961 1 oprof = NULL; d7091 1 a7091 1 int i, wide, high, row, col; d7095 1 a7095 1 ushort (*img)[4], (*pix)[4]; d7129 2 a7130 1 int newdim, row, col, c; a7131 1 ushort (*img)[4], *pix0, *pix1; d7352 1 a7352 1 char opt, *ofname, *sp, *cp, *dark_frame = NULL; d7357 1 a7357 1 char *cam_profile = NULL, *out_profile = NULL; a7379 1 puts(_("-a Use automatic white balance")); d7381 3 a7383 1 puts(_("-r <4 numbers> Set custom white balance")); d7410 2 a7411 2 if ((cp = strchr (sp="nbrktqsH", opt))) for (i=0; i < "11411111"[cp-sp]-'0'; i++) d7444 1 d7476 3 a7478 2 image = NULL; oprof = NULL; a7481 1 if (image) free (image); d7483 1 a7483 1 continue; d7598 1 a7598 2 image = (ushort (*)[4]) calloc (iheight*iwidth*sizeof *image + meta_length, 1); d7600 4 a7603 1 meta_data = (char *) (image + iheight*iwidth); d7609 1 d7668 2 d7671 1 a7671 2 free (ofname); free (image); @ 1.376 log @Optimized AHD interpolation to take 22% less time. @ text @d25 1 a25 1 #define VERSION "8.68" d4742 3 a4744 2 if (tiff_samples == 3 && tiff_bps == 8) if (!dng_version) is_raw = 0; @ 1.375 log @Support the Fuji FinePix S5Pro. @ text @d25 1 a25 1 #define VERSION "8.67" a3690 31 void CLASS cam_to_cielab (ushort cam[4], float lab[3]) { int c, i, j, k; float r, xyz[3]; static float cbrt[0x10000], xyz_cam[3][4]; if (cam == NULL) { for (i=0; i < 0x10000; i++) { r = i / 65535.0; cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0; } for (i=0; i < 3; i++) for (j=0; j < colors; j++) for (xyz_cam[i][j] = k=0; k < 3; k++) xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i]; } else { xyz[0] = xyz[1] = xyz[2] = 0.5; FORCC { xyz[0] += xyz_cam[0][c] * cam[c]; xyz[1] += xyz_cam[1][c] * cam[c]; xyz[2] += xyz_cam[2][c] * cam[c]; } xyz[0] = cbrt[CLIP((int) xyz[0])]; xyz[1] = cbrt[CLIP((int) xyz[1])]; xyz[2] = cbrt[CLIP((int) xyz[2])]; lab[0] = 116 * xyz[1] - 16; lab[1] = 500 * (xyz[0] - xyz[1]); lab[2] = 200 * (xyz[1] - xyz[2]); } } d3699 1 a3699 1 int i, j, top, left, row, col, tr, tc, fc, c, d, val, hm[2]; d3703 1 a3703 1 float flab[3]; d3705 1 a3705 1 short (*lab)[TS][TS][3]; d3710 10 a3719 1 border_interpolate(3); d3726 2 a3727 3 for (top=0; top < height; top += TS-6) for (left=0; left < width; left += TS-6) { memset (rgb, 0, 12*TS*TS); d3730 3 a3732 4 for (row = top < 2 ? 2:top; row < top+TS && row < height-2; row++) { col = left + (FC(row,left) == 1); if (col < 2) col += 2; for (fc = FC(row,col); col < left+TS && col < width-2; col+=2) { d3734 2 a3735 2 val = ((pix[-1][1] + pix[0][fc] + pix[1][1]) * 2 - pix[-2][fc] - pix[2][fc]) >> 2; d3737 2 a3738 2 val = ((pix[-width][1] + pix[0][fc] + pix[width][1]) * 2 - pix[-2*width][fc] - pix[2*width][fc]) >> 2; d3744 2 a3745 2 for (row=top+1; row < top+TS-1 && row < height-1; row++) for (col=left+1; col < left+TS-1 && col < width-1; col++) { d3748 1 d3764 12 a3775 2 cam_to_cielab (rix[0], flab); FORC3 lab[d][row-top][col-left][c] = 64*flab[c]; d3779 1 a3779 1 for (row=top+2; row < top+TS-2 && row < height; row++) { d3781 1 a3781 1 for (col=left+2; col < left+TS-2 && col < width; col++) { d3783 8 a3790 3 for (d=0; d < 2; d++) for (i=0; i < 4; i++) ldiff[d][i] = ABS(lab[d][tr][tc][0]-lab[d][tr][tc+dir[i]][0]); a3792 5 for (d=0; d < 2; d++) for (i=0; i < 4; i++) if (i >> 1 == d || ldiff[d][i] <= leps) abdiff[d][i] = SQR(lab[d][tr][tc][1]-lab[d][tr][tc+dir[i]][1]) + SQR(lab[d][tr][tc][2]-lab[d][tr][tc+dir[i]][2]); d3802 1 a3802 1 for (row=top+3; row < top+TS-3 && row < height-3; row++) { d3804 1 a3804 1 for (col=left+3; col < left+TS-3 && col < width-3; col++) { a7448 1 cam_to_cielab (NULL,NULL); @ 1.374 log @Refactored wavelet_denoise() to use memory more intelligently. @ text @d25 1 a25 1 #define VERSION "8.66" d5159 2 a5160 4 if (fuji_layout) { height *= 2; width /= 2; } d5431 2 d5768 1 a5768 1 raw_height = raw_width = fuji_width = cr2_slice[0] = 0; d6220 2 a6221 2 data_offset += (shot_select > 0) * ( strcmp(model+7," S3Pro") ? (raw_width *= 2) : raw_height*raw_width*2 ); @ 1.373 log @Detect and report data errors wherever possible. @ text @d25 1 a25 1 #define VERSION "8.65" d1370 1 a1370 1 if (shrink || !meta_length) return; d1611 1 a1611 1 if ((shot = shot_select) || shrink) { d1619 4 d1638 1 a1638 1 filters = 0; a3306 2 for (i=0; i < size; i++) base[st*i] = temp[i] * 0.25; d3311 2 a3312 2 float *fimg, *temp, thold, val, mul[2], avg, diff; int scale=1, depth=6, lev, row, col, size, nc, c, i, wlast; d3323 1 a3323 1 fimg = (float *) calloc (depth*size+iheight+iwidth, sizeof *fimg); d3325 1 a3325 1 temp = fimg + depth*size; d3330 12 a3341 6 for (lev=0; lev < depth-1; lev++) { memcpy (fimg+size*(lev+1), fimg+size*lev, size*sizeof *fimg); for (i=0; i < iheight; i++) hat_transform (temp, fimg+size*(lev+1)+i*iwidth,1,iwidth, 1 << lev); for (i=0; i < iwidth; i++) hat_transform (temp, fimg+size*(lev+1)+i,iwidth, iheight, 1 << lev); d3343 6 a3348 5 for (i=size*lev; i < size*(lev+1); i++) { fimg[i] -= fimg[i+size]; if (fimg[i] < -thold) fimg[i] += thold; else if (fimg[i] > thold) fimg[i] -= thold; else fimg[i] = 0; d3350 1 d3352 2 a3353 5 for (i=0; i < size; i++) { for (val=lev=0; lev < depth; lev++) val += fimg[size*lev+i]; image[i][c] = CLIP(val*val/0x10000); } d3461 1 a3461 1 int row, col; d3472 4 a3475 2 for (col=0; col < width; col++) img[row*width+col][FC(row,col)] = BAYER(row,col); @ 1.372 log @Use the "a trous" wavelet transform instead of the JPEG2000 method. Apply sqrt() to denoise highlights and shadows evenly. @ text @d25 1 a25 1 #define VERSION "8.64" d108 1 a108 1 int zero_after_ff, is_raw, dng_version, is_foveon; d248 12 d330 1 a330 1 fread (pixel, 2, count, ifp); d460 1 a460 1 fread (data, raw_width * 10 / 8, 1, ifp); d545 1 a545 1 c = fgetc(ifp); d547 1 a547 1 bitbuf = (bitbuf << 8) + c; d700 1 a700 1 int lowbits, i, row, r, col, save, val; d715 2 a716 1 for (block=0; block < raw_width >> 3; block++) { d739 2 a740 1 pixel[(block << 6) + i] = ( base[i & 1] += diffbuf[i] ); d855 2 a856 1 *outp = col ? outp[-jh->clrs]+diff : (jh->vpred[c] += diff); d1005 1 d1039 2 a1040 3 diff = hpred[col & 1]; if (diff >= csize) diff = csize-1; BAYER(row,col-left_margin) = curve[diff]; d1065 1 a1065 1 getbits(8); d1215 1 a1215 1 int row, col, r, c; d1218 2 a1219 1 pixel = (ushort *) calloc (raw_width, sizeof *pixel); d1222 3 a1224 2 read_shorts (pixel, raw_width); for (col=0; col < fuji_width << !fuji_layout; col++) { d1560 1 d1656 1 a1656 1 getbits(8); d1663 1 a1663 1 int row, col; d1665 1 d1667 1 a1667 1 pixel = (ushort *) calloc (raw_width, sizeof *pixel); d1670 2 a1671 1 read_shorts (pixel, raw_width); d1673 1 a1673 1 BAYER2(row,col) = pixel[col]; d1695 1 a1695 1 fread (data, 1, dwide, ifp); d1697 2 a1698 1 if (((dp-data) & 15) == 15) dp++; d1732 1 a1732 1 fread (pixel, 1, 768, ifp); d1762 1 a1762 1 fread (pixel, 1, raw_width, ifp); d1914 2 a1915 4 if (c) BAYER(row+y*2+c-1,x*2+2-c) = val; else BAYER(row+r*2+y,x*2+y) = val; d2000 1 a2000 1 fread (pixel, 848, 1, ifp); d2018 1 a2018 1 fread (pixel, 1, raw_width, ifp); d2070 2 a2071 1 pixel[pi] = pred + ljpeg_diff (decode[chess]); d2140 2 a2141 1 BAYER(row,col+i) = curve[ret ? buf[i] : (pred[i & 1] += buf[i])]; d2164 1 a2164 1 y[j][k] = y[j][k^1] + *bp++; d2184 1 a2184 1 FORC3 ip[c] = (rgb[c] += *bp++) & 0xfff; d2234 1 a2234 1 fread (pixel, 2, raw_width, ifp); d2239 2 a2240 1 BAYER(row,col) = ntohs(pixel[col+left_margin]); d2263 1 a2263 1 sum += diff; d2498 1 a2498 1 short diff[1024], pred[3]; d2500 1 a2500 1 int fixed, row, col, bit=-1, c, i; d2522 1 d5780 1 a5780 1 mix_green = profile_length = 0; d6674 1 a6674 1 width = 2576; @ 1.371 log @Added the Olympus SP550UZ. @ text @d25 1 a25 1 #define VERSION "8.63" d3271 13 d3286 2 a3287 2 float *fimg, *temp, mul[2], avg, diff; int scale=1, dim=0, row, col, size, sh, nc, c, i, j, k, m, wlast; d3289 2 a3290 2 static const float wlet[] = /* Daubechies 9-tap/7-tap filter */ { 1.149604398, -1.586134342, -0.05298011854, 0.8829110762, 0.4435068522 }; d3297 2 a3298 2 while (1 << dim < iwidth || 1 << dim < iheight) dim++; fimg = (float *) calloc ((1 << dim*2)+(1 << dim)+2, sizeof *fimg); d3300 1 a3300 1 temp = fimg + (1 << dim*2) + 1; d3303 21 a3323 50 for (row=0; row < iheight; row++) for (col=0; col < iwidth; col++) fimg[(row << dim)+col] = image[row*iwidth+col][c] << scale; for (size = 1 << dim; size > 1; size >>= 1) for (sh=0; sh <= dim; sh += dim) for (i=0; i < size; i++) { for (j=0; j < size; j++) temp[j] = fimg[(i << (dim-sh))+(j << sh)]; for (k=1; k < 5; k+=2) { temp[size] = temp[size-2]; for (m=1; m < size; m+=2) temp[m] += wlet[k] * (temp[m-1] + temp[m+1]); temp[-1] = temp[1]; for (m=0; m < size; m+=2) temp[m] += wlet[k+1] * (temp[m-1] + temp[m+1]); } for (m=0; m < size; m++) temp[m] *= (m & 1) ? 1/wlet[0] : wlet[0]; for (j=k=0; j < size; j++, k+=2) { if (k == size) k = 1; fimg[(i << (dim-sh))+(j << sh)] = temp[k]; } } for (i=0; i < 1 << dim*2; i++) if (fimg[i] < -threshold) fimg[i] += threshold; else if (fimg[i] > threshold) fimg[i] -= threshold; else fimg[i] = 0; for (size = 2; size <= 1 << dim; size <<= 1) for (sh=dim; sh >= 0; sh -= dim) for (i=0; i < size; i++) { for (j=k=0; j < size; j++, k+=2) { if (k == size) k = 1; temp[k] = fimg[(i << (dim-sh))+(j << sh)]; } for (m=0; m < size; m++) temp[m] *= (m & 1) ? wlet[0] : 1/wlet[0]; for (k=3; k > 0; k-=2) { temp[-1] = temp[1]; for (m=0; m < size; m+=2) temp[m] -= wlet[k+1] * (temp[m-1] + temp[m+1]); temp[size] = temp[size-2]; for (m=1; m < size; m+=2) temp[m] -= wlet[k] * (temp[m-1] + temp[m+1]); } for (j=0; j < size; j++) fimg[(i << (dim-sh))+(j << sh)] = temp[j]; } for (row=0; row < iheight; row++) for (col=0; col < iwidth; col++) image[row*iwidth+col][c] = CLIP(fimg[(row << dim)+col] + 0.5); d3337 1 d3342 4 a3345 3 diff = BAYER(row,col) - avg; if (diff < -threshold/M_SQRT2) diff += threshold/M_SQRT2; else if (diff > threshold/M_SQRT2) diff -= threshold/M_SQRT2; d3347 1 a3347 1 BAYER(row,col) = CLIP(avg + diff + 0.5); @ 1.370 log @Support the Canon EOS-1D Mark III. @ text @d25 1 a25 1 #define VERSION "8.62" d98 1 a98 1 unsigned shot_order, kodak_cbpp, filters, unique_id, *oprof; d4186 1 a4186 1 unsigned kodak, entries, tag, type, len, save; d4206 4 d4719 2 a5920 2 if (!strncmp (make,"OLYMPUS",7)) height += height & 1; a6470 15 } else if (!strcmp(model,"E-1") || !strcmp(model,"E-400")) { filters = 0x61616161; maximum = 0xfff0; } else if (!strcmp(model,"E-10") || !strncmp(model,"E-20",4)) { maximum = 0xffc0; black <<= 2; } else if (!strcmp(model,"E-300") || !strcmp(model,"E-500")) { width -= 20; maximum = 0xfc30; if (load_raw == &CLASS unpacked_load_raw) black = 0; } else if (!strcmp(model,"E-330")) { width -= 30; d6477 21 a6497 6 load_raw = &CLASS olympus_cseries_load_raw; if (!strcmp(model,"C5050Z") || !strcmp(model,"C8080WZ")) filters = 0x16161616; if (!strncmp(model,"SP5",3)) filters = 0x49494949; @ 1.369 log @As the Pentax K10D was cropped, do likewise for the Samsung GX10. @ text @d25 1 a25 1 #define VERSION "8.61" d870 2 d4146 1 a4146 1 i = len == 582 ? 50 : len == 653 ? 68 : len == 796 ? 126 : 0; d6046 6 @ 1.368 log @Found larger JPEG thumbs for Nikon D100,D1H,D1X,D2H,D2X,E5000,E5700. @ text @d5887 1 a5887 1 if (!strcmp(model,"K10D")) { /* Camera DNGs are not cropped! */ @ 1.367 log @Reworded the copyright notice to avoid mention of the GPL. @ text @d25 1 a25 1 #define VERSION "8.60" d3917 2 d4021 4 d4326 1 a4326 1 int CLASS parse_tiff_ifd (int base, int level) d4437 1 a4437 1 if (parse_tiff_ifd (base, level+1)) break; d4615 1 a4615 1 parse_tiff_ifd (base, level+1); d4643 1 a4643 1 parse_tiff_ifd (-sony_offset, level); d4677 1 a4677 1 if (parse_tiff_ifd (base, 0)) break; @ 1.366 log @Replaced bilateral filter with wavelet denoising. Fixed incompatibility between "-f" and "-p". Fixed strange color casts with the Polaroid x530. Added Adobe matrices for the Nikon D40 and Pentax K10D. @ text @d8 12 a19 13 Attention! Some parts of this program are restricted under the terms of the GNU General Public License. Such code is enclosed in "BEGIN GPL BLOCK" and "END GPL BLOCK" declarations. Any code not declared GPL is free for all uses. Starting in Revision 1.237, the code to support Foveon cameras is under GPL. To lawfully redistribute dcraw.c, you must either (a) include full source code for all executable files containing restricted functions, (b) remove these functions, re-implement them, or copy them from an earlier, non-GPL Revision of dcraw.c, or (c) purchase a license from the author. d2385 1 a2385 1 /* BEGIN GPL BLOCK */ d3022 1 a3022 1 /* END GPL BLOCK */ @ 1.365 log @Added a color matrix for the Fuji S6000fd. Set aspect ratio for the Kodak DC20 and DC25. @ text @d26 1 a26 1 #define VERSION "8.54" d106 1 a106 1 int black, maximum, raw_color, use_gamma; d111 2 a112 2 float bright=1, user_mul[4]={0,0,0,0}, sigma_d=0, sigma_r=0; int four_color_rgb=0, document_mode=0, highlight=0; d2681 5 a2688 7 else { #define LAST(x,y) last[(i+x)%3][(c+y)%3] for (i=0; i < 3; i++) FORC3 diag[c][i] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1); #undef LAST FORC3 div[c] = diag[c][0]*0.3127 + diag[c][1]*0.329 + diag[c][2]*0.3583; } d3270 97 d3369 1 a3369 1 int row, col, x, y, c, val, sum[8]; a3372 1 maximum -= black; d3375 2 a3376 2 for (row=0; row < height-7; row += 8) for (col=0; col < width-7; col += 8) { d3381 1 a3381 1 val = image[y*width+x][c]; d3383 1 a3384 1 if (val > maximum-25) goto skip_block; d3414 3 d3426 1 a3426 1 fprintf (stderr,_("Scaling with black %d, multipliers"), black); d3430 2 a3431 2 for (row=0; row < height; row++) for (col=0; col < width; col++) d3433 1 a3433 1 val = image[row*width+col][c]; d3437 1 a3437 1 image[row*width+col][c] = CLIP(val); d3439 23 d3463 2 a3464 4 if (four_color_rgb) { colors++; FORC3 rgb_cam[c][3] = rgb_cam[c][1] /= 2; } else { a3815 57 /* Bilateral Filtering was developed by C. Tomasi and R. Manduchi. */ void CLASS bilateral_filter() { float (**window)[7], *kernel, scale_r, elut[1024], sum[5]; int c, i, wr, ws, wlast, row, col, y, x; unsigned sep; if (verbose) fprintf (stderr,_("Bilateral filtering...\n")); wr = ceil(sigma_d*2); /* window radius */ ws = 2*wr + 1; /* window size */ window = (float (**)[7]) calloc ((ws+1)*sizeof *window + ws*width*sizeof **window + ws*sizeof *kernel, 1); merror (window, "bilateral_filter()"); for (i=0; i <= ws; i++) window[i] = (float (*)[7]) (window+ws+1) + i*width; kernel = (float *) window[ws] + wr; for (i=-wr; i <= wr; i++) kernel[i] = 256 / (2*SQR(sigma_d)) * i*i + 0.25; scale_r = 256 / (2*SQR(sigma_r)); for (i=0; i < 1024; i++) elut[i] = exp (-i/256.0); for (wlast=-1, row=0; row < height; row++) { while (wlast < row+wr) { wlast++; for (i=0; i <= ws; i++) /* rotate window rows */ window[(ws+i) % (ws+1)] = window[i]; if (wlast < height) for (col=0; col < width; col++) { FORCC window[ws-1][col][c] = image[wlast*width+col][c]; cam_to_cielab (image[wlast*width+col], window[ws-1][col]+4); } } for (col=0; col < width; col++) { memset (sum, 0, sizeof sum); for (y=-wr; y <= wr; y++) if ((unsigned)(row+y) < height) for (x=-wr; x <= wr; x++) if ((unsigned)(col+x) < width) { sep = ( SQR(window[wr+y][col+x][4] - window[wr][col][4]) + SQR(window[wr+y][col+x][5] - window[wr][col][5]) + SQR(window[wr+y][col+x][6] - window[wr][col][6]) ) * scale_r + kernel[y] + kernel[x]; if (sep < 1024) { FORCC sum[c] += elut[sep] * window[wr+y][col+x][c]; sum[4] += elut[sep]; } } FORCC image[row*width+col][c] = sum[c]/sum[4]; } } free (window); } d4029 1 a4029 1 while ((c = fgetc(ifp))) d5512 2 d5587 1 a5587 1 { 28402,-6651,-983,-14699,32553,6467,-1746,1571,25283 } }, d5758 1 a5758 1 profile_length = 0; d6792 1 a6792 1 int mix_green, row, col, c, i, j, k; a6879 1 mix_green = rgb_cam[1][1] == rgb_cam[1][3]; a6893 2 else if (mix_green) img[1] = (img[1] + img[3]) >> 1; d6896 1 a6896 1 if (colors == 4 && (output_color || mix_green)) colors = 3; d7161 2 a7162 2 int timestamp_only=0, thumbnail_only=0, identify_only=0, write_to_stdout=0; int half_size=0, use_fuji_rotate=1, quality, i, c; d7195 1 a7210 1 puts(_("-B Apply bilateral filter to smooth noise")); d7220 2 a7221 2 if ((cp = strchr (sp="BbrktqsH", opt))) for (i=0; i < "21411111"[cp-sp]-'0'; i++) d7227 1 a7227 2 case 'B': sigma_d = atof(argv[arg++]); sigma_r = atof(argv[arg++]); break; d7368 1 a7368 1 shrink = half_size && filters; a7417 2 height = iheight; width = iwidth; d7426 1 a7426 1 if (shrink) filters = 0; a7434 1 if (sigma_d > 0 && sigma_r > 0) bilateral_filter(); d7437 3 @ 1.364 log @The last version broke 16-bit PPM byte order. @ text @d26 1 a26 1 #define VERSION "8.53" d4163 2 a4164 1 "","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65" }; d5351 2 d5529 1 a5529 1 { "Panasonic DMC-FZ50", 0, d5531 1 a5531 1 { "Panasonic DMC-L1", 0, d5533 1 a5533 1 { "Panasonic DMC-LC1", 0, d5535 1 a5535 1 { "Panasonic DMC-LX1", 0, d5537 1 a5537 1 { "Panasonic DMC-LX2", 0, d6488 1 d6491 1 @ 1.363 log @If the JPEG thumbnail has no EXIF table, add one. Built a color matrix for the Canon PowerShot S3 IS. @ text @d26 1 a26 1 #define VERSION "8.52" d7086 1 a7086 1 if (output_bps == 16 && !output_tiff && th.order == 0x4949) @ 1.362 log @Added the Olympus SP510UZ. @ text @d26 1 a26 1 #define VERSION "8.50" d1220 1 a1220 9 void CLASS jpeg_thumb (FILE *tfp) { char *thumb = (char *) malloc (thumb_length); merror (thumb, "jpeg_thumb()"); fread (thumb, 1, thumb_length, ifp); thumb[0] = 0xff; fwrite (thumb, 1, thumb_length, tfp); free (thumb); } d5320 2 d5804 1 a5804 1 if (!is_raw) return; a6654 2 if (flip == -1) flip = tiff_flip; if (flip == -1) flip = 0; d6666 3 d6978 72 a7049 1 #define TOFF(ptr) ((char *)(&(ptr)) - (char *)(&th)) a7053 1 struct tm *t; d7056 1 a7056 1 int i, c, row, col, psize=0, soff, rstep, cstep; a7063 39 memset (&th, 0, sizeof th); th.order = htonl(0x4d4d4949) >> 16; th.magic = 42; th.ifd = 10; tiff_set (&th.ntag, 256, 4, 1, width); tiff_set (&th.ntag, 257, 4, 1, height); tiff_set (&th.ntag, 258, 3, colors, output_bps); if (colors > 2) th.tag[th.ntag-1].val.i0 = TOFF(th.bps); FORC4 th.bps[c] = output_bps; tiff_set (&th.ntag, 259, 3, 1, 1); tiff_set (&th.ntag, 262, 3, 1, 1 + (colors > 1)); tiff_set (&th.ntag, 271, 2, 64, TOFF(th.make)); tiff_set (&th.ntag, 272, 2, 72, TOFF(th.model)); if (oprof) psize = ntohl(oprof[0]); tiff_set (&th.ntag, 273, 4, 1, sizeof th + psize); tiff_set (&th.ntag, 277, 3, 1, colors); tiff_set (&th.ntag, 278, 4, 1, height); tiff_set (&th.ntag, 279, 4, 1, height*width*colors*output_bps/8); tiff_set (&th.ntag, 305, 2, 32, TOFF(th.soft)); tiff_set (&th.ntag, 306, 2, 20, TOFF(th.date)); tiff_set (&th.ntag, 34665, 4, 1, TOFF(th.nexif)); if (psize) tiff_set (&th.ntag, 34675, 7, psize, sizeof th); tiff_set (&th.nexif, 33434, 5, 1, TOFF(th.rat[0])); tiff_set (&th.nexif, 33437, 5, 1, TOFF(th.rat[2])); tiff_set (&th.nexif, 34855, 3, 1, iso_speed); tiff_set (&th.nexif, 37386, 5, 1, TOFF(th.rat[4])); for (i=0; i < 6; i++) th.rat[i] = 1000000; th.rat[0] *= shutter; th.rat[2] *= aperture; th.rat[4] *= focal_len; strncpy (th.make, make, 64); strncpy (th.model, model, 64); strcpy (th.soft, "dcraw v"VERSION); t = gmtime (×tamp); sprintf (th.date, "%04d:%02d:%02d %02d:%02d:%02d", t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); d7065 1 d7067 2 a7068 2 if (psize) fwrite (oprof, psize, 1, ofp); d7236 7 a7303 7 if (user_flip >= 0) flip = user_flip; switch ((flip+3600) % 360) { case 270: flip = 5; break; case 180: flip = 3; break; case 90: flip = 6; } @ 1.361 log @Support the Panasonic DMC-L1, Leica Digilux 3, and Casio EX-Z4. Run remove_zeroes() on most Panasonic and Leica models. Built a color matrix for the Canon PowerShot A610. Support Sinar IA file format. @ text @d26 1 a26 1 #define VERSION "8.49" d5514 2 d6419 1 a6419 1 if (!strcmp(model,"SP500UZ")) @ 1.360 log @Support internationalization if LOCALEDIR is defined. Added stretch() function for cameras with non-square pixels. Support "-h" and "-s" with Sinar 4-shot files. Never append "DNG" to the camera model. @ text @d3 1 a3 1 Copyright 1997-2006 by Dave Coffin, dcoffin a cybercom o net d26 1 a26 1 #define VERSION "8.48" d1665 6 d4952 32 d5324 2 a5325 2 { "Canon PowerShot A610", 0, /* copied from the S60 */ { 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } }, d5532 2 d5665 1 a5665 1 { 6114240, "PENTAX", "Optio S4" ,1 }, /* or S4i */ d5776 2 d6199 1 a6199 1 } else if (!strncmp(model,"Optio S4",8)) { d6344 1 d6347 6 d6357 1 d6365 1 d6372 1 d6378 1 a6391 1 load_raw = &CLASS unpacked_load_raw; d6538 1 a6538 1 } else if (!strcmp(make,"Rollei")) { @ 1.359 log @Added the Kodak DCS200 and Canon PowerShots A620 and S3 IS. @ text @d26 1 a26 1 #define VERSION "8.46" d51 6 d96 1 a96 1 char *ifname, make[64], model[72], model2[64], *meta_data, cdesc[5]; d107 2 a108 1 int iheight, iwidth, shrink, flip, xmag, ymag; d245 1 a245 1 fprintf (stderr, "%s: Out of memory in %s\n", ifname, where); d584 1 a584 1 fprintf (stderr, "%s: decoder table overflow\n", ifname); d1361 1 a1361 1 if (verbose) fprintf (stderr, "Phase One correction...\n"); d1593 2 d1600 8 d1950 1 a1950 1 fprintf (stderr, "%s: incorrect JPEG dimensions\n", ifname); d2403 1 a2403 1 fprintf (stderr, "%s: decoder table overflow\n", ifname); d2562 1 a2562 1 fprintf (stderr, "%s: \"%s\" matrix not found!\n", ifname, name); d2647 1 a2647 1 fprintf (stderr, "Foveon interpolation...\n"); d2673 1 a2673 1 { fprintf (stderr, "%s: Invalid white balance \"%s\"\n", ifname, model2); d3080 1 a3080 1 fprintf (stderr, "Fixed bad pixels at:"); d3111 1 a3111 1 fprintf (stderr, "%s is not a valid PGM file!\n", fname); d3114 1 a3114 1 fprintf (stderr, "%s has the wrong dimensions!\n", fname); d3317 1 a3317 1 fprintf (stderr, "%s: Cannot use camera white balance.\n", ifname); d3331 1 a3331 1 fprintf (stderr, "Scaling with black=%d, pre_mul[] =", black); d3385 1 a3385 1 if (verbose) fprintf (stderr, "Bilinear interpolation...\n"); d3462 1 a3462 1 if (verbose) fprintf (stderr, "VNG interpolation...\n"); d3604 1 a3604 1 if (verbose) fprintf (stderr, "AHD interpolation...\n"); d3709 1 a3709 1 if (verbose) fprintf (stderr, "Bilateral filtering...\n"); d3767 1 a3767 1 if (verbose) fprintf (stderr, "Highlight recovery...\n"); d4267 1 a4267 1 double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num, sx, sy; d4519 2 a4520 4 sx = getrat(); sy = getrat(); if (sx > sy) xmag = sx / sy; else ymag = sy / sx; d4765 1 a4765 1 fprintf (stderr, "Reading metadata from %s...\n", jname); d4773 1 a4773 1 fprintf (stderr, "Failed to read metadata from %s\n", jname); d5646 1 a5646 1 is_raw = raw_color = use_gamma = xmag = ymag = 1; d5776 1 a5776 1 xmag = ymag = 1; a5782 1 strcat (model," DNG"); d5810 2 a5811 2 if (height*2 < width) ymag = 2; if (height > width) xmag = 2; d5819 1 d5828 1 d5952 3 a5954 1 ymag = 2; d6464 1 d6603 1 a6603 1 fprintf (stderr, "%s: You must link dcraw.c with libjpeg!!\n", ifname); d6642 1 a6642 1 fprintf (stderr, "%s has no embedded profile.\n", ifname); d6658 1 a6658 1 fprintf (stderr, "Cannot open %s!\n", output); d6661 1 a6661 1 fprintf (stderr, "Applying color profile...\n"); d6760 2 a6761 2 fprintf (stderr, raw_color ? "Building histograms...\n" : "Converting to %s colorspace...\n", name[output_color-1]); d6796 1 a6796 1 fprintf (stderr, "Rotating image 45 degrees...\n"); d6824 37 d6912 1 a6912 1 char make[64], model[72], soft[32], date[20]; d6941 2 a6942 5 if (flip & 4) { SWAP(height,width); SWAP(ymag,xmag); } ppm = (uchar *) calloc (width, colors*xmag*output_bps/8); d6950 2 a6951 2 tiff_set (&th.ntag, 256, 4, 1, xmag*width); tiff_set (&th.ntag, 257, 4, 1, ymag*height); d6963 2 a6964 2 tiff_set (&th.ntag, 278, 4, 1, ymag*height); tiff_set (&th.ntag, 279, 4, 1, ymag*height*xmag*width*colors*output_bps/8); d6978 1 a6978 1 strncpy (th.model, model, 72); d6991 1 a6991 1 xmag*width, ymag*height, colors, (1 << output_bps)-1, cdesc); d6994 1 a6994 1 colors/2+5, xmag*width, ymag*height, (1 << output_bps)-1); d6996 1 a6996 2 if (output_bps == 8) gamma_lut (lut); d7002 3 a7004 4 FORCC for (i=0; i < xmag; i++) if (output_bps == 8) ppm [(col*xmag+i)*colors+c] = lut[image[soff][c]]; else ppm2[(col*xmag+i)*colors+c] = image[soff][c]; d7006 2 a7007 3 swab (ppm2, ppm2, xmag*width*colors*2); for (i=0; i < ymag; i++) fwrite (ppm, colors*output_bps/8, xmag*width, ofp); d7028 7 d7036 18 a7053 19 fprintf (stderr, "\nRaw Photo Decoder \"dcraw\" v"VERSION "\nby Dave Coffin, dcoffin a cybercom o net" "\n\nUsage: %s [options] file1 file2 ...\n" "\nValid options:" "\n-v Print verbose messages" "\n-c Write image data to standard output" "\n-e Extract embedded thumbnail image" "\n-i Identify files without decoding them" "\n-z Change file dates to camera timestamp" "\n-a Use automatic white balance" "\n-w Use camera white balance, if possible" "\n-r Set raw white balance (four values required)" "\n-b Adjust brightness (default = 1.0)" "\n-k Set black point" "\n-K Subtract dark frame (16-bit raw PGM)" "\n-H [0-9] Highlight mode (0=clip, 1=no clip, 2+=recover)" "\n-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)" "\n-o [0-5] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)" d7055 2 a7056 2 "\n-o Apply output ICC profile from file" "\n-p Apply camera ICC profile from file or \"embed\"" d7058 11 a7068 11 "\n-d Document Mode (no color, no interpolation)" "\n-D Document Mode without scaling (totally raw)" "\n-q [0-3] Set the interpolation quality" "\n-h Half-size color image (twice as fast as \"-q 0\")" "\n-f Interpolate RGGB as four colors" "\n-B Apply bilateral filter to reduce noise" "\n-j Show Fuji Super CCD images tilted 45 degrees" "\n-s [0-99] Select a different raw image from the same file" "\n-4 Write 16-bit linear instead of 8-bit with gamma" "\n-T Write TIFF instead of PPM" "\n\n", argv[0]); a7070 1 d7077 1 a7077 1 fprintf (stderr, "Non-numeric argument to \"-%c\"\n", opt); a7108 2 case 'd': document_mode = 1; break; case 'D': document_mode = 2; break; d7111 2 d7118 1 a7118 1 fprintf (stderr, "Unknown option \"-%c\".\n", opt); d7123 1 a7123 1 fprintf (stderr, "No files to process.\n"); d7128 1 a7128 1 fprintf (stderr, "Will not write an image to the terminal!\n"); d7157 1 a7157 1 fprintf (stderr, "%s has no timestamp.\n", ifname); d7162 1 a7162 1 fprintf (stderr, "%s time set to %d.\n", ifname, (int) timestamp); d7171 1 a7171 1 fprintf (stderr, "%s has no thumbnail.\n", ifname); d7190 10 a7199 5 printf ("\nFilename: %s\n", ifname); printf ("Timestamp: %s", ctime(×tamp)); printf ("Camera: %s %s\n", make, model); printf ("ISO speed: %d\n", (int) iso_speed); printf ("Shutter: "); d7202 8 a7209 6 printf ("%0.1f sec\n", shutter); printf ("Aperture: f/%0.1f\n", aperture); printf ("Focal Length: %0.1f mm\n", focal_len); printf ("Secondary pixels: %s\n", fuji_secondary ? "yes":"no"); printf ("Embedded ICC profile: %s\n", profile_length ? "yes":"no"); printf ("Decodable with dcraw: %s\n", is_raw ? "yes":"no"); d7211 2 a7212 2 printf ("Thumb size: %4d x %d\n", thumb_width, thumb_height); printf ("Full size: %4d x %d\n", raw_width, raw_height); d7214 1 a7214 1 fprintf (stderr, "Cannot decode %s\n", ifname); d7228 9 a7236 4 if (fuji_width && use_fuji_rotate) { fuji_width = (fuji_width - 1 + shrink) >> shrink; iwidth = fuji_width / sqrt(0.5); iheight = (iheight - fuji_width) / sqrt(0.5); a7237 2 iheight *= ymag; iwidth *= xmag; d7240 3 a7242 3 printf ("Image size: %4d x %d\n", width, height); printf ("Output size: %4d x %d\n", iwidth, iheight); printf ("Raw colors: %d", colors); d7244 1 a7244 1 printf ("\nFilter pattern: "); d7249 1 a7249 1 printf ("\nDaylight multipliers:"); d7252 1 a7252 1 printf ("\nCamera multipliers:"); d7257 1 a7257 1 printf ("%s is a %s %s image.\n", ifname, make, model); d7268 1 a7268 1 "Loading %s %s image from %s...\n", make, model, ifname); d7299 1 d7310 1 a7310 1 strcpy (ofname, "standard output"); d7325 1 a7325 1 fprintf (stderr, "Writing data to %s ...\n", ofname); @ 1.358 log @Added the Pentax K10D. @ text @d26 1 a26 1 #define VERSION "8.45" d493 1 a493 1 ushort data[1670], *dp, pixel; d1238 4 a1241 2 char *thumb; colors = thumb_misc >> 5; d1245 1 a1245 1 5 + (thumb_misc >> 6), thumb_width, thumb_height); d1248 1 a1248 1 FORCC putc (thumb[i+thumb_length*c], tfp); d5273 2 d5564 1 a5564 1 char make[12], model[15], withjpeg; d5568 1 d5586 2 d5837 16 d6058 2 d6448 11 @ 1.357 log @Added the Canon PowerShot A610. Added "-K" option for dark-frame subtraction. @ text @d26 1 a26 1 #define VERSION "8.44" d441 1 a441 2 for (irow=row=0; irow < height; irow++) { d443 1 a443 2 for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8) { d960 25 d987 4 a990 5 static const uchar nikon_tree[] = { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, 5,4,3,6,2,7,1,0,8,9,11,10,12 }; int csize, row, col, i, diff; a1004 1 d1006 1 a1006 2 for (col=0; col < raw_width; col++) { d3106 1 d4638 2 d5467 2 d5756 4 d6942 1 a6942 2 if (argc == 1) { d6989 1 a6989 2 switch (opt) { @ 1.356 log @Get the Olympus black level from the ORF metadata. Don't truncate PPM thumbnails. @ text @d26 1 a26 1 #define VERSION "8.43" d476 17 d495 2 a496 3 uchar data[1940], *dp; ushort pixel[1552], *pix; int row, col; d498 10 a507 12 for (row=0; row < height; row++) { fread (data, raw_width * 10 / 8, 1, ifp); for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=10, pix+=8) { pix[0] = (dp[1] << 2) + (dp[0] >> 6); pix[1] = (dp[0] << 4) + (dp[3] >> 4); pix[2] = (dp[3] << 6) + (dp[2] >> 2); pix[3] = (dp[2] << 8) + (dp[5] ); pix[4] = (dp[4] << 2) + (dp[7] >> 6); pix[5] = (dp[7] << 4) + (dp[6] >> 4); pix[6] = (dp[6] << 6) + (dp[9] >> 2); pix[7] = (dp[9] << 8) + (dp[8] ); a508 4 for (col=0; col < width; col++) BAYER(row,col) = (pixel[col] & 0x3ff); for (col=width; col < raw_width; col++) black += pixel[col] & 0x3ff; d510 1 a510 2 if (raw_width > width) black /= (raw_width - width) * height; d512 1 d3049 39 d4284 1 a4284 1 if (!tiff_ifd[ifd].width) { d5246 2 d5555 1 d5793 8 d6902 1 a6902 1 char opt, *ofname, *sp, *cp; d6930 1 d6982 2 d7144 1 @ 1.355 log @Support the Olympus E-400 and Sinar 4-shot files. Updated color matrices from DNG Converter 3.6. Changed "-s" option to support multi-shot cameras. @ text @d26 1 a26 1 #define VERSION "8.42" d1195 3 a1197 1 char *thumb = (char *) malloc (thumb_length); d1620 1 a1620 1 int dwide, row, col, bls=width, ble=raw_width; a1621 2 if (raw_width == 3360) bls += 4; if (raw_width == 3280) ble = bls + 8; a1634 2 for (col=bls; col < ble; col++) black += pixel[col] & 0xfff; a1635 1 if (ble > bls) black /= (ble - bls) * height; d1638 1 d1654 1 d3187 1 a3187 2 int row, col, x, y, c, val; int min[4], max[4], sum[8]; a3192 2 FORC4 min[c] = INT_MAX; FORC4 max[c] = 0; a3201 2 if (min[c] > val) min[c] = val; if (max[c] < val) max[c] = val; d3971 3 d6208 2 a6209 1 } else if (!strcmp(model,"E-1")) { d6212 2 a6213 5 black = 1024; } else if (!strcmp(model,"E-10")) { maximum = 0xfff0; black = 2048; } else if (!strncmp(model,"E-20",4)) { d6215 1 a6215 1 black = 2560; d6220 1 a6222 4 } else if (!strcmp(model,"E-400")) { filters = 0x61616161; maximum = 0xfff0; black = 1552; @ 1.354 log @Found a more reliable way to identify 4775936-byte images. @ text @d26 1 a26 1 #define VERSION "8.41" d108 1 a108 1 int fuji_layout, fuji_secondary, use_secondary=0; d135 1 d879 1 a879 1 if (fuji_secondary && use_secondary) (*rp)++; d894 1 a894 1 if (fuji_secondary && use_secondary) (*rp)--; a1531 1 if (filters && c != MIN(1,tiff_samples-1)) continue; d1537 1 d1552 23 d4276 1 d4557 1 a4557 1 if (raw >= 0) d5154 2 d5230 1 a5230 1 { "FUJIFILM FinePix S9", 0, d5232 6 d5330 2 a5331 2 { "NIKON D80", 0, /* copied from above */ { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, d5376 2 d5396 2 a5397 2 { "PENTAX K100D", 0, { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, d5407 2 a5408 2 { 7970,-2904,-583,-6252,13395,3191,-1641,2282,6864 } }, { "SAMSUNG GX-1S", 0, d5629 1 a5629 1 if (fuji_secondary && use_secondary) d5848 1 d5952 1 a5952 1 data_offset += use_secondary * ( strcmp(model+7," S3Pro") d6133 1 a6133 1 load_raw = &CLASS unpacked_load_raw; d6227 4 d6892 1 a6892 1 "\n-s Use secondary pixels (Fuji Super CCD SR only)" d6902 2 a6903 2 if ((cp = strchr (sp="BbrktqH", opt))) for (i=0; i < "2141111"[cp-sp]-'0'; i++) d6918 1 a6940 1 case 's': use_secondary = 1; break; @ 1.353 log @Updated link to Ting Chen's webpage. @ text @d26 1 a26 1 #define VERSION "8.40" d1075 19 a1093 21 int i, sum[] = { 0, 0 }; uchar tail[952]; fseek (ifp, -sizeof tail, SEEK_END); fread (tail, 1, sizeof tail, ifp); for (i=0; i < sizeof tail; i++) sum[(i>>2) & 1] += tail[i]; if (sum[0] > 4*sum[1]) return; if (sum[1] > 4*sum[0]) { strcpy (make, "OLYMPUS"); strcpy (model, "C740UZ"); return; } sum[0] = sum[1] = 0; for (i=0; i < sizeof tail; i++) sum[i & 1] += tail[i]; if (sum[1] > 4*sum[0] || sum[0]+sum[1] > 216000) { strcpy (make, "PENTAX"); strcpy (model,"Optio 33WR"); } else strcpy (model, "E3200"); d4240 1 @ 1.352 log @Fixed "maximum" for the Canon EOS 5D. Added the Nikon E3200. @ text @d3320 1 a3320 1 described in http://www-ise.stanford.edu/~tingchen/algodep/vargra.html @ 1.351 log @Display the focal length of Canon CRW images. @ text @d26 1 a26 1 #define VERSION "8.39" d1073 1 a1073 6 /* Returns 0 for a Pentax Optio 33WR, 1 for a Nikon E3700, 2 for an Olympus C740UZ. */ int CLASS nikon_3700() d1082 14 a1095 2 if (sum[1] > 4*sum[0]) return 2; return sum[0] > 4*sum[1]; d5779 1 d5870 4 a5873 6 if ((i = nikon_3700()) == 2) { strcpy (make, "OLYMPUS"); strcpy (model, "C740UZ"); } else if (i == 0) { strcpy (make, "PENTAX"); strcpy (model,"Optio 33WR"); @ 1.350 log @Added color matrices from Adobe DNG Converter 3.5. @ text @d4773 4 d6981 1 a6981 1 printf ("Focal Length: %d mm\n", (int) focal_len); @ 1.349 log @Fixed problems with the Panasonic DMC-FZ50 and DMC-LX2. @ text @d26 1 a26 1 #define VERSION "8.38" d5235 2 d5352 1 a5352 1 { 20129,-6819,-1857,-12757,32020,5793,-1219,1356,17788 } }, d5355 2 a5356 2 { "Panasonic DMC-FZ50", 0, /* copied from above */ { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } }, d5361 2 a5362 2 { "Panasonic DMC-LX2", 0, /* copied from above */ { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } }, d5374 1 a5374 1 { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } } @ 1.348 log @Added the Panasonic DMC-FZ50. @ text @d26 1 a26 1 #define VERSION "8.37" d4173 3 d6139 6 d6147 1 a6148 1 width -= 22; d6150 6 a6160 1 filters = 0x16161616; @ 1.347 log @Added the Nikon D80. @ text @d26 1 a26 1 #define VERSION "8.36" d5350 2 d6129 7 @ 1.346 log @Added the Panasonic DMC-LX2. @ text @d26 1 a26 1 #define VERSION "8.35" d5282 2 d5778 3 @ 1.345 log @Added the Canon EOS 400D. @ text @d26 1 a26 1 #define VERSION "8.34" a5235 4 { "LEICA DIGILUX 2", 0, { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } }, { "LEICA D-LUX2", 0, { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } }, d5352 2 d6115 9 a6123 1 if (width == 3880) { a6124 1 maximum = 0xf7f0; d6126 9 a6134 4 } else if (width == 3304) { maximum = 0xf94c; width -= 16; } else maximum = 0xfff0; @ 1.344 log @Improved support for the Nikon D200. @ text @d26 1 a26 1 #define VERSION "8.33" d5725 2 d5751 7 d5767 2 a5768 2 height = raw_height - top_margin; width = raw_width - left_margin; @ 1.343 log @Correctly display long exposure times for CRW files. @ text @d26 1 a26 1 #define VERSION "8.32" d5773 5 @ 1.342 log @Support the Pentax K100D. @ text @d26 1 a26 1 #define VERSION "8.31" d4688 1 a4688 1 int tboff, nrecs, i, c, type, len, save, wbi=-1; d4696 1 a4696 1 for (i=0; i < nrecs; i++) { d4725 1 a4725 1 aperture = pow (2, (get2(),get2())/64.0); d4729 2 @ 1.341 log @Get the correct thumbnail offset and size from Sony ARW files. @ text @d26 1 a26 1 #define VERSION "8.30" d4152 1 a4152 1 double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num; d4399 4 a4402 5 i = get4(); j = get4() * get4(); i *= get4(); if (i > j) xmag = i / j; else ymag = j / i; d5346 2 @ 1.340 log @Clear a "struct tm" before using it. @ text @d26 1 a26 1 #define VERSION "8.29" d3734 1 a3734 1 void CLASS parse_olympus_note (int base) d3741 2 a3742 2 if (tag == 257) thumb_offset = get4(); if (tag == 258) thumb_length = get4(); d3959 5 a3963 1 parse_olympus_note (base); @ 1.339 log @Improved support for the Olympus E-330. @ text @d3989 1 d4785 1 d4958 1 @ 1.338 log @Previous version segfaulted with Fuji photos. @ text @d26 1 a26 1 #define VERSION "8.28" d1611 1 d4523 4 a4526 1 &CLASS unpacked_load_raw : &CLASS eight_bit_load_raw; break; a6115 4 if (fsize <= 15728640) { maximum = 0xfff; load_raw = &CLASS olympus_e300_load_raw; } a6117 1 load_raw = &CLASS olympus_e300_load_raw; @ 1.337 log @Halved memory usage by moving flip logic into write_ppm_tiff(). @ text @d26 1 a26 1 #define VERSION "8.27" d6654 2 @ 1.336 log @Support the Leaf CatchLight with VNG interpolation. Added the Samsung GX-1S. @ text @d26 1 a26 1 #define VERSION "8.26" d6578 4 a6581 29 if (flip & 1) col = width - 1 - col; if (flip & 2) row = height - 1 - row; return (flip & 4) ? col * height + row : row * width + col; } void CLASS flip_image() { int row, col, soff=0, doff, rstep, cstep; INT64 *src, *dest; if (verbose) fprintf (stderr, "Flipping image %c:%c:%c...\n", flip & 1 ? 'H':'0', flip & 2 ? 'V':'0', flip & 4 ? 'T':'0'); src = (INT64 *) image; dest = (INT64 *) calloc (height * width, sizeof *dest); merror (dest, "flip_image()"); doff = flip_index (0, 0); cstep = flip_index (0, 1) - doff; rstep = flip_index (1, 0) - flip_index (0, width); for (row=0; row < height; row++, doff += rstep) for (col=0; col < width; col++, doff += cstep) dest[doff] = src[soff++]; image = (ushort (*)[4]) dest; free (src); if (flip & 4) { SWAP(height,width); SWAP(ymag,xmag); } d6652 1 a6652 1 int i, c, row, col, psize=0; d6654 4 d6714 5 a6718 2 for (row=0; row < height; row++) { for (col=0; col < width; col++) d6721 2 a6722 2 ppm [(col*xmag+i)*colors+c] = lut[image[row*width+col][c]]; else ppm2[(col*xmag+i)*colors+c] = image[row*width+col][c]; a7000 1 if (flip) flip_image(); @ 1.335 log @Udi added &CLASS qualifiers for C++ compatibility. @ text @d26 1 a26 1 #define VERSION "8.25" d154 3 a157 6 */ #define FC(row,col) \ (filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) #define BAYER(row,col) \ image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)] a158 1 /* d188 33 d1580 1 a1580 1 BAYER(row,col) = pixel[col]; d2995 2 a2996 2 (r != row || c != col) && FC(r,c) == FC(row,col)) { tot += BAYER(r,c); d2999 1 a2999 1 BAYER(row,col) = tot/n; d3246 1 a3246 1 unsigned row, col, y, x, c, sum[8]; d3256 3 a3258 2 sum[FC(y,x)] += BAYER(y,x); sum[FC(y,x)+4]++; d3260 2 a3261 1 FORCC if (c != FC(row,col)) d3268 1 a3268 1 int code[8][2][32], *ip, sum[4]; d3275 2 a3276 2 for (row=0; row < 8; row++) for (col=0; col < 2; col++) { d3283 1 a3283 1 color = FC(row+y,col+x); d3290 1 a3290 1 if (c != FC(row,col)) { d3298 1 a3298 1 ip = code[row & 7][col & 1]; d3344 1 a3344 1 int code[8][2][320], *ip, gval[8], gmin, gmax, sum[4]; d3351 6 a3356 3 for (row=0; row < 8; row++) { /* Precalculate for VNG */ for (col=0; col < 2; col++) { ip = code[row][col]; d3362 3 a3364 3 color = FC(row+y1,col+x1); if (FC(row+y2,col+x2) != color) continue; diag = (FC(row,col+1) == color && FC(row+1,col) == color) ? 2:1; d3377 2 a3378 2 color = FC(row,col); if (FC(row+y,col+x) != color && FC(row+y*2,col+x*2) == color) a3383 1 } d3391 1 a3391 1 ip = code[row & 7][col & 1]; d3414 1 a3414 1 color = FC(row,col); d3440 1 d4146 1 a4146 1 double dblack, cc[4][4], cm[4][3], cam_xyz[4][3]; d4287 12 d5342 2 d5469 2 a5470 1 "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One" }; d6059 2 a6060 2 colors = 1; filters = 0; d6062 1 a6062 1 top_margin = 7; left_margin = 18; height = 2033; width = 2016; d6480 1 a6480 1 oprof[oprof[0]/4] = i < 2 ? pbody[i*3+1] : 0x58595a20; d6967 2 a6968 2 for (i=0; i < 32; i+=2) putchar (cdesc[filters >> i & 3]); @ 1.334 log @Replaced gmtime_r() with the more common gmtime(). @ text @d4397 1 a4397 1 load_raw = packed_12_load_raw; d4476 1 a4476 1 unpacked_load_raw : eight_bit_load_raw; break; d4478 1 a4478 1 load_raw = lossless_jpeg_load_raw; break; d4480 1 a4480 1 load_raw = kodak_262_load_raw; break; d4482 1 a4482 1 load_raw = packed_12_load_raw; break; d4485 3 a4487 3 case 2: load_raw = kodak_rgb_load_raw; filters = 0; break; case 6: load_raw = kodak_ycbcr_load_raw; filters = 0; break; case 32803: load_raw = kodak_65000_load_raw; d4507 1 a4507 1 write_thumb = layer_thumb; d4511 1 a4511 1 thumb_load_raw = kodak_thumb_load_raw; d4513 1 a4513 1 write_thumb = ppm_thumb; d4517 1 a4517 1 kodak_ycbcr_load_raw : kodak_rgb_load_raw; d4762 1 a4762 1 write_thumb = rollei_thumb; d4820 1 a4820 1 phase_one_load_raw : phase_one_load_raw_c; d4933 2 a4934 2 if (ver == 6) load_raw = smal_v6_load_raw; if (ver == 9) load_raw = smal_v9_load_raw; d4986 1 a4986 1 write_thumb = foveon_thumb; d5431 1 a5431 1 write_thumb = jpeg_thumb; d5573 1 a5573 1 load_raw = adobe_dng_load_raw_nc; d5575 1 a5575 1 load_raw = adobe_dng_load_raw_lj; d5584 1 a5584 1 lossless_jpeg_load_raw : canon_compressed_load_raw; d5589 1 a5589 1 nikon_compressed_load_raw : nikon_load_raw; d5599 1 a5599 1 load_raw = foveon_load_raw; d5607 1 a5607 1 load_raw = canon_600_load_raw; d5615 1 a5615 1 load_raw = canon_a5_load_raw; d5622 1 a5622 1 load_raw = canon_a5_load_raw; d5628 1 a5628 1 load_raw = canon_a5_load_raw; d5707 1 a5707 1 if (tiff_compress == 34713 && load_raw == nikon_load_raw) d5719 1 a5719 1 load_raw = nikon_e900_load_raw; d5731 1 a5731 1 load_raw = nikon_e900_load_raw; d5741 1 a5741 1 load_raw = nikon_load_raw; d5755 1 a5755 1 load_raw = nikon_e2100_load_raw; d5768 1 a5768 1 load_raw = nikon_e2100_load_raw; d5791 1 a5791 1 load_raw = nikon_e2100_load_raw; d5804 1 a5804 1 load_raw = nikon_load_raw; d5807 1 a5807 1 load_raw = unpacked_load_raw; d5826 1 a5826 1 load_raw = fuji_load_raw; d5833 1 a5833 1 load_raw = minolta_rd175_load_raw; d5842 1 a5842 1 load_raw = unpacked_load_raw; d5847 1 a5847 1 load_raw = packed_12_load_raw; d5854 1 a5854 1 load_raw = packed_12_load_raw; d5872 1 a5872 1 load_raw = unpacked_load_raw; d5882 1 a5882 1 load_raw = eight_bit_load_raw; d5891 1 a5891 1 load_raw = packed_12_load_raw; d5900 1 a5900 1 load_raw = packed_12_load_raw; d5907 1 a5907 1 load_raw = eight_bit_load_raw; d5918 1 a5918 1 load_raw = unpacked_load_raw; d5924 1 a5924 1 load_raw = unpacked_load_raw; d5930 1 a5930 1 load_raw = eight_bit_load_raw; d5934 1 a5934 1 load_raw = eight_bit_load_raw; d5938 2 a5939 1 load_raw = (fsize < 7500000) ? eight_bit_load_raw : unpacked_load_raw; d5944 1 a5944 1 load_raw = unpacked_load_raw; d5952 2 a5953 1 load_raw = (fsize < 2000000) ? eight_bit_load_raw : unpacked_load_raw; d5961 1 a5961 1 load_raw = unpacked_load_raw; d5966 2 a5967 1 load_raw = (fsize < 10000000) ? eight_bit_load_raw : unpacked_load_raw; d5973 1 a5973 1 load_raw = unpacked_load_raw; d5987 1 a5987 1 load_raw = imacon_full_load_raw; d5990 1 a5990 1 load_raw = unpacked_load_raw; d6001 1 a6001 1 load_raw = unpacked_load_raw; d6007 1 a6007 1 load_raw = leaf_hdr_load_raw; d6048 1 a6048 1 load_raw = unpacked_load_raw; d6065 1 a6065 1 load_raw = olympus_e300_load_raw; d6069 1 a6069 1 load_raw = olympus_e300_load_raw; d6074 1 a6074 1 load_raw = nikon_e2100_load_raw; d6076 1 a6076 1 load_raw = olympus_cseries_load_raw; d6087 1 a6087 1 load_raw = packed_12_load_raw; d6093 1 a6093 1 load_raw = sony_load_raw; d6101 1 a6101 1 load_raw = sony_load_raw; d6108 1 a6108 1 load_raw = sony_arw_load_raw; d6142 2 a6143 2 if (load_raw == eight_bit_load_raw) load_raw = kodak_easy_load_raw; d6162 1 a6162 1 load_raw = kodak_easy_load_raw; d6168 1 a6168 1 load_raw = kodak_radc_load_raw; d6174 1 a6174 1 load_raw = kodak_radc_load_raw; d6179 2 a6180 2 load_raw = (tiff_compress == 7) ? kodak_jpeg_load_raw : kodak_dc120_load_raw; d6186 1 a6186 1 load_raw = kodak_radc_load_raw; d6204 1 a6204 1 load_raw = rollei_load_raw; d6211 1 a6211 1 load_raw = eight_bit_load_raw; d6218 1 a6218 1 load_raw = eight_bit_load_raw; d6223 1 a6223 1 load_raw = eight_bit_load_raw; d6227 1 a6227 1 load_raw = unpacked_load_raw; d6232 1 a6232 1 load_raw = casio_qv5700_load_raw; d6237 1 a6237 1 load_raw = packed_12_load_raw; d6244 1 a6244 1 load_raw = packed_12_load_raw; d6251 1 a6251 1 load_raw = packed_12_load_raw; d6258 1 a6258 1 load_raw = packed_12_load_raw; d6265 1 a6265 1 load_raw = packed_12_load_raw; d6272 1 a6272 1 load_raw = packed_12_load_raw; d6279 1 a6279 1 load_raw = packed_12_load_raw; d6284 1 a6284 1 load_raw = unpacked_load_raw; d6287 1 a6287 1 load_raw = nucore_load_raw; d6305 1 a6305 1 if (load_raw == kodak_jpeg_load_raw) { d6850 1 a6850 1 write_fun = write_ppm_tiff; d6867 1 a6867 1 if (load_raw == kodak_ycbcr_load_raw) { d6972 1 a6972 1 if (write_fun == jpeg_thumb) d6974 1 a6974 1 else if (output_tiff && write_fun == write_ppm_tiff) @ 1.333 log @New "-T" option provides TIFF output with metadata and ICC profile. Support old Leaf cameras, plus new and obsolete Leaf image formats. Added camera WB for the Imacon Ixpress and Kodak P850/P880. @ text @d6622 1 a6622 1 struct tm t; d6665 1 a6665 1 gmtime_r (×tamp, &t); d6667 1 a6667 1 t.tm_year+1900,t.tm_mon+1,t.tm_mday,t.tm_hour,t.tm_min,t.tm_sec); @ 1.332 log @Support Kodak NC2000 images compressed by Photo Mechanic. @ text @d26 2 d93 1 a93 1 unsigned shot_order, kodak_cbpp, filters, unique_id; d97 1 a97 1 int tiff_nifds, tiff_flip, tiff_bps, tiff_compress; d106 2 a107 1 int verbose=0, use_auto_wb=0, use_camera_wb=0, output_color=1; a115 1 void write_ppm(FILE *); d413 1 a413 1 fread (data, 1120, 1, ifp); d427 1 a427 1 for (col=width; col < 896; col++) d431 2 a432 1 black = black / ((896 - width) * height) - 4; d785 1 a785 1 ushort *outp=jh->row; d789 3 a791 1 if (jrow) get2(); /* Eat the FF Dx marker */ d1129 1 d1486 1 d1489 1 a1489 1 void CLASS leaf_full_load_raw() d1492 1 a1492 1 int r, c, row, col; d1495 8 a1502 3 merror (pixel, "leaf_full_load_raw()"); for (r=0; r < height-32; r+=32) FORC3 for (row=r; row < r+32; row++) { d1504 1 d1506 2 a1507 1 image[row*width+col][c] = pixel[col]; d1509 1 d1511 4 d1545 1 d3425 9 a3433 5 for (i=0; i < 3; i++) { for (xyz[i]=0.5, c=0; c < colors; c++) xyz[i] += xyz_cam[i][c] * cam[c]; xyz[i] = cbrt[CLIP((int) xyz[i])]; } d3900 6 a3905 2 if (tag == 0xf00 && len == 614 && type == 7) { fseek (ifp, 176, SEEK_CUR); d3931 1 d3993 3 a3995 3 { { 2.0564, -0.7932, -0.2632 }, { -0.2118, 1.2490, -0.0372 }, { -0.0152, -0.1405, 1.1556 } }; d4008 3 a4010 1 static const char *mod[] = { "Aptus","Valeo","Volare" }; d4015 2 a4016 3 fread (data, 1, 8, ifp); if (strcmp(data,"PKTS")) break; if (!make[0]) strcpy (make, "Leaf"); d4028 4 a4031 5 if (!strcmp(data,"CaptProf_serial_number")) { fread (data, 1, 40, ifp); for (i=0; i < sizeof mod / sizeof *mod; i++) if (data[0] == mod[i][0] && data[1] == toupper(mod[i][1])) sprintf (model, "%s %d", mod[i], atoi(data+2)); d4051 1 a4051 1 if (!strcmp(data,"NeutObj_neutrals")) { d4073 31 d4190 1 d4198 3 d4202 1 a4202 1 tiff_ifd[ifd].offset = level ? ftell(ifp) : get4(); d4240 4 d4250 3 d4255 2 d4295 3 a4297 1 fseek (ifp, 178, SEEK_CUR); a4429 31 void CLASS parse_kodak_ifd (int base) { unsigned entries, tag, type, len, save; int i, c, wbi=-2, wbtemp=6500; float mul[3], num; entries = get2(); if (entries > 1024) return; while (entries--) { tiff_get (base, &tag, &type, &len, &save); if (tag == 1020) wbi = getint(type); if (tag == 1021 && len == 72) { /* WB set in software */ fseek (ifp, 40, SEEK_CUR); FORC3 cam_mul[c] = 2048.0 / get2(); wbi = -2; } if (tag == 2118) wbtemp = getint(type); if (tag == 2130 + wbi) FORC3 mul[c] = getreal(type); if (tag == 2140 + wbi && wbi >= 0) FORC3 { for (num=i=0; i < 4; i++) num += getreal(type) * pow (wbtemp/100.0, i); cam_mul[c] = 2048 / (num * mul[c]); } if (tag == 2317) linear_table (len); if (tag == 6020) iso_speed = getint(type); fseek (ifp, save, SEEK_SET); } } a4444 4 if (!dng_version && !strncmp(make,"Kodak",5)) { fseek (ifp, 12+base, SEEK_SET); parse_kodak_ifd (base); } d4477 1 a4477 1 case 6: case 7: d5182 2 d5417 2 a5418 1 { 33292868, "Sinar", "" ,0 } }; d5436 1 a5536 2 parse_mos(8); parse_mos(3472); d5604 1 a5818 1 data_offset += (top_margin*raw_width + left_margin) * 2; d5976 2 a5977 3 data_offset = (2048 * 16 + 28) * 2; height -= 16; width -= 28; a5985 1 data_offset += (top_margin*raw_width + left_margin) * 2; a6000 2 if (tiff_compress == 99) load_raw = lossless_jpeg_load_raw; d6002 33 a6034 5 if (filters == 0) { strcpy (model, "Volare"); load_raw = leaf_full_load_raw; maximum = 0xffff; raw_color = 0; d6038 1 a6038 1 data_offset += 12; d6326 1 a6326 1 cmsHPROFILE hInProfile=NULL, hOutProfile; d6328 2 d6344 15 a6358 2 hOutProfile = output ? cmsOpenProfileFromFile (output, "r") : cmsCreate_sRGBProfile(); d6378 7 d6389 1 a6389 1 static const double wgd65_rgb[3][3] = d6394 3 a6396 3 { { 0.522966, 0.346773, 0.130274 }, { 0.089210, 0.862705, 0.048090 }, { 0.017725, 0.109450, 0.872912 } }; d6398 1 a6398 1 { adobe_rgb, wgd65_rgb, prophoto_rgb, xyz_rgb }; d6400 17 a6416 1 { "sRGB", "Adobe 1998 RGB", "Wide Gamut D65", "ProPhoto D65", "XYZ" }; d6419 40 a6458 7 raw_color |= colors == 1 || output_color < 1 || output_color > 5; if (!raw_color) if (output_color > 1) for (i=0; i < 3; i++) for (j=0; j < colors; j++) for (out_cam[i][j] = k=0; k < 3; k++) out_cam[i][j] += out_rgb[output_color-2][i][k] * rgb_cam[k][j]; d6463 1 a6463 1 mix_green = raw_color && rgb_cam[1][1] == rgb_cam[1][3]; d6465 12 a6476 4 for (row=0; row < height; row++) for (col=0; col < width; col++) { img = image[row*width+col]; if (document_mode && filters) a6479 5 else if (!raw_color) { FORC3 for (out[c]=i=0; i < colors; i++) out[c] += img[i] * out_cam[c][i]; FORC3 img[c] = CLIP((int) out[c]); } d6557 1 a6557 1 void CLASS write_ppm (FILE *ofp) d6559 1 a6559 2 uchar *ppm, lut[0x10000]; int perc, c, val, total, i, row, col; a6561 10 ppm = (uchar *) calloc (width, colors*xmag); merror (ppm, "write_ppm()"); if (colors > 3) fprintf (ofp, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL 255\nTUPLTYPE %s\nENDHDR\n", xmag*width, ymag*height, colors, cdesc); else fprintf (ofp, "P%d\n%d %d\n255\n", colors/2+5, xmag*width, ymag*height); a6581 8 for (row=0; row < height; row++) { for (col=0; col < width; col++) FORCC for (i=0; i < xmag; i++) ppm[(col*xmag+i)*colors+c] = lut[image[row*width+col][c]]; for (i=0; i < ymag; i++) fwrite (ppm, colors*xmag, width, ofp); } free (ppm); d6584 21 a6604 1 void CLASS write_ppm16 (FILE *ofp) d6606 1 a6606 2 int row, col, c; ushort *ppm; d6608 66 a6673 3 ppm = (ushort *) calloc (width, 2*colors); merror (ppm, "write_ppm16()"); if (colors > 3) d6676 1 a6676 1 width, height, colors, 65535, cdesc); d6679 1 a6679 1 colors/2+5, width, height, 65535); d6681 2 d6685 8 a6692 2 FORCC ppm[col*colors+c] = htons(image[row*width+col][c]); fwrite (ppm, 2*colors, width, ofp); a6696 38 void CLASS write_psd (FILE *ofp) { char head[] = { '8','B','P','S', /* signature */ 0,1,0,0,0,0,0,0, /* version and reserved */ 0,3, /* number of channels */ 0,0,0,0, /* height, big-endian */ 0,0,0,0, /* width, big-endian */ 0,16, /* 16-bit color */ 0,3, /* mode (1=grey, 3=rgb) */ 0,0,0,0, /* color mode data */ 0,0,0,0, /* image resources */ 0,0,0,0, /* layer/mask info */ 0,0 /* no compression */ }; int hw[2], psize, row, col, c; ushort *buffer, *pred; hw[0] = htonl(height); /* write the header */ hw[1] = htonl(width); memcpy (head+14, hw, sizeof hw); head[13] = head[25] = colors; fwrite (head, 40, 1, ofp); psize = height*width; buffer = (ushort *) calloc (colors, psize*2); merror (buffer, "write_psd()"); pred = buffer; for (row=0; row < height; row++) for (col=0; col < width; col++) { FORCC pred[c*psize] = htons(image[row*width+col][c]); pred++; } fwrite(buffer, psize*2, colors, ofp); free (buffer); } a6705 1 void (*write_image)(FILE *) = write_ppm; d6716 1 a6716 1 "\nRaw Photo Decoder \"dcraw\" v8.23" d6745 2 a6746 3 "\n-2 Write 8-bit non-linear PPM (default)" "\n-4 Write 16-bit linear PPM" "\n-3 Write 16-bit linear PSD (Adobe Photoshop)" a6792 1 case 'n': highlight = 1; break; d6794 2 a6795 5 case '2': write_image = write_ppm; break; case '4': write_image = write_ppm16; break; case '3': write_image = write_psd; break; d6820 1 d6847 1 a6847 1 write_fun = write_image; d6879 1 d6905 2 a6906 4 if (write_fun == write_ppm) { iheight *= ymag; iwidth *= xmag; } d6971 2 a6972 2 else if (write_fun == write_psd) write_ext = ".psd"; d6998 1 @ 1.331 log @Added the Sony DSLR-A100, Minolta DiMAGE G530, and Sinar 4080x4080. Support software white balance for Kodak DSLRs. Correctly decode Phase One IIQ Small images. @ text @d1866 1 a1866 1 unsigned row, col, icol; d1875 4 a1878 5 icol = col - left_margin; if (icol < width) BAYER(row,icol) = (ushort) curve[pixel[col]]; else black += curve[pixel[col]]; d1889 48 d4432 18 a4449 14 if (raw >= 0) { if (tiff_compress < 2) load_raw = tiff_bps > 8 ? unpacked_load_raw : eight_bit_load_raw; if (tiff_compress/2 == 3) load_raw = lossless_jpeg_load_raw; if (tiff_compress == 32773) load_raw = packed_12_load_raw; if (tiff_compress == 65000) switch (tiff_ifd[raw].phint) { case 2: load_raw = kodak_rgb_load_raw; filters = 0; break; case 6: load_raw = kodak_ycbcr_load_raw; filters = 0; break; case 32803: load_raw = kodak_65000_load_raw; } } d6544 1 a6544 1 "\nRaw Photo Decoder \"dcraw\" v8.22" @ 1.330 log @Fixed the filter pattern on the Micron 2010. @ text @d1450 2 d1468 2 d2053 20 d3677 1 a3677 1 unsigned ver97=0, serial=0, i; d3687 1 a3687 3 if (!strncmp (buf,"KC" ,2) || /* these aren't TIFF format */ !strncmp (buf,"KDK" ,3) || !strncmp (buf,"MLY" ,3) || d3691 12 d3997 2 d4094 4 d4255 4 a4258 1 fseek (ifp, get4()+base, SEEK_SET); d4311 1 a4311 4 int i, c, wbi=-2, wbtemp; char line[128]; static const char *wbs[] = { "Auto","Daylight","Tungsten","Fluorescent","Flash" }; d4318 7 a4324 11 if (tag == 1009) while ((int) len > 0) { fgets (line, 128, ifp); len -= strlen(line) + 1; if (!strncmp (line, "White bal", 9)) { wbtemp = atoi (line + strlen(line) - 5); if (wbtemp < 1000) wbtemp = 6500; for (i=0; i < 5; i++) if (strstr (line, wbs[i])) wbi = i-1; } } a4336 1 if (wbi == -1) cam_mul[0] = -1; d4431 1 a4431 1 void CLASS parse_minolta() d4435 4 a4438 2 fseek (ifp, 4, SEEK_SET); offset = get4() + 8; d4440 2 a4441 1 tag = get4(); d4456 1 a4461 1 data_offset = offset; d4963 2 d5045 1 a5045 1 { "KODAK NC2000F", 0, /* DJC */ d5093 4 d5177 2 d5183 2 d5187 2 d5210 3 a5212 1 { 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } } d5323 2 a5324 1 { 12582980, "Sinar", "" ,0 } }; d5372 2 a5373 1 fseek (ifp, 4 + get2(), SEEK_SET); d5431 1 a5431 1 parse_minolta(); d5459 2 d5741 1 a5741 1 } else if (!strcmp(model,"Digital Camera KD-400Z")) { a5744 2 data_offset = 4034; fseek (ifp, 2032, SEEK_SET); d5746 1 a5746 5 } else if (!strcmp(model,"Digital Camera KD-510Z")) { data_offset = 4032; pre_mul[0] = 1.297; pre_mul[2] = 1.438; fseek (ifp, 2032, SEEK_SET); d5759 2 a5760 1 sprintf (model, "DYNAX %s", model+6 + (model[0]=='M')); a5764 4 data_offset = 5056; pre_mul[0] = 1.602; pre_mul[2] = 1.441; fseek (ifp, 2078, SEEK_SET); a5767 2 data_offset = 4016; fseek (ifp, 1936, SEEK_SET); a5772 2 data_offset = 4032; fseek (ifp, 2030, SEEK_SET); d5776 1 a5781 5 FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2(); } if (pre_mul[0] == 1 && pre_mul[2] == 1) { pre_mul[0] = 1.42; pre_mul[2] = 1.25; d5986 4 d5994 1 a5994 1 if (!strcmp(model,"NC2000F")) { d6043 1 a6043 1 } else if (!strcmp(model,"Digital Camera 40")) { d6493 1 a6493 1 "\nRaw Photo Decoder \"dcraw\" v8.21" @ 1.329 log @Added the Sony XCD-SX910CR and Micron 2010 sensors. Added camera WB for the Kodak DCS Pro SLR models. After scale_colors(), use "65535" instead of "maximum". @ text @d5055 2 d5824 1 d6450 1 a6450 1 "\nRaw Photo Decoder \"dcraw\" v8.20" @ 1.328 log @Changed the "-H" option so the user can control color spread. @ text @d3326 1 a3326 1 r = (float) i / maximum; d3953 10 a4170 1 case 2317: d4172 1 a4172 6 if (len > 0x1000) len = 0x1000; read_shorts (curve, len); for (i=len; i < 0x1000; i++) curve[i] = curve[i-1]; maximum = curve[0xfff]; d4265 39 d4321 1 a4321 1 parse_tiff_ifd (base, 2); d5240 3 d5811 14 a6186 1 maximum = 0xffff; d6447 1 a6447 1 "\nRaw Photo Decoder \"dcraw\" v8.19" @ 1.327 log @Added pointer casts for C++ compatibility. @ text @d3515 1 a3515 1 #define SCALE (8 >> shrink) d3518 1 a3518 1 float *map, sum, wgt; d3527 2 a3528 1 FORCC hsat[c] = 31000 * pre_mul[c]; d3552 1 a3552 1 for (spread = 100; spread--; ) { d3566 1 a3566 1 map[mrow*wide+mcol] = -sum / count * (15/16.0) - (1/16.0); d6279 1 d6388 1 a6388 1 "\nRaw Photo Decoder \"dcraw\" v8.18" d6402 1 a6402 1 "\n-H [0-2] Highlight mode (0=clip, 1=no clip, 2=recover)" @ 1.326 log @Greatly improved the highlight recovery. @ text @d648 1 a648 1 pixel = calloc (raw_width*8, sizeof *pixel); d759 1 a759 1 jh->row = calloc (jh->wide*jh->clrs, 2); d901 1 a901 1 pixel = calloc (raw_width * tiff_samples, sizeof *pixel); d932 1 a932 1 curve = calloc (csize, sizeof *curve); d1124 1 a1124 1 pixel = calloc (raw_width, sizeof *pixel); d1144 1 a1144 1 char *thumb = malloc (thumb_length); d1154 1 a1154 1 char *thumb = malloc (thumb_length); d1167 1 a1167 1 thumb = malloc (thumb_length*colors); d1180 1 a1180 1 ushort *thumb = calloc (size, 2); d1231 1 a1231 1 mrow = calloc (nc*wide, sizeof *mrow); d1359 1 a1359 1 yval[0] = calloc (head[1]*head[3] + head[2]*head[4], 6); d1401 1 a1401 1 pixel = calloc (raw_width, sizeof *pixel); d1440 1 a1440 1 pixel = calloc (raw_width + raw_height*4, 2); d1483 1 a1483 1 pixel = calloc (raw_width, sizeof *pixel); d1522 1 a1522 1 pixel = calloc (raw_width, sizeof *pixel); d1541 1 a1541 1 data = malloc (dwide + raw_width*2); d1608 1 a1608 1 pixel = calloc (raw_width, sizeof *pixel); d1644 1 a1644 1 pixel = calloc (width, 2); d1829 1 a1829 1 pixel = (void *) buf[0]; d1866 1 a1866 1 pixel = calloc (raw_width, sizeof *pixel); d2029 1 a2029 1 sony_decrypt ((void *) head, 10, 1, key); d2033 1 a2033 1 pixel = calloc (raw_width, sizeof *pixel); d2037 1 a2037 1 sony_decrypt ((void *) pixel, raw_width/2, !row, key); d2234 1 a2234 1 buf = malloc (bwide); d2313 1 a2313 1 char * CLASS foveon_camf_param (char *block, char *param) d2335 1 a2335 1 void * CLASS foveon_camf_matrix (int dim[3], char *name) d2355 1 a2355 1 mat = malloc (size * 4); d2368 1 a2368 1 int CLASS foveon_fixed (void *ptr, int size, char *name) d2401 1 a2401 1 curve = calloc (size+1, sizeof *curve); d2445 2 a2446 1 char str[128], *cp; d2519 1 a2519 1 sgain = foveon_camf_matrix (dim, "SpatialGain"); d2521 1 a2521 1 sgrow = calloc (dim[1], sizeof *sgrow); d2524 1 a2524 1 black = calloc (height, sizeof *black); d2613 1 a2613 1 if ((badpix = foveon_camf_matrix (dim, "BadPixels"))) { d2632 1 a2632 1 smrow[6] = calloc (width*5, sizeof **smrow); d2755 1 a2755 1 shrink = calloc ((width/4) * (height/4), sizeof *shrink); d2843 1 a2843 1 fname = malloc (len); d3260 1 a3260 1 brow[4] = calloc (width*3, sizeof **brow); d3365 1 a3365 1 buffer = malloc (26*TS*TS); /* 1664 kB */ d3367 3 a3369 3 rgb = (void *) buffer; lab = (void *) (buffer + 12*TS*TS); homo = (void *) (buffer + 24*TS*TS); d3471 2 a3472 2 window = calloc ((ws+1)*sizeof *window + ws*width*sizeof **window + ws*sizeof *kernel, 1); d3532 1 a3532 1 map = calloc (high*wide, sizeof *map); d4133 1 a4133 1 if (!(cbuf = malloc(len))) break; d4231 1 a4231 1 if (sony_length && (buf = malloc(sony_length))) { d4398 1 a4398 1 jname = malloc (strlen(ifname) + 1); d6109 1 a6109 1 prof = malloc (profile_length); d6204 1 a6204 1 img = calloc (wide*high, sizeof *img); d6244 1 a6244 1 dest = calloc (height * width, sizeof *dest); d6266 1 a6266 1 ppm = calloc (width, colors*xmag); d6310 1 a6310 1 ppm = calloc (width, 2*colors); d6353 1 a6353 1 buffer = calloc (colors, psize*2); d6371 2 a6372 1 char opt, *write_ext, *ofname, *sp, *cp; d6606 2 a6607 1 image = calloc (iheight*iwidth*sizeof *image + meta_length, 1); d6650 1 a6650 1 ofname = malloc (strlen(ifname) + 16); @ 1.325 log @Replaced "-r" and "-l" options with raw white balance. Added "-H 2" option for rudimentary highlight recovery. @ text @d3514 1 a3514 2 #define SIGMA 3 #define FS 13 d3517 6 a3522 4 float base[FS][FS], (*filt)[FS]; int c, y, x, s, ns, row, col, val, sat[4]; double sum, wgt; ushort *cent, *test; d3526 19 a3544 19 filt = (float (*)[FS]) &base[FS/2][FS/2]; for (y=-FS/2; y <= FS/2; y++) for (x=-FS/2; x <= FS/2; x++) filt[y][x] = exp(-(x*x+y*y)/(2*SIGMA*SIGMA)); for (ns=0, c=1; c < colors; c++) if (pre_mul[ns] < pre_mul[c]) ns = c; FORCC sat[c] = 62000 * pre_mul[c]; for (row=0; row < height; row++) for (col=0; col < width; col++) { cent = image[row*width+col]; for (s=0; s < colors; s++) { if (s == ns || cent[s] < sat[s]) continue; sum = wgt = 4; for (y = MAX(-FS/2,-row); y <= MIN(FS/2,height-row-1); y++) for (x = MAX(-FS/2,-col); x <= MIN(FS/2,width-col-1); x++) { test = image[(row+y)*width+col+x]; if (2*test[s]/sat[s] == 1 && test[ns]/32700 == 1) { sum += filt[y][x] * test[s] / test[ns]; wgt += filt[y][x]; d3547 2 a3548 2 if (cent[s] < (val = sum*cent[ns]/wgt)) cent[s] = CLIP(val); d3550 22 d3573 15 d3589 1 a3589 2 #undef SIGMA #undef FS d6384 1 a6384 1 "\nRaw Photo Decoder \"dcraw\" v8.17" @ 1.324 log @Improved support for Leaf, Imacon, Sinar, and Phase One backs. Rewrote Canon CRW parsing to get correct camera WB. @ text @d98 1 a98 1 int black, maximum, clip_max, raw_color, use_gamma; d102 2 a103 2 float bright=1, red_scale=1, blue_scale=1, sigma_d=0, sigma_r=0; int four_color_rgb=0, document_mode=0, clip_color=1; d144 1 a144 1 #define CLIP(x) LIM(x,0,clip_max) d1468 5 a1472 3 for (col=0; col < width; col++) BAYER(row-top_margin,col) = (pixel[col+left_margin] << 2) - ph1.black + black[row][col >= ph1.split_col]; a2310 1 clip_max = 0xffff; d3037 1 a3037 1 int row, col, x, y, c, val, shift=0; d3039 2 a3040 1 double dsum[8], dmin; d3047 2 a3048 2 for (row=0; row < height-7; row++) for (col=0; col < width-7; col++) { d3050 2 a3051 2 for (y=row; y < row+7; y++) for (x=col; x < col+7; x++) d3085 2 a3086 4 if (raw_color || !output_color) { pre_mul[0] *= red_scale; pre_mul[2] *= blue_scale; } d3088 5 a3092 14 dmin = DBL_MAX; FORC4 if (dmin > pre_mul[c]) dmin = pre_mul[c]; FORC4 pre_mul[c] /= dmin; while (maximum << shift < 0x8000) shift++; FORC4 pre_mul[c] *= 1 << shift; maximum <<= shift; if (write_fun != write_ppm || bright < 1) { maximum *= bright; if (maximum > 0xffff) maximum = 0xffff; FORC4 pre_mul[c] *= bright; d3094 2 a3100 1 clip_max = clip_color ? maximum : 0xffff; d3107 1 a3107 1 val *= pre_mul[c]; d3514 40 d4969 2 d6121 1 a6121 1 if (!raw_color) { a6126 5 FORCC { out_cam[0][c] *= red_scale; out_cam[2][c] *= blue_scale; } } a6273 1 if (maximum < 256) maximum = 256; d6277 1 a6277 1 width, height, colors, maximum, cdesc); d6280 1 a6280 1 colors/2+5, width, height, maximum); d6333 1 a6333 1 char opt, *write_ext, *ofname, *cp; d6347 1 a6347 1 "\nRaw Photo Decoder \"dcraw\" v8.15" d6358 2 a6359 3 "\n-r Set red multiplier (default = 1.0)" "\n-l Set blue multiplier (default = 1.0)" "\n-b Set brightness (default = 1.0)" d6361 2 a6362 1 "\n-n Don't clip colors" a6375 1 "\n-t [0-7] Flip image (0 = none, 3 = 180, 5 = 90CCW, 6 = 90CW)" d6386 6 a6391 5 if ((strchr("Bbrlktq", opt) && !isdigit(argv[arg][0])) || (opt == 'B' && !isdigit(argv[arg+1][0]))) { fprintf (stderr, "Non-numeric argument to \"-%c\"\n", opt); return 1; } d6397 2 a6398 2 case 'r': red_scale = atof(argv[arg++]); break; case 'l': blue_scale = atof(argv[arg++]); break; d6402 1 d6425 1 a6425 1 case 'n': clip_color = 0; break; d6596 1 @ 1.323 log @Fixed camera WB for Canon EOS 10D, 300D, and clones. Use the correct color matrix for the Canon EOS Kiss Digital N. @ text @a111 2 #define camera_red cam_mul[0] #define camera_blue cam_mul[2] d127 5 d255 3 a257 1 double num; d261 2 a262 2 case 5: num = (unsigned int) get4(); return num / (unsigned int) get4(); d265 2 a266 2 case 10: num = (signed int) get4(); return num / (signed int) get4(); d269 4 a272 2 fprintf (stderr, "%s: TIFF doubles not supported!\n", ifname); longjmp (failure, 4); d1223 44 d1270 2 a1271 1 int len, i, j, val[4], dev[4], sum, max; d1275 2 d1278 2 a1279 1 if (!meta_length) return; d1291 20 a1310 1 if (tag == 0x400) /* Sensor defects */ d1340 14 d1356 33 d1396 1 a1396 1 fseek (ifp, curve_offset, SEEK_SET); d1399 1 a1399 1 mask = tiff_compress == 1 ? 0x5555:0x1354; a1414 1 maximum = 0xffff; d1438 1 d1440 1 a1440 1 pixel = calloc (raw_width + raw_height*2, 2); d1446 4 d1469 2 a1470 1 BAYER(row-top_margin,col) = pixel[col+left_margin]; a1472 1 maximum = 0x3fff; d1476 1 a1476 1 void CLASS hdr_load_raw() d1482 1 a1482 1 merror (pixel, "hdr_load_raw()"); d1492 9 d3041 1 a3041 1 if (use_auto_wb || (use_camera_wb && camera_red == -1)) { d3067 1 a3067 1 if (use_camera_wb && camera_red != -1) { d3078 1 a3078 1 else if (camera_red && camera_blue) d3633 2 a3634 2 camera_red = getrat(); camera_blue = getrat(); d3721 2 a3722 2 camera_red = get2() * 508 * 1.078 / 0x10000; camera_blue = get2() * 382 * 1.173 / 0x10000; d3734 1 a3734 1 camera_red = get2() / 256.0; d3736 1 a3736 1 camera_blue = get2() / 256.0; d3740 2 a3741 2 camera_red = get2() / 256.0; camera_blue = get2() / 256.0; d3809 14 d3828 1 a3828 2 static const unsigned bayer[] = { 0x94949494, 0x61616161, 0x16161616, 0x49494949 }; d3852 5 d3878 2 a3879 1 filters = (planes == 1) * bayer[(flip/90 + frot) & 3]; d3885 1 a3885 1 int ifd, use_cm=0, cfa, i, j, c; d4044 1 d4050 10 d4391 1 a4391 1 int tboff, nrecs, i, c, type, len, roff, aoff, save, wbi=-1; a4393 5 if (strcmp(model,"Canon PowerShot G6") && strcmp(model,"Canon PowerShot S60") && strcmp(model,"Canon PowerShot S70") && strcmp(model,"Canon PowerShot Pro1")) key[0] = key[1] = 0; d4402 6 a4407 5 roff = get4(); aoff = offset + roff; save = ftell(ifp); if (type == 0x080a) { /* Get the camera make and model */ fseek (ifp, aoff, SEEK_SET); d4409 1 a4409 1 fseek (ifp, aoff+strlen(make)+1, SEEK_SET); d4412 18 a4429 5 if (type == 0x102a) { /* Exposure info */ fseek (ifp, aoff+4, SEEK_SET); iso_speed = 50 * pow (2, get2()/32.0 - 4); aperture = (get2(), pow (2, get2()/64.0)); shutter = pow (2, ((short) get2())/-32.0); d4433 3 a4435 4 if (type == 0x102c) { /* Get white balance (G2) */ if (!strcmp(model,"Canon PowerShot G1") || !strcmp(model,"Canon PowerShot Pro90 IS")) { fseek (ifp, aoff+120, SEEK_SET); d4437 21 a4457 3 } else { fseek (ifp, aoff+100, SEEK_SET); goto common; d4460 4 a4463 30 if (type == 0x0032) { /* Get white balance (D30 & G3) */ if (!strcmp(model,"Canon EOS D30")) { fseek (ifp, aoff+72, SEEK_SET); common: camera_red = get2() ^ key[0]; camera_red =(get2() ^ key[1]) / camera_red; camera_blue = get2() ^ key[0]; camera_blue /= get2() ^ key[1]; if (!wbi) camera_red = -1; /* Use my auto WB for this photo */ } else if (key[0]) { fseek (ifp, aoff+96 + 8*("01345:000000006008"[wbi]-'0'), SEEK_SET); goto common; } else { fseek (ifp, aoff+80 + (wbi < 6 ? 8*("123451"[wbi]-'0') : 0), SEEK_SET); if (!camera_red) goto common; } } if (type == 0x10a9) { /* Get white balance (D60) */ if (strcmp(model,"Canon EOS D60")) wbi = "0134567028"[wbi]-'0'; fseek (ifp, aoff+2 + wbi*8, SEEK_SET); camera_red = get2(); camera_red /= get2(); camera_blue = get2(); camera_blue = get2() / camera_blue; } if (type == 0x1030 && (wbi == 6 || wbi == 15)) { fseek (ifp, aoff, SEEK_SET); /* Get white sample */ ciff_block_1030(); d4465 4 a4468 3 if (type == 0x1031) { /* Get the raw width and height */ fseek (ifp, aoff+2, SEEK_SET); raw_width = get2(); d4471 6 a4476 6 if (type == 0x180e) { /* Get the timestamp */ fseek (ifp, aoff, SEEK_SET); timestamp = get4(); } if (type == 0x580e) timestamp = len; a4480 27 if (type == 0x5813) flash_used = int_to_float(len); if (type == 0x5814) canon_ev = int_to_float(len); if (type == 0x5817) shot_order = len; if (type == 0x5834) unique_id = len; if (type == 0x1810) { /* Get the rotation */ fseek (ifp, aoff+12, SEEK_SET); flip = get4(); } if (type == 0x1818) { fseek (ifp, aoff+4, SEEK_SET); shutter = pow (2, -int_to_float(get4())); aperture = pow (2, int_to_float(get4())/2); } if (type == 0x1835) { /* Get the decoder table */ fseek (ifp, aoff, SEEK_SET); tiff_compress = get4(); } if (type == 0x2007) { /* Found the JPEG thumbnail */ thumb_offset = aoff; thumb_length = len; } if (type >> 8 == 0x28 || type >> 8 == 0x30) /* Get sub-tables */ parse_ciff(aoff, len); d4525 1 d4528 1 d4545 3 a4547 2 for (raw_color = i=0; i < 3; i++) FORC3 rgb_cam[i][c] = int_to_float(get4()); d4550 1 a4550 1 FORC3 cam_mul[c] = pre_mul[c] = int_to_float(get4()); d4558 1 a4558 1 case 0x10e: tiff_compress = data; break; d4561 8 a4568 3 meta_length = len; break; case 0x112: curve_offset = save - 4; break; case 0x21c: strip_offset = data+base; break; d4576 1 a4576 1 load_raw = tiff_compress < 3 ? d4578 1 d4889 2 d5017 2 d5035 2 d5427 2 a5428 2 camera_red *= 256/527.0; camera_blue *= 256/317.0; d5531 1 a5531 1 } else if (!strcmp(model,"R-D1")) { d5630 2 a5631 2 camera_red *= 4; camera_blue *= 4; d5717 5 a5721 6 if (raw_width < 4096) { data_offset += 6 + raw_width*12; height = raw_height - 6; width = raw_width - 10; filters = 0x61616161; flip = height > width+10 ? 5:3; a5722 1 load_raw = unpacked_load_raw; a5723 2 pre_mul[0] = 1.963; pre_mul[2] = 1.430; d5740 1 a5740 1 load_raw = hdr_load_raw; a5753 2 } else if (!strcmp(model,"P 30") || !strcmp(model,"P 45")) { black = 256; d5807 2 a5808 1 } else if (!strcmp(model,"DSC-R1")) { d6077 3 a6079 3 { { 0.529317, 0.330092, 0.140588 }, { 0.098368, 0.873465, 0.028169 }, { 0.016879, 0.117663, 0.865457 } }; d6319 1 a6319 1 "\nRaw Photo Decoder \"dcraw\" v8.13" d6529 1 a6529 1 FORCC printf (" %f", cam_mul[c]); @ 1.322 log @Added the Leica D-Lux 2. @ text @d91 1 a91 1 unsigned shot_order, kodak_cbpp, filters; d3502 2 a4258 3 if (((!strcmp(model,"Canon EOS DIGITAL REBEL") || !strcmp(model,"Canon EOS 300D DIGITAL"))) && wbi == 6) wbi++; d4289 2 a4290 2 if (!strcmp(model,"Canon EOS 10D")) wbi = "0134560028"[wbi]-'0'; d4322 2 a4665 2 { "Canon EOS DIGITAL REBEL XT", 0, { 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } }, d5006 1 a5006 1 iso_speed = shutter = aperture = focal_len = 0; d5255 2 d6171 1 a6171 1 "\nRaw Photo Decoder \"dcraw\" v8.12" @ 1.321 log @Added the Leaf Aptus 75. Correctly handle the DNG AsShotWhiteXY tag. @ text @d4787 2 d6170 1 a6170 1 "\nRaw Photo Decoder \"dcraw\" v8.11" @ 1.320 log @Better support the Imacon Ixpress 22-Mp. @ text @d111 1 d1351 1 a1351 1 void CLASS leaf_load_raw() d1357 1 a1357 1 merror (pixel, "leaf_load_raw()"); a3194 1 static const float d65[3] = { 0.950456, 1, 1.088754 }; d3205 1 a3205 1 xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65[i]; d3676 2 a3677 1 int skip, from, i, c, neut[4]; d3697 16 a3712 5 if (!strcmp(data,"CaptProf_number_of_planes")) { fscanf (ifp, "%d", &i); if (i > 1) filters = 0; } if (!strcmp(data,"CaptProf_raw_data_rotation") && filters) { d3714 1 a3714 1 filters = bayer[i/90]; d3717 1 a3717 2 for (i=0; i < 4; i++) fscanf (ifp, "%d", neut+i); d3723 2 d3853 7 a3859 4 case 33434: shutter = getrat(); break; case 33437: aperture = getrat(); break; case 37386: focal_len = getrat(); break; case 34310: d3874 7 a3880 1 case 37400: d3886 1 a3886 1 case 46275: d3970 1 d4787 1 a4787 1 { "Leaf Valeo", 0, a5585 1 strcpy (model, "Valeo"); d5587 2 a5588 1 load_raw = leaf_load_raw; d5590 1 a5590 1 strcpy (model, "Volare"); d6168 1 a6168 1 "\nRaw Photo Decoder \"dcraw\" v8.10" @ 1.319 log @Don't search for the best black value in colorcheck(). Added new color matrix for the Nikon E700, E800, and E950. @ text @d3867 5 a3871 2 raw_width = 4090; raw_height = len / raw_width / 2; a5536 4 height = raw_height - 6; width = raw_width - 10; data_offset += 6 + raw_width*12; flip = height > width+10 ? 5:3; d5538 7 a5544 1 filters = 0x61616161; d6145 1 a6145 1 "\nRaw Photo Decoder \"dcraw\" v8.09" @ 1.318 log @Added getreal(), and use getint() more often. @ text @d2753 1 a2753 1 void CLASS pseudoinverse (const double (*in)[3], double (*out)[3], int size) d2799 1 a2799 1 pseudoinverse ((const double (*)[3]) cam_rgb, inverse, colors); d2837 28 a2864 28 static const double gmb_xyz[NSQ][3] = { { 11.078, 9.870, 6.738 }, // Dark Skin { 37.471, 35.004, 26.057 }, // Light Skin { 18.187, 19.306, 35.425 }, // Blue Sky { 10.825, 13.827, 7.600 }, // Foliage { 24.769, 23.304, 43.943 }, // Blue Flower { 31.174, 42.684, 45.277 }, // Bluish Green { 36.238, 29.188, 6.222 }, // Orange { 13.661, 11.845, 38.929 }, // Purplish Blue { 27.999, 19.272, 14.265 }, // Moderate Red { 8.398, 6.309, 14.211 }, // Purple { 33.692, 44.346, 11.288 }, // Yellow Green { 45.000, 42.144, 8.429 }, // Orange Yellow { 8.721, 6.130, 31.181 }, // Blue { 14.743, 24.049, 9.778 }, // Green { 19.777, 11.530, 5.101 }, // Red { 55.978, 59.599, 10.047 }, // Yellow { 29.421, 19.271, 31.167 }, // Magenta { 13.972, 18.952, 37.646 }, // Cyan { 82.819, 87.727, 94.479 }, // White { 55.950, 58.959, 64.375 }, // Neutral 8 { 32.877, 34.536, 38.097 }, // Neutral 6.5 { 18.556, 19.701, 21.487 }, // Neutral 5 { 8.353, 8.849, 9.812 }, // Neutral 3.5 { 2.841, 2.980, 3.332 } }; // Black double inverse[NSQ][3], gmb_cam[NSQ][4], cam_xyz[4][3]; double num, error, minerr=DBL_MAX, best[4][3]; int b, c, i, j, k, sq, row, col, count[4]; d2876 5 a2880 1 FORCC gmb_cam[sq][c] /= count[c]; d2882 6 a2887 22 for (b=0; b < 1; b++) { pseudoinverse (gmb_xyz, inverse, NSQ); for (i=0; i < colors; i++) for (j=0; j < 3; j++) for (cam_xyz[i][j] = k=0; k < NSQ; k++) cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j]; for (error=sq=0; sq < NSQ; sq++) FORCC { for (num=j=0; j < 3; j++) num += cam_xyz[c][j] * gmb_xyz[sq][j]; if (num < 0) num=0; error += pow (num - gmb_cam[sq][c], 2); gmb_cam[sq][c]--; // for the next black value } if (error < minerr) { black = b; minerr = error; memcpy (best, cam_xyz, sizeof best); } } cam_xyz_coeff (best); d2890 1 a2890 1 num = 10000 / (best[1][0] + best[1][1] + best[1][2]); d2892 1 a2892 1 printf ("%c%d", (c | j) ? ',':' ', (int) (best[c][j] * num + 0.5)); d4617 1 a4617 1 void CLASS adobe_coeff() d4799 2 d4889 1 a4889 1 /* index 3 -- Nikon E700, E800, and E950 */ d5282 1 a5282 4 simple_coeff(3); pre_mul[0] = 1.18193; pre_mul[2] = 1.16452; pre_mul[3] = 1.17250; d5816 1 a5816 1 if (raw_color) adobe_coeff(); d6140 1 a6140 1 "\nRaw Photo Decoder \"dcraw\" v8.08" d6370 3 a6375 3 quality = 2 + !fuji_width; if (user_qual >= 0) quality = user_qual; if (user_black >= 0) black = user_black; @ 1.317 log @Use unmagnified dimensions in write_ppm16(). @ text @a241 6 double CLASS getrat() { double num = get4(); return num / get4(); } d249 21 d3924 1 a3924 1 dblack += getrat(); d3928 1 a3928 1 maximum = get2(); d3951 1 a3951 1 FORCC asn[c] = type == 3 ? get2() : getrat(); d3967 4 a3970 4 top_margin = get4(); left_margin = get4(); height = get4() - top_margin; width = get4() - left_margin; d6153 1 a6153 1 "\nRaw Photo Decoder \"dcraw\" v8.07" @ 1.316 log @Support the Olympus E-330. Added "-D" option to output unscaled raw pixels. For DNG, support ICC profiles and short AsShotNeutral tags. Fix defective pixels and columns in Phase One images. @ text @d6068 1 a6068 1 xmag*width, ymag*height, colors, maximum, cdesc); d6071 1 a6071 1 colors/2+5, xmag*width, ymag*height, maximum); d6138 1 a6138 1 "\nRaw Photo Decoder \"dcraw\" v8.06" @ 1.315 log @Improved detection of non-raw files. @ text @d1195 59 d1279 1 d1332 1 d1384 1 a1384 1 int dwide, row, col; d1386 2 d1401 1 a1401 1 for (col=width+4; col < raw_width; col++) d1404 1 a1404 1 black /= (raw_width - width - 4) * height; d2155 3 d3848 1 d3936 1 a3936 1 FORCC asn[c] = getrat(); d4389 2 d5592 3 d5926 1 a5926 1 if (document_mode) d5938 1 a5938 1 if (document_mode) colors = 1; d6138 1 a6138 1 "\nRaw Photo Decoder \"dcraw\" v8.05" d6160 1 d6210 1 d6374 2 a6375 2 if (is_foveon) foveon_interpolate(); else scale_colors(); @ 1.314 log @Updated color matrices based on Adobe DNG Converter 3.3. Added Kodak ProPhoto D65 as an output option. @ text @d3392 1 d3417 1 d3988 1 a3988 5 if (((strstr(make,"Minolta") || strstr(make,"MINOLTA")) && tiff_bps == 8) || (!strncmp(make,"NIKON",5) && filters == UINT_MAX) || (!strcmp(make,"SONY") && tiff_bps != 14) || (!strcmp(make,"Canon") && tiff_bps == 8) || (tiff_samples == 3 && data_offset == 8)) d6066 1 a6066 1 "\nRaw Photo Decoder \"dcraw\" v8.04" @ 1.313 log @Improved Phase One code, set black=256 for P 30 and P 45. @ text @d2093 1 a2093 1 maximum = clip_max = 0xffff; d3521 1 a3521 1 if (tag == 0x1011 && len == 9) { d3989 1 d4562 3 a4564 1 { 6228,-404,-967,-8314,16108,2312,-1923,2179,7499 } }, d4621 2 d4639 4 d4646 1 a4646 1 { 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } }, d4685 4 a4688 2 { "KODAK P8", 0, /* DJC */ { 17293,-6824,-2050,-3999,12397,1602,-1209,2283,5375 } }, d4717 2 a4718 2 { "NIKON D1", 0, { 7559,-2130,-965,-7611,15713,1972,-2478,3042,8290 } }, d4727 2 d4773 2 d4787 2 a4788 2 { "SONY DSC-R1", 512, /* DJC */ { 10528,-3695,-517,-2822,10699,2124,406,1240,5342 } }, d5825 4 d5830 1 a5830 1 { adobe_rgb, wgd65_rgb, xyz_rgb }; d5832 1 a5832 1 { "sRGB", "Adobe 1998 RGB", "Wide Gamut D65", "XYZ" }; d5835 1 a5835 1 raw_color |= colors == 1 || output_color < 1 || output_color > 4; d6068 1 a6068 1 "\nRaw Photo Decoder \"dcraw\" v8.03" d6084 1 a6084 1 "\n-o [0-4] Output colorspace (raw,sRGB,Adobe,Wide,XYZ)" d6345 1 a6345 1 fprintf (stderr, "Writing data to %s...\n", ofname); @ 1.312 log @Added the Phase One P 30 and P 45. @ text @d94 1 a94 1 int data_offset, meta_offset, meta_length, nikon_curve_offset; d906 1 a906 1 fseek (ifp, nikon_curve_offset, SEEK_SET); d1200 1 a1200 1 fseek (ifp, nikon_curve_offset, SEEK_SET); d1246 1 d1250 1 a1250 1 fseek (ifp, 20 + offset[row], SEEK_SET); d3460 1 a3460 1 nikon_curve_offset = ftell(ifp) + 2112; d3462 1 a3462 1 nikon_curve_offset = ftell(ifp) + 2; d4315 10 a4324 11 case 0x108: raw_width = data; break; case 0x109: raw_height = data; break; case 0x10a: left_margin = data; break; case 0x10b: top_margin = data; break; case 0x10c: width = data; break; case 0x10d: height = data; break; case 0x10e: tiff_compress = data; break; case 0x10f: case 0x21c: data_offset = data + base; break; case 0x112: nikon_curve_offset = save - 4; break; d4326 3 a4328 3 fread (model, 64, 1, ifp); cp = strstr(model," camera"); if (cp && cp < model+64) *cp = 0; d5490 2 d6049 1 a6049 1 "\nRaw Photo Decoder \"dcraw\" v8.02" @ 1.311 log @Changed auto white balance to better handle saturated pixels. Allow "dcraw -i -v" to work with non-raw photos. @ text @d1142 1 d1144 1 a1144 1 char *thumb = malloc (thumb_length*colors); d1240 1 a1240 1 int len[2], pred[2], row, col, ncols, i, j; d1243 1 a1243 2 ncols = (raw_width + 7) & -8; pixel = calloc (ncols, sizeof *pixel); d1245 3 d1249 1 d1252 1 a1252 1 for (col=0; col < ncols; col++) { d4321 2 a4322 1 case 0x10f: data_offset = data+base; break; d6047 1 a6047 1 "\nRaw Photo Decoder \"dcraw\" v8.01" @ 1.310 log @Dcraw v8.00 major release: * Added "-e" option to extract thumbnail images. * Added "-o" option to select output colorspace. * Enabled "-p" option for ICC color profiles by default. * Generate monochrome or four-color output in some cases. * Use more memory to flip images five times faster. * Use the correct formula for Kodak YCbCr images. @ text @d91 1 a91 1 unsigned shot_order, kodak_cbpp; d98 1 a98 1 int black, maximum, clip_max, clip_color=1; d100 1 a100 3 int dng_version, is_foveon, raw_color, use_gamma; int zero_after_ff; unsigned filters; d103 1 a103 1 int four_color_rgb=0, document_mode=0; d624 1 d2005 1 a2005 1 int width, height, bwide, row, col, bit=-1, c, i; d2011 2 a2012 4 width = get4(); height = get4(); bwide = get4(); fprintf (tfp, "P6\n%d %d\n255\n", width, height); d2016 1 a2016 1 for (row=0; row < height; row++) { d2018 1 a2018 1 fwrite (buf, 3, width, tfp); d2025 1 a2025 1 for (row=0; row < height; row++) { d2028 1 a2028 1 for (col=bit=0; col < width; col++) d2827 3 a2829 3 int row, col, c, val, shift=0; int min[4], max[4], count[4]; double sum[4], dmin; d2834 23 a2856 15 FORC4 max[c] = count[c] = sum[c] = 0; for (row=0; row < height; row++) for (col=0; col < width; col++) FORC4 { val = image[row*width+col][c]; if (!val) continue; if (min[c] > val) min[c] = val; if (max[c] < val) max[c] = val; val -= black; if (val > maximum-25) continue; if (val < 0) val = 0; sum[c] += val; count[c]++; } FORC4 if (sum[c]) pre_mul[c] = count[c] / sum[c]; d2859 1 a2859 1 FORC4 count[c] = sum[c] = 0; d2865 1 a2865 1 count[c]++; d2868 1 a2868 1 FORC4 pre_mul[c] = count[c] / sum[c]; d3415 5 d3724 1 a3724 1 make[0] = 0; d3982 1 d3985 1 a3985 1 if (!dng_version) make[0] = 0; d4085 1 d4234 1 a4234 1 crw_init_tables (get4()); d4370 1 a4370 1 int len, save, hlen; d4375 1 a4375 1 while (fgetc(ifp) == 0xff && fgetc(ifp) >> 4 != 0xd) { d4379 5 d4490 3 a4492 1 thumb_offset = off+16; d4835 1 a4882 2 /* What format is this file? Set make[] if we recognize it. */ d4895 1 a4895 1 raw_color = use_gamma = xmag = ymag = 1; a4921 2 if (!dng_version && !strncmp(make,"NIKON",5) && filters == UINT_MAX) make[0] = 0; d4998 2 a4999 4 if (make[0] == 0) { parse_jpeg(0); make[0] = 0; } d5013 1 a5013 1 if (make[0] == 0) return; d5723 7 d5731 7 d6042 1 a6042 1 "\nRaw Photo Decoder \"dcraw\" v8.00" d6160 1 a6160 1 identify(); d6191 1 a6191 13 if ((status = !make[0])) { fprintf (stderr, "%s: unsupported file format.\n", ifname); goto next; } else if ((status = !load_raw || !height)) { fprintf (stderr, "%s: Cannot decode %s %s images.\n", ifname, make, model); goto next; #ifdef NO_JPEG } else if (load_raw == kodak_jpeg_load_raw) { fprintf (stderr, "%s: dcraw was not linked with libjpeg.\n", ifname); goto next; #endif } else if (load_raw == kodak_ycbcr_load_raw) { d6195 19 d6226 13 a6238 10 printf ("Filename: %s\n", ifname); printf ("Timestamp: %s", ctime(×tamp)); printf ("Camera: %s %s\n", make, model); printf ("ISO speed: %d\n", (int) iso_speed); printf ("Shutter: "); if (shutter > 0 && shutter < 1) shutter = (printf ("1/"), 1 / shutter); printf ("%0.1f sec\n", shutter); printf ("Aperture: f/%0.1f\n", aperture); printf ("Focal Length: %d mm\n", (int) focal_len); d6252 1 a6252 14 printf ("\nRaw size: %d x %d\n", raw_width, raw_height); printf ("Image size: %d x %d\n", width, height); if (fuji_width && use_fuji_rotate) { fuji_width = (fuji_width - 1 + shrink) >> shrink; iwidth = fuji_width / sqrt(0.5); iheight = (iheight - fuji_width) / sqrt(0.5); } if (write_fun == write_ppm) { iheight *= ymag; iwidth *= xmag; } if (flip & 4) SWAP(iheight,iwidth); printf ("Output size: %d x %d\n\n", iwidth, iheight); @ 1.309 log @Apply DiMAGE Z2 color matrix to the Nikon E4300. Added the Canon EOS-1D Mark II N. @ text @d3 1 a3 1 Copyright 1997-2005 by Dave Coffin, dcoffin a cybercom o net d40 2 a41 2 By defining NO_JPEG, you lose only the ability to decode compressed .KDC files from the Kodak DC120. d46 3 d88 1 a88 1 char *ifname, make[64], model[70], model2[64], *meta_data; d92 2 d95 1 a95 1 int tiff_bps, tiff_data_compression, kodak_data_compression; d99 1 a99 1 int iheight, iwidth, shrink; a100 1 int flip, xmag, ymag; a103 1 void (*load_raw)(); d106 1 a106 1 int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_rgb=0; d115 1 a115 1 int histogram[3][0x2000]; d117 2 a118 1 void (*write_fun)(FILE *) = write_ppm; a120 5 #ifdef USE_LCMS #include int profile_offset, profile_length; #endif d126 4 d239 5 d700 1 a700 1 int CLASS ljpeg_start (struct jhead *jh) d703 1 a703 1 uchar data[256], *dp; d710 1 a710 1 if (data[0] != 0xff || data[1] != 0xd8) return 0; d715 1 a715 1 if (tag <= 0xff00 || len > 255) return 0; d718 1 d726 1 d736 1 d739 1 a739 2 zero_after_ff = 1; return 1; d777 1 a777 1 int jwide, jrow, jcol, val, jidx, i, j, row, col; d781 1 a781 1 if (!ljpeg_start (&jh)) return; a789 1 jidx = jrow*jwide + jcol; d791 1 a797 3 } else { row = jidx / raw_width; col = jidx % raw_width; d799 8 a806 6 if ((unsigned) (row-top_margin) >= height) continue; if ((unsigned) (col-left_margin) < width) { BAYER(row-top_margin,col-left_margin) = val; if (min > val) min = val; } else black += val; d849 1 a849 1 if (!ljpeg_start (&jh)) break; d954 1 a954 1 if (tiff_data_compression == 34713 && (col % 10) == 9) d970 1 a970 1 if (tiff_data_compression != 34713) d1120 49 d1203 1 a1203 1 mask = tiff_data_compression == 1 ? 0x5555:0x1354; a1621 1 d1667 1 a1667 1 void CLASS kodak_compressed_load_raw() d1669 1 a1669 1 uchar c, blen[256]; a1670 1 unsigned row, col, len, save, i, israw=0, bits=0, pred[2]; d1672 45 a1716 1 int diff; d1719 6 a1724 49 for (col=0; col < width; col++) { if ((col & 255) == 0) { /* Get the bit-lengths of the */ len = width - col; /* next 256 pixel values */ if (len > 256) len = 256; save = ftell(ifp); for (israw=i=0; i < len; i+=2) { c = fgetc(ifp); if ((blen[i+0] = c & 15) > 12 || (blen[i+1] = c >> 4) > 12 ) israw = 1; } bitbuf = bits = pred[0] = pred[1] = 0; if (len % 8 == 4) { bitbuf = fgetc(ifp) << 8; bitbuf += fgetc(ifp); bits = 16; } if (israw) fseek (ifp, save, SEEK_SET); } if (israw) { /* If the data is not compressed */ switch (col & 7) { case 0: read_shorts (raw, 6); diff = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12; break; case 1: diff = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12; break; default: diff = raw[(col & 7) - 2] & 0xfff; } } else { /* If the data is compressed */ len = blen[col & 255]; /* Number of bits for this pixel */ if (bits < len) { /* Got enough bits in the buffer? */ for (i=0; i < 32; i+=8) bitbuf += (INT64) fgetc(ifp) << (bits+(i^8)); bits += 32; } diff = bitbuf & (0xffff >> (16-len)); /* Pull bits from buffer */ bitbuf >>= len; bits -= len; if ((diff & (1 << (len-1))) == 0) diff -= (1 << len) - 1; pred[col & 1] += diff; diff = pred[col & 1]; } BAYER(row,col) = curve[diff]; d1728 1 a1728 1 void CLASS kodak_yuv_load_raw() d1730 2 a1731 4 uchar c, blen[384]; unsigned row, col, len, bits=0; INT64 bitbuf=0; int i, li=0, si, diff, six[6], y[4], cb=0, cr=0, rgb[3]; d1735 16 a1750 42 for (col=0; col < width; col+=2) { if ((col & 127) == 0) { len = (width - col + 1) * 3 & -4; if (len > 384) len = 384; for (i=0; i < len; ) { c = fgetc(ifp); blen[i++] = c & 15; blen[i++] = c >> 4; } li = bitbuf = bits = y[1] = y[3] = cb = cr = 0; if (len % 8 == 4) { bitbuf = fgetc(ifp) << 8; bitbuf += fgetc(ifp); bits = 16; } } for (si=0; si < 6; si++) { len = blen[li++]; if (bits < len) { for (i=0; i < 32; i+=8) bitbuf += (INT64) fgetc(ifp) << (bits+(i^8)); bits += 32; } diff = bitbuf & (0xffff >> (16-len)); bitbuf >>= len; bits -= len; if ((diff & (1 << (len-1))) == 0) diff -= (1 << len) - 1; six[si] = diff; } y[0] = six[0] + y[1]; y[1] = six[1] + y[0]; y[2] = six[2] + y[3]; y[3] = six[3] + y[2]; cb += six[4]; cr += six[5]; for (i=0; i < 4; i++) { ip = image[(row+(i >> 1))*width + col+(i & 1)]; rgb[0] = y[i] + cr; rgb[1] = y[i]; rgb[2] = y[i] + cb; FORC3 if (rgb[c] > 0) ip[c] = curve[rgb[c]]; d1755 26 d1973 1 a1973 1 void CLASS foveon_decoder (unsigned huff[1024], unsigned code) d1975 1 d1979 5 d1990 1 a1990 1 for (i=0; i < 1024; i++) d1999 1 a1999 1 foveon_decoder (huff, code); d2001 42 a2042 1 foveon_decoder (huff, code+1); d2063 1 a2063 1 unsigned huff[1024], bitbuf=0; d2068 2 a2069 6 if (!fixed) { for (i=0; i < 1024; i++) huff[i] = get4(); init_decoder(); foveon_decoder (huff, 0); } d2622 1 a2622 1 for (len=16 ; ; len *= 2) { d2625 1 a2625 1 if (getcwd (fname, len-12)) break; d2629 1 a2629 1 #ifdef WIN32 d2869 1 a2869 1 if (raw_color) { d3309 25 a3333 1 void CLASS parse_makernote() d3368 1 a3368 1 unsigned base=0, offset=0, entries, tag, type, len, save, c; a3370 1 static const int size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 }; d3379 5 a3383 3 if (!strncmp (buf,"KC" ,2) || /* these aren't TIFF format */ !strncmp (buf,"KDK",3) || !strncmp (buf,"MLY",3)) return; d3407 1 a3407 7 tag = get2(); type = get2(); len = get4(); save = ftell(ifp); if (len * size[type < 13 ? type:0] > 4) fseek (ifp, get4()+base, SEEK_SET); d3427 17 a3476 4 if (tag == 0xe0 && len == 17) { raw_width = (get2(),get2()); raw_height = get2(); } d3503 1 a3503 1 fseek (ifp, 188, SEEK_CUR); d3521 2 d3529 1 a3529 1 fseek (ifp, save+4, SEEK_SET); d3562 2 a3563 2 int kodak, entries, tag, type, len, save; static const int size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 }; d3568 1 a3568 6 tag = get2(); type = get2(); len = get4(); save = ftell(ifp); if (len * size[type < 13 ? type:0] > 4) fseek (ifp, get4()+base, SEEK_SET); d3575 2 a3576 1 case 37377: shutter = pow (2, -getrat()); break; d3579 1 a3579 1 case 37500: parse_makernote(); break; d3583 1 a3583 1 fseek (ifp, save+4, SEEK_SET); d3587 40 a3626 2 void CLASS parse_mos (int offset); void CLASS sony_decrypt (unsigned *data, int len, int start, int key); d3631 1 a3631 2 int done=0, use_cm=0, cfa, i, j, c; static const int size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 }; a3632 1 static const int flip_map[] = { 0,1,3,2,4,6,7,5 }; d3637 1 d3640 3 d3649 1 a3649 7 tag = get2(); type = get2(); len = get4(); save = ftell(ifp); if (tag > 50700 && tag < 50800) done = 1; if (len * size[type < 13 ? type:0] > 4) fseek (ifp, get4()+base, SEEK_SET); d3651 1 a3651 2 case 0x11: case 0x12: d3653 1 a3653 1 cam_mul[(tag-0x11)*2] = get2() / 256.0; d3655 1 a3655 3 case 0x24: case 0x25: case 0x26: d3658 1 a3658 1 case 0x27: d3663 2 a3664 13 case 0x2: case 0x100: /* ImageWidth */ if ((strcmp(make,"Canon") || level) && len == 1) raw_width = type==3 ? get2() : get4(); break; case 0x3: case 0x101: /* ImageHeight */ if ((strcmp(make,"Canon") || level) && len == 1) raw_height = type==3 ? get2() : get4(); break; case 0x102: /* Bits per sample */ fuji_secondary = len == 2; maximum = (1 << (tiff_bps = get2())) - 1; d3666 2 a3667 2 case 0x103: /* Compression */ tiff_data_compression = get2(); d3669 3 a3671 2 case 0x106: /* Kodak color format */ kodak_data_compression = get2(); d3673 7 a3679 1 case 0x10f: /* Make */ d3682 1 a3682 1 case 0x110: /* Model */ d3685 16 a3700 2 case 0x111: /* StripOffset */ data_offset = get4(); d3702 2 a3703 2 case 0x112: /* Orientation */ flip = flip_map[(get2()-1) & 7]; d3705 3 a3707 2 case 0x115: /* SamplesPerPixel */ tiff_samples = get2(); d3709 1 a3709 1 case 0x131: /* Software tag */ d3716 1 a3716 1 case 0x132: /* DateTime tag */ d3719 2 a3720 7 case 0x144: /* TileOffsets */ if (level) { data_offset = ftell(ifp); } else { data_offset = get4(); done = 1; } d3722 1 a3722 3 case 0x14a: /* SubIFD tag */ if (len > 2 && !dng_version && !strcmp(make,"Kodak")) len = 2; d3730 4 d3764 4 a3781 1 done = 1; d3801 1 d3807 1 a3807 1 fuji_width = (raw_width+1)/2; d3811 2 a3812 2 case 0x123: case 0x90d: d3818 2 a3819 1 maximum = curve[i] = curve[i-1]; d3880 1 a3880 1 fseek (ifp, save+4, SEEK_SET); a3895 2 if (!(base | level | dng_version) && (strstr(make,"Minolta") || strstr(make,"MINOLTA"))) make[0] = 0; d3908 1 a3908 1 return done; d3913 2 a3914 1 int doff, maxifd=1000; d3920 3 a3922 1 while ((doff = get4()) && maxifd--) { a3924 1 if (!dng_version && data_offset == 8) make[0] = 0; d3930 73 d4073 1 a4113 3 static const int remap[] = { 1,2,3,4,5,1 }; static const int remap_10d[] = { 0,1,3,4,5,6,0,0,2,8 }; static const int remap_s70[] = { 0,1,3,4,5,10,0,0,0,0,0,0,0,0,6,0,0,8 }; d4169 1 a4169 1 fseek (ifp, aoff+96 + remap_s70[wbi]*8, SEEK_SET); d4172 1 a4172 1 fseek (ifp, aoff+80 + (wbi < 6 ? remap[wbi]*8 : 0), SEEK_SET); d4179 1 a4179 1 wbi = remap_10d[wbi]; d4224 4 a4236 1 int tx=0, ty=0; d4251 1 a4251 1 data_offset = atoi(val); d4257 1 a4257 1 tx = atoi(val); d4259 1 a4259 1 ty = atoi(val); d4261 1 a4265 1 data_offset += tx * ty * 2; d4268 1 a4268 39 } void CLASS parse_mos (int offset) { char data[40]; int skip, from, i, c, neut[4]; static const unsigned bayer[] = { 0x94949494, 0x61616161, 0x16161616, 0x49494949 }; fseek (ifp, offset, SEEK_SET); while (1) { fread (data, 1, 8, ifp); if (strcmp(data,"PKTS")) break; if (!make[0]) strcpy (make, "Leaf"); fread (data, 1, 40, ifp); skip = get4(); from = ftell(ifp); #ifdef USE_LCMS if (!strcmp(data,"icc_camera_profile")) { profile_length = skip; profile_offset = from; } #endif if (!strcmp(data,"CaptProf_number_of_planes")) { fscanf (ifp, "%d", &i); if (i > 1) filters = 0; } if (!strcmp(data,"CaptProf_raw_data_rotation") && filters) { fscanf (ifp, "%d", &i); filters = bayer[i/90]; } if (!strcmp(data,"NeutObj_neutrals")) { for (i=0; i < 4; i++) fscanf (ifp, "%d", neut+i); FORC3 cam_mul[c] = (float) neut[0] / neut[c+1]; } parse_mos (from); fseek (ifp, skip+from, SEEK_SET); } d4290 1 d4304 1 a4304 1 case 0x10e: tiff_data_compression = data; break; d4315 2 a4316 2 load_raw = tiff_data_compression < 3 ? phase_one_load_raw:phase_one_load_raw_c; a4318 1 sprintf (model, "%dx%d", width, height); d4329 1 a4329 1 int entries, tag, len, save, c; d4439 1 a4439 1 int entries, off, len, tag, save, i, wide, high, pent, poff[256][2]; d4467 9 d4810 1 a4810 1 accordingly. Return nonzero if the file cannot be decoded. d4812 1 a4812 1 int CLASS identify (int no_decode) d4815 1 a4815 1 unsigned hlen, fsize, i, c, is_jpeg=0, is_canon; d4861 1 a4861 1 "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar" }; d4865 4 a4868 4 load_raw = NULL; raw_height = raw_width = fuji_width = flip = cr2_slice[0] = 0; height = width = top_margin = left_margin = 0; make[0] = model[0] = model2[0] = 0; d4871 4 a4874 1 data_offset = meta_length = tiff_bps = tiff_data_compression = 0; a4877 1 filters = UINT_MAX; /* 0 = no filters, UINT_MAX = unknown */ d4884 1 a4885 2 maximum = 0xfff; #ifdef USE_LCMS a4886 1 #endif d4894 2 a4895 2 if ((cp = memmem (head, 32, "MMMM", 4)) || (cp = memmem (head, 32, "IIII", 4))) d4897 2 a4898 1 else if (order == 0x4949 || order == 0x4d4d) { d4913 1 d4948 3 d4953 1 a4953 2 fseek (ifp, 84, SEEK_SET); if ((hlen = get4()) > 120) { d4960 2 a4961 3 i = get4(); parse_tiff (hlen+12); data_offset = i; d4982 4 a4985 3 if (make[0] == 0) is_jpeg = parse_jpeg(0); if (no_decode) return !timestamp; d4999 1 a5000 4 if (make[0] == 0) { fprintf (stderr, "%s: unsupported file format.\n", ifname); return 1; } d5003 1 d5016 1 a5016 1 if (tiff_data_compression == 1) d5018 1 a5018 1 if (tiff_data_compression == 7) a5025 1 if (filters == UINT_MAX) filters = 0x94949494; a5118 10 } else if (!strcmp(model,"EOS-1D")) { raw_height = height = 1662; raw_width = width = 2496; data_offset = 288912; filters = 0x61616161; } else if (!strcmp(model,"EOS-1DS")) { raw_height = height = 2718; raw_width = width = 4082; data_offset = 289168; filters = 0x61616161; d5148 1 a5148 1 if (tiff_data_compression == 34713 && load_raw == nikon_load_raw) d5247 1 a5247 1 tiff_data_compression = 34713; d5338 2 a5339 3 } else if (!strncmp(model,"*ist D",6)) { load_raw = model[6] ? packed_12_load_raw : unpacked_load_raw; if (model[6] == 'S') height -= 2; d5428 1 a5428 1 sprintf (model, "%dx%d", width, height); d5452 1 a5452 2 load_raw = unpacked_load_raw; if (tiff_data_compression == 99) a5472 1 load_raw = unpacked_load_raw; a5475 1 load_raw = unpacked_load_raw; a5478 1 load_raw = unpacked_load_raw; d5484 4 a5487 5 load_raw = olympus_e300_load_raw; maximum = 0xfff; if (fsize > 15728640) { load_raw = unpacked_load_raw; maximum = 0xfc30; d5515 1 a5523 1 load_raw = unpacked_load_raw; d5526 2 a5527 2 } else if (!strcasecmp(make,"KODAK") && !load_raw) { filters = 0x61616161; d5556 1 a5556 3 switch (tiff_data_compression) { case 0: /* No compression */ case 1: a5557 20 break; case 7: /* Lossless JPEG */ load_raw = lossless_jpeg_load_raw; case 32867: break; case 65000: /* Kodak DCR compression */ if (kodak_data_compression == 32803) load_raw = kodak_compressed_load_raw; else { load_raw = kodak_yuv_load_raw; height = (height+1) & -2; width = (width +1) & -2; filters = 0; } break; default: fprintf (stderr, "%s: %s %s uses unsupported compression method %d.\n", ifname, make, model, tiff_data_compression); return 1; } d5593 2 a5594 4 if (tiff_data_compression == 7) load_raw = kodak_jpeg_load_raw; else load_raw = kodak_dc120_load_raw; d5705 3 d5710 4 a5713 11 if (!load_raw || !height || is_jpeg) { fprintf (stderr, "%s: Cannot decode %s %s%s images.\n", ifname, make, model, is_jpeg ? " JPEG":""); return 1; } #ifdef NO_JPEG if (load_raw == kodak_jpeg_load_raw) { fprintf (stderr, "%s: decoder was not linked with libjpeg.\n", ifname); return 1; } #endif a5715 5 raw_color |= use_camera_rgb && colors == 3; FORCC { /* Apply user-selected color balance */ rgb_cam[0][c] *= red_scale; rgb_cam[2][c] *= blue_scale; } a5722 2 fseek (ifp, data_offset, SEEK_SET); return 0; d5725 2 a5726 2 #ifdef USE_LCMS void CLASS apply_profile (char *pfname) d5732 3 a5734 2 if (pfname) hInProfile = cmsOpenProfileFromFile (pfname, "r"); d5742 2 a5743 1 } d5745 3 a5749 5 maximum = 0xffff; use_gamma = 0; raw_color = 1; /* Don't use rgb_cam with a profile */ hOutProfile = cmsCreate_sRGBProfile(); d5753 2 a5754 1 d5756 2 a5758 1 cmsCloseProfile (hOutProfile); a5761 3 /* Convert the entire image to RGB colorspace and build a histogram. */ d5764 1 a5764 1 int row, col, c, i, fc=0; d5766 27 a5792 2 float rgb[3]; d5794 2 a5795 2 fprintf (stderr, raw_color ? "Building histograms...\n" : "Converting to sRGB colorspace...\n"); d5797 1 a5797 2 if (document_mode) colors = 1; d5803 2 a5804 2 fc = FC(row,col); if (colors == 4 && raw_color) /* Recombine the greens */ d5806 6 a5811 10 if (colors == 1) /* RGB from grayscale */ FORC3 rgb[c] = img[fc]; else if (raw_color) /* RGB from RGB (easy) */ goto norgb; else FORC3 /* RGB via rgb_cam */ for (rgb[c]=i=0; i < colors; i++) rgb[c] += img[i] * rgb_cam[c][i]; FORC3 img[c] = CLIP((int) rgb[c]); norgb: FORC3 histogram[c][img[c] >> 3]++; d5813 2 d5855 8 d5865 2 a5866 3 unsigned *flag; int size, base, dest, next, row, col; INT64 *img, hold; d5871 11 a5881 31 img = (INT64 *) image; size = height * width; flag = calloc ((size+31) >> 5, sizeof *flag); merror (flag, "flip_image()"); for (base=0; base < size; base++) { if (flag[base >> 5] & (1 << (base & 31))) continue; dest = base; hold = img[base]; while (1) { if (flip & 4) { row = dest % height; col = dest / height; } else { row = dest / width; col = dest % width; } if (flip & 2) row = height - 1 - row; if (flip & 1) col = width - 1 - col; next = row * width + col; if (next == base) break; flag[next >> 5] |= 1 << (next & 31); img[dest] = img[next]; dest = next; } img[dest] = hold; } free (flag); a5887 3 /* Write the image to an 8-bit PPM file. */ d5890 1 a5890 1 uchar (*ppm)[3], lut[0x10000]; d5894 1 a5894 2 fprintf (ofp, "P6\n%d %d\n255\n", xmag*width, ymag*height); ppm = calloc (width, 3*xmag); d5897 7 d5906 1 a5906 1 FORC3 { d5925 2 a5926 2 FORC3 for (i=0; i < xmag; i++) ppm[xmag*col+i][c] = lut[image[row*width+col][c]]; d5928 25 a5952 1 fwrite (ppm, width, 3*xmag, ofp); a5956 3 /* Write the image to a 16-bit Photoshop file. */ d5978 1 d5982 1 a5982 1 buffer = calloc (6, psize); d5988 1 a5988 1 FORC3 pred[c*psize] = htons(image[row*width+col][c]); d5991 1 a5991 1 fwrite(buffer, psize, 6, ofp); a5994 22 /* Write the image to a 16-bit PPM file. */ void CLASS write_ppm16 (FILE *ofp) { int row, col, c; ushort (*ppm)[3]; if (maximum < 256) maximum = 256; fprintf (ofp, "P6\n%d %d\n%d\n", width, height, maximum); ppm = calloc (width, 6); merror (ppm, "write_ppm16()"); for (row=0; row < height; row++) { for (col=0; col < width; col++) FORC3 ppm[col][c] = htons(image[row*width+col][c]); fwrite (ppm, width, 6, ofp); } free (ppm); } d5998 1 a5998 1 int timestamp_only=0, identify_only=0, write_to_stdout=0; d6000 1 a6000 1 char opt, *ofname, *cp; a6001 1 const char *write_ext = ".ppm"; d6003 3 a6005 2 #ifdef USE_LCMS char *profile = NULL; d6014 1 a6014 1 "\nRaw Photo Decoder \"dcraw\" v7.94" d6019 3 a6022 2 "\n-i Identify files without decoding them" "\n-c Write to standard output" d6030 4 a6033 3 "\n-m Don't convert camera RGB to sRGB" #ifdef USE_LCMS "\n-p Apply color profile from file" d6043 2 a6044 1 "\n-2 Write 8-bit PPM with 0.45 gamma (default)" a6045 1 "\n-4 Write 16-bit linear PPM" d6068 7 a6074 2 #ifdef USE_LCMS case 'p': profile = argv[arg++] ; break; d6076 1 d6078 1 d6090 1 a6090 1 case 'm': use_camera_rgb = 1; break; d6092 3 a6094 3 case '2': write_fun = write_ppm; write_ext = ".ppm"; break; case '3': write_fun = write_psd; write_ext = ".psd"; break; case '4': write_fun = write_ppm16; write_ext = ".ppm"; break; d6132 1 d6134 1 a6134 1 if ((status = identify(1))) d6137 1 a6137 1 printf ("%10ld%10d %s\n", timestamp, shot_order, ifname); d6146 33 a6178 1 if ((status = identify(0))) goto next; d6204 1 a6204 2 cp = "RGBGMCYRGBE" + (colors == 3 ? 0 : strcmp(model,"DSC-F828") ? 3 : 7); d6206 1 a6206 1 putchar (cp[filters >> i & 3]); d6240 1 d6264 2 a6265 2 #ifdef USE_LCMS apply_profile (profile); d6269 7 a6275 1 fclose(ifp); d6283 2 d6296 2 a6297 2 if (ofp != stdout) fclose(ofp); @ 1.308 log @Improved camera WB for Panasonic DMC-FZ30 and DMC-LX1. @ text @d99 1 a99 1 ushort (*image)[4], white[8][8], curve[0x1000]; d767 1 a767 1 int jwide, jrow, jcol, val, jidx, i, row, col; d781 7 a787 17 if (raw_width == 5108) { i = jidx / (1680*jh.high); if (i < 2) { row = jidx / 1680 % jh.high; col = jidx % 1680 + i*1680; } else { jidx -= 2*1680*jh.high; row = jidx / 1748; col = jidx % 1748 + 2*1680; } } else if (raw_width == 4476 || raw_width == 3516) { row = jidx / (raw_width/2); col = jidx % (raw_width/2); if (row >= raw_height) { row -= raw_height; col += raw_width/2; } d3392 2 a3393 2 fseek (ifp, strstr(model,"EOS-1D") ? 68 : strstr(model,"EOS 5D") ? 126 : 50, SEEK_CUR); d3692 3 d4329 2 d4453 1 a4453 1 { "MINOLTA DiMAGE Z2", 0, /* DJC */ d4479 2 d4649 1 a4649 1 raw_height = raw_width = fuji_width = flip = 0; d5018 1 a5018 2 } else if (!strcmp(model,"E4300")) { if (!timestamp && minolta_z2()) goto dimage_z2; d5022 6 a5027 11 pre_mul[0] = 508; pre_mul[1] = 256; pre_mul[2] = 322; } else if (!strcmp(model,"DiMAGE Z2")) { dimage_z2: strcpy (make, "MINOLTA"); strcpy (model,"DiMAGE Z2"); height = 1710; width = 2288; filters = 0x16161616; load_raw = nikon_e2100_load_raw; d5836 1 a5836 1 "\nRaw Photo Decoder \"dcraw\" v7.93" @ 1.307 log @Added the Olympus C3030Z. New color matrices for the Minolta Z2 and Kodak P850/P880. @ text @d3504 5 d3510 1 a3510 1 if (len < 50) break; d5845 1 a5845 1 "\nRaw Photo Decoder \"dcraw\" v7.92" @ 1.306 log @Moved constant black values from identify() to adobe_coeff(). @ text @d943 1 a943 1 if (model[0] == 'E') { d983 1 a983 1 Returns 1 for a Coolpix 990, 0 for a Coolpix 995. d985 1 a985 1 int CLASS nikon_e990() d991 1 a991 1 fseek (ifp, 2064*1540*3/4, SEEK_SET); d995 3 a997 3 if (histo[often[i]] > 400) return 1; return 0; d2707 1 a2707 1 for (b=0; b < 2000; b++) { d3807 1 a3807 1 if (strlen(ext) != 4 || ext-file != 8) return; d4435 2 a4436 2 { "KODAK P880", 0, /* DJC */ { 22050,-9634,-1863,-1864,9899,1966,-349,1453,4769 } }, d4453 2 a4454 2 { "MINOLTA DiMAGE Z2", 68, /* DJC */ { 11222,-3449,-1675,-5789,13566,2225,-2339,2670,5549 } }, d4620 1 a4620 1 { 4771840, "NIKON", "E990" ,1 }, /* or E995 */ d4970 1 a4970 14 } else if (!strcmp(model,"E880") || !strcmp(model,"E990")) { if (!timestamp && !nikon_e990()) goto cp_e995; height = 1540; width = 2064; colors = 4; filters = 0xb4b4b4b4; simple_coeff(3); pre_mul[0] = 1.196; pre_mul[1] = 1.246; pre_mul[2] = 1.018; } else if (!strcmp(model,"E995")) { cp_e995: strcpy (model, "E995"); d4975 10 d5840 1 a5840 1 "\nRaw Photo Decoder \"dcraw\" v7.91" @ 1.305 log @Collect interesting metadata and display it with "dcraw -i -v" @ text @d2730 1 a2730 1 fprintf (stderr, " { \"%s %s\",\n\t{ ", make, model); d2733 2 a2734 2 fprintf (stderr, "%d,", (int) (best[c][j] * num + 0.5)); fprintf (stderr, "\b } },\n"); d4311 1 a4311 1 short trans[12]; d4313 1 a4313 1 { "Canon EOS D2000", d4315 1 a4315 1 { "Canon EOS D6000", d4317 1 a4317 1 { "Canon EOS D30", d4319 1 a4319 1 { "Canon EOS D60", d4321 1 a4321 1 { "Canon EOS 5D", d4323 1 a4323 1 { "Canon EOS 20D", d4325 1 a4325 1 { "Canon EOS 350D", d4327 1 a4327 1 { "Canon EOS DIGITAL REBEL XT", d4329 1 a4329 1 { "Canon EOS-1Ds Mark II", d4331 1 a4331 1 { "Canon EOS-1D Mark II", d4333 1 a4333 1 { "Canon EOS-1DS", d4335 1 a4335 1 { "Canon EOS-1D", d4337 1 a4337 1 { "Canon EOS", d4339 1 a4339 1 { "Canon PowerShot A50", d4341 1 a4341 1 { "Canon PowerShot A5", d4343 1 a4343 1 { "Canon PowerShot G1", d4345 1 a4345 1 { "Canon PowerShot G2", d4347 1 a4347 1 { "Canon PowerShot G3", d4349 1 a4349 1 { "Canon PowerShot G5", d4351 1 a4351 1 { "Canon PowerShot G6", d4353 1 a4353 1 { "Canon PowerShot Pro1", d4355 1 a4355 1 { "Canon PowerShot Pro70", d4357 1 a4357 1 { "Canon PowerShot Pro90", d4359 1 a4359 1 { "Canon PowerShot S30", d4361 1 a4361 1 { "Canon PowerShot S40", d4363 1 a4363 1 { "Canon PowerShot S45", d4365 1 a4365 1 { "Canon PowerShot S50", d4367 1 a4367 1 { "Canon PowerShot S60", d4369 1 a4369 1 { "Canon PowerShot S70", d4371 1 a4371 1 { "Contax N Digital", d4373 1 a4373 1 { "EPSON R-D1", d4375 1 a4375 1 { "FUJIFILM FinePix E550", d4377 1 a4377 1 { "FUJIFILM FinePix F8", d4379 1 a4379 1 { "FUJIFILM FinePix F7", d4381 1 a4381 1 { "FUJIFILM FinePix S20Pro", d4383 1 a4383 1 { "FUJIFILM FinePix S2Pro", d4385 1 a4385 1 { "FUJIFILM FinePix S3Pro", d4387 1 a4387 1 { "FUJIFILM FinePix S5000", d4389 1 a4389 1 { "FUJIFILM FinePix S5100", d4391 1 a4391 1 { "FUJIFILM FinePix S5500", d4393 1 a4393 1 { "FUJIFILM FinePix S7000", d4395 1 a4395 1 { "FUJIFILM FinePix S9", d4397 1 a4397 1 { "KODAK NC2000F", /* DJC */ d4399 1 a4399 1 { "Kodak DCS315C", d4401 1 a4401 1 { "Kodak DCS330C", d4403 1 a4403 1 { "KODAK DCS420", d4405 1 a4405 1 { "KODAK DCS460", d4407 1 a4407 1 { "KODAK EOSDCS1", d4409 1 a4409 1 { "KODAK EOSDCS3B", d4411 1 a4411 1 { "Kodak DCS520C", d4413 1 a4413 1 { "Kodak DCS560C", d4415 1 a4415 1 { "Kodak DCS620C", d4417 1 a4417 1 { "Kodak DCS620X", d4419 1 a4419 1 { "Kodak DCS660C", d4421 1 a4421 1 { "Kodak DCS720X", d4423 1 a4423 1 { "Kodak DCS760C", d4425 1 a4425 1 { "Kodak DCS Pro SLR", d4427 1 a4427 1 { "Kodak DCS Pro 14nx", d4429 1 a4429 1 { "Kodak DCS Pro 14", d4431 1 a4431 1 { "Kodak ProBack645", d4433 1 a4433 1 { "Kodak ProBack", d4435 1 a4435 1 { "KODAK P880", /* DJC */ d4437 1 a4437 1 { "LEICA DIGILUX 2", d4439 1 a4439 1 { "Leaf Valeo", d4441 1 a4441 1 { "Minolta DiMAGE 5", d4443 1 a4443 1 { "Minolta DiMAGE 7Hi", d4445 1 a4445 1 { "Minolta DiMAGE 7", d4447 1 a4447 1 { "Minolta DiMAGE A1", d4449 1 a4449 1 { "MINOLTA DiMAGE A200", d4451 1 a4451 1 { "Minolta DiMAGE A2", d4453 1 a4453 1 { "MINOLTA DiMAGE Z2", /* DJC */ d4455 1 a4455 1 { "MINOLTA DYNAX 5", d4457 1 a4457 1 { "MINOLTA DYNAX 7", d4459 1 a4459 1 { "NIKON D100", d4461 1 a4461 1 { "NIKON D1H", d4463 1 a4463 1 { "NIKON D1X", d4465 1 a4465 1 { "NIKON D1", d4467 1 a4467 1 { "NIKON D2H", d4469 1 a4469 1 { "NIKON D2X", d4471 1 a4471 1 { "NIKON D50", d4473 1 a4473 1 { "NIKON D70", d4475 1 a4475 1 { "NIKON E995", /* copied from E5000 */ d4477 1 a4477 1 { "NIKON E2500", d4479 1 a4479 1 { "NIKON E4500", d4481 1 a4481 1 { "NIKON E5000", d4483 1 a4483 1 { "NIKON E5400", d4485 1 a4485 1 { "NIKON E5700", d4487 1 a4487 1 { "NIKON E8400", d4489 1 a4489 1 { "NIKON E8700", d4491 1 a4491 1 { "NIKON E8800", d4493 1 a4493 1 { "OLYMPUS C5050", d4495 1 a4495 1 { "OLYMPUS C5060", d4497 1 a4497 1 { "OLYMPUS C7070", d4499 1 a4499 1 { "OLYMPUS C70", d4501 1 a4501 1 { "OLYMPUS C80", d4503 1 a4503 1 { "OLYMPUS E-10", d4505 1 a4505 1 { "OLYMPUS E-1", d4507 1 a4507 1 { "OLYMPUS E-20", d4509 1 a4509 1 { "OLYMPUS E-300", d4511 1 a4511 1 { "OLYMPUS E-500", d4513 1 a4513 1 { "OLYMPUS SP500UZ", d4515 1 a4515 1 { "PENTAX *ist DL", d4517 1 a4517 1 { "PENTAX *ist DS", d4519 1 a4519 1 { "PENTAX *ist D", d4521 1 a4521 1 { "Panasonic DMC-FZ30", d4523 1 a4523 1 { "Panasonic DMC-LC1", d4525 1 a4525 1 { "Panasonic DMC-LX1", d4527 1 a4527 1 { "SONY DSC-F828", d4529 1 a4529 1 { "SONY DSC-R1", /* DJC */ d4531 1 a4531 1 { "SONY DSC-V3", d4541 2 a4851 1 black = 34; a5034 1 black = 68; a5056 1 black = 128; a5319 1 black = 491; a5328 1 black = 512; a5341 4 } else if (!strcmp(model,"DCS315C")) { black = 8; } else if (!strcmp(model,"DCS330C")) { black = 8; a5352 10 } else if (!strcmp(model,"DCS520C")) { black = 180; } else if (!strcmp(model,"DCS560C")) { black = 188; } else if (!strcmp(model,"DCS620C")) { black = 180; } else if (!strcmp(model,"DCS620X")) { black = 185; } else if (!strcmp(model,"DCS660C")) { black = 214; d5843 1 a5843 1 "\nRaw Photo Decoder \"dcraw\" v7.90" @ 1.304 log @Added Adobe matrix for the PENTAX *ist DL. @ text @d86 1 a86 1 float flash_used, canon_5814; d140 1 d312 1 a312 1 i = canon_5814 + 0.5; d3301 2 d3354 1 a3354 2 get2(); raw_width = get2(); d3440 2 a3441 1 int entries, tag, type, len, val, save; d3443 1 a3448 1 val = get4(); d3450 14 a3463 8 fseek (ifp, base+val, SEEK_SET); if (tag == 0x9003 || tag == 0x9004) get_timestamp(0); if (tag == 0x927c) parse_makernote(); if (!strncmp(make,"EASTMAN",7)) { if (tag == 0xa002) raw_width = val; if (tag == 0xa003) raw_height = val; d3465 1 a3465 1 fseek (ifp, save, SEEK_SET); d3592 3 d3849 1 a3849 3 get2(); if (get4() != 0x80008) return; if (get4() == 0) return; d3897 6 a3902 3 if (type == 0x102a) { /* Find the White Balance index */ fseek (ifp, aoff+14, SEEK_SET); /* 0=auto, 1=daylight, 2=cloudy ... */ wbi = get2(); a3957 2 if (type == 0x5817) shot_order = len; d3967 3 a3969 1 canon_5814 = int_to_float(len); d3974 5 d4058 1 a4058 1 FORC3 cam_mul[c] = 1.0 / neut[c+1]; d4234 1 a4234 1 char name[64]; d4242 1 a4242 2 get4(); entries = get4(); d4269 1 a4269 2 get4(); pent = get4(); d4277 3 d4281 1 a4281 1 foveon_gets (poff[i][1], make, 64); d4283 1 a4283 1 foveon_gets (poff[i][1], model, 64); d4285 1 a4285 1 foveon_gets (poff[i][1], model2, 64); d4287 7 a4293 1 timestamp = atoi (foveon_gets (poff[i][1], name, 64)); d4391 2 d4542 1 a4542 1 cam_xyz[0][j] = table[i].trans[j]; d4648 1 d4708 1 a4708 2 get4(); raw_width = get4(); d5051 1 a5051 1 maximum = 0xffff; d5694 1 a5694 1 int size, base, dest, next, row, col, temp; d5732 2 a5733 6 temp = height; height = width; width = temp; temp = ymag; ymag = xmag; xmag = temp; d5845 1 a5845 1 int half_size=0, use_fuji_rotate=1, quality; d5860 1 a5860 1 "\nRaw Photo Decoder \"dcraw\" v7.86" d5990 3 d5994 41 a6034 1 fprintf (stderr, "%s is a %s %s image.\n", ifname, make, model); a6038 3 shrink = half_size && filters; iheight = (height + shrink) >> shrink; iwidth = (width + shrink) >> shrink; @ 1.303 log @Added the Kodak P880, Olympus C7070WZ, and Olympus SP500UZ. @ text @d4488 2 @ 1.302 log @Correctly parse Sony JPEG makernotes. Fixed "memmem" conflict. @ text @d3452 4 d3573 1 d3690 7 d4368 1 a4368 1 { "FUJIFILM FinePix S9", /* copied from S7000 */ d4408 2 d4470 2 d4484 4 a4487 2 { "OLYMPUS E-500", /* copied from E-300 */ { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } }, d5276 2 d5304 2 a5305 6 height = 1950; width = 2608; data_offset = 76456; filters = 0x16161616; load_raw = packed_12_load_raw; } else if (!strcasecmp(make,"KODAK")) { d5835 1 a5835 1 "\nRaw Photo Decoder \"dcraw\" v7.85" @ 1.301 log @Improved camera WB for the Canon PowerShot G6, S60, S70, and Pro1. Avoid an infinite loop with Kodak DX3600 JPEG files. Added the AVT F-145C. @ text @d185 1 a185 1 char *memmem (char *haystack, size_t haystacklen, d194 1 d3277 1 @ 1.300 log @Correctly parse Ricoh makernotes. Support the Casio QV-R61. @ text @d3267 1 d3848 1 a3848 1 static const int remap_s70[] = { 0,1,2,9,4,3,6,7,8,9,10,0,0,0,7,0,0,8 }; d3876 1 d3900 1 a3900 3 } else if (!strcmp(model,"Canon PowerShot G6") || !strcmp(model,"Canon PowerShot S60") || !strcmp(model,"Canon PowerShot S70")) { a3902 3 } else if (!strcmp(model,"Canon PowerShot Pro1")) { fseek (ifp, aoff+96 + wbi*8, SEEK_SET); goto common; d4557 1 d5141 4 d5817 1 a5817 1 "\nRaw Photo Decoder \"dcraw\" v7.84" @ 1.299 log @Olympus ORF metadata contains an excellent rgb_cam[] matrix. @ text @d3280 1 d5479 1 a5479 1 } else if (!strcmp(model,"EX-P600")) { @ 1.298 log @Added the Kodak KAI-0340 imaging module. @ text @d3380 5 d5814 1 a5814 1 "\nRaw Photo Decoder \"dcraw\" v7.83" @ 1.297 log @Trim garbage pixels from several Nikon cameras. @ text @d4550 1 d5123 8 d5809 1 a5809 1 "\nRaw Photo Decoder \"dcraw\" v7.82" @ 1.296 log @Updated the color matrices based on Adobe DNG Converter 3.2. Added the Panasonic DMC-LX1. @ text @d4877 1 a4877 1 width = 4024; d4879 2 a4880 1 } else if (!strcmp(model,"D70")) { d4886 1 a4886 2 } else if (!strcmp(model,"D2H")) { width = 2482; d4888 1 d4890 1 a4890 1 width = 4312; @ 1.295 log @Support the Sinar STI file format. @ text @a526 1 a528 1 a531 1 a547 1 a562 1 a578 1 a3535 1 if (!make[0]) strcpy (make, "Leaf"); d3712 1 a3712 1 int doff; d3718 1 a3718 1 while ((doff = get4())) { d4002 1 d4280 1 a4280 3 { 7082,-1419,-376,-6858,14220,2900,-969,1328,7630 } }, { "Canon EOS 10D", { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, d4283 4 d4294 1 a4294 1 { 6906,-278,-1017,-6649,15074,1621,-2848,3897,7611 } }, d4397 2 d4409 1 a4409 1 { "MINOLTA DYNAX 5D", d4411 1 a4411 1 { "MINOLTA DYNAX 7D", d4414 1 a4414 1 { 5915,-949,-778,-7516,15364,2282,-1228,1337,6404 } }, d4418 1 a4418 1 { 7620,-2173,-966,-7604,15843,1805,-2356,2811,8439 } }, d4469 2 d4473 2 a4474 2 { "Panasonic DMC-FZ30", { 10473,-3277,-1222,-6421,14252,2352,-1907,2596,7460 } }, d4480 1 a4480 1 { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } } d4636 2 a4637 1 } else if (!memcmp (head,"BM",2)) { d4641 1 a4641 1 if (get4() == 2834 && get4() == 2834) { d5048 1 a5048 1 sprintf (model, "DYNAX%s", strchr (model,' ')); d5197 8 a5204 1 if (width == 3304) width -= 16; a5205 1 maximum = 0xfff0; d5799 1 a5799 1 "\nRaw Photo Decoder \"dcraw\" v7.81" @ 1.294 log @Added the Olympus E-500. @ text @d3461 1 a3461 1 char software[64]; d3542 1 a3542 1 strcpy (make, "Leaf"); d3544 1 d3599 9 d4586 1 a4586 1 "MINOLTA", "Minolta", "Konica", "CASIO" }; d4716 1 a4716 1 if (!strncmp (model, make, i++)) d5174 8 a5181 6 } else if (!strcmp(make,"Sinar") && !memcmp(head,"8BPS",4)) { fseek (ifp, 14, SEEK_SET); height = get4(); width = get4(); filters = 0x61616161; data_offset = 68; d5183 1 a5183 1 maximum = 0xffff; d5792 1 a5792 1 "\nRaw Photo Decoder \"dcraw\" v7.80" @ 1.293 log @Added casts to avoid signedness warnings with GCC 4.0. @ text @d1290 2 d1293 1 d4455 2 d5200 3 a5202 2 } else if (!strcmp(model,"E-300")) { width -= 21; d5208 1 a5208 2 } else black = 62; d5780 1 a5780 1 "\nRaw Photo Decoder \"dcraw\" v7.79" @ 1.292 log @Smoothed out single-pixel artifacts in ahd_interpolate(). @ text @d225 1 d1526 1 a1526 1 static char jpeg_buffer[4096]; d1976 1 a1976 1 read_shorts (diff, 1024); d2116 1 a2116 1 int CLASS foveon_apply_curve (ushort *curve, int i) d2122 2 d2364 1 a2364 1 for (pix=image[0]; pix < (short *) image[height*width]; pix+=4) { d2433 1 a2433 1 for (pix=image[0]; pix < (short *) image[height*width]; pix+=4) { d2520 1 d3987 1 a3987 1 uchar data[40]; @ 1.291 log @Silently ignore the "-w" flag for DNG files. Refactored Fuji FinePix support yet again. @ text @d135 5 a139 3 #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define CLIP(x) (MAX(0,MIN((x),clip_max))) d3086 1 a3086 1 rgb[0][row-top][col-left][1] = CLIP(val); d3089 1 a3089 1 rgb[1][row-top][col-left][1] = CLIP(val); d5771 1 a5771 1 "\nRaw Photo Decoder \"dcraw\" v7.78" @ 1.290 log @Support "-w" with the Fuji FinePix S9000/S9500. @ text @d104 1 a104 1 int fuji_secondary, use_secondary=0; d1099 1 a1099 1 void CLASS fuji_s2_load_raw() d1101 1 a1101 31 ushort pixel[2944]; int row, col, r, c; for (row=0; row < 2144; row++) { read_shorts (pixel, 2944); for (col=0; col < 2880; col++) { r = row + ((col+1) >> 1); c = 2143 - row + (col >> 1); BAYER(r,c) = pixel[col]; } } } void CLASS fuji_s3_load_raw() { ushort pixel[4352]; int row, col, r, c; for (row=0; row < 1440; row++) { read_shorts (pixel, 4352); for (col=0; col < 4288; col++) { r = 2143 + row - (col >> 1); c = row + ((col+1) >> 1); BAYER(r,c) = pixel[col]; } } } void CLASS fuji_common_load_raw() { ushort pixel[2944]; d1104 2 d1108 8 a1115 3 for (col=0; col <= fuji_width; col++) { r = fuji_width - col + (row >> 1); c = col + ((row+1) >> 1); d1119 1 d4084 8 d4096 4 d4652 6 a4657 1 parse_tiff (get4()+12); d4659 3 a4661 2 fread (&data_offset, 4, 1, ifp); data_offset = ntohl(data_offset); d4721 1 a4970 19 } else if (!strcmp(model,"FinePixS2Pro")) { height = 3584; width = 3583; fuji_width = 2144; data_offset += (24*2944+32)*2; filters = 0x61616161; load_raw = fuji_s2_load_raw; black = 128; strcpy (model+7, " S2Pro"); } else if (!strcmp(model,"FinePix S3Pro")) { height = 3583; width = 3584; fuji_width = 2144; data_offset += (2*4352+32)*2; if (fsize > 18000000 && use_secondary) data_offset += 1444*4352*2; filters = 0x49494949; load_raw = fuji_s3_load_raw; maximum = 0x3dfd; a4972 4 height = 1735; width = 2304; data_offset += width*10; filters = 0x49494949; d4975 21 a4995 31 } else if (!strcmp(model,"FinePix S5000")) { raw_height = 2152; raw_width = 1472; fuji_width = 1423; data_offset += (4*raw_width+24)*2; goto fuji_common; } else if (!strcmp(model,"FinePix E550") || !strncmp(model,"FinePix F8",10) || !strcmp(model,"FinePix S7000")) { raw_height = 3080; raw_width = 2048; fuji_width = 2047; goto fuji_common; } else if (!strcmp(model,"FinePix S9000") || !strcmp(model,"FinePix S9500")) { raw_height = 3688; raw_width = 2512; fuji_width = 2447; data_offset += 64; goto fuji_common; } else if (!strncmp(model,"FinePix F7",10) || !strcmp(model,"FinePix S20Pro")) { raw_height = 2168; raw_width = 2944; fuji_width = 1439; data_offset += 32 + use_secondary*2944; fuji_common: width = 1 + (height = raw_height/2 + fuji_width); load_raw = fuji_common_load_raw; filters = 0x49494949; maximum = 0x3e00; d5569 1 a5569 1 fuji_width = (fuji_width + shrink) >> shrink; d5752 1 a5752 1 int arg, status=0, user_flip=-1, user_black=-1; d5754 1 a5754 1 int half_size=0, use_fuji_rotate=1, quality=3; d5769 1 a5769 1 "\nRaw Photo Decoder \"dcraw\" v7.77" d5789 1 a5789 1 "\n-q [0-3] Set the interpolation quality (default = 3)" d5820 1 a5820 1 case 'q': quality = atoi(argv[arg++]); break; d5921 2 d5931 1 a5931 1 else if (quality < 3 || colors > 3 || fuji_width) @ 1.289 log @Added the Fuji S9000/S9500 and refactored Fuji code. Added camera white balance for Sony SR2 files. Improved color for the Kodak DC40/DC50/DC120, fixed DC50 bug. Detect and reject more non-raw images. @ text @d4101 1 a4101 1 if (entries > 60) return; @ 1.288 log @Added the Canon EOS 5D. @ text @d88 1 a88 1 unsigned shot_order; a1103 1 fseek (ifp, (2944*24+32)*2, SEEK_CUR); a1118 1 fseek (ifp, (4352*2+32)*2, SEEK_CUR); d1129 1 a1129 1 void CLASS fuji_common_load_raw (int ncol, int icol, int nrow) d1131 1 a1131 1 ushort pixel[2048]; d1134 4 a1137 4 for (row=0; row < nrow; row++) { read_shorts (pixel, ncol); for (col=0; col <= icol; col++) { r = icol - col + (row >> 1); a1143 32 void CLASS fuji_s5000_load_raw() { fseek (ifp, (1472*4+24)*2, SEEK_CUR); fuji_common_load_raw (1472, 1423, 2152); } void CLASS fuji_s7000_load_raw() { fuji_common_load_raw (2048, 2047, 3080); } /* The Fuji Super CCD SR has two photodiodes for each pixel. The secondary has about 1/16 the sensitivity of the primary, but this ratio may vary. */ void CLASS fuji_f700_load_raw() { ushort pixel[2944]; int row, col, r, c, val; for (row=0; row < 2168; row++) { read_shorts (pixel, 2944); for (col=0; col < 1440; col++) { r = 1439 - col + (row >> 1); c = col + ((row+1) >> 1); val = pixel[col+16 + use_secondary*1472]; BAYER(r,c) = val; } } } d1456 2 a1457 2 if (model[2] == '5') return (getbits(6) << 2) + 2; /* DC50 */ d1532 1 a1532 1 maximum = 0x1fff; /* wild guess */ d3045 1 a3045 1 static float cbrt[0x10000], xyz_cam[3][3]; d3466 2 a3467 1 void parse_mos(int offset); d3479 2 d3569 6 d3595 9 d3676 5 d3689 16 d3731 1 d4346 2 d4492 3 a4494 1 /* index 2 -- Nikon E700, E800, and E950 */ d4585 1 a4585 1 zero_after_ff = dng_version = fuji_secondary = 0; d4879 1 a4879 1 simple_coeff(2); d4891 1 a4891 1 simple_coeff(2); d4902 1 a4902 1 simple_coeff(2); d4978 1 d4987 1 d4989 1 a4989 1 data_offset += 4352*2*1444; a4992 7 } else if (!strcmp(model,"FinePix S5000")) { height = 2499; width = 2500; fuji_width = 1423; filters = 0x49494949; load_raw = fuji_s5000_load_raw; maximum = 0x3e00; d5001 6 d5010 2 a5011 2 height = 3587; width = 3588; d5013 8 a5020 3 filters = 0x49494949; load_raw = fuji_s7000_load_raw; maximum = 0x3e00; d5023 7 a5029 3 height = 2523; width = 2524; fuji_width = 1440; a5030 1 load_raw = fuji_f700_load_raw; d5389 1 d5805 1 a5805 1 "\nRaw Photo Decoder \"dcraw\" v7.74" @ 1.287 log @Interpolate every pixel -- do not trim borders. Changed "-q" flag to take a numeric argument. Allow "-z" to work with Canon camera AVI files. @ text @d95 1 a95 1 int dng_version, is_canon, is_foveon, raw_color, use_gamma; d792 3 a794 3 } else if (raw_width == 3516) { row = jidx / 1758; col = jidx % 1758; d797 1 a797 1 col += 1758; a1787 1 maximum = 0xe74; d3444 2 a3445 1 fseek (ifp, strstr(model,"EOS-1D") ? 68:50, SEEK_CUR); d3549 1 a3549 1 if (level) maximum = (1 << (tiff_bps = get2())) - 1; d4270 2 d4521 1 a4521 1 unsigned hlen, fsize, i, c, is_jpeg=0; d4721 1 a4721 1 if ((is_canon = !strcmp(make,"Canon"))) d4724 2 d4833 4 d5209 1 d5785 1 a5785 1 "\nRaw Photo Decoder \"dcraw\" v7.73" @ 1.286 log @Removed edge-sensing from ahd_interpolate() to save time. Added bilateral_filter() to smooth noise while preserving edges. If a file contains multiple timestamps, use only the first. If a Canon CRW camera is set to Auto WB, use _my_ Auto WB. @ text @d88 1 d90 1 a90 1 int tiff_data_compression, kodak_data_compression; d96 1 a96 1 int trim, flip, xmag, ymag; d102 1 a102 1 int four_color_rgb=0, document_mode=0, quick_interpolate=0; d879 1 a879 1 int row, col, nbits; a882 1 for (nbits=0; 1 << nbits <= maximum; nbits++); d884 1 a884 1 if (nbits == 16) d889 1 a889 1 pixel[col] = getbits(nbits); d1071 2 a1072 2 uchar data[3432], *dp; ushort pixel[2288], *pix; d1515 1 a1515 2 for (i=0; i < 3; i++) mul[i] = getbits(6); d2881 61 d2980 1 a2980 1 int row, col, shift, x, y, x1, x2, y1, y2, t, weight, grads, color, diag; d2983 2 a2984 37 if (verbose) fprintf (stderr, "%s interpolation...\n", quick_interpolate ? "Bilinear":"VNG"); for (row=0; row < 8; row++) { /* Precalculate for bilinear */ for (col=1; col < 3; col++) { ip = code[row][col & 1]; memset (sum, 0, sizeof sum); for (y=-1; y <= 1; y++) for (x=-1; x <= 1; x++) { shift = (y==0) + (x==0); if (shift == 2) continue; color = FC(row+y,col+x); *ip++ = (width*y + x)*4 + color; *ip++ = shift; *ip++ = color; sum[color] += 1 << shift; } FORCC if (c != FC(row,col)) { *ip++ = c; *ip++ = sum[c]; } } } for (row=1; row < height-1; row++) { /* Do bilinear interpolation */ for (col=1; col < width-1; col++) { pix = image[row*width+col]; ip = code[row & 7][col & 1]; memset (sum, 0, sizeof sum); for (g=8; g--; ip+=3) sum[ip[2]] += pix[ip[0]] << ip[1]; for (g=colors; --g; ip+=2) pix[ip[0]] = sum[ip[0]] / ip[1]; } } if (quick_interpolate) return; d3121 2 d3133 2 a3134 2 /* Horizontally interpolate green into rgb[0]: */ for (row = top; row < top+TS && row < height; row++) { a3141 7 } } /* Vertically interpolate green into rgb[1]: */ for (row = top < 2 ? 2:top; row < top+TS && row < height-2; row++) { col = left + (FC(row,left) == 1); for (fc = FC(row,col); col < left+TS && col < width; col+=2) { pix = image + row*width+col; d3149 1 a3149 2 for (row=top+1; row < top+TS-1 && row < height-1; row++) { tr = row-top; a3150 1 tc = col-left; d3152 1 a3152 1 rix = &rgb[d][tr][tc]; d3169 1 a3169 1 FORC3 lab[d][tr][tc][c] = 64*flab[c]; a3170 1 } a3212 1 trim = 3; d3350 2 a3461 1 time_t ts; d3476 2 a3477 3 putenv ("TZ=UTC"); /* Remove this to assume local time */ if ((ts = mktime(&t)) > 0) timestamp = ts; d3549 1 a3549 1 if (level) maximum = (1 << get2()) - 1; d3574 3 a3576 1 if (!strncmp(software,"Adobe",5)) d3932 2 d3936 4 a3962 1 time_t ts; d3988 2 a3989 3 putenv ("TZ="); if ((ts = mktime(&t)) > 0) timestamp = ts; d4127 31 d4244 3 d4516 1 a4516 1 int CLASS identify (int will_decode) d4572 1 a4572 1 data_offset = meta_length = tiff_data_compression = 0; d4574 1 a4574 1 timestamp = tiff_samples = black = is_foveon = 0; d4654 3 d4675 1 d5466 2 a5467 3 if (will_decode) fprintf (stderr, "%s: Cannot decode %s %s%s images.\n", ifname, make, model, is_jpeg ? " JPEG":""); d5545 2 a5546 2 for (row = trim; row < height-trim; row++) for (col = trim; col < width-trim; col++) { d5662 2 a5663 3 fprintf (ofp, "P6\n%d %d\n255\n", xmag*(width-trim*2), ymag*(height-trim*2)); ppm = calloc (width-trim*2, 3*xmag); d5685 2 a5686 2 for (row=trim; row < height-trim; row++) { for (col=trim; col < width-trim; col++) d5688 1 a5688 1 ppm[xmag*(col-trim)+i][c] = lut[image[row*width+col][c]]; d5690 1 a5690 1 fwrite (ppm, width-trim*2, 3*xmag, ofp); d5716 2 a5717 2 hw[0] = htonl(height-trim*2); /* write the header */ hw[1] = htonl(width-trim*2); d5721 1 a5721 1 psize = (height-trim*2) * (width-trim*2); d5726 2 a5727 2 for (row = trim; row < height-trim; row++) for (col = trim; col < width-trim; col++) { d5744 1 a5744 2 fprintf (ofp, "P6\n%d %d\n%d\n", width-trim*2, height-trim*2, maximum); d5746 1 a5746 1 ppm = calloc (width-trim*2, 6); d5749 4 a5752 4 for (row = trim; row < height-trim; row++) { for (col = trim; col < width-trim; col++) FORC3 ppm[col-trim][c] = htons(image[row*width+col][c]); fwrite (ppm, width-trim*2, 6, ofp); d5761 1 a5761 1 int half_size=0, use_fuji_rotate=1, use_vng=0; d5770 3 d5776 1 a5776 1 "\nRaw Photo Decoder \"dcraw\" v7.70" d5796 2 a5797 3 "\n-V Use VNG interpolation" "\n-q Quick, low-quality bilinear interpolation" "\n-h Half-size color image (3x faster than -q)" d5813 1 a5813 1 if ((strchr("Bbrlkt", opt) && !isdigit(argv[arg][0])) || d5827 1 a5837 2 case 'V': use_vng = 1; break; case 'q': quick_interpolate = 1; break; d5886 1 a5886 2 identify(0); if ((status = !timestamp)) d5888 2 d5898 1 a5898 1 if ((status = identify(1))) goto next; d5933 4 a5936 2 if ((trim = filters && !document_mode)) { if (quick_interpolate || use_vng || colors > 3) @ 1.285 log @Added the Kodak P850. @ text @d100 1 a100 1 float bright=1.0, red_scale=1.0, blue_scale=1.0; d3050 28 d3086 1 a3086 2 int i, j, k, top, left, row, col, tr, tc, fc, c, d, val; int west, east, north, south, num, total[3], hm[3]; d3089 2 a3090 3 static const float d65[3] = { 0.950456, 1, 1.088754 }; unsigned ldiff[3][4], abdiff[3][4], leps, abeps; float r, *cbrt, xyz[3], xyz_cam[3][3]; d3096 1 a3096 1 buffer = malloc (0x40000 + 39*TS*TS); /* 2752 kB */ d3098 3 a3100 14 cbrt = (void *) buffer; rgb = (void *) (buffer + 0x40000); lab = (void *) (buffer + 0x40000 + 18*TS*TS); homo = (void *) (buffer + 0x40000 + 36*TS*TS); /* Prepare conversion from raw color to CIELab: */ for (i=0; i < 0x10000; i++) { r = (float) i / maximum; cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0; } for (i=0; i < 3; i++) for (j=0; j < 3; j++) for (xyz_cam[i][j] = k=0; k < 3; k++) xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65[i]; d3104 1 a3104 1 memset (rgb, 0, 18*TS*TS); a3126 23 /* Combine these into rgb[2] using edge-sensing: */ for (row = top < 1 ? 1:top; row < top+TS && row < height-1; row++) { tr = row - top; col = left + (FC(row,left) == 1); if (col < 1) col += 2; for ( ; col < left+TS && col < width-1; col+=2) { tc = col - left; pix = image + row*width+col; west = rgb[0][tr][tc][1] - pix[-1][1]; east = rgb[0][tr][tc][1] - pix[+1][1]; north = rgb[1][tr][tc][1] - pix[-width][1]; south = rgb[1][tr][tc][1] - pix[+width][1]; if ((val = ABS(west) + ABS(east) - ABS(north) - ABS(south))) rgb[2][tr][tc][1] = rgb[val > 0][tr][tc][1]; else { west *= east; north *= south; rgb[2][tr][tc][1] = (west*north < 0) ? rgb[west > 0][tr][tc][1] : (rgb[0][tr][tc][1] + rgb[1][tr][tc][1]) >> 1; } } } d3128 1 a3128 1 for (d=0; d < 3; d++) d3137 2 a3138 2 val = ( pix[-1][2-c] + pix[1][2-c] + 2*pix[0][1] - rix[-1][1] - rix[1][1] ) >> 1; d3140 7 a3146 14 val = ( pix[-width][c] + pix[width][c] + 2*pix[0][1] - rix[-TS][1] - rix[TS][1] ) >> 1; } else { north = 2*rix[0][1] - (rix[-TS-1][1] + rix[TS+1][1]); west = 2*rix[0][1] - (rix[-TS+1][1] + rix[TS-1][1]); val = (d < 2) ? 0 : ABS(pix[-width-1][c] - pix[width+1][c]) + ABS(north) - ABS(pix[-width+1][c] - pix[width-1][c]) - ABS(west); north += pix[-width-1][c] + pix[width+1][c]; west += pix[-width+1][c] + pix[width-1][c]; if (val == 0) val = (north + west) >> 2; else if (val < 0) val = north >> 1; else val = west >> 1; } d3150 2 a3151 8 for (i=0; i < 3; i++) { for (xyz[i]=0.5, c=0; c < 3; c++) xyz[i] += xyz_cam[i][c] * rix[0][c]; xyz[i] = cbrt[CLIP((int) xyz[i])]; } lab[d][tr][tc][0] = 32*116 * xyz[1] - 32*16; lab[d][tr][tc][1] = 32*500 * (xyz[0] - xyz[1]); lab[d][tr][tc][2] = 32*200 * (xyz[1] - xyz[2]); d3155 1 a3155 1 memset (homo, 0, 3*TS*TS); d3160 1 a3160 1 for (d=0; d < 3; d++) d3165 1 a3165 1 for (d=0; d < 3; d++) d3172 1 a3172 1 for (d=0; d < 3; d++) d3183 1 a3183 1 for (d=0; d < 3; d++) d3187 5 a3191 7 FORC3 total[c] = 0; for (num=d=0; d < 3; d++) if (hm[d] >= hm[0] && hm[d] >= hm[1] && hm[d] >= hm[2]) { FORC3 total[c] += rgb[d][tr][tc][c]; num++; } FORC3 image[row*width+col][c] = total[c] / num; d3200 57 d3448 1 d3877 1 a3931 2 if (wbi == 0 && !strcmp(model,"Canon EOS D30")) camera_red = -1; /* Use my auto WB for this photo */ d5716 1 a5716 1 "\nRaw Photo Decoder \"dcraw\" v7.65" d5740 1 d5754 3 a5756 2 if (strchr ("brlkt", opt) && !isdigit(argv[arg][0])) { fprintf (stderr, "\"-%c\" requires a numeric argument.\n", opt); d5761 2 d5873 1 d5879 1 @ 1.284 log @For CIELab, divide XYZ by the D65 white point. Added "-V" flag to always use vng_interpolate(). @ text @d4472 1 a4472 1 { "Canon", "NIKON", "EPSON", "Kodak", "OLYMPUS", "PENTAX", d5147 6 d5682 1 a5682 1 "\nRaw Photo Decoder \"dcraw\" v7.64" @ 1.283 log @Added the SONY DSC-R1. @ text @d3062 1 d3085 1 a3085 1 xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j]; d5664 1 a5664 1 int half_size=0, use_fuji_rotate=1; d5676 1 a5676 1 "\nRaw Photo Decoder \"dcraw\" v7.63" d5696 2 a5697 1 "\n-q Quick, low-quality color interpolation" d5734 1 d5830 1 a5830 1 if (quick_interpolate || colors > 3) @ 1.282 log @Always treat RGB as four colors until the end of scale_colors(). Read bit-packed uncompressed DNG files (untested). @ text @d2754 1 d2838 1 d4365 2 d5141 5 a5389 2 if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1; if (cam_mul[3] == 0) cam_mul[3] = colors < 4 ? cam_mul[1] : 1; d5675 1 a5675 1 "\nRaw Photo Decoder \"dcraw\" v7.62" @ 1.281 log @Don't add integers to a void pointer. @ text @d443 1 a443 1 static unsigned long bitbuf=0; d445 1 a445 1 unsigned c, ret; a446 3 if (nbits == 0 || nbits > vbits) return 0; if (nbits == -2) return ftell(ifp) + (-vbits >> 3); d448 3 a450 6 ret = bitbuf = vbits = reset = 0; else { ret = bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - nbits); vbits -= nbits; } while (!reset && vbits < LONG_BIT - 7) { d452 1 a452 1 if ((reset = zero_after_ff && c == 0xff && fgetc(ifp))) break; d456 2 a457 1 return ret; d754 1 d878 1 a878 1 int row, col; d882 1 d884 7 a890 1 read_shorts (pixel, raw_width * tiff_samples); d1898 1 a1898 1 if (getbits(-2) + 12 > seg[1][1]) d2800 2 a2801 2 FORCC min[c] = INT_MAX; FORCC max[c] = count[c] = sum[c] = 0; d2804 1 a2804 1 FORCC { d2815 1 a2815 1 FORCC pre_mul[c] = count[c] / sum[c]; d2818 1 a2818 1 FORCC count[c] = sum[c] = 0; d2826 2 a2827 4 val = 1; FORCC if (sum[c] == 0) val = 0; if (val) FORCC pre_mul[c] = count[c] / sum[c]; d2838 1 a2838 1 FORCC if (dmin > pre_mul[c]) d2840 1 a2840 1 FORCC pre_mul[c] /= dmin; d2843 1 a2843 1 FORCC pre_mul[c] *= 1 << shift; d2850 1 a2850 1 FORCC pre_mul[c] *= bright; d2854 1 a2854 1 FORCC fprintf (stderr, " %f", pre_mul[c]); d2860 1 a2860 1 FORCC { d2867 11 d3440 2 a3441 6 if (tag == 0x927c) { if (!strncmp(make,"SONY",4)) data_offset = base+val+len; else parse_makernote(); } d3939 1 a3939 1 int skip, from, i, neut[4]; d3967 1 a3967 2 camera_red = (float) neut[2] / neut[1]; camera_blue = (float) neut[2] / neut[3]; d4483 2 a4484 2 cam_mul[i] = 1 & i; pre_mul[i] = 1; d5127 1 d5135 1 d5374 1 a5374 1 if (four_color_rgb && filters && colors == 3) { d5381 2 a5382 5 colors++; cam_mul[3] = cam_mul[1]; pre_mul[3] = pre_mul[1]; FORC3 rgb_cam[c][3] = rgb_cam[c][1] /= 2; } d5668 1 a5668 1 "\nRaw Photo Decoder \"dcraw\" v7.60" @ 1.280 log @Renamed "coeff" to "rgb_cam", and "!use_coeff" to "raw_color". Added SRGB_GAMMA compile option and "-k" flag to set black point. Use Adaptive Homogeneity-Directed interpolation when colors == 3. @ text @d3058 3 a3060 3 rgb = (void *) buffer + 0x40000; lab = (void *) buffer + 0x40000 + 18*TS*TS; homo = (void *) buffer + 0x40000 + 36*TS*TS; @ 1.279 log @Added the Pentax *ist DL. @ text @d94 1 a94 1 int dng_version, is_canon, is_foveon, use_coeff, use_gamma; d104 5 a108 1 float cam_mul[4], pre_mul[4], coeff[3][4]; d132 6 d362 2 a363 3 for (i=0; i < 3; i++) FORCC coeff[i][c] = table[t][i*4 + c] / 1024.0; use_coeff = 1; d2245 1 a2245 1 FORC3 trans[i][j] += coeff[i][c] * last[c][j] * div[j]; a2662 4 static const double xyz_rgb[3][3] = { /* XYZ from RGB */ { 0.412453, 0.357580, 0.180423 }, { 0.212671, 0.715160, 0.072169 }, { 0.019334, 0.119193, 0.950227 } }; d2679 1 a2679 1 for (i=0; i < 3; i++) d2681 1 a2681 2 coeff[i][j] = inverse[j][i]; use_coeff = 1; d2832 1 a2832 1 if (!use_coeff) { d2864 1 a2864 3 if (val < 0) val = 0; if (val > clip_max) val = clip_max; image[row*width+col][c] = val; d2939 4 a2942 9 for (g=8; g--; ) { diff = pix[*ip++]; diff <<= *ip++; sum[*ip++] += diff; } for (g=colors; --g; ) { c = *ip++; pix[c] = sum[c] / *ip++; } d2945 1 a2945 2 if (quick_interpolate) return; d2988 2 a2989 2 num = (diff = pix[g] - pix[ip[1]]) >> 31; gval[ip[3]] += (diff = ((diff ^ num) - num) << ip[2]); d3021 3 a3023 6 if (c != color) { t += (sum[c] - sum[color])/num; if (t < 0) t = 0; if (t > clip_max) t = clip_max; } brow[2][col][c] = t; d3036 172 d3987 3 a3989 1 use_coeff = 1; d3991 1 a3991 5 for (i=0; i < 3; i++) if (tag == 0x106) FORC3 coeff[i][c] = int_to_float(get4()); else cam_mul[i] = pre_mul[i] = int_to_float(get4()); d4387 2 a4388 3 for (i=0; i < 3; i++) FORCC coeff[i][c] = table[index][i*colors+c]; use_coeff = 1; a4469 1 timestamp = tiff_samples = 0; d4472 2 a4473 2 black = is_foveon = use_coeff = 0; use_gamma = xmag = ymag = 1; d4478 1 d5344 1 a5344 1 if (!use_coeff) adobe_coeff(); d5360 5 a5364 7 if (use_camera_rgb && colors == 3) use_coeff = 0; if (use_coeff) /* Apply user-selected color balance */ for (i=0; i < colors; i++) { coeff[0][i] *= red_scale; coeff[2][i] *= blue_scale; } d5375 1 a5375 2 if (use_coeff) FORC3 coeff[c][3] = coeff[c][1] /= 2; d5402 2 a5403 1 use_gamma = use_coeff = 0; d5421 1 a5421 1 int row, col, r, g, c=0; d5426 2 a5427 2 fprintf (stderr, use_coeff ? "Converting to sRGB colorspace...\n" : "Building histograms...\n"); d5436 2 a5437 2 c = FC(row,col); if (colors == 4 && !use_coeff) /* Recombine the greens */ d5440 2 a5441 7 for (r=0; r < 3; r++) rgb[r] = img[c]; else if (use_coeff) { /* RGB via coeff[][] */ for (r=0; r < 3; r++) for (rgb[r]=g=0; g < colors; g++) rgb[r] += img[g] * coeff[r][g]; } else /* RGB from RGB (easy) */ d5443 4 a5446 5 for (r=0; r < 3; r++) { if (rgb[r] < 0) rgb[r] = 0; if (rgb[r] > clip_max) rgb[r] = clip_max; img[r] = rgb[r]; } d5448 1 a5448 2 for (r=0; r < 3;