head 1.478; access; symbols; locks; strict; comment @ * @; 1.478 date 2018.06.01.20.36.25; author dcoffin; state Exp; branches; next 1.477; 1.477 date 2016.05.10.21.30.43; author dcoffin; state Exp; branches; next 1.476; 1.476 date 2015.05.25.02.29.14; author dcoffin; state Exp; branches; next 1.475; 1.475 date 2015.04.11.00.08.36; author dcoffin; state Exp; branches; next 1.474; 1.474 date 2015.04.10.20.54.50; author dcoffin; state Exp; branches; next 1.473; 1.473 date 2015.02.25.18.18.18; author dcoffin; state Exp; branches; next 1.472; 1.472 date 2015.02.23.23.15.48; author dcoffin; state Exp; branches; next 1.471; 1.471 date 2015.02.23.03.53.34; author dcoffin; state Exp; branches; next 1.470; 1.470 date 2015.02.13.03.48.53; author dcoffin; state Exp; branches; next 1.469; 1.469 date 2015.02.10.23.02.37; author dcoffin; state Exp; branches; next 1.468; 1.468 date 2015.01.30.05.02.56; author dcoffin; state Exp; branches; next 1.467; 1.467 date 2014.07.03.21.19.24; author dcoffin; state Exp; branches; next 1.466; 1.466 date 2014.06.29.21.25.57; author dcoffin; state Exp; branches; next 1.465; 1.465 date 2014.06.28.23.32.30; author dcoffin; state Exp; branches; next 1.464; 1.464 date 2014.06.13.23.01.50; author dcoffin; state Exp; branches; next 1.463; 1.463 date 2014.05.05.22.03.20; author dcoffin; state Exp; branches; next 1.462; 1.462 date 2014.05.05.03.50.20; author dcoffin; state Exp; branches; next 1.461; 1.461 date 2014.01.31.04.05.31; author dcoffin; state Exp; branches; next 1.460; 1.460 date 2014.01.26.23.56.04; author dcoffin; state Exp; branches; next 1.459; 1.459 date 2014.01.16.21.27.02; author dcoffin; state Exp; branches; next 1.458; 1.458 date 2014.01.15.00.24.09; author dcoffin; state Exp; branches; next 1.457; 1.457 date 2014.01.14.21.54.46; author dcoffin; state Exp; branches; next 1.456; 1.456 date 2013.06.16.18.01.08; author dcoffin; state Exp; branches; next 1.455; 1.455 date 2013.06.01.14.47.41; author dcoffin; state Exp; branches; next 1.454; 1.454 date 2012.12.23.19.25.36; author dcoffin; state Exp; branches; next 1.453; 1.453 date 2012.12.23.03.39.15; author dcoffin; state Exp; branches; next 1.452; 1.452 date 2012.07.23.04.28.00; author dcoffin; state Exp; branches; next 1.451; 1.451 date 2012.07.05.04.33.11; author dcoffin; state Exp; branches; next 1.450; 1.450 date 2012.06.30.20.36.46; author dcoffin; state Exp; branches; next 1.449; 1.449 date 2012.06.26.02.43.41; author dcoffin; state Exp; branches; next 1.448; 1.448 date 2012.06.18.19.44.18; author dcoffin; state Exp; branches; next 1.447; 1.447 date 2011.12.26.17.31.23; author dcoffin; state Exp; branches; next 1.446; 1.446 date 2011.12.21.01.21.23; author dcoffin; state Exp; branches; next 1.445; 1.445 date 2011.10.07.01.00.37; author dcoffin; state Exp; branches; next 1.444; 1.444 date 2011.07.23.20.33.32; author dcoffin; state Exp; branches; next 1.443; 1.443 date 2011.05.11.03.09.54; author dcoffin; state Exp; branches; next 1.442; 1.442 date 2011.04.01.23.30.09; author dcoffin; state Exp; branches; next 1.441; 1.441 date 2011.02.19.04.26.53; author dcoffin; state Exp; branches; next 1.440; 1.440 date 2011.01.29.07.43.38; author dcoffin; state Exp; branches; next 1.439; 1.439 date 2010.11.11.12.43.11; author dcoffin; state Exp; branches; next 1.438; 1.438 date 2010.07.28.21.18.20; author dcoffin; state Exp; branches; next 1.437; 1.437 date 2010.06.27.00.23.33; author dcoffin; state Exp; branches; next 1.436; 1.436 date 2010.06.14.19.44.30; author dcoffin; state Exp; branches; next 1.435; 1.435 date 2010.06.11.07.03.46; author dcoffin; state Exp; branches; next 1.434; 1.434 date 2010.05.30.15.57.43; author dcoffin; state Exp; branches; next 1.433; 1.433 date 2010.05.28.01.29.41; author dcoffin; state Exp; branches; next 1.432; 1.432 date 2009.12.25.18.51.16; author dcoffin; state Exp; branches; next 1.431; 1.431 date 2009.09.22.16.06.07; author dcoffin; state Exp; branches; next 1.430; 1.430 date 2009.09.19.05.00.03; author dcoffin; state Exp; branches; next 1.429; 1.429 date 2009.09.17.03.52.31; author dcoffin; state Exp; branches; next 1.428; 1.428 date 2009.08.31.15.23.49; author dcoffin; state Exp; branches; next 1.427; 1.427 date 2009.08.28.23.09.34; author dcoffin; state Exp; branches; next 1.426; 1.426 date 2009.08.14.04.51.38; author dcoffin; state Exp; branches; next 1.425; 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.478 log @Caught up on two years' worth of new cameras. @ text @/* dcraw.c -- Dave Coffin's raw photo decoder Copyright 1997-2018 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 DCRAW_VERSION "9.28" #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #define _USE_MATH_DEFINES #include #include #include #include #include #include #include #include #include #include #include #include #if defined(DJGPP) || defined(__MINGW32__) #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 NODEPS #define NO_JASPER #define NO_JPEG #define NO_LCMS #endif #ifndef NO_JASPER #include /* Decode Red camera movies */ #endif #ifndef NO_JPEG #include /* Decode compressed Kodak DC120 photos */ #endif /* and Adobe Lossy DNGs */ #ifndef NO_LCMS #include /* Support color profiles */ #endif #ifdef LOCALEDIR #include #define _(String) gettext(String) #else #define _(String) (String) #endif #if !defined(uchar) #define uchar unsigned char #endif #if !defined(ushort) #define ushort unsigned short #endif /* All global variables are defined here, and all functions that access them are prefixed with "CLASS". For thread-safety, all non-const static local variables except cbrt[] must be declared "thread_local". */ FILE *ifp, *ofp; short order; const char *ifname; char *meta_data, xtrans[6][6], xtrans_abs[6][6]; 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; off_t strip_offset, data_offset; off_t thumb_offset, meta_offset, profile_offset; unsigned shot_order, kodak_cbpp, exif_cfa, unique_id; 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; unsigned flip, tiff_flip, filters, colors; ushort raw_height, raw_width, height, width, top_margin, left_margin; ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; ushort *raw_image, (*image)[4], cblack[4102]; ushort white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4]; double pixel_aspect, aber[4]={1,1,1,1}, gamm[6]={ 0.45,4.5,0,0,0,0 }; float bright=1, user_mul[4]={0,0,0,0}, threshold=0; int mask[8][4]; 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; int tile_width, tile_length; float shutter; } tiff_ifd[10]; struct ph1 { int format, key_off, tag_21a; int black, split_col, black_col, split_row, black_row; 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((int)(x),0,65535) #define SWAP(a,b) { a=a+b; b=a-b; a=a-b; } /* 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 RAW(row,col) \ raw_image[(row)*raw_width+(col)] #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)][fcol(row,col)] int CLASS fcol (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 filter[(row+top_margin)&15][(col+left_margin)&15]; if (filters == 9) return xtrans[(row+6) % 6][(col+6) % 6]; return FC(row,col); } #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 char *my_strcasestr (char *haystack, const char *needle) { char *c; for (c = haystack; *c; c++) if (!strncasecmp(c, needle, strlen(needle))) return c; return 0; } #define strcasestr my_strcasestr #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++; } 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 cubic_spline (const int *x_, const int *y_, const int len) { float **A, *b, *c, *d, *x, *y; int i, j; A = (float **) calloc (((2*len + 4)*sizeof **A + sizeof *A), 2*len); if (!A) return; A[0] = (float *) (A + 2*len); for (i = 1; i < 2*len; i++) A[i] = A[0] + 2*len*i; y = len + (x = i + (d = i + (c = i + (b = A[0] + i*i)))); for (i = 0; i < len; i++) { x[i] = x_[i] / 65535.0; y[i] = y_[i] / 65535.0; } for (i = len-1; i > 0; i--) { b[i] = (y[i] - y[i-1]) / (x[i] - x[i-1]); d[i-1] = x[i] - x[i-1]; } for (i = 1; i < len-1; i++) { A[i][i] = 2 * (d[i-1] + d[i]); if (i > 1) { A[i][i-1] = d[i-1]; A[i-1][i] = d[i-1]; } A[i][len-1] = 6 * (b[i+1] - b[i]); } for(i = 1; i < len-2; i++) { float v = A[i+1][i] / A[i][i]; for(j = 1; j <= len-1; j++) A[i+1][j] -= v * A[i][j]; } for(i = len-2; i > 0; i--) { float acc = 0; for(j = i; j <= len-2; j++) acc += A[i][j]*c[j]; c[i] = (A[i][len-1] - acc) / A[i][i]; } for (i = 0; i < 0x10000; i++) { float x_out = (float)(i / 65535.0); float y_out = 0; for (j = 0; j < len-1; j++) { if (x[j] <= x_out && x_out <= x[j+1]) { float v = x_out - x[j]; y_out = y[j] + ((y[j+1] - y[j]) / d[j] - (2 * d[j] * c[j] + c[j+1] * d[j])/6) * v + (c[j] * 0.5) * v*v + ((c[j+1] - c[j]) / (6 * d[j])) * v*v*v; } } curve[i] = y_out < 0.0 ? 0 : (y_out >= 1.0 ? 65535 : (ushort)(y_out * 65535.0 + 0.5)); } free (A); } 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 *pix; int irow, row; for (irow=row=0; irow < height; irow++) { if (fread (data, 1, 1120, ifp) < 1120) derror(); pix = raw_image + row*raw_width; for (dp=data; 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 ); } if ((row+=2) > height) row = 1; } } void CLASS canon_600_correct() { int row, col, val; static const short mul[4][2] = { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } }; 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; } 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; } unsigned CLASS getbithuff (int nbits, ushort *huff) { static unsigned bitbuf=0; static int vbits=0, reset=0; unsigned c; if (nbits > 25) return 0; if (nbits < 0) 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_load_raw() { ushort *pixel, *prow, *huff[2]; int nblocks, lowbits, i, c, row, r, save, val; int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2]; crw_init_tables (tiff_compress, huff); 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) { pixel = raw_image + row*raw_width; 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); } } FORC(2) free (huff[c]); } struct jhead { int algo, bits, high, wide, clrs, sraw, psv, restart, vpred[6]; ushort quant[64], idct[64], *huff[20], *free[20], *row; }; int CLASS ljpeg_start (struct jhead *jh, int info_only) { ushort c, tag, len; uchar data[0x10000]; const uchar *dp; memset (jh, 0, sizeof *jh); jh->restart = INT_MAX; if ((fgetc(ifp),fgetc(ifp)) != 0xd8) return 0; do { if (!fread (data, 2, 2, ifp)) return 0; 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 0xffc1: case 0xffc0: jh->algo = tag & 0xff; 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++) & -20); ) 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 0xffdb: FORC(64) jh->quant[c] = data[c*2+1] << 8 | data[c*2+2]; break; case 0xffdd: jh->restart = data[0] << 8 | data[1]; } } while (tag != 0xffda); if (jh->bits > 16 || jh->clrs > 6 || !jh->bits || !jh->high || !jh->wide || !jh->clrs) return 0; if (info_only) return 1; if (!jh->huff[0]) return 0; FORC(19) 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; struct jhead jh; 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); if (load_flags & 1) row = jrow & 1 ? height-1-jrow/2 : jrow/2; for (jcol=0; jcol < jwide; jcol++) { val = curve[*rp++]; if (cr2_slice[0]) { jidx = jrow*jwide + jcol; i = jidx / (cr2_slice[1]*raw_height); if ((j = i >= cr2_slice[0])) i = cr2_slice[0]; jidx -= i * (cr2_slice[1]*raw_height); 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 < raw_height) RAW(row,col) = val; if (++col >= raw_width) col = (row++,0); } } ljpeg_end (&jh); } 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) || jh.clrs < 4) 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 >= 0x80000281 || (unique_id == 0x80000218 && ver > 1000006)) 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 == 0x80000218 || unique_id == 0x80000250 || unique_id == 0x80000261 || unique_id == 0x80000281 || unique_id == 0x80000287) { rp[1] = (rp[1] << 2) + hue; rp[2] = (rp[2] << 2) + hue; pix[0] = rp[0] + (( 50*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); } else { if (unique_id < 0x80000218) rp[0] -= 512; pix[0] = rp[0] + rp[2]; pix[2] = rp[0] + rp[1]; pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12); } FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10); } ljpeg_end (&jh); maximum = 0x3fff; } void CLASS adobe_copy_pixel (unsigned row, unsigned col, ushort **rp) { int c; if (tiff_samples == 2 && shot_select) (*rp)++; if (raw_image) { if (row < raw_height && col < raw_width) RAW(row,col) = curve[**rp]; *rp += tiff_samples; } else { if (row < height && col < width) FORC(tiff_samples) image[row*width+col][c] = curve[(*rp)[c]]; *rp += tiff_samples; } if (tiff_samples == 2 && shot_select) (*rp)--; } void CLASS ljpeg_idct (struct jhead *jh) { int c, i, j, len, skip, coef; float work[3][8][8]; static float cs[106] = { 0 }; static const uchar zigzag[80] = { 0, 1, 8,16, 9, 2, 3,10,17,24,32,25,18,11, 4, 5,12,19,26,33, 40,48,41,34,27,20,13, 6, 7,14,21,28,35,42,49,56,57,50,43,36, 29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54, 47,55,62,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63 }; if (!cs[0]) FORC(106) cs[c] = cos((c & 31)*M_PI/16)/2; memset (work, 0, sizeof work); work[0][0][0] = jh->vpred[0] += ljpeg_diff (jh->huff[0]) * jh->quant[0]; for (i=1; i < 64; i++ ) { len = gethuff (jh->huff[16]); i += skip = len >> 4; if (!(len &= 15) && skip < 15) break; coef = getbits(len); if ((coef & (1 << (len-1))) == 0) coef -= (1 << len) - 1; ((float *)work)[zigzag[i]] = coef * jh->quant[i]; } FORC(8) work[0][0][c] *= M_SQRT1_2; FORC(8) work[0][c][0] *= M_SQRT1_2; for (i=0; i < 8; i++) for (j=0; j < 8; j++) FORC(8) work[1][i][j] += work[0][i][c] * cs[(j*2+1)*c]; for (i=0; i < 8; i++) for (j=0; j < 8; j++) FORC(8) work[2][i][j] += work[1][c][j] * cs[(i*2+1)*c]; FORC(64) jh->idct[c] = CLIP(((float *)work[2])[c]+0.5); } void CLASS lossless_dng_load_raw() { unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col, i, j; 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 /= MIN (is_raw, tiff_samples); switch (jh.algo) { case 0xc1: jh.vpred[0] = 16384; getbits(-1); for (jrow=0; jrow+7 < jh.high; jrow += 8) { for (jcol=0; jcol+7 < jh.wide; jcol += 8) { ljpeg_idct (&jh); rp = jh.idct; row = trow + jcol/tile_width + jrow*2; col = tcol + jcol%tile_width; for (i=0; i < 16; i+=2) for (j=0; j < 8; j++) adobe_copy_pixel (row+i, col+j, &rp); } } break; case 0xc3: 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 packed_dng_load_raw() { ushort *pixel, *rp; int row, col; pixel = (ushort *) calloc (raw_width, tiff_samples*sizeof *pixel); merror (pixel, "packed_dng_load_raw()"); 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_load_raw() { ushort bit[2][15], huff[4097]; int dep, row, col, diff, c, i; ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2]; fseek (ifp, meta_offset, SEEK_SET); dep = (get2() + 12) & 15; fseek (ifp, 12, SEEK_CUR); FORC(dep) bit[0][c] = get2(); FORC(dep) bit[1][c] = fgetc(ifp); FORC(dep) 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 < raw_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; RAW(row,col) = hpred[col & 1]; if (hpred[col & 1] >> tiff_bps) derror(); } } void CLASS nikon_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(); RAW(row,col) = curve[LIM((short)hpred[col & 1],0,0x3fff)]; } } free (huff); } void CLASS nikon_yuv_load_raw() { int row, col, yuv[4], rgb[3], b, c; UINT64 bitbuf=0; for (row=0; row < raw_height; row++) for (col=0; col < raw_width; col++) { if (!(b = col & 1)) { bitbuf = 0; FORC(6) bitbuf |= (UINT64) fgetc(ifp) << c*8; FORC(4) yuv[c] = (bitbuf >> c*12 & 0xfff) - (c >> 1 << 11); } rgb[0] = yuv[b] + 1.370705*yuv[3]; rgb[1] = yuv[b] - 0.337633*yuv[2] - 0.698001*yuv[3]; rgb[2] = yuv[b] + 1.732446*yuv[2]; FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,0xfff)] / cam_mul[c]; } } /* 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; } 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 ppm16_thumb() { int i; char *thumb; thumb_length = thumb_width*thumb_height*3; thumb = (char *) calloc (thumb_length, 2); merror (thumb, "ppm16_thumb()"); read_shorts ((ushort *) thumb, thumb_length); for (i=0; i < thumb_length; i++) thumb[i] = ((ushort *) thumb)[i] >> 8; fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height); 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, 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) raw_image[todo[i]] = (todo[i+1] & 0x3ff); } maximum = 0x3ff; } int CLASS raw (unsigned row, unsigned col) { return (row < raw_height && col < raw_width) ? RAW(row,col) : 0; } void CLASS phase_one_flat_field (int is_float, int nc) { ushort head[8]; unsigned wide, high, y, x, c, rend, cend, row, col; float *mrow, num, mult[4]; read_shorts (head, 8); if (head[2] * head[3] * head[4] * head[5] == 0) return; wide = head[2] / head[4] + (head[2] % head[4] != 0); high = head[3] / head[5] + (head[3] % head[5] != 0); mrow = (float *) calloc (nc*wide, sizeof *mrow); merror (mrow, "phase_one_flat_field()"); for (y=0; y < high; 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] + y*head[5]; for (row = rend-head[5]; row < raw_height && row < rend && row < head[1]+head[3]-head[5]; 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] + x*head[4]; for (col = cend-head[4]; col < raw_width && col < cend && col < head[0]+head[2]-head[4]; col++) { c = nc > 2 ? FC(row-top_margin,col-left_margin) : 0; if (!(c & 1)) { c = RAW(row,col) * mult[c]; RAW(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]; int qmult_applied = 0, qlin_applied = 0; 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 < raw_height; row++) for (col = (tag & 1)*ph1.split_col; col < raw_width; col++) RAW(row,col) = curve[RAW(row,col)]; } else if (tag == 0x400) { /* Sensor defects */ while ((len -= 8) >= 0) { col = get2(); row = get2(); type = get2(); get2(); if (col >= raw_width) continue; if (type == 131 || type == 137) /* Bad column */ for (row=0; row < raw_height; row++) if (FC(row-top_margin,col-left_margin) == 1) { for (sum=i=0; i < 4; i++) sum += val[i] = raw (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; } RAW(row,col) = (sum - val[max])/3.0 + 0.5; } else { for (sum=0, i=8; i < 12; i++) sum += raw (row+dir[i][0], col+dir[i][1]); RAW(row,col) = 0.5 + sum * 0.0732233 + (raw(row,col-2) + raw(row,col+2)) * 0.3535534; } else if (type == 129) { /* Bad pixel */ if (row >= raw_height) continue; j = (FC(row-top_margin,col-left_margin) != 1) * 4; for (sum=0, i=j; i < j+8; i++) sum += raw (row+dir[i][0], col+dir[i][1]); RAW(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; } } else if (tag == 0x41f && !qlin_applied) { /* Quadrant linearization */ ushort lc[2][2][16], ref[16]; int qr, qc; for (qr = 0; qr < 2; qr++) for (qc = 0; qc < 2; qc++) for (i = 0; i < 16; i++) lc[qr][qc][i] = get4(); for (i = 0; i < 16; i++) { int v = 0; for (qr = 0; qr < 2; qr++) for (qc = 0; qc < 2; qc++) v += lc[qr][qc][i]; ref[i] = (v + 2) >> 2; } for (qr = 0; qr < 2; qr++) { for (qc = 0; qc < 2; qc++) { int cx[19], cf[19]; for (i = 0; i < 16; i++) { cx[1+i] = lc[qr][qc][i]; cf[1+i] = ref[i]; } cx[0] = cf[0] = 0; cx[17] = cf[17] = ((unsigned) ref[15] * 65535) / lc[qr][qc][15]; cx[18] = cf[18] = 65535; cubic_spline(cx, cf, 19); for (row = (qr ? ph1.split_row : 0); row < (qr ? raw_height : ph1.split_row); row++) for (col = (qc ? ph1.split_col : 0); col < (qc ? raw_width : ph1.split_col); col++) RAW(row,col) = curve[RAW(row,col)]; } } qlin_applied = 1; } else if (tag == 0x41e && !qmult_applied) { /* Quadrant multipliers */ float qmult[2][2] = { { 1, 1 }, { 1, 1 } }; get4(); get4(); get4(); get4(); qmult[0][0] = 1.0 + getreal(11); get4(); get4(); get4(); get4(); get4(); qmult[0][1] = 1.0 + getreal(11); get4(); get4(); get4(); qmult[1][0] = 1.0 + getreal(11); get4(); get4(); get4(); qmult[1][1] = 1.0 + getreal(11); for (row=0; row < raw_height; row++) for (col=0; col < raw_width; col++) { i = qmult[row >= ph1.split_row][col >= ph1.split_col] * RAW(row,col); RAW(row,col) = LIM(i,0,65535); } qmult_applied = 1; } else if (tag == 0x431 && !qmult_applied) { /* Quadrant combined */ ushort lc[2][2][7], ref[7]; int qr, qc; for (i = 0; i < 7; i++) ref[i] = get4(); for (qr = 0; qr < 2; qr++) for (qc = 0; qc < 2; qc++) for (i = 0; i < 7; i++) lc[qr][qc][i] = get4(); for (qr = 0; qr < 2; qr++) { for (qc = 0; qc < 2; qc++) { int cx[9], cf[9]; for (i = 0; i < 7; i++) { cx[1+i] = ref[i]; cf[1+i] = ((unsigned) ref[i] * lc[qr][qc][i]) / 10000; } cx[0] = cf[0] = 0; cx[8] = cf[8] = 65535; cubic_spline(cx, cf, 9); for (row = (qr ? ph1.split_row : 0); row < (qr ? raw_height : ph1.split_row); row++) for (col = (qc ? ph1.split_col : 0); col < (qc ? raw_width : ph1.split_col); col++) RAW(row,col) = curve[RAW(row,col)]; } } qmult_applied = 1; qlin_applied = 1; } 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 < raw_height; row++) for (col=0; col < raw_width; col++) { cfrac = (float) col * head[3] / raw_width; cfrac -= cip = cfrac; num = RAW(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 + num) * 2; RAW(row,col) = LIM(i,0,65535); } free (yval[0]); } } void CLASS phase_one_load_raw() { int a, b, i; ushort akey, bkey, mask; fseek (ifp, ph1.key_off, SEEK_SET); akey = get2(); bkey = get2(); mask = ph1.format == 1 ? 0x5555:0x1354; fseek (ifp, data_offset, SEEK_SET); read_shorts (raw_image, raw_width*raw_height); if (ph1.format) for (i=0; i < raw_width*raw_height; i+=2) { a = raw_image[i+0] ^ akey; b = raw_image[i+1] ^ bkey; raw_image[i+0] = (a & mask) | (b & ~mask); raw_image[i+1] = (b & mask) | (a & ~mask); } } 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 (*cblack)[2], (*rblack)[2]; pixel = (ushort *) calloc (raw_width*3 + 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(); cblack = (short (*)[2]) (offset + raw_height); fseek (ifp, ph1.black_col, SEEK_SET); if (ph1.black_col) read_shorts ((ushort *) cblack[0], raw_height*2); rblack = cblack + raw_height; fseek (ifp, ph1.black_row, SEEK_SET); if (ph1.black_row) read_shorts ((ushort *) rblack[0], raw_width*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]]; } for (col=0; col < raw_width; col++) { i = (pixel[col] << 2*(ph1.format != 8)) - ph1.black + cblack[row][col >= ph1.split_col] + rblack[col][row >= ph1.split_row]; if (i > 0) RAW(row,col) = i; } } free (pixel); maximum = 0xfffc - ph1.black; } void CLASS hasselblad_load_raw() { struct jhead jh; int shot, row, col, *back[5], len[2], diff[12], pred, sh, f, s, c; unsigned upix, urow, ucol; ushort *ip; if (!ljpeg_start (&jh, 0)) return; order = 0x4949; ph1_bits(-1); back[4] = (int *) calloc (raw_width, 3*sizeof **back); merror (back[4], "hasselblad_load_raw()"); FORC3 back[c] = back[4] + c*raw_width; cblack[6] >>= sh = tiff_samples > 1; shot = LIM(shot_select, 1, tiff_samples) - 1; for (row=0; row < raw_height; row++) { FORC4 back[(c+3) & 3] = back[c]; for (col=0; col < raw_width; col+=2) { for (s=0; s < tiff_samples*2; s+=2) { FORC(2) len[c] = ph1_huff(jh.huff[0]); FORC(2) { diff[s+c] = ph1_bits(len[c]); if ((diff[s+c] & (1 << (len[c]-1))) == 0) diff[s+c] -= (1 << len[c]) - 1; if (diff[s+c] == 65535) diff[s+c] = -32768; } } for (s=col; s < col+2; s++) { pred = 0x8000 + load_flags; if (col) pred = back[2][s-2]; if (col && row > 1) switch (jh.psv) { case 11: pred += back[0][s]/2 - back[0][s-2]/2; break; } f = (row & 1)*3 ^ ((col+s) & 1); FORC (tiff_samples) { pred += diff[(s & 1)*tiff_samples+c]; upix = pred >> sh & 0xffff; if (raw_image && c == shot) RAW(row,s) = upix; if (image) { urow = row-top_margin + (c & 1); ucol = col-left_margin - ((c >> 1) & 1); ip = &image[urow*width+ucol][f]; if (urow < height && ucol < width) *ip = c < 4 ? upix : (*ip + upix) >> 1; } } back[2][s] = pred; } } } free (back[4]); ljpeg_end (&jh); if (image) mix_green = 1; } void CLASS leaf_hdr_load_raw() { ushort *pixel=0; unsigned tile=0, r, c, row, col; if (!filters) { 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(), SEEK_SET); } if (filters && c != shot_select) continue; if (filters) pixel = raw_image + r*raw_width; read_shorts (pixel, raw_width); if (!filters && (row = r - top_margin) < height) for (col=0; col < width; col++) image[row*width+col][c] = pixel[col+left_margin]; } if (!filters) { maximum = 0xffff; raw_color = 1; free (pixel); } } void CLASS unpacked_load_raw() { int row, col, bits=0; while (1 << ++bits < maximum); read_shorts (raw_image, raw_width*raw_height); for (row=0; row < raw_height; row++) for (col=0; col < raw_width; col++) if ((RAW(row,col) >>= load_flags) >> bits && (unsigned) (row-top_margin) < height && (unsigned) (col-left_margin) < width) derror(); } void CLASS sinar_4shot_load_raw() { ushort *pixel; unsigned shot, row, col, r, c; if (raw_image) { shot = LIM (shot_select, 1, 4) - 1; fseek (ifp, data_offset + shot*4, SEEK_SET); fseek (ifp, get4(), SEEK_SET); unpacked_load_raw(); return; } 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][(row & 1)*3 ^ (~col & 1)] = pixel[col]; } } } free (pixel); mix_green = 1; } void CLASS imacon_full_load_raw() { int row, col; if (!image) return; for (row=0; row < height; row++) for (col=0; col < width; col++) read_shorts (image[row*width+col], 3); } void CLASS packed_load_raw() { int vbits=0, bwide, rbits, bite, half, irow, row, col, val, i; UINT64 bitbuf=0; bwide = raw_width * tiff_bps / 8; bwide += bwide & load_flags >> 9; rbits = bwide * 8 - raw_width * tiff_bps; if (load_flags & 1) bwide = bwide * 16 / 15; bite = 8 + (load_flags & 56); half = (raw_height+1) >> 1; for (irow=0; irow < raw_height; irow++) { row = irow; if (load_flags & 2 && (row = irow % half * 2 + irow / half) == 1 && load_flags & 4) { if (vbits=0, tiff_compress) fseek (ifp, data_offset - (-half*bwide & -2048), SEEK_SET); else { fseek (ifp, 0, SEEK_END); fseek (ifp, ftell(ifp) >> 3 << 2, SEEK_SET); } } for (col=0; col < raw_width; col++) { for (vbits -= tiff_bps; vbits < 0; vbits += bite) { bitbuf <<= bite; for (i=0; i < bite; i+=8) bitbuf |= ((UINT64) fgetc(ifp) << i); } val = bitbuf << (64-tiff_bps-vbits) >> (64-tiff_bps); RAW(row,col ^ (load_flags >> 6 & 3)) = val; if (load_flags & 1 && (col % 10) == 9 && fgetc(ifp) && row < height+top_margin && col < width+left_margin) derror(); } vbits -= rbits; } } void CLASS nokia_load_raw() { uchar *data, *dp; int rev, dwide, row, col, c; double sum[]={0,0}; rev = 3 * (order == 0x4949); dwide = (raw_width * 5 + 1) / 4; data = (uchar *) malloc (dwide*2); merror (data, "nokia_load_raw()"); for (row=0; row < raw_height; row++) { if (fread (data+dwide, 1, dwide, ifp) < dwide) derror(); FORC(dwide) data[c] = data[dwide+(c ^ rev)]; for (dp=data, col=0; col < raw_width; dp+=5, col+=4) FORC4 RAW(row,col+c) = (dp[c] << 2) | (dp[4] >> (c << 1) & 3); } free (data); maximum = 0x3ff; if (strcmp(make,"OmniVision")) return; row = raw_height/2; FORC(width-1) { sum[ c & 1] += SQR(RAW(row,c)-RAW(row+1,c+1)); sum[~c & 1] += SQR(RAW(row+1,c)-RAW(row,c+1)); } if (sum[1] > sum[0]) filters = 0x4b4b4b4b; } void CLASS canon_rmf_load_raw() { int row, col, bits, orow, ocol, c; for (row=0; row < raw_height; row++) for (col=0; col < raw_width-2; col+=3) { bits = get4(); FORC3 { orow = row; if ((ocol = col+c-4) < 0) { ocol += raw_width; if ((orow -= 2) < 0) orow += raw_height; } RAW(orow,ocol) = curve[bits >> (10*c+2) & 0x3ff]; } } maximum = curve[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 ((RAW(row,col) = pred[col & 1]) > 4098 && col < width) derror(); } } void CLASS olympus_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 = RAW(row,col-2); else if (col < 2) pred = RAW(row-2,col); else { w = RAW(row,col-2); n = RAW(row-2,col); nw = RAW(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 ((RAW(row,col) = pred + ((diff << 2) | low)) >> 12) derror(); } } } void CLASS canon_crx_load_raw() { } void CLASS fuji_xtrans_load_raw() { } 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) RAW(row,col) = (col+1) & 2 ? pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1; RAW(row,1) = pixel[1] << 1; RAW(row,1533) = pixel[765] << 1; } else for (col=row & 1; col < 1534; col+=2) RAW(row,col) = pixel[col/2] << 1; } maximum = 0xff << 1; } 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++) RAW(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]) ((ushort *)huff)[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++) ((short *)buf)[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++) ((short *)buf[c])[i] = (((short *)buf[c])[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) RAW(row+y*2+c-1,x*2+2-c) = val; else RAW(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 = (RAW(y,x)-2048)*2 + (RAW(y,r)+RAW(y,s))/2; if (val < 0) val = 0; RAW(y,x) = val; } } for (i=0; i < height*width; i++) raw_image[i] = curve[raw_image[i]]; maximum = 0x3fff; } #undef FORYX #undef PREDICTOR #ifdef NO_JPEG void CLASS kodak_jpeg_load_raw() {} void CLASS lossy_dng_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) { RAW(row+0,col+0) = pixel[col+0][1] << 1; RAW(row+1,col+1) = pixel[col+1][1] << 1; RAW(row+0,col+1) = pixel[col][0] + pixel[col+1][0]; RAW(row+1,col+0) = pixel[col][2] + pixel[col+1][2]; } } jpeg_finish_decompress (&cinfo); jpeg_destroy_decompress (&cinfo); maximum = 0xff << 1; } void CLASS gamma_curve (double pwr, double ts, int mode, int imax); void CLASS lossy_dng_load_raw() { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPARRAY buf; JSAMPLE (*pixel)[3]; unsigned sorder=order, ntags, opcode, deg, i, j, c; unsigned save=data_offset-4, trow=0, tcol=0, row, col; ushort cur[3][256]; double coeff[9], tot; if (meta_offset) { fseek (ifp, meta_offset, SEEK_SET); order = 0x4d4d; ntags = get4(); while (ntags--) { opcode = get4(); get4(); get4(); if (opcode != 8) { fseek (ifp, get4(), SEEK_CUR); continue; } fseek (ifp, 20, SEEK_CUR); if ((c = get4()) > 2) break; fseek (ifp, 12, SEEK_CUR); if ((deg = get4()) > 8) break; for (i=0; i <= deg && i < 9; i++) coeff[i] = getreal(12); for (i=0; i < 256; i++) { for (tot=j=0; j <= deg; j++) tot += coeff[j] * pow(i/255.0, j); cur[c][i] = tot*0xffff; } } order = sorder; } else { gamma_curve (1/2.4, 12.92, 1, 255); FORC3 memcpy (cur[c], curve, sizeof cur[0]); } cinfo.err = jpeg_std_error (&jerr); jpeg_create_decompress (&cinfo); while (trow < raw_height) { fseek (ifp, save+=4, SEEK_SET); if (tile_length < INT_MAX) fseek (ifp, get4(), SEEK_SET); jpeg_stdio_src (&cinfo, ifp); jpeg_read_header (&cinfo, TRUE); jpeg_start_decompress (&cinfo); buf = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, cinfo.output_width*3, 1); while (cinfo.output_scanline < cinfo.output_height && (row = trow + cinfo.output_scanline) < height) { jpeg_read_scanlines (&cinfo, buf, 1); pixel = (JSAMPLE (*)[3]) buf[0]; for (col=0; col < cinfo.output_width && tcol+col < width; col++) { FORC3 image[row*width+tcol+col][c] = cur[c][pixel[col][c]]; } } jpeg_abort_decompress (&cinfo); if ((tcol += tile_width) >= raw_width) trow += tile_length + (tcol = 0); } jpeg_destroy_decompress (&cinfo); maximum = 0xffff; } #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++) RAW(row,col) = (ushort) pixel[(col + shift) % 848]; } maximum = 0xff; } void CLASS eight_bit_load_raw() { uchar *pixel; unsigned row, col; pixel = (uchar *) calloc (raw_width, sizeof *pixel); merror (pixel, "eight_bit_load_raw()"); for (row=0; row < raw_height; row++) { if (fread (pixel, 1, raw_width, ifp) < raw_width) derror(); for (col=0; col < raw_width; col++) RAW(row,col) = curve[pixel[col]]; } free (pixel); maximum = curve[0xff]; } void CLASS kodak_c330_load_raw() { uchar *pixel; int row, col, y, cb, cr, rgb[3], c; pixel = (uchar *) calloc (raw_width, 2*sizeof *pixel); merror (pixel, "kodak_c330_load_raw()"); for (row=0; row < height; row++) { if (fread (pixel, raw_width, 2, ifp) < 2) derror(); if (load_flags && (row & 31) == 31) fseek (ifp, raw_width*32, SEEK_CUR); for (col=0; col < width; col++) { y = pixel[col*2]; cb = pixel[(col*2 & -4) | 1] - 128; cr = pixel[(col*2 & -4) | 3] - 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_c603_load_raw() { uchar *pixel; int row, col, y, cb, cr, rgb[3], c; pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel); merror (pixel, "kodak_c603_load_raw()"); for (row=0; row < height; row++) { if (~row & 1) if (fread (pixel, raw_width, 3, ifp) < 3) derror(); for (col=0; col < 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++]]; RAW(row,col) = val; } } free (pixel); FORC(2) free (huff[c]); } 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 ((RAW(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; if (!image) return; 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-- && p++) *data++ ^= pad[(p-1) & 127] = pad[p & 127] ^ pad[(p+64) & 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 *) head, 10, 1, key); for (i=26; i-- > 22; ) key = key << 8 | head[i]; fseek (ifp, data_offset, SEEK_SET); for (row=0; row < raw_height; row++) { pixel = raw_image + row*raw_width; if (fread (pixel, 2, raw_width, ifp) < raw_width) derror(); sony_decrypt ((unsigned *) pixel, raw_width/2, !row, key); for (col=0; col < raw_width; col++) if ((pixel[col] = ntohs(pixel[col])) >> 14) derror(); } maximum = 0x3ff0; } void CLASS sony_arw_load_raw() { ushort huff[32770]; 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, sum=0; huff[0] = 15; 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; if ((sum += ljpeg_diff(huff)) >> 12) derror(); if (row < height) RAW(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+1); merror (data, "sony_arw2_load_raw()"); for (row=0; row < height; row++) { fread (data, 1, raw_width, ifp); for (dp=data, col=0; col < raw_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) RAW(row,col) = curve[pix[i] << 1] >> 2; col -= col & 1 ? 1:31; } } free (data); } void CLASS samsung_load_raw() { int row, col, c, i, dir, op[4], len[4]; order = 0x4949; for (row=0; row < raw_height; row++) { fseek (ifp, strip_offset+row*4, SEEK_SET); fseek (ifp, data_offset+get4(), SEEK_SET); ph1_bits(-1); FORC4 len[c] = row < 2 ? 7:4; for (col=0; col < raw_width; col+=16) { dir = ph1_bits(1); FORC4 op[c] = ph1_bits(2); FORC4 switch (op[c]) { case 3: len[c] = ph1_bits(4); break; case 2: len[c]--; break; case 1: len[c]++; } for (c=0; c < 16; c+=2) { i = len[((c & 1) << 1) | (c >> 3)]; RAW(row,col+c) = ((signed) ph1_bits(i) << (32-i) >> (32-i)) + (dir ? RAW(row+(~c | -2),col+c) : col ? RAW(row,col+(c | -2)) : 128); if (c == 14) c = -1; } } } for (row=0; row < raw_height-1; row+=2) for (col=0; col < raw_width-1; col+=2) SWAP (RAW(row,col+1), RAW(row+1,col)); } void CLASS samsung2_load_raw() { static const ushort tab[14] = { 0x304,0x307,0x206,0x205,0x403,0x600,0x709, 0x80a,0x90b,0xa0c,0xa0d,0x501,0x408,0x402 }; ushort huff[1026], vpred[2][2] = {{0,0},{0,0}}, hpred[2]; int i, c, n, row, col, diff; huff[0] = 10; for (n=i=0; i < 14; i++) FORC(1024 >> (tab[i] >> 8)) huff[++n] = tab[i]; getbits(-1); for (row=0; row < raw_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; RAW(row,col) = hpred[col & 1]; if (hpred[col & 1] >> tiff_bps) derror(); } } void CLASS samsung3_load_raw() { int opt, init, mag, pmode, row, tab, col, pred, diff, i, c; ushort lent[3][2], len[4], *prow[2]; order = 0x4949; fseek (ifp, 9, SEEK_CUR); opt = fgetc(ifp); init = (get2(),get2()); for (row=0; row < raw_height; row++) { fseek (ifp, (data_offset-ftell(ifp)) & 15, SEEK_CUR); ph1_bits(-1); mag = 0; pmode = 7; FORC(6) ((ushort *)lent)[c] = row < 2 ? 7:4; prow[ row & 1] = &RAW(row-1,1-((row & 1) << 1)); // green prow[~row & 1] = &RAW(row-2,0); // red and blue for (tab=0; tab+15 < raw_width; tab+=16) { if (~opt & 4 && !(tab & 63)) { i = ph1_bits(2); mag = i < 3 ? mag-'2'+"204"[i] : ph1_bits(12); } if (opt & 2) pmode = 7 - 4*ph1_bits(1); else if (!ph1_bits(1)) pmode = ph1_bits(3); if (opt & 1 || !ph1_bits(1)) { FORC4 len[c] = ph1_bits(2); FORC4 { i = ((row & 1) << 1 | (c & 1)) % 3; len[c] = len[c] < 3 ? lent[i][0]-'1'+"120"[len[c]] : ph1_bits(4); lent[i][0] = lent[i][1]; lent[i][1] = len[c]; } } FORC(16) { col = tab + (((c & 7) << 1)^(c >> 3)^(row & 1)); pred = (pmode == 7 || row < 2) ? (tab ? RAW(row,tab-2+(col & 1)) : init) : (prow[col & 1][col-'4'+"0224468"[pmode]] + prow[col & 1][col-'4'+"0244668"[pmode]] + 1) >> 1; diff = ph1_bits (i = len[c >> 2]); if (diff >> (i-1)) diff -= 1 << i; diff = diff * (mag*2+1) + mag; RAW(row,col) = pred + diff; } } } } #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 pix, s, count, bin, next, i, sym[3]; uchar diff, pred[]={0,0}; ushort data=0, range=0; fseek (ifp, seg[0][1]+1, SEEK_SET); getbits(-1); if (seg[1][0] > raw_width*raw_height) seg[1][0] = raw_width*raw_height; 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; raw_image[pix] = pred[pix & 1] += diff; if (!(pix & 1) && HOLE(pix / raw_width)) 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] = RAW(row-1,col-1); val[1] = RAW(row-1,col+1); val[2] = RAW(row+1,col-1); val[3] = RAW(row+1,col+1); RAW(row,col) = median4(val); } for (col=2; col < width-2; col+=4) if (HOLE(row-2) || HOLE(row+2)) RAW(row,col) = (RAW(row,col-2) + RAW(row,col+2)) >> 1; else { val[0] = RAW(row,col-2); val[1] = RAW(row,col+2); val[2] = RAW(row-2,col); val[3] = RAW(row+2,col); RAW(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 = (uchar) fgetc(ifp); fseek (ifp, offset, SEEK_SET); for (i=0; i < nseg*2; i++) ((unsigned *)seg)[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); } void CLASS redcine_load_raw() { #ifndef NO_JASPER int c, row, col; jas_stream_t *in; jas_image_t *jimg; jas_matrix_t *jmat; jas_seqent_t *data; ushort *img, *pix; jas_init(); in = jas_stream_fopen (ifname, "rb"); jas_stream_seek (in, data_offset+20, SEEK_SET); jimg = jas_image_decode (in, -1, 0); if (!jimg) longjmp (failure, 3); jmat = jas_matrix_create (height/2, width/2); merror (jmat, "redcine_load_raw()"); img = (ushort *) calloc ((height+2), (width+2)*2); merror (img, "redcine_load_raw()"); FORC4 { jas_image_readcmpt (jimg, c, 0, 0, width/2, height/2, jmat); data = jas_matrix_getref (jmat, 0, 0); for (row = c >> 1; row < height; row+=2) for (col = c & 1; col < width; col+=2) img[(row+1)*(width+2)+col+1] = data[(row/2)*(width/2)+col/2]; } for (col=1; col <= width; col++) { img[col] = img[2*(width+2)+col]; img[(height+1)*(width+2)+col] = img[(height-1)*(width+2)+col]; } for (row=0; row < height+2; row++) { img[row*(width+2)] = img[row*(width+2)+2]; img[(row+1)*(width+2)-1] = img[(row+1)*(width+2)-3]; } for (row=1; row <= height; row++) { pix = img + row*(width+2) + (col = 1 + (FC(row,1) & 1)); for ( ; col <= width; col+=2, pix+=2) { c = (((pix[0] - 0x800) << 3) + pix[-(width+2)] + pix[width+2] + pix[-1] + pix[1]) >> 2; pix[0] = LIM(c,0,4095); } } for (row=0; row < height; row++) for (col=0; col < width; col++) RAW(row,col) = curve[img[(row+1)*(width+2)+col+1]]; free (img); jas_matrix_destroy (jmat); jas_image_destroy (jimg); jas_stream_close (in); #endif } /* 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_sd_load_raw() { struct decode *dindex; short diff[1024]; unsigned bitbuf=0; int pred[3], row, col, bit=-1, c, i; read_shorts ((ushort *) diff, 1024); if (!load_flags) foveon_decoder (1024, 0); for (row=0; row < height; row++) { memset (pred, 0, sizeof pred); if (!bit && !load_flags && atoi(model+2) < 14) get4(); for (col=bit=0; col < width; col++) { if (load_flags) { 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]; } } } void CLASS foveon_huff (ushort *huff) { int i, j, clen, code; huff[0] = 8; for (i=0; i < 13; i++) { clen = getc(ifp); code = getc(ifp); for (j=0; j < 256 >> clen; ) huff[code+ ++j] = clen << 8 | i; } get2(); } void CLASS foveon_dp_load_raw() { unsigned c, roff[4], row, col, diff; ushort huff[512], vpred[2][2], hpred[2]; fseek (ifp, 8, SEEK_CUR); foveon_huff (huff); roff[0] = 48; FORC3 roff[c+1] = -(-(roff[c] + get4()) & -16); FORC3 { fseek (ifp, data_offset+roff[c], SEEK_SET); getbits(-1); vpred[0][0] = vpred[0][1] = vpred[1][0] = vpred[1][1] = 512; for (row=0; row < height; row++) { for (col=0; col < width; col++) { diff = ljpeg_diff(huff); if (col < 2) hpred[col] = vpred[row & 1][col] += diff; else hpred[col & 1] += diff; image[row*width+col][c] = hpred[col & 1]; } } } } void CLASS foveon_load_camf() { unsigned type, wide, high, i, j, row, col, diff; ushort huff[258], vpred[2][2] = {{512,512},{512,512}}, hpred[2]; fseek (ifp, meta_offset, SEEK_SET); type = get4(); get4(); get4(); wide = get4(); high = get4(); if (type == 2) { fread (meta_data, 1, meta_length, ifp); for (i=0; i < meta_length; i++) { high = (high * 1597 + 51749) % 244944; wide = high * (INT64) 301593171 >> 24; meta_data[i] ^= ((((high << 8) - wide) >> 1) + wide) >> 17; } } else if (type == 4) { free (meta_data); meta_data = (char *) malloc (meta_length = wide*high*3/2); merror (meta_data, "foveon_load_camf()"); foveon_huff (huff); get4(); getbits(-1); for (j=row=0; row < high; row++) { for (col=0; col < wide; col++) { diff = ljpeg_diff(huff); if (col < 2) hpred[col] = vpred[row & 1][col] += diff; else hpred[col & 1] += diff; if (col & 1) { meta_data[j++] = hpred[0] >> 4; meta_data[j++] = hpred[0] << 4 | hpred[1] >> 8; meta_data[j++] = hpred[1]; } } } } else fprintf (stderr,_("%s has unknown CAMF type %d.\n"), ifname, type); } 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]; if (!name) return 0; 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_load_camf(); 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++) ((float *)ddft[0])[i] = ((float *)ddft[1])[i] + row / (height-1.0) * (((float *)ddft[2])[i] - ((float *)ddft[1])[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++) ((float *)ddft[0])[i] = ((float *)ddft[1])[i] + row / (height-1.0) * (((float *)ddft[2])[i] - ((float *)ddft[1])[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 *) 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 ((height/4), (width/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 */ void CLASS crop_masked_pixels() { int row, col; unsigned r, c, m, mblack[8], zero, val; if (load_raw == &CLASS phase_one_load_raw || load_raw == &CLASS phase_one_load_raw_c) phase_one_correct(); if (fuji_width) { for (row=0; row < raw_height-top_margin*2; row++) { for (col=0; col < fuji_width << !fuji_layout; 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); } if (r < height && c < width) BAYER(r,c) = RAW(row+top_margin,col+left_margin); } } } else { for (row=0; row < height; row++) for (col=0; col < width; col++) BAYER2(row,col) = RAW(row+top_margin,col+left_margin); } if (mask[0][3] > 0) goto mask_set; if (load_raw == &CLASS canon_load_raw || load_raw == &CLASS lossless_jpeg_load_raw) { mask[0][1] = mask[1][1] += 2; mask[0][3] -= 2; goto sides; } if (load_raw == &CLASS canon_600_load_raw || load_raw == &CLASS sony_load_raw || (load_raw == &CLASS eight_bit_load_raw && strncmp(model,"DC2",3)) || load_raw == &CLASS kodak_262_load_raw || (load_raw == &CLASS packed_load_raw && (load_flags & 256))) { sides: mask[0][0] = mask[1][0] = top_margin; mask[0][2] = mask[1][2] = top_margin+height; mask[0][3] += left_margin; mask[1][1] += left_margin+width; mask[1][3] += raw_width; } if (load_raw == &CLASS nokia_load_raw) { mask[0][2] = top_margin; mask[0][3] = width; } mask_set: memset (mblack, 0, sizeof mblack); for (zero=m=0; m < 8; m++) for (row=MAX(mask[m][0],0); row < MIN(mask[m][2],raw_height); row++) for (col=MAX(mask[m][1],0); col < MIN(mask[m][3],raw_width); col++) { c = FC(row-top_margin,col-left_margin); mblack[c] += val = RAW(row,col); mblack[4+c]++; zero += !val; } if (load_raw == &CLASS canon_600_load_raw && width < raw_width) { black = (mblack[0]+mblack[1]+mblack[2]+mblack[3]) / (mblack[4]+mblack[5]+mblack[6]+mblack[7]) - 4; canon_600_correct(); } else if (zero < mblack[4] && mblack[5] && mblack[6] && mblack[7]) { FORC4 cblack[c] = mblack[c] / mblack[4+c]; cblack[4] = cblack[5] = cblack[6] = 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; } } /* 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) && fcol(r,c) == fcol(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); fclose (fp); memset (cblack, 0, sizeof cblack); 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 (float rgb_cam[3][4], 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 (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], balance[4], num; int c, i, j, k, sq, row, col, pass, 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] += BAYER2(row,col); BAYER2(row,col) = black + (BAYER2(row,col)-black)/2; 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 (pass=0; pass < 2; pass++) { for (raw_color = 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 (rgb_cam, cam_xyz); FORCC balance[c] = pre_mul[c] * gmb_cam[20][c]; for (sq=0; sq < NSQ; sq++) FORCC gmb_cam[sq][c] *= balance[c]; } 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, blk[2]; 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; FORC4 cblack[c] <<= 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]; blk[row] = cblack[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] - blk[~row & 1]*4 ) * mul[row & 1] + (window[1][col] + blk[row & 1]) * 0.5; 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 = fcol(y,x); val = BAYER2(y,x); } else val = image[y*width+x][c]; if (val > maximum-25) goto skip_block; if ((val -= cblack[c]) < 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] - cblack[c]) > 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[1] == 0) pre_mul[1] = 1; 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); } if (filters > 1000 && (cblack[4]+1)/2 == 1 && (cblack[5]+1)/2 == 1) { FORC4 cblack[FC(c/2,c%2)] += cblack[6 + c/2 % cblack[4] * cblack[5] + c%2 % cblack[5]]; cblack[4] = cblack[5] = 0; } size = iheight*iwidth; for (i=0; i < size*4; i++) { if (!(val = ((ushort *)image)[i])) continue; if (cblack[4] && cblack[5]) val -= cblack[6 + i/4 / iwidth % cblack[4] * cblack[5] + i/4 % iwidth % cblack[5]]; val -= cblack[i & 3]; val *= scale_mul[i & 3]; ((ushort *)image)[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; if (filters == 9) { for (row=0; row < 3; row++) for (col=1; col < 4; col++) if (!(image[row*width+col][0] | image[row*width+col][2])) goto break2; break2: for ( ; row < height; row+=3) for (col=(col-1)%3+1; col < width-1; col+=3) { img = image + row*width+col; for (c=0; c < 3; c+=2) img[0][c] = (img[-1][c] + img[1][c]) >> 1; } } } 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 = fcol(row,col); img[row*width+col][c] = image[(row >> 1)*iwidth+(col >> 1)][c]; } free (image); image = img; shrink = 0; } } if (filters > 1000 && colors == 3) { mix_green = four_color_rgb ^ half_size; if (four_color_rgb | half_size) 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 = fcol(y,x); sum[f] += image[y*width+x][f]; sum[f+4]++; } f = fcol(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], size=16, *ip, sum[4]; int f, c, i, x, y, row, col, shift, color; ushort *pix; if (verbose) fprintf (stderr,_("Bilinear interpolation...\n")); if (filters == 9) size = 6; border_interpolate(1); for (row=0; row < size; row++) for (col=0; col < size; col++) { ip = code[row][col]+1; f = fcol(row,col); memset (sum, 0, sizeof sum); for (y=-1; y <= 1; y++) for (x=-1; x <= 1; x++) { shift = (y==0) + (x==0); color = fcol(row+y,col+x); if (color == f) continue; *ip++ = (width*y + x)*4 + color; *ip++ = shift; *ip++ = color; sum[color] += 1 << shift; } code[row][col][0] = (ip - code[row][col]) / 3; FORCC if (c != f) { *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 % size][col % size]; memset (sum, 0, sizeof sum); for (i=*ip++; 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/pages/labsite/1999/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=8, pcol=2, *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 = 16; if (filters == 9) prow = pcol = 6; ip = (int *) calloc (prow*pcol, 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 = fcol(row+y1,col+x1); if (fcol(row+y2,col+x2) != color) continue; diag = (fcol(row,col+1) == color && fcol(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 = fcol(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); } } void CLASS cielab (ushort rgb[3], short lab[3]) { int c, i, j, k; float r, xyz[3]; static float cbrt[0x10000], xyz_cam[3][4]; if (!rgb) { 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]; return; } xyz[0] = xyz[1] = xyz[2] = 0.5; FORCC { xyz[0] += xyz_cam[0][c] * rgb[c]; xyz[1] += xyz_cam[1][c] * rgb[c]; xyz[2] += xyz_cam[2][c] * rgb[c]; } xyz[0] = cbrt[CLIP((int) xyz[0])]; xyz[1] = cbrt[CLIP((int) xyz[1])]; xyz[2] = cbrt[CLIP((int) xyz[2])]; lab[0] = 64 * (116 * xyz[1] - 16); lab[1] = 64 * 500 * (xyz[0] - xyz[1]); lab[2] = 64 * 200 * (xyz[1] - xyz[2]); } #define TS 512 /* Tile Size */ #define fcol(row,col) xtrans[(row+6) % 6][(col+6) % 6] /* Frank Markesteijn's algorithm for Fuji X-Trans sensors */ void CLASS xtrans_interpolate (int passes) { int c, d, f, g, h, i, v, ng, row, col, top, left, mrow, mcol; int val, ndir, pass, hm[8], avg[4], color[3][8]; static const short orth[12] = { 1,0,0,1,-1,0,0,-1,1,0,0,1 }, patt[2][16] = { { 0,1,0,-1,2,0,-1,0,1,1,1,-1,0,0,0,0 }, { 0,1,0,-2,1,0,-2,0,1,1,-2,-2,1,-1,-1,1 } }, dir[4] = { 1,TS,TS+1,TS-1 }; short allhex[3][3][2][8], *hex; ushort min, max, sgrow, sgcol; ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4]; short (*lab) [TS][3], (*lix)[3]; float (*drv)[TS][TS], diff[6], tr; char (*homo)[TS][TS], *buffer; if (verbose) fprintf (stderr,_("%d-pass X-Trans interpolation...\n"), passes); cielab (0,0); ndir = 4 << (passes > 1); buffer = (char *) malloc (TS*TS*(ndir*11+6)); merror (buffer, "xtrans_interpolate()"); rgb = (ushort(*)[TS][TS][3]) buffer; lab = (short (*) [TS][3])(buffer + TS*TS*(ndir*6)); drv = (float (*)[TS][TS]) (buffer + TS*TS*(ndir*6+6)); homo = (char (*)[TS][TS]) (buffer + TS*TS*(ndir*10+6)); /* Map a green hexagon around each non-green pixel and vice versa: */ for (row=0; row < 3; row++) for (col=0; col < 3; col++) for (ng=d=0; d < 10; d+=2) { g = fcol(row,col) == 1; if (fcol(row+orth[d],col+orth[d+2]) == 1) ng=0; else ng++; if (ng == 4) { sgrow = row; sgcol = col; } if (ng == g+1) FORC(8) { v = orth[d ]*patt[g][c*2] + orth[d+1]*patt[g][c*2+1]; h = orth[d+2]*patt[g][c*2] + orth[d+3]*patt[g][c*2+1]; allhex[row][col][0][c^(g*2 & d)] = h + v*width; allhex[row][col][1][c^(g*2 & d)] = h + v*TS; } } /* Set green1 and green3 to the minimum and maximum allowed values: */ for (row=2; row < height-2; row++) for (min=~(max=0), col=2; col < width-2; col++) { if (fcol(row,col) == 1 && (min=~(max=0))) continue; pix = image + row*width + col; hex = allhex[row % 3][col % 3][0]; if (!max) FORC(6) { val = pix[hex[c]][1]; if (min > val) min = val; if (max < val) max = val; } pix[0][1] = min; pix[0][3] = max; switch ((row-sgrow) % 3) { case 1: if (row < height-3) { row++; col--; } break; case 2: if ((min=~(max=0)) && (col+=2) < width-3 && row > 2) row--; } } for (top=3; top < height-19; top += TS-16) for (left=3; left < width-19; left += TS-16) { mrow = MIN (top+TS, height-3); mcol = MIN (left+TS, width-3); for (row=top; row < mrow; row++) for (col=left; col < mcol; col++) memcpy (rgb[0][row-top][col-left], image[row*width+col], 6); FORC3 memcpy (rgb[c+1], rgb[0], sizeof *rgb); /* Interpolate green horizontally, vertically, and along both diagonals: */ for (row=top; row < mrow; row++) for (col=left; col < mcol; col++) { if ((f = fcol(row,col)) == 1) continue; pix = image + row*width + col; hex = allhex[row % 3][col % 3][0]; color[1][0] = 174 * (pix[ hex[1]][1] + pix[ hex[0]][1]) - 46 * (pix[2*hex[1]][1] + pix[2*hex[0]][1]); color[1][1] = 223 * pix[ hex[3]][1] + pix[ hex[2]][1] * 33 + 92 * (pix[ 0 ][f] - pix[ -hex[2]][f]); FORC(2) color[1][2+c] = 164 * pix[hex[4+c]][1] + 92 * pix[-2*hex[4+c]][1] + 33 * (2*pix[0][f] - pix[3*hex[4+c]][f] - pix[-3*hex[4+c]][f]); FORC4 rgb[c^!((row-sgrow) % 3)][row-top][col-left][1] = LIM(color[1][c] >> 8,pix[0][1],pix[0][3]); } for (pass=0; pass < passes; pass++) { if (pass == 1) memcpy (rgb+=4, buffer, 4*sizeof *rgb); /* Recalculate green from interpolated values of closer pixels: */ if (pass) { for (row=top+2; row < mrow-2; row++) for (col=left+2; col < mcol-2; col++) { if ((f = fcol(row,col)) == 1) continue; pix = image + row*width + col; hex = allhex[row % 3][col % 3][1]; for (d=3; d < 6; d++) { rix = &rgb[(d-2)^!((row-sgrow) % 3)][row-top][col-left]; val = rix[-2*hex[d]][1] + 2*rix[hex[d]][1] - rix[-2*hex[d]][f] - 2*rix[hex[d]][f] + 3*rix[0][f]; rix[0][1] = LIM(val/3,pix[0][1],pix[0][3]); } } } /* Interpolate red and blue values for solitary green pixels: */ for (row=(top-sgrow+4)/3*3+sgrow; row < mrow-2; row+=3) for (col=(left-sgcol+4)/3*3+sgcol; col < mcol-2; col+=3) { rix = &rgb[0][row-top][col-left]; h = fcol(row,col+1); memset (diff, 0, sizeof diff); for (i=1, d=0; d < 6; d++, i^=TS^1, h^=2) { for (c=0; c < 2; c++, h^=2) { g = 2*rix[0][1] - rix[i< 1) diff[d] += SQR (rix[i< 1 && (d & 1)) if (diff[d-1] < diff[d]) FORC(2) color[c*2][d] = color[c*2][d-1]; if (d < 2 || (d & 1)) { FORC(2) rix[0][c*2] = CLIP(color[c*2][d]/2); rix += TS*TS; } } } /* Interpolate red for blue pixels and vice versa: */ for (row=top+3; row < mrow-3; row++) for (col=left+3; col < mcol-3; col++) { if ((f = 2-fcol(row,col)) == 1) continue; rix = &rgb[0][row-top][col-left]; c = (row-sgrow) % 3 ? TS:1; h = 3 * (c ^ TS ^ 1); for (d=0; d < 4; d++, rix += TS*TS) { i = d > 1 || ((d ^ c) & 1) || ((ABS(rix[0][1]-rix[c][1])+ABS(rix[0][1]-rix[-c][1])) < 2*(ABS(rix[0][1]-rix[h][1])+ABS(rix[0][1]-rix[-h][1]))) ? c:h; rix[0][f] = CLIP((rix[i][f] + rix[-i][f] + 2*rix[0][1] - rix[i][1] - rix[-i][1])/2); } } /* Fill in red and blue for 2x2 blocks of green: */ for (row=top+2; row < mrow-2; row++) if ((row-sgrow) % 3) for (col=left+2; col < mcol-2; col++) if ((col-sgcol) % 3) { rix = &rgb[0][row-top][col-left]; hex = allhex[row % 3][col % 3][1]; for (d=0; d < ndir; d+=2, rix += TS*TS) if (hex[d] + hex[d+1]) { g = 3*rix[0][1] - 2*rix[hex[d]][1] - rix[hex[d+1]][1]; for (c=0; c < 4; c+=2) rix[0][c] = CLIP((g + 2*rix[hex[d]][c] + rix[hex[d+1]][c])/3); } else { g = 2*rix[0][1] - rix[hex[d]][1] - rix[hex[d+1]][1]; for (c=0; c < 4; c+=2) rix[0][c] = CLIP((g + rix[hex[d]][c] + rix[hex[d+1]][c])/2); } } } rgb = (ushort(*)[TS][TS][3]) buffer; mrow -= top; mcol -= left; /* Convert to CIELab and differentiate in all directions: */ for (d=0; d < ndir; d++) { for (row=2; row < mrow-2; row++) for (col=2; col < mcol-2; col++) cielab (rgb[d][row][col], lab[row][col]); for (f=dir[d & 3],row=3; row < mrow-3; row++) for (col=3; col < mcol-3; col++) { lix = &lab[row][col]; g = 2*lix[0][0] - lix[f][0] - lix[-f][0]; drv[d][row][col] = SQR(g) + SQR((2*lix[0][1] - lix[f][1] - lix[-f][1] + g*500/232)) + SQR((2*lix[0][2] - lix[f][2] - lix[-f][2] - g*500/580)); } } /* Build homogeneity maps from the derivatives: */ memset(homo, 0, ndir*TS*TS); for (row=4; row < mrow-4; row++) for (col=4; col < mcol-4; col++) { for (tr=FLT_MAX, d=0; d < ndir; d++) if (tr > drv[d][row][col]) tr = drv[d][row][col]; tr *= 8; for (d=0; d < ndir; d++) for (v=-1; v <= 1; v++) for (h=-1; h <= 1; h++) if (drv[d][row+v][col+h] <= tr) homo[d][row][col]++; } /* Average the most homogenous pixels for the final result: */ if (height-top < TS+4) mrow = height-top+2; if (width-left < TS+4) mcol = width-left+2; for (row = MIN(top,8); row < mrow-8; row++) for (col = MIN(left,8); col < mcol-8; col++) { for (d=0; d < ndir; d++) for (hm[d]=0, v=-2; v <= 2; v++) for (h=-2; h <= 2; h++) hm[d] += homo[d][row+v][col+h]; for (d=0; d < ndir-4; d++) if (hm[d] < hm[d+4]) hm[d ] = 0; else if (hm[d] > hm[d+4]) hm[d+4] = 0; for (max=hm[0],d=1; d < ndir; d++) if (max < hm[d]) max = hm[d]; max -= max >> 3; memset (avg, 0, sizeof avg); for (d=0; d < ndir; d++) if (hm[d] >= max) { FORC3 avg[c] += rgb[d][row][col][c]; avg[3]++; } FORC3 image[(row+top)*width+col+left][c] = avg[c]/avg[3]; } } free(buffer); border_interpolate(8); } #undef fcol /* Adaptive Homogeneity-Directed interpolation is based on the work of Keigo Hirakawa, Thomas Parks, and Paul Lee. */ void CLASS ahd_interpolate() { int i, j, top, left, row, col, tr, tc, c, d, val, hm[2]; static const int dir[4] = { -1, 1, -TS, TS }; unsigned ldiff[2][4], abdiff[2][4], leps, abeps; ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4]; short (*lab)[TS][TS][3], (*lix)[3]; char (*homo)[TS][TS], *buffer; if (verbose) fprintf (stderr,_("AHD interpolation...\n")); cielab (0,0); border_interpolate(5); buffer = (char *) malloc (26*TS*TS); 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]; cielab (rix[0],lix[0]); } /* 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 * ("11124811248484"[*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 morder, 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. */ if (!strcmp(make,"Nokia")) return; 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") || !strcmp (buf,"PENTAX ")) { base = ftell(ifp)-10; fseek (ifp, -2, SEEK_CUR); order = get2(); if (buf[0] == 'O') get2(); } else if (!strncmp (buf,"SONY",4) || !strcmp (buf,"Panasonic")) { goto nf; } else if (!strncmp (buf,"FUJIFILM",8)) { base = ftell(ifp)-10; nf: 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); if (!strncmp(make,"SAMSUNG",7)) base = ftell(ifp); } entries = get2(); if (entries > 1000) return; morder = order; while (entries--) { order = morder; tiff_get (base, &tag, &type, &len, &save); tag |= uptag << 16; if (tag == 2 && strstr(make,"NIKON") && !iso_speed) 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 == 4 || tag == 0x114) && !strncmp(make,"KONICA",6)) { fseek (ifp, tag == 4 ? 140:160, SEEK_CUR); switch (get2()) { case 72: flip = 0; break; case 76: flip = 6; break; case 82: flip = 5; break; } } 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) FORC3 cam_mul[(c << 1 | c >> 1) & 3] = getreal(type); if (tag == 0xd && type == 7 && get2() == 0xaaaa) { for (c=i=2; (ushort) c != 0xbbbb && i < len; i++) c = c << 8 | fgetc(ifp); while ((i+=4) < len-5) if (get4() == 257 && (i=len) && (c = (get4(),fgetc(ifp))) < 3) flip = "065"[c]-'0'; } 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 && type == 7) { if (len == 2560) { fseek (ifp, 1248, SEEK_CUR); goto get2_256; } fread (buf, 1, 10, ifp); if (!strncmp(buf,"NRW ",4)) { fseek (ifp, strcmp(buf+4,"0100") ? 46:1546, SEEK_CUR); cam_mul[0] = get4() << 2; cam_mul[1] = get4() + get4(); cam_mul[2] = get4() << 2; } } 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 == 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 == 0x3d && type == 3 && len == 4) FORC4 cblack[c ^ c >> 1] = get2() >> (14-tiff_bps); 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 == 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); FORC4 cam_mul[c ^ (c >> 1)] = get2(); break; 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 == 0xa1 && type == 7) { order = 0x4949; fseek (ifp, 140, SEEK_CUR); FORC3 cam_mul[c] = get4(); } if (tag == 0xa4 && type == 3) { fseek (ifp, wbi*48, SEEK_CUR); FORC3 cam_mul[c] = get2(); } if (tag == 0xa7 && (unsigned) (ver97-200) < 17) { 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;:;55"[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) FORC4 cblack[c ^ c >> 1] = get2(); if (tag == 0x201 && len == 4) FORC4 cam_mul[c ^ (c >> 1)] = get2(); if (tag == 0x220 && type == 7) meta_offset = ftell(ifp); if (tag == 0x401 && type == 4 && len == 4) FORC4 cblack[c ^ c >> 1] = get4(); if (tag == 0xe01) { /* Nikon Capture Note */ 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); } } 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) FORC4 cblack[c ^ c >> 1] = get2(); 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 || type == 13)) fseek (ifp, get4()+base, SEEK_SET); if (tag == 0x2020 && !strncmp(buf,"OLYMP",5)) parse_thumb_note (base, 257, 258); if (tag == 0x2040) parse_makernote (base, 0x2040); if (tag == 0xb028) { fseek (ifp, get4()+base, 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); FORC4 cam_mul[c ^ (c >> 1)] = get2(); for (i+=18; i <= len; i+=10) { get2(); FORC4 sraw_mul[c ^ (c >> 1)] = get2(); if (sraw_mul[1] == 1170) break; } } if (tag == 0x4021 && get4() && get4()) FORC4 cam_mul[c] = 1024; if (tag == 0xa021) FORC4 cam_mul[c ^ (c >> 1)] = get4(); if (tag == 0xa028) FORC4 cam_mul[c ^ (c >> 1)] -= get4(); if (tag == 0xb001) unique_id = 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; t.tm_isdst = -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) && tiff_nifds < 3; entries = get2(); while (entries--) { tiff_get (base, &tag, &type, &len, &save); switch (tag) { case 33434: tiff_ifd[tiff_nifds-1].shutter = 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) tiff_ifd[tiff_nifds-1].shutter = 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", "AFi-II 7","Aptus-II 7","","Aptus-II 6","","","Aptus-II 10","Aptus-II 5", "","","","","Aptus-II 10R","Aptus-II 8","","Aptus-II 12","","AFi-II 12" }; 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++) ((float *)romm_cam)[i] = int_to_float(get4()); romm_coeff (romm_cam); } if (!strcmp(data,"CaptProf_color_matrix")) { for (i=0; i < 9; i++) fscanf (ifp, "%f", (float *)romm_cam + 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]; } if (!strcmp(data,"Rows_data")) load_flags = get4(); 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]={1,1,1}, num; static const int wbtag[] = { 64037,64040,64039,64041,-1,-1,64042 }; 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 == 2120 + wbi && wbi >= 0) FORC3 cam_mul[c] = 2048.0 / getreal(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); if (tag == 64013) wbi = fgetc(ifp); if ((unsigned) wbi < 7 && tag == wbtag[wbi]) FORC3 cam_mul[c] = get4(); if (tag == 64019) width = getint(type); if (tag == 64020) height = (getint(type)+1) & -2; fseek (ifp, save, SEEK_SET); } } void CLASS parse_minolta (int base); int CLASS parse_tiff (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 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 5: width = get2(); break; case 6: height = get2(); break; case 7: width += get2(); break; case 9: if ((i = get2())) filters = i; break; 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 28: case 29: case 30: cblack[tag-28] = get2(); cblack[3] = cblack[1]; break; case 36: case 37: case 38: cam_mul[tag-36] = 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 61440: /* Fuji HS10 table */ fseek (ifp, get4()+base, SEEK_SET); parse_tiff_ifd (base); break; case 2: case 256: case 61441: /* ImageWidth */ tiff_ifd[ifd].width = getint(type); break; case 3: case 257: case 61442: /* ImageHeight */ tiff_ifd[ifd].height = getint(type); break; case 258: /* BitsPerSample */ case 61443: tiff_ifd[ifd].samples = len & 7; if ((tiff_ifd[ifd].bps = getint(type)) > 32) tiff_ifd[ifd].bps = 8; if (tiff_bps < tiff_ifd[ifd].bps) tiff_bps = tiff_ifd[ifd].bps; break; case 61446: raw_height = 0; load_flags = get4() ? 24:80; break; case 259: /* Compression */ tiff_ifd[ifd].comp = getint(type); 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: /* JpegIFOffset */ case 61447: tiff_ifd[ifd].offset = get4()+base; if (!tiff_ifd[ifd].bps && tiff_ifd[ifd].offset > 0) { fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET); if (ljpeg_start (&jh, 1)) { tiff_ifd[ifd].comp = 6; tiff_ifd[ifd].width = jh.wide; tiff_ifd[ifd].height = jh.high; tiff_ifd[ifd].bps = jh.bits; tiff_ifd[ifd].samples = jh.clrs; if (!(jh.sraw || (jh.clrs & 1))) tiff_ifd[ifd].width *= jh.clrs; if ((tiff_ifd[ifd].width > 4*tiff_ifd[ifd].height) & ~jh.clrs) { tiff_ifd[ifd].width /= 2; tiff_ifd[ifd].height *= 2; } i = order; parse_tiff (tiff_ifd[ifd].offset + 12); order = i; } } 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: case 61448: tiff_ifd[ifd].bytes = get4(); break; case 61454: FORC3 cam_mul[(4-c) % 3] = getint(type); 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 */ tiff_ifd[ifd].tile_width = getint(type); break; case 323: /* TileLength */ tiff_ifd[ifd].tile_length = getint(type); break; case 324: /* TileOffsets */ tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4(); if (len == 1) tiff_ifd[ifd].tile_width = tiff_ifd[ifd].tile_length = 0; 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] = get2(); i = (cam_mul[1] == 1024 && cam_mul[2] == 1024) << 1; SWAP (cam_mul[i],cam_mul[i+1]) break; case 33405: /* Model2 */ fgets (model2, 64, ifp); break; case 33421: /* CFARepeatPatternDim */ if (get2() == 6 && get2() == 6) filters = 9; break; case 33422: /* CFAPattern */ if (filters == 9) { FORC(36) ((char *)xtrans)[c] = fgetc(ifp) & 3; break; } case 64777: /* Kodak P-series */ if ((plen=len) > 16) plen = 16; fread (cfa_pat, 1, plen, ifp); for (colors=cfa=i=0; i < plen && colors < 4; 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: case 65024: fseek (ifp, get4()+base, SEEK_SET); parse_kodak_ifd (base); break; case 33434: /* ExposureTime */ tiff_ifd[ifd].shutter = 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 40976: strip_offset = get4(); switch (tiff_ifd[ifd].comp) { case 32770: load_raw = &CLASS samsung_load_raw; break; case 32772: load_raw = &CLASS samsung2_load_raw; break; case 32773: load_raw = &CLASS samsung3_load_raw; break; } break; case 46275: /* Imacon tags */ strcpy (make, "Imacon"); data_offset = ftell(ifp); ima_len = len; break; case 46279: if (!ima_len) break; fseek (ifp, 38, SEEK_CUR); case 46274: fseek (ifp, 40, 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); raw_width = width; raw_height = height; left_margin = top_margin = 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 50708: /* UniqueCameraModel */ if (model[0]) break; fgets (make, 64, ifp); if ((cp = strchr(make,' '))) { strcpy(model,cp+1); *cp = 0; } break; case 50710: /* CFAPlaneColor */ if (filters == 9) break; 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]]; filters -= !filters; break; case 50711: /* CFALayout */ if (get2() == 2) fuji_width = 1; break; case 291: case 50712: /* LinearizationTable */ linear_table (len); break; case 50713: /* BlackLevelRepeatDim */ cblack[4] = get2(); cblack[5] = get2(); if (cblack[4] * cblack[5] > sizeof cblack / sizeof *cblack - 6) cblack[4] = cblack[5] = 1; break; case 61450: cblack[4] = cblack[5] = MIN(sqrt(len),64); case 50714: /* BlackLevel */ if (!(cblack[4] * cblack[5])) cblack[4] = cblack[5] = 1; FORC (cblack[4] * cblack[5]) cblack[6+c] = getreal(type); black = 0; break; case 50715: /* BlackLevelDeltaH */ case 50716: /* BlackLevelDeltaV */ for (num=i=0; i < (len & 0xffff); i++) num += getreal(type); black += num/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); break; 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 50830: /* MaskedAreas */ for (i=0; i < len && i < 32; i++) ((int *)mask)[i] = getint(type); black = 0; break; case 51009: /* OpcodeList2 */ meta_offset = ftell(ifp); 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_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 (cmatrix, 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; } int CLASS parse_tiff (int base) { int doff; fseek (ifp, base, SEEK_SET); order = get2(); if (order != 0x4949 && order != 0x4d4d) return 0; get2(); while ((doff = get4())) { fseek (ifp, doff+base, SEEK_SET); if (parse_tiff_ifd (base)) break; } return 1; } void CLASS apply_tiff() { int max_samp=0, ties=0, os, ns, raw=-1, thm=-1, i; struct jhead jh; 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=tiff_nifds; i--; ) { if (tiff_ifd[i].shutter) shutter = tiff_ifd[i].shutter; tiff_ifd[i].shutter = shutter; } 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; os = raw_width*raw_height; ns = tiff_ifd[i].width*tiff_ifd[i].height; if (tiff_bps) { os *= tiff_bps; ns *= tiff_ifd[i].bps; } if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) && (tiff_ifd[i].width | tiff_ifd[i].height) < 0x10000 && ns && ((ns > os && (ties = 1)) || (ns == os && shot_select == ties++))) { 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; tile_width = tiff_ifd[i].tile_width; tile_length = tiff_ifd[i].tile_length; shutter = tiff_ifd[i].shutter; raw = i; } } if (is_raw == 1 && ties) is_raw = ties; if (!tile_width ) tile_width = INT_MAX; if (!tile_length) tile_length = INT_MAX; for (i=tiff_nifds; i--; ) if (tiff_ifd[i].flip) tiff_flip = tiff_ifd[i].flip; if (raw >= 0 && !load_raw) switch (tiff_compress) { case 32767: if (tiff_ifd[raw].bytes == raw_width*raw_height) { tiff_bps = 12; maximum = 4095; load_raw = &CLASS sony_arw2_load_raw; break; } if (tiff_ifd[raw].bytes*8 != raw_width*raw_height*tiff_bps) { raw_height += 8; load_raw = &CLASS sony_arw_load_raw; break; } load_flags = 79; case 32769: load_flags++; case 32770: case 32773: goto slr; case 0: case 1: if (!strncmp(make,"OLYMPUS",7) && tiff_ifd[raw].bytes*2 == raw_width*raw_height*3) load_flags = 24; if (!strcmp(make,"SONY") && tiff_bps < 14 && tiff_ifd[raw].bytes == raw_width*raw_height*2) tiff_bps = 14; if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) { load_flags = 81; tiff_bps = 12; } slr: switch (tiff_bps) { case 8: load_raw = &CLASS eight_bit_load_raw; break; case 12: if (tiff_ifd[raw].phint == 2) load_flags = 6; load_raw = &CLASS packed_load_raw; break; case 14: load_raw = &CLASS packed_load_raw; if (tiff_ifd[raw].bytes*4 == raw_width*raw_height*7) break; load_flags = 0; case 16: load_raw = &CLASS unpacked_load_raw; if (!strncmp(make,"OLYMPUS",7) && tiff_ifd[raw].bytes*7 > raw_width*raw_height) load_raw = &CLASS olympus_load_raw; } if (filters == 9 && tiff_ifd[raw].bytes*8 < raw_width*raw_height*tiff_bps) load_raw = &CLASS fuji_xtrans_load_raw; 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 34713: if ((raw_width+9)/10*16*raw_height == tiff_ifd[raw].bytes) { load_raw = &CLASS packed_load_raw; load_flags = 1; } else if (raw_width*raw_height*3 == tiff_ifd[raw].bytes*2) { load_raw = &CLASS packed_load_raw; if (model[0] == 'N') load_flags = 80; } else if (raw_width*raw_height*3 == tiff_ifd[raw].bytes) { load_raw = &CLASS nikon_yuv_load_raw; gamma_curve (1/2.4, 12.92, 1, 4095); memset (cblack, 0, sizeof cblack); filters = 0; } else if (raw_width*raw_height*2 == tiff_ifd[raw].bytes) { load_raw = &CLASS unpacked_load_raw; load_flags = 4; order = 0x4d4d; } else load_raw = &CLASS nikon_load_raw; break; case 65535: load_raw = &CLASS pentax_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: case 34892: break; default: is_raw = 0; } if (!dng_version) if ( (tiff_samples == 3 && tiff_ifd[raw].bytes && tiff_bps != 14 && (tiff_compress & -16) != 32768) || (tiff_bps == 8 && strncmp(make,"Phase",5) && !strcasestr(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) && tiff_ifd[i].comp != 34892) { 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) write_thumb = &CLASS ppm_thumb; else if (!strcmp(make,"Imacon")) write_thumb = &CLASS ppm16_thumb; else thumb_load_raw = &CLASS kodak_thumb_load_raw; 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 >> (vbits -= bpp) & ~(-1 << bpp); } } /* Parse a CIFF file, better known as Canon CRW format. */ void CLASS parse_ciff (int offset, int length, int depth) { 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 | depth) > 127) 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, depth+1); /* 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) { width = get4(); height = get4(); pixel_aspect = int_to_float(get4()); 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++) ((float *)romm_cam)[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; break; case 0x223: ph1.black_col = data+base; break; case 0x224: ph1.split_row = data; break; case 0x225: ph1.black_row = 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; fuji_width = !(fgetc(ifp) & 8); } else if (tag == 0x131) { filters = 9; FORC(36) xtrans_abs[0][35-c] = fgetc(ifp) & 3; } else if (tag == 0x2ff0) { FORC4 cam_mul[c ^ 1] = get2(); } else if (tag == 0xc000 && len > 20000) { c = order; order = 0x4949; while ((tag = get4()) > raw_width); width = tag; height = get4(); order = c; } 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 || mark == 0xc9) { fgetc(ifp); raw_height = get2(); raw_width = get2(); } order = get2(); hlen = get4(); if (get4() == 0x48454150) /* "HEAP" */ parse_ciff (save+hlen, len-hlen, 0); if (parse_tiff (save+6)) apply_tiff(); 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 && !feof(ifp)) 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_crx (int end) { unsigned i, save, size, tag, base; static int index=0, wide, high, off, len; order = 0x4d4d; while (ftell(ifp)+7 < end) { save = ftell(ifp); if ((size = get4()) < 8) break; switch (tag = get4()) { case 0x6d6f6f76: /* moov */ case 0x7472616b: /* trak */ case 0x6d646961: /* mdia */ case 0x6d696e66: /* minf */ case 0x7374626c: /* stbl */ parse_crx (save+size); break; case 0x75756964: /* uuid */ switch (i=get4()) { case 0xeaf42b5e: fseek (ifp, 8, SEEK_CUR); case 0x85c0b687: fseek (ifp, 12, SEEK_CUR); parse_crx (save+size); } break; case 0x434d5431: /* CMT1 */ case 0x434d5432: /* CMT2 */ base = ftell(ifp); order = get2(); fseek (ifp, 6, SEEK_CUR); tag & 1 ? parse_tiff_ifd (base) : parse_exif (base); order = 0x4d4d; break; case 0x746b6864: /* tkhd */ fseek (ifp, 12, SEEK_CUR); index = get4(); fseek (ifp, 58, SEEK_CUR); wide = get4(); high = get4(); break; case 0x7374737a: /* stsz */ len = (get4(),get4()); break; case 0x636f3634: /* co64 */ fseek (ifp, 12, SEEK_CUR); off = get4(); switch (index) { case 1: /* 1 = full size, 2 = 27% size */ thumb_width = wide; thumb_height = high; thumb_length = len; thumb_offset = off; break; case 3: raw_width = wide; raw_height = high; data_offset = off; load_raw = &CLASS canon_crx_load_raw; } break; case 0x50525657: /* PRVW */ fseek (ifp, 6, SEEK_CUR); } fseek (ifp, save+size, SEEK_SET); } } void CLASS parse_qt (int end) { unsigned save, size; char tag[4]; order = 0x4d4d; while (ftell(ifp)+7 < end) { save = ftell(ifp); if ((size = get4()) < 8) return; fread (tag, 4, 1, ifp); if (!memcmp(tag,"moov",4) || !memcmp(tag,"udta",4) || !memcmp(tag,"CNTH",4)) parse_qt (save+size); if (!memcmp(tag,"CNDA",4)) parse_jpeg (ftell(ifp)); fseek (ifp, save+size, SEEK_SET); } } 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; } void CLASS parse_redcine() { unsigned i, len, rdvo; order = 0x4d4d; is_raw = 0; fseek (ifp, 52, SEEK_SET); width = get4(); height = get4(); fseek (ifp, 0, SEEK_END); fseek (ifp, -(i = ftello(ifp) & 511), SEEK_CUR); if (get4() != i || get4() != 0x52454f42) { fprintf (stderr,_("%s: Tail is missing, parsing from head...\n"), ifname); fseek (ifp, 0, SEEK_SET); while ((len = get4()) != EOF) { if (get4() == 0x52454456) if (is_raw++ == shot_select) data_offset = ftello(ifp) - 8; fseek (ifp, len-8, SEEK_CUR); } } else { rdvo = get4(); fseek (ifp, 12, SEEK_CUR); is_raw = get4(); fseeko (ifp, rdvo+8 + shot_select*4, SEEK_SET); data_offset = get4(); } } 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, 8, SEEK_CUR); pent = get4(); wide = get4(); high = get4(); if (wide > raw_width && high > raw_height) { switch (pent) { case 5: load_flags = 1; case 6: load_raw = &CLASS foveon_sd_load_raw; break; case 30: load_raw = &CLASS foveon_dp_load_raw; break; default: load_raw = 0; } raw_width = wide; raw_height = high; data_offset = off+28; is_foveon = 1; } 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+8; meta_length = len-28; 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++) ((int *)poff)[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); } } /* All matrices are from Adobe DNG Converter unless otherwise noted. */ 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 5DS", 0, 0x3c96, { 6250,-711,-808,-5153,12794,2636,-1249,2198,5610 } }, { "Canon EOS 5D Mark IV", 0, 0, { 6446,-366,-864,-4436,12204,2513,-952,2496,6348 } }, { "Canon EOS 5D Mark III", 0, 0x3c80, { 6722,-635,-963,-4287,12460,2028,-908,2162,5668 } }, { "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 6D Mark II", 0, 0, { 6875,-970,-932,-4691,12459,2501,-874,1953,5809 } }, { "Canon EOS 6D", 0, 0x3c82, { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } }, { "Canon EOS 7D Mark II", 0, 0x3510, { 7268,-1082,-969,-4186,11839,2663,-825,2029,5839 } }, { "Canon EOS 7D", 0, 0x3510, { 6844,-996,-856,-3876,11761,2396,-593,1772,6198 } }, { "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 60D", 0, 0x2ff7, { 6719,-994,-925,-4408,12426,2211,-887,2129,6051 } }, { "Canon EOS 70D", 0, 0x3bc7, { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } }, { "Canon EOS 77D", 0, 0, { 7377,-742,-998,-4235,11981,2549,-673,1918,5538 } }, { "Canon EOS 80D", 0, 0, { 7457,-671,-937,-4849,12495,2643,-1213,2354,5492 } }, { "Canon EOS 100D", 0, 0x350f, { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } }, { "Canon EOS 200D", 0, 0, { 7377,-742,-998,-4235,11981,2549,-673,1918,5538 } }, { "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 500D", 0, 0x3479, { 4763,712,-646,-6821,14399,2640,-1921,3276,6561 } }, { "Canon EOS 550D", 0, 0x3dd7, { 6941,-1164,-857,-3825,11597,2534,-416,1540,6039 } }, { "Canon EOS 600D", 0, 0x3510, { 6461,-907,-882,-4300,12184,2378,-819,1944,5931 } }, { "Canon EOS 650D", 0, 0x354d, { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } }, { "Canon EOS 700D", 0, 0x3c00, { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } }, { "Canon EOS 750D", 0, 0x368e, { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } }, { "Canon EOS 760D", 0, 0x350f, { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } }, { "Canon EOS 800D", 0, 0, { 6970,-512,-968,-4425,12161,2553,-739,1982,5601 } }, { "Canon EOS 1000D", 0, 0xe43, { 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } }, { "Canon EOS 1100D", 0, 0x3510, { 6444,-904,-893,-4563,12308,2535,-903,2016,6728 } }, { "Canon EOS 1200D", 0, 0x37c2, { 6461,-907,-882,-4300,12184,2378,-819,1944,5931 } }, { "Canon EOS 1300D", 0, 0x3510, { 6939,-1016,-866,-4428,12473,2177,-1175,2178,6162 } }, { "Canon EOS 1500D", 0, 0, { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, { "Canon EOS 3000D", 0, 0, { 6939,-1016,-866,-4428,12473,2177,-1175,2178,6162 } }, { "Canon EOS M6", 0, 0, { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, { "Canon EOS M5", 0, 0, /* also M50 */ { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, { "Canon EOS M3", 0, 0, { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } }, { "Canon EOS M100", 0, 0, { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, { "Canon EOS M10", 0, 0, { 6400,-480,-888,-5294,13416,2047,-1296,2203,6137 } }, { "Canon EOS M", 0, 0, { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } }, { "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 IV", 0, 0x3bb0, { 6014,-220,-795,-4109,12014,2361,-561,1824,5787 } }, { "Canon EOS-1D Mark III", 0, 0x3bb0, { 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } }, { "Canon EOS-1D Mark II N", 0, 0xe80, { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } }, { "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 C", 0, 0x3c4e, { 6847,-614,-1014,-4669,12737,2139,-1197,2488,6846 } }, { "Canon EOS-1D X Mark II", 0, 0, { 7596,-978,-967,-4808,12571,2503,-1398,2567,5752 } }, { "Canon EOS-1D X", 0, 0x3c4e, { 6847,-614,-1014,-4669,12737,2139,-1197,2488,6846 } }, { "Canon EOS-1D", 0, 0xe20, { 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } }, { "Canon EOS C500", 853, 0, /* DJC */ { 17851,-10604,922,-7425,16662,763,-3660,3636,22278 } }, { "Canon PowerShot A530", 0, 0, { 0 } }, /* don't want the A5 matrix */ { "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 G11", 0, 0, { 12177,-4817,-1069,-1612,9864,2049,-98,850,4471 } }, { "Canon PowerShot G12", 0, 0, { 13244,-5501,-1248,-1508,9858,1935,-270,1083,4366 } }, { "Canon PowerShot G15", 0, 0, { 7474,-2301,-567,-4056,11456,2975,-222,716,4181 } }, { "Canon PowerShot G16", 0, 0, { 8020,-2687,-682,-3704,11879,2052,-965,1921,5556 } }, { "Canon PowerShot G1 X Mark III", 0, 0, { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, { "Canon PowerShot G1 X", 0, 0, { 7378,-1255,-1043,-4088,12251,2048,-876,1946,5805 } }, { "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 X", 0, 0, { 9701,-3857,-921,-3149,11537,1817,-786,1817,5147 } }, { "Canon PowerShot G3", 0, 0, { 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } }, { "Canon PowerShot G5 X", 0, 0, { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } }, { "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 G7 X", 0, 0, { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } }, { "Canon PowerShot G9 X Mark II", 0, 0, { 10056,-4131,-944,-2576,11143,1625,-238,1294,5179 } }, { "Canon PowerShot G9 X", 0, 0, { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } }, { "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 S90", 0, 0, { 12374,-5016,-1049,-1677,9902,2078,-83,852,4683 } }, { "Canon PowerShot S95", 0, 0, { 13440,-5896,-1279,-1236,9598,1931,-180,1001,4651 } }, { "Canon PowerShot S100", 0, 0, { 7968,-2565,-636,-2873,10697,2513,180,667,4211 } }, { "Canon PowerShot S110", 0, 0, { 8039,-2643,-654,-3783,11230,2930,-206,690,4194 } }, { "Canon PowerShot S120", 0, 0, { 6961,-1685,-695,-4625,12945,1836,-1114,2152,5518 } }, { "Canon PowerShot SX1 IS", 0, 0, { 6578,-259,-502,-5974,13030,3309,-308,1058,4970 } }, { "Canon PowerShot SX50 HS", 0, 0, { 12432,-4753,-1247,-2110,10691,1629,-412,1623,4926 } }, { "Canon PowerShot SX60 HS", 0, 0, { 13161,-5451,-1344,-1989,10654,1531,-47,1271,4955 } }, { "Canon PowerShot A3300", 0, 0, /* DJC */ { 10826,-3654,-1023,-3215,11310,1906,0,999,4960 } }, { "Canon PowerShot A470", 0, 0, /* DJC */ { 12513,-4407,-1242,-2680,10276,2405,-878,2215,4734 } }, { "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 SX110 IS", 0, 0, /* DJC */ { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } }, { "Canon PowerShot SX220", 0, 0, /* DJC */ { 13898,-5076,-1447,-1405,10109,1297,-244,1860,3687 } }, { "Canon IXUS 160", 0, 0, /* DJC */ { 11657,-3781,-1136,-3544,11262,2283,-160,1219,4700 } }, { "Casio EX-S20", 0, 0, /* DJC */ { 11634,-3924,-1128,-4968,12954,2015,-1588,2648,7206 } }, { "Casio EX-Z750", 0, 0, /* DJC */ { 10819,-3873,-1099,-4903,13730,1175,-1755,3751,4632 } }, { "Casio EX-Z10", 128, 0xfff, /* DJC */ { 9790,-3338,-603,-2321,10222,2099,-344,1273,4799 } }, { "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 } }, { "DXO ONE", 0, 0, { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } }, { "Epson R-D1", 0, 0, { 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } }, { "Fujifilm E550", 0, 0, { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } }, { "Fujifilm E900", 0, 0, { 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } }, { "Fujifilm F5", 0, 0, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, { "Fujifilm F6", 0, 0, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, { "Fujifilm F77", 0, 0xfe9, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, { "Fujifilm F7", 0, 0, { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, { "Fujifilm F8", 0, 0, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, { "Fujifilm GFX 50S", 0, 0, { 11756,-4754,-874,-3056,11045,2305,-381,1457,6006 } }, { "Fujifilm S100FS", 514, 0, { 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } }, { "Fujifilm S1", 0, 0, { 12297,-4882,-1202,-2106,10691,1623,-88,1312,4790 } }, { "Fujifilm S20Pro", 0, 0, { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, { "Fujifilm S20", 512, 0x3fff, { 11401,-4498,-1312,-5088,12751,2613,-838,1568,5941 } }, { "Fujifilm S2Pro", 128, 0xf15, { 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } }, { "Fujifilm S3Pro", 0, 0x3dff, { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } }, { "Fujifilm S5Pro", 0, 0, { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } }, { "Fujifilm S5000", 0, 0, { 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } }, { "Fujifilm S5100", 0, 0, { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } }, { "Fujifilm S5500", 0, 0, { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } }, { "Fujifilm S5200", 0, 0, { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } }, { "Fujifilm S5600", 0, 0, { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } }, { "Fujifilm S6", 0, 0, { 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } }, { "Fujifilm S7000", 0, 0, { 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } }, { "Fujifilm S9000", 0, 0, { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } }, { "Fujifilm S9500", 0, 0, { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } }, { "Fujifilm S9100", 0, 0, { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } }, { "Fujifilm S9600", 0, 0, { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } }, { "Fujifilm SL1000", 0, 0, { 11705,-4262,-1107,-2282,10791,1709,-555,1713,4945 } }, { "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 } }, { "Fujifilm HS10 HS11", 0, 0xf68, { 12440,-3954,-1183,-1123,9674,1708,-83,1614,4086 } }, { "Fujifilm HS2", 0, 0xfef, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, { "Fujifilm HS3", 0, 0, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, { "Fujifilm HS50EXR", 0, 0, { 12085,-4727,-953,-3257,11489,2002,-511,2046,4592 } }, { "Fujifilm F900EXR", 0, 0, { 12085,-4727,-953,-3257,11489,2002,-511,2046,4592 } }, { "Fujifilm X100F", 0, 0, { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, { "Fujifilm X100S", 0, 0, { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } }, { "Fujifilm X100T", 0, 0, { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } }, { "Fujifilm X100", 0, 0, { 12161,-4457,-1069,-5034,12874,2400,-795,1724,6904 } }, { "Fujifilm X10", 0, 0, { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } }, { "Fujifilm X20", 0, 0, { 11768,-4971,-1133,-4904,12927,2183,-480,1723,4605 } }, { "Fujifilm X30", 0, 0, { 12328,-5256,-1144,-4469,12927,1675,-87,1291,4351 } }, { "Fujifilm X70", 0, 0, { 10450,-4329,-878,-3217,11105,2421,-752,1758,6519 } }, { "Fujifilm X-Pro1", 0, 0, { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } }, { "Fujifilm X-Pro2", 0, 0, { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, { "Fujifilm X-A10", 0, 0, { 11540,-4999,-991,-2949,10963,2278,-382,1049,5605 } }, { "Fujifilm X-A20", 0, 0, { 11540,-4999,-991,-2949,10963,2278,-382,1049,5605 } }, { "Fujifilm X-A1", 0, 0, { 11086,-4555,-839,-3512,11310,2517,-815,1341,5940 } }, { "Fujifilm X-A2", 0, 0, { 10763,-4560,-917,-3346,11311,2322,-475,1135,5843 } }, { "Fujifilm X-A3", 0, 0, { 12407,-5222,-1086,-2971,11116,2120,-294,1029,5284 } }, { "Fujifilm X-A5", 0, 0, { 11673,-4760,-1041,-3988,12058,2166,-771,1417,5569 } }, { "Fujifilm X-E1", 0, 0, { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } }, { "Fujifilm X-E2S", 0, 0, { 11562,-5118,-961,-3022,11007,2311,-525,1569,6097 } }, { "Fujifilm X-E2", 0, 0, { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } }, { "Fujifilm X-E3", 0, 0, { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, { "Fujifilm X-H1", 0, 0, { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, { "Fujifilm X-M1", 0, 0, { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } }, { "Fujifilm X-S1", 0, 0, { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } }, { "Fujifilm X-T1", 0, 0, /* also X-T10 */ { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } }, { "Fujifilm X-T2", 0, 0, /* also X-T20 */ { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, { "Fujifilm XF1", 0, 0, { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } }, { "Fujifilm XQ", 0, 0, /* XQ1 and XQ2 */ { 9252,-2704,-1064,-5893,14265,1717,-1101,2341,4349 } }, { "GoPro HERO5 Black", 0, 0, { 10344,-4210,-620,-2315,10625,1948,93,1058,5541 } }, { "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", 178, 0, { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, { "Kodak DCS560C", 177, 0, { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } }, { "Kodak DCS620C", 177, 0, { 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } }, { "Kodak DCS620X", 176, 0, { 13095,-6231,154,12221,-21,-2137,895,4602,2258 } }, { "Kodak DCS660C", 173, 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 } }, { "Kodak EasyShare Z980", 0, 0, { 11313,-3559,-1101,-3893,11891,2257,-1214,2398,4908 } }, { "Kodak EasyShare Z981", 0, 0, { 12729,-4717,-1188,-1367,9187,2582,274,860,4411 } }, { "Kodak EasyShare Z990", 0, 0xfed, { 11749,-4048,-1309,-1867,10572,1489,-138,1449,4522 } }, { "Kodak EASYSHARE Z1015", 0, 0xef1, { 11265,-4286,-992,-4694,12343,2647,-1090,1523,5447 } }, { "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 D200", 0, 0xfbc, { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } }, { "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 D3000", 0, 0, { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } }, { "Nikon D3100", 0, 0, { 7911,-2167,-813,-5327,13150,2408,-1288,2483,7968 } }, { "Nikon D3200", 0, 0xfb9, { 7013,-1408,-635,-5268,12902,2640,-1470,2801,7379 } }, { "Nikon D3300", 0, 0, { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } }, { "Nikon D3400", 0, 0, { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } }, { "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 D3S", 0, 0, { 8828,-2406,-694,-4874,12603,2541,-660,1509,7587 } }, { "Nikon D3", 0, 0, { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } }, { "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 D4S", 0, 0, { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } }, { "Nikon D4", 0, 0, { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } }, { "Nikon Df", 0, 0, { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } }, { "Nikon D5000", 0, 0xf00, { 7309,-1403,-519,-8474,16008,2622,-2433,2826,8064 } }, { "Nikon D5100", 0, 0x3de6, { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, { "Nikon D5200", 0, 0, { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, { "Nikon D5300", 0, 0, { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } }, { "Nikon D5500", 0, 0, { 8821,-2938,-785,-4178,12142,2287,-824,1651,6860 } }, { "Nikon D5600", 0, 0, { 8821,-2938,-785,-4178,12142,2287,-824,1651,6860 } }, { "Nikon D500", 0, 0, { 8813,-3210,-1036,-4703,12868,2021,-1054,1940,6129 } }, { "Nikon D50", 0, 0, { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, { "Nikon D5", 0, 0, { 9200,-3522,-992,-5755,13803,2117,-753,1486,6338 } }, { "Nikon D600", 0, 0x3e07, { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } }, { "Nikon D610", 0, 0, { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } }, { "Nikon D60", 0, 0, { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } }, { "Nikon D7000", 0, 0, { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, { "Nikon D7100", 0, 0, { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, { "Nikon D7200", 0, 0, { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, { "Nikon D7500", 0, 0, { 8813,-3210,-1036,-4703,12868,2021,-1054,1940,6129 } }, { "Nikon D750", 0, 0, { 9020,-2890,-715,-4535,12436,2348,-934,1919,7086 } }, { "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 D850", 0, 0, { 10405,-3755,-1270,-5461,13787,1793,-1040,2015,6785 } }, { "Nikon D810", 0, 0, { 9369,-3195,-791,-4488,12430,2301,-893,1796,6872 } }, { "Nikon D800", 0, 0, { 7866,-2108,-555,-4869,12483,2681,-1176,2069,7501 } }, { "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 E700", 0, 0x3dd, /* DJC */ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, { "Nikon E800", 0, 0x3dd, /* DJC */ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, { "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 E3200", 0, 0, /* DJC */ { 9846,-2085,-1019,-3278,11109,2170,-774,2134,5745 } }, { "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 A", 0, 0, { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, { "Nikon COOLPIX B700", 200, 0, { 14387,-6014,-1299,-1357,9975,1616,467,1047,4744 } }, { "Nikon COOLPIX P330", 200, 0, { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, { "Nikon COOLPIX P340", 200, 0, { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, { "Nikon COOLPIX P6000", 0, 0, { 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } }, { "Nikon COOLPIX P7000", 0, 0, { 11432,-3679,-1111,-3169,11239,2202,-791,1380,4455 } }, { "Nikon COOLPIX P7100", 0, 0, { 11053,-4269,-1024,-1976,10182,2088,-526,1263,4469 } }, { "Nikon COOLPIX P7700", 200, 0, { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, { "Nikon COOLPIX P7800", 200, 0, { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, { "Nikon 1 V3", 0, 0, { 5958,-1559,-571,-4021,11453,2939,-634,1548,5087 } }, { "Nikon 1 J4", 0, 0, { 5958,-1559,-571,-4021,11453,2939,-634,1548,5087 } }, { "Nikon 1 J5", 0, 0, { 7520,-2518,-645,-3844,12102,1945,-913,2249,6835 } }, { "Nikon 1 S2", 200, 0, { 6612,-1342,-618,-3338,11055,2623,-174,1792,5075 } }, { "Nikon 1 V2", 0, 0, { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } }, { "Nikon 1 J3", 0, 0, { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } }, { "Nikon 1 AW1", 0, 0, { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } }, { "Nikon 1 ", 0, 0, /* J1, J2, S1, V1 */ { 8994,-2667,-865,-4594,12324,2552,-699,1786,6260 } }, { "Olympus AIR A01", 0, 0, { 8992,-3093,-639,-2563,10721,2122,-437,1270,5473 } }, { "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, 0xffc, { 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } }, { "Olympus E-1", 0, 0, { 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } }, { "Olympus E-20", 0, 0xffc, { 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, 0xfbc, { 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, 0, { 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-450", 0, 0xfd2, { 8745,-2425,-1095,-7594,15613,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 E-5", 0, 0xeec, { 11200,-3783,-1325,-4576,12593,2206,-695,1742,7504 } }, { "Olympus E-600", 0, 0xfaf, { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } }, { "Olympus E-620", 0, 0xfaf, { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } }, { "Olympus E-P1", 0, 0xffd, { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } }, { "Olympus E-P2", 0, 0xffd, { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } }, { "Olympus E-P3", 0, 0, { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } }, { "Olympus E-P5", 0, 0, { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, { "Olympus E-PL1s", 0, 0, { 11409,-3872,-1393,-4572,12757,2003,-709,1810,7415 } }, { "Olympus E-PL1", 0, 0, { 11408,-4289,-1215,-4286,12385,2118,-387,1467,7787 } }, { "Olympus E-PL2", 0, 0xcf3, { 15030,-5552,-1806,-3987,12387,1767,-592,1670,7023 } }, { "Olympus E-PL3", 0, 0, { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } }, { "Olympus E-PL5", 0, 0xfcb, { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, { "Olympus E-PL6", 0, 0, { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, { "Olympus E-PL7", 0, 0, { 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 } }, { "Olympus E-PL8", 0, 0, { 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 } }, { "Olympus E-PL9", 0, 0, { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, { "Olympus E-PM1", 0, 0, { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } }, { "Olympus E-PM2", 0, 0, { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, { "Olympus E-M10", 0, 0, /* also E-M10 Mark II & III */ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, { "Olympus E-M1Mark II", 0, 0, { 9383,-3170,-763,-2457,10702,2020,-384,1236,5552 } }, { "Olympus E-M1", 0, 0, { 7687,-1984,-606,-4327,11928,2721,-1381,2339,6452 } }, { "Olympus E-M5MarkII", 0, 0, { 9422,-3258,-711,-2655,10898,2015,-512,1354,5512 } }, { "Olympus E-M5", 0, 0xfe1, { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, { "Olympus PEN-F", 0, 0, { 9476,-3182,-765,-2613,10958,1893,-449,1315,5268 } }, { "Olympus SH-2", 0, 0, { 10156,-3425,-1077,-2611,11177,1624,-385,1592,5080 } }, { "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 } }, { "Olympus STYLUS1", 0, 0, { 8360,-2420,-880,-3928,12353,1739,-1381,2416,5173 } }, { "Olympus TG-4", 0, 0, { 11426,-4159,-1126,-2066,10678,1593,-120,1327,4998 } }, { "Olympus TG-5", 0, 0, { 10899,-3833,-1082,-2112,10736,1575,-267,1452,5269 } }, { "Olympus XZ-10", 0, 0, { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } }, { "Olympus XZ-1", 0, 0, { 10901,-4095,-1074,-1141,9208,2293,-62,1417,5158 } }, { "Olympus XZ-2", 0, 0, { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } }, { "OmniVision", 0, 0, /* DJC */ { 12782,-4059,-379,-478,9066,1413,1340,1513,5176 } }, { "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 } }, { "Pentax K-x", 0, 0, { 8843,-2837,-625,-5025,12644,2668,-411,1234,7410 } }, { "Pentax K-r", 0, 0, { 9895,-3077,-850,-5304,13035,2521,-883,1768,6936 } }, { "Pentax K-1", 0, 0, { 8596,-2981,-639,-4202,12046,2431,-685,1424,6122 } }, { "Pentax K-30", 0, 0, { 8710,-2632,-1167,-3995,12301,1881,-981,1719,6535 } }, { "Pentax K-3 II", 0, 0, { 8626,-2607,-1155,-3995,12301,1881,-1039,1822,6925 } }, { "Pentax K-3", 0, 0, { 7415,-2052,-721,-5186,12788,2682,-1446,2157,6773 } }, { "Pentax K-5 II", 0, 0, { 8170,-2725,-639,-4440,12017,2744,-771,1465,6599 } }, { "Pentax K-5", 0, 0, { 8713,-2833,-743,-4342,11900,2772,-722,1543,6247 } }, { "Pentax K-70", 0, 0, { 8270,-2117,-1299,-4359,12953,1515,-1078,1933,5975 } }, { "Pentax K-7", 0, 0, { 9142,-2947,-678,-8648,16967,1663,-2224,2898,8615 } }, { "Pentax K-S1", 0, 0, { 8512,-3211,-787,-4167,11966,2487,-638,1288,6054 } }, { "Pentax K-S2", 0, 0, { 8662,-3280,-798,-3928,11771,2444,-586,1232,6054 } }, { "Pentax KP", 0, 0, { 8617,-3228,-1034,-4674,12821,2044,-803,1577,5728 } }, { "Pentax Q-S1", 0, 0, { 12995,-5593,-1107,-1879,10139,2027,-64,1233,4919 } }, { "Pentax 645D", 0, 0x3e00, { 10646,-3593,-1158,-3329,11699,1831,-667,2874,6287 } }, { "Panasonic DMC-CM1", 15, 0, { 8770,-3194,-820,-2871,11281,1803,-513,1552,4434 } }, { "Panasonic DC-FZ80", 0, 0, { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } }, { "Panasonic DMC-FZ8", 0, 0xf7f, { 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, 0xf96, { 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } }, { "Panasonic DMC-FZ2500", 15, 0, { 7386,-2443,-743,-3437,11864,1757,-608,1660,4766 } }, { "Panasonic DMC-FZ330", 15, 0, { 8378,-2798,-769,-3068,11410,1877,-538,1792,4623 } }, { "Panasonic DMC-FZ300", 15, 0, { 8378,-2798,-769,-3068,11410,1877,-538,1792,4623 } }, { "Panasonic DMC-FZ30", 0, 0xf94, { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } }, { "Panasonic DMC-FZ3", 15, 0, /* FZ35, FZ38 */ { 9938,-2780,-890,-4604,12393,2480,-1117,2304,4620 } }, { "Panasonic DMC-FZ4", 15, 0, /* FZ40, FZ45 */ { 13639,-5535,-1371,-1698,9633,2430,316,1152,4108 } }, { "Panasonic DMC-FZ50", 0, 0, { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } }, { "Panasonic DMC-FZ7", 15, 0, /* FZ70, FZ72 */ { 11532,-4324,-1066,-2375,10847,1749,-564,1699,4351 } }, { "Leica V-LUX1", 0, 0, { 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, 0xf7f, { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } }, { "Leica DIGILUX 3", 0, 0xf7f, { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } }, { "Panasonic DMC-LC1", 0, 0, { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } }, { "Leica DIGILUX 2", 0, 0, { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } }, { "Panasonic DMC-LX100", 15, 0, { 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 } }, { "Leica D-LUX (Typ 109)", 15, 0, { 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 } }, { "Panasonic DMC-LF1", 15, 0, { 9379,-3267,-816,-3227,11560,1881,-926,1928,5340 } }, { "Leica C (Typ 112)", 15, 0, { 9379,-3267,-816,-3227,11560,1881,-926,1928,5340 } }, { "Panasonic DMC-LX1", 0, 0xf7f, { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } }, { "Leica D-LUX2", 0, 0xf7f, { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } }, { "Panasonic DMC-LX2", 0, 0, { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } }, { "Leica D-LUX3", 0, 0, { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } }, { "Panasonic DMC-LX3", 15, 0, { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } }, { "Leica D-LUX 4", 15, 0, { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } }, { "Panasonic DMC-LX5", 15, 0, { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } }, { "Leica D-LUX 5", 15, 0, { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } }, { "Panasonic DMC-LX7", 15, 0, { 10148,-3743,-991,-2837,11366,1659,-701,1893,4899 } }, { "Leica D-LUX 6", 15, 0, { 10148,-3743,-991,-2837,11366,1659,-701,1893,4899 } }, { "Panasonic DMC-LX9", 15, 0, { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, { "Panasonic DMC-FZ1000", 15, 0, { 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 } }, { "Leica V-LUX (Typ 114)", 15, 0, { 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 } }, { "Panasonic DMC-FZ100", 15, 0xfff, { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } }, { "Leica V-LUX 2", 15, 0xfff, { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } }, { "Panasonic DMC-FZ150", 15, 0xfff, { 11904,-4541,-1189,-2355,10899,1662,-296,1586,4289 } }, { "Leica V-LUX 3", 15, 0xfff, { 11904,-4541,-1189,-2355,10899,1662,-296,1586,4289 } }, { "Panasonic DMC-FZ200", 15, 0xfff, { 8112,-2563,-740,-3730,11784,2197,-941,2075,4933 } }, { "Leica V-LUX 4", 15, 0xfff, { 8112,-2563,-740,-3730,11784,2197,-941,2075,4933 } }, { "Panasonic DMC-FX150", 15, 0xfff, { 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } }, { "Panasonic DMC-G10", 0, 0, { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } }, { "Panasonic DMC-G1", 15, 0xf94, { 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } }, { "Panasonic DMC-G2", 15, 0xf3c, { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } }, { "Panasonic DMC-G3", 15, 0xfff, { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } }, { "Panasonic DMC-G5", 15, 0xfff, { 7798,-2562,-740,-3879,11584,2613,-1055,2248,5434 } }, { "Panasonic DMC-G6", 15, 0xfff, { 8294,-2891,-651,-3869,11590,2595,-1183,2267,5352 } }, { "Panasonic DMC-G7", 15, 0xfff, { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, { "Panasonic DMC-G8", 15, 0xfff, /* G8, G80, G81, G85 */ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, { "Panasonic DC-G9", 15, 0xfff, { 7685,-2375,-634,-3687,11700,2249,-748,1546,5111 } }, { "Panasonic DMC-GF1", 15, 0xf92, { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } }, { "Panasonic DMC-GF2", 15, 0xfff, { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } }, { "Panasonic DMC-GF3", 15, 0xfff, { 9051,-2468,-1204,-5212,13276,2121,-1197,2510,6890 } }, { "Panasonic DMC-GF5", 15, 0xfff, { 8228,-2945,-660,-3938,11792,2430,-1094,2278,5793 } }, { "Panasonic DMC-GF6", 15, 0, { 8130,-2801,-946,-3520,11289,2552,-1314,2511,5791 } }, { "Panasonic DMC-GF7", 15, 0, { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, { "Panasonic DMC-GF8", 15, 0, { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, { "Panasonic DC-GF9", 15, 0, { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, { "Panasonic DMC-GH1", 15, 0xf92, { 6299,-1466,-532,-6535,13852,2969,-2331,3112,5984 } }, { "Panasonic DMC-GH2", 15, 0xf95, { 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 } }, { "Panasonic DMC-GH3", 15, 0, { 6559,-1752,-491,-3672,11407,2586,-962,1875,5130 } }, { "Panasonic DMC-GH4", 15, 0, { 7122,-2108,-512,-3155,11201,2231,-541,1423,5045 } }, { "Panasonic DC-GH5S", 15, 0, { 6929,-2355,-708,-4192,12534,1828,-1097,1989,5195 } }, { "Panasonic DC-GH5", 15, 0, { 7641,-2336,-605,-3218,11299,2187,-485,1338,5121 } }, { "Panasonic DMC-GM1", 15, 0, { 6770,-1895,-744,-5232,13145,2303,-1664,2691,5703 } }, { "Panasonic DMC-GM5", 15, 0, { 8238,-3244,-679,-3921,11814,2384,-836,2022,5852 } }, { "Panasonic DMC-GX1", 15, 0, { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } }, { "Panasonic DMC-GX7", 15, 0, { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, { "Panasonic DMC-GX85", 15, 0, { 7771,-3020,-629,-4029,11950,2345,-821,1977,6119 } }, { "Panasonic DMC-GX8", 15, 0, { 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 } }, { "Panasonic DC-GX9", 15, 0, { 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 } }, { "Panasonic DMC-ZS100", 15, 0, { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, { "Panasonic DC-ZS200", 15, 0, { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, { "Panasonic DMC-ZS40", 15, 0, { 8607,-2822,-808,-3755,11930,2049,-820,2060,5224 } }, { "Panasonic DMC-ZS50", 15, 0, { 8802,-3135,-789,-3151,11468,1904,-550,1745,4810 } }, { "Panasonic DMC-TZ82", 15, 0, { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } }, { "Panasonic DMC-ZS6", 15, 0, { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } }, { "Panasonic DMC-ZS70", 15, 0, { 9052,-3117,-883,-3045,11346,1927,-205,1520,4730 } }, { "Leica S (Typ 007)", 0, 0, { 6063,-2234,-231,-5210,13787,1500,-1043,2866,6997 } }, { "Leica X", 0, 0, /* X and X-U, both (Typ 113) */ { 7712,-2059,-653,-3882,11494,2726,-710,1332,5958 } }, { "Leica Q (Typ 116)", 0, 0, { 11865,-4523,-1441,-5423,14458,935,-1587,2687,4830 } }, { "Leica M (Typ 262)", 0, 0, { 6653,-1486,-611,-4221,13303,929,-881,2416,7226 } }, { "Leica SL (Typ 601)", 0, 0, { 11865,-4523,-1441,-5423,14458,935,-1587,2687,4830 } }, { "Leica TL2", 0, 0, { 5836,-1626,-647,-5384,13326,2261,-1207,2129,5861 } }, { "Leica TL", 0, 0, { 5463,-988,-364,-4634,12036,2946,-766,1389,6522 } }, { "Leica CL", 0, 0, { 7414,-2393,-840,-5127,13180,2138,-1585,2468,5064 } }, { "Leica M10", 0, 0, { 8249,-2849,-620,-5415,14756,565,-957,3074,6517 } }, { "Phase One H 20", 0, 0, /* DJC */ { 1313,1855,-109,-6715,15908,808,-327,1840,6020 } }, { "Phase One H 25", 0, 0, { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } }, { "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 P40", 0, 0, { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, { "Phase One P65", 0, 0, { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, { "Photron BC2-HD", 0, 0, /* DJC */ { 14603,-4122,-528,-1810,9794,2017,-297,2763,5936 } }, { "Red One", 704, 0xffff, /* DJC */ { 21014,-7891,-2613,-3056,12201,856,-2203,5125,8042 } }, { "Ricoh GR II", 0, 0, { 4630,-834,-423,-4977,12805,2417,-638,1467,6115 } }, { "Ricoh GR", 0, 0, { 3708,-543,-160,-5381,12254,3556,-1471,1929,8234 } }, { "Samsung EX1", 0, 0x3e00, { 8898,-2498,-994,-3144,11328,2066,-760,1381,4576 } }, { "Samsung EX2F", 0, 0x7ff, { 10648,-3897,-1055,-2022,10573,1668,-492,1611,4742 } }, { "Samsung EK-GN120", 0, 0, { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, { "Samsung NX mini", 0, 0, { 5222,-1196,-550,-6540,14649,2009,-1666,2819,5657 } }, { "Samsung NX3300", 0, 0, { 8060,-2933,-761,-4504,12890,1762,-630,1489,5227 } }, { "Samsung NX3000", 0, 0, { 8060,-2933,-761,-4504,12890,1762,-630,1489,5227 } }, { "Samsung NX30", 0, 0, /* NX30, NX300, NX300M */ { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, { "Samsung NX2000", 0, 0, { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, { "Samsung NX2", 0, 0xfff, /* NX20, NX200, NX210 */ { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } }, { "Samsung NX1000", 0, 0, { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } }, { "Samsung NX1100", 0, 0, { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } }, { "Samsung NX11", 0, 0, { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } }, { "Samsung NX10", 0, 0, /* also NX100 */ { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } }, { "Samsung NX500", 0, 0, { 10686,-4042,-1052,-3595,13238,276,-464,1259,5931 } }, { "Samsung NX5", 0, 0, { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } }, { "Samsung NX1", 0, 0, { 10686,-4042,-1052,-3595,13238,276,-464,1259,5931 } }, { "Samsung WB2000", 0, 0xfff, { 12093,-3557,-1155,-1000,9534,1733,-22,1787,4576 } }, { "Samsung GX-1", 0, 0, { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, { "Samsung GX20", 0, 0, /* copied from Pentax K20D */ { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } }, { "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", 0, 0, { 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } }, { "Sony DSC-R1", 0, 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 DSC-RX100M", 0, 0, /* M2, M3, M4, and M5 */ { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } }, { "Sony DSC-RX100", 0, 0, { 8651,-2754,-1057,-3464,12207,1373,-568,1398,4434 } }, { "Sony DSC-RX10M4", 0, 0, { 7699,-2566,-629,-2967,11270,1928,-378,1286,4807 } }, { "Sony DSC-RX10", 0, 0, /* also RX10M2, RX10M3 */ { 6679,-1825,-745,-5047,13256,1953,-1580,2422,5183 } }, { "Sony DSC-RX1RM2", 0, 0, { 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 } }, { "Sony DSC-RX1", 0, 0, { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, { "Sony DSC-RX0", 200, 0, { 9396,-3507,-843,-2497,11111,1572,-343,1355,5089 } }, { "Sony DSLR-A100", 0, 0xfeb, { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } }, { "Sony DSLR-A290", 0, 0, { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } }, { "Sony DSLR-A2", 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-A330", 0, 0, { 9847,-3091,-929,-8485,16346,2225,-714,595,7103 } }, { "Sony DSLR-A350", 0, 0xffc, { 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } }, { "Sony DSLR-A380", 0, 0, { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } }, { "Sony DSLR-A390", 0, 0, { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } }, { "Sony DSLR-A450", 0, 0xfeb, { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } }, { "Sony DSLR-A580", 0, 0xfeb, { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } }, { "Sony DSLR-A500", 0, 0xfeb, { 6046,-1127,-278,-5574,13076,2786,-691,1419,7625 } }, { "Sony DSLR-A5", 0, 0xfeb, { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } }, { "Sony DSLR-A700", 0, 0, { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } }, { "Sony DSLR-A850", 0, 0, { 5413,-1162,-365,-5665,13098,2866,-608,1179,8440 } }, { "Sony DSLR-A900", 0, 0, { 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } }, { "Sony ILCA-68", 0, 0, { 6435,-1903,-536,-4722,12449,2550,-663,1363,6517 } }, { "Sony ILCA-77M2", 0, 0, { 5991,-1732,-443,-4100,11989,2381,-704,1467,5992 } }, { "Sony ILCA-99M2", 0, 0, { 6660,-1918,-471,-4613,12398,2485,-649,1433,6447 } }, { "Sony ILCE-6", 0, 0, /* 6300, 6500 */ { 5973,-1695,-419,-3826,11797,2293,-639,1398,5789 } }, { "Sony ILCE-7M2", 0, 0, { 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 } }, { "Sony ILCE-7M3", 0, 0, { 7374,-2389,-551,-5435,13162,2519,-1006,1795,6552 } }, { "Sony ILCE-7S", 0, 0, /* also ILCE-7SM2 */ { 5838,-1430,-246,-3497,11477,2297,-748,1885,5778 } }, { "Sony ILCE-7RM3", 0, 0, { 6640,-1847,-503,-5238,13010,2474,-993,1673,6527 } }, { "Sony ILCE-7RM2", 0, 0, { 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 } }, { "Sony ILCE-7R", 0, 0, { 4913,-541,-202,-6130,13513,2906,-1564,2151,7183 } }, { "Sony ILCE-7", 0, 0, { 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 } }, { "Sony ILCE-9", 0, 0, { 6389,-1703,-378,-4562,12265,2587,-670,1489,6550 } }, { "Sony ILCE", 0, 0, /* 3000, 5000, 5100, 6000, and QX1 */ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony NEX-5N", 0, 0, { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony NEX-5R", 0, 0, { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, { "Sony NEX-5T", 0, 0, { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, { "Sony NEX-3N", 0, 0, { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, { "Sony NEX-3", 138, 0, /* DJC */ { 6907,-1256,-645,-4940,12621,2320,-1710,2581,6230 } }, { "Sony NEX-5", 116, 0, /* DJC */ { 6807,-1350,-342,-4216,11649,2567,-1089,2001,6420 } }, { "Sony NEX-3", 0, 0, /* Adobe */ { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } }, { "Sony NEX-5", 0, 0, /* Adobe */ { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } }, { "Sony NEX-6", 0, 0, { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, { "Sony NEX-7", 0, 0, { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, { "Sony NEX", 0, 0, /* NEX-C3, NEX-F3 */ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony SLT-A33", 0, 0, { 6069,-1221,-366,-5221,12779,2734,-1024,2066,6834 } }, { "Sony SLT-A35", 0, 0, { 5986,-1618,-415,-4557,11820,3120,-681,1404,6971 } }, { "Sony SLT-A37", 0, 0, { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony SLT-A55", 0, 0, { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } }, { "Sony SLT-A57", 0, 0, { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony SLT-A58", 0, 0, { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony SLT-A65", 0, 0, { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, { "Sony SLT-A77", 0, 0, { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, { "Sony SLT-A99", 0, 0, { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, { "YI M1", 0, 0, { 7712,-2059,-653,-3882,11494,2726,-710,1332,5958 } }, }; 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; if (table[i].trans[0]) { for (raw_color = j=0; j < 12; j++) ((double *)cam_xyz)[j] = table[i].trans[j] / 10000.0; cam_xyz_coeff (rgb_cam, 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; } float CLASS find_green (int bps, int bite, int off0, int off1) { UINT64 bitbuf=0; int vbits, col, i, c; ushort img[2][2064]; double sum[]={0,0}; FORC(2) { fseek (ifp, c ? off1:off0, SEEK_SET); for (vbits=col=0; col < width; col++) { for (vbits -= bps; vbits < 0; vbits += bite) { bitbuf <<= bite; for (i=0; i < bite; i+=8) bitbuf |= (unsigned) (fgetc(ifp) << i); } img[c][col] = bitbuf << (64-bps-vbits) >> (64-bps); } } FORC(width-1) { sum[ c & 1] += ABS(img[0][c]-img[1][c+1]); sum[~c & 1] += ABS(img[1][c]-img[0][c+1]); } return 100 * log(sum[0]/sum[1]); } /* Identify which camera created this file, and set global variables accordingly. */ void CLASS identify() { static const short pana[][6] = { { 3130, 1743, 4, 0, -6, 0 }, { 3130, 2055, 4, 0, -6, 0 }, { 3130, 2319, 4, 0, -6, 0 }, { 3170, 2103, 18, 0,-42, 20 }, { 3170, 2367, 18, 13,-42,-21 }, { 3177, 2367, 0, 0, -1, 0 }, { 3304, 2458, 0, 0, -1, 0 }, { 3330, 2463, 9, 0, -5, 0 }, { 3330, 2479, 9, 0,-17, 4 }, { 3370, 1899, 15, 0,-44, 20 }, { 3370, 2235, 15, 0,-44, 20 }, { 3370, 2511, 15, 10,-44,-21 }, { 3690, 2751, 3, 0, -8, -3 }, { 3710, 2751, 0, 0, -3, 0 }, { 3724, 2450, 0, 0, 0, -2 }, { 3770, 2487, 17, 0,-44, 19 }, { 3770, 2799, 17, 15,-44,-19 }, { 3880, 2170, 6, 0, -6, 0 }, { 4060, 3018, 0, 0, 0, -2 }, { 4290, 2391, 3, 0, -8, -1 }, { 4330, 2439, 17, 15,-44,-19 }, { 4508, 2962, 0, 0, -3, -4 }, { 4508, 3330, 0, 0, -3, -6 }, }; static const ushort canon[][11] = { { 1944, 1416, 0, 0, 48, 0 }, { 2144, 1560, 4, 8, 52, 2, 0, 0, 0, 25 }, { 2224, 1456, 48, 6, 0, 2 }, { 2376, 1728, 12, 6, 52, 2 }, { 2672, 1968, 12, 6, 44, 2 }, { 3152, 2068, 64, 12, 0, 0, 16 }, { 3160, 2344, 44, 12, 4, 4 }, { 3344, 2484, 4, 6, 52, 6 }, { 3516, 2328, 42, 14, 0, 0 }, { 3596, 2360, 74, 12, 0, 0 }, { 3744, 2784, 52, 12, 8, 12 }, { 3944, 2622, 30, 18, 6, 2 }, { 3948, 2622, 42, 18, 0, 2 }, { 3984, 2622, 76, 20, 0, 2, 14 }, { 4104, 3048, 48, 12, 24, 12 }, { 4116, 2178, 4, 2, 0, 0 }, { 4152, 2772, 192, 12, 0, 0 }, { 4160, 3124, 104, 11, 8, 65 }, { 4176, 3062, 96, 17, 8, 0, 0, 16, 0, 7, 0x49 }, { 4192, 3062, 96, 17, 24, 0, 0, 16, 0, 0, 0x49 }, { 4312, 2876, 22, 18, 0, 2 }, { 4352, 2874, 62, 18, 0, 0 }, { 4476, 2954, 90, 34, 0, 0 }, { 4480, 3348, 12, 10, 36, 12, 0, 0, 0, 18, 0x49 }, { 4480, 3366, 80, 50, 0, 0 }, { 4496, 3366, 80, 50, 12, 0 }, { 4768, 3516, 96, 16, 0, 0, 0, 16 }, { 4832, 3204, 62, 26, 0, 0 }, { 4832, 3228, 62, 51, 0, 0 }, { 5108, 3349, 98, 13, 0, 0 }, { 5120, 3318, 142, 45, 62, 0 }, { 5280, 3528, 72, 52, 0, 0 }, { 5344, 3516, 142, 51, 0, 0 }, { 5344, 3584, 126,100, 0, 2 }, { 5360, 3516, 158, 51, 0, 0 }, { 5568, 3708, 72, 38, 0, 0 }, { 5632, 3710, 96, 17, 0, 0, 0, 16, 0, 0, 0x49 }, { 5712, 3774, 62, 20, 10, 2 }, { 5792, 3804, 158, 51, 0, 0 }, { 5920, 3950, 122, 80, 2, 0 }, { 6096, 4051, 76, 35, 0, 0 }, { 6096, 4056, 72, 34, 0, 0 }, { 6288, 4056, 264, 36, 0, 0 }, { 6384, 4224, 120, 44, 0, 0 }, { 6880, 4544, 136, 42, 0, 0 }, { 8896, 5920, 160, 64, 0, 0 }, }; static const struct { ushort id; char model[20]; } unique[] = { { 0x168, "EOS 10D" }, { 0x001, "EOS-1D" }, { 0x175, "EOS 20D" }, { 0x174, "EOS-1D Mark II" }, { 0x234, "EOS 30D" }, { 0x232, "EOS-1D Mark II N" }, { 0x190, "EOS 40D" }, { 0x169, "EOS-1D Mark III" }, { 0x261, "EOS 50D" }, { 0x281, "EOS-1D Mark IV" }, { 0x287, "EOS 60D" }, { 0x167, "EOS-1DS" }, { 0x325, "EOS 70D" }, { 0x408, "EOS 77D" }, { 0x331, "EOS M" }, { 0x350, "EOS 80D" }, { 0x328, "EOS-1D X Mark II" }, { 0x346, "EOS 100D" }, { 0x417, "EOS 200D" }, { 0x170, "EOS 300D" }, { 0x188, "EOS-1Ds Mark II" }, { 0x176, "EOS 450D" }, { 0x215, "EOS-1Ds Mark III" }, { 0x189, "EOS 350D" }, { 0x324, "EOS-1D C" }, { 0x236, "EOS 400D" }, { 0x269, "EOS-1D X" }, { 0x252, "EOS 500D" }, { 0x213, "EOS 5D" }, { 0x270, "EOS 550D" }, { 0x218, "EOS 5D Mark II" }, { 0x286, "EOS 600D" }, { 0x285, "EOS 5D Mark III" }, { 0x301, "EOS 650D" }, { 0x302, "EOS 6D" }, { 0x326, "EOS 700D" }, { 0x250, "EOS 7D" }, { 0x393, "EOS 750D" }, { 0x289, "EOS 7D Mark II" }, { 0x347, "EOS 760D" }, { 0x406, "EOS 6D Mark II" }, { 0x405, "EOS 800D" }, { 0x349, "EOS 5D Mark IV" }, { 0x254, "EOS 1000D" }, { 0x288, "EOS 1100D" }, { 0x327, "EOS 1200D" }, { 0x382, "EOS 5DS" }, { 0x404, "EOS 1300D" }, { 0x401, "EOS 5DS R" }, { 0x422, "EOS 1500D" }, { 0x432, "EOS 3000D" }, }, sonique[] = { { 0x002, "DSC-R1" }, { 0x100, "DSLR-A100" }, { 0x101, "DSLR-A900" }, { 0x102, "DSLR-A700" }, { 0x103, "DSLR-A200" }, { 0x104, "DSLR-A350" }, { 0x105, "DSLR-A300" }, { 0x108, "DSLR-A330" }, { 0x109, "DSLR-A230" }, { 0x10a, "DSLR-A290" }, { 0x10d, "DSLR-A850" }, { 0x111, "DSLR-A550" }, { 0x112, "DSLR-A500" }, { 0x113, "DSLR-A450" }, { 0x116, "NEX-5" }, { 0x117, "NEX-3" }, { 0x118, "SLT-A33" }, { 0x119, "SLT-A55V" }, { 0x11a, "DSLR-A560" }, { 0x11b, "DSLR-A580" }, { 0x11c, "NEX-C3" }, { 0x11d, "SLT-A35" }, { 0x11e, "SLT-A65V" }, { 0x11f, "SLT-A77V" }, { 0x120, "NEX-5N" }, { 0x121, "NEX-7" }, { 0x123, "SLT-A37" }, { 0x124, "SLT-A57" }, { 0x125, "NEX-F3" }, { 0x126, "SLT-A99V" }, { 0x127, "NEX-6" }, { 0x128, "NEX-5R" }, { 0x129, "DSC-RX100" }, { 0x12a, "DSC-RX1" }, { 0x12e, "ILCE-3000" }, { 0x12f, "SLT-A58" }, { 0x131, "NEX-3N" }, { 0x132, "ILCE-7" }, { 0x133, "NEX-5T" }, { 0x134, "DSC-RX100M2" }, { 0x135, "DSC-RX10" }, { 0x136, "DSC-RX1R" }, { 0x137, "ILCE-7R" }, { 0x138, "ILCE-6000" }, { 0x139, "ILCE-5000" }, { 0x13d, "DSC-RX100M3" }, { 0x13e, "ILCE-7S" }, { 0x13f, "ILCA-77M2" }, { 0x153, "ILCE-5100" }, { 0x154, "ILCE-7M2" }, { 0x155, "DSC-RX100M4" },{ 0x156, "DSC-RX10M2" }, { 0x158, "DSC-RX1RM2" }, { 0x15a, "ILCE-QX1" }, { 0x15b, "ILCE-7RM2" }, { 0x15e, "ILCE-7SM2" }, { 0x161, "ILCA-68" }, { 0x162, "ILCA-99M2" }, { 0x163, "DSC-RX10M3" }, { 0x164, "DSC-RX100M5" }, { 0x165, "ILCE-6300" }, { 0x166, "ILCE-9" }, { 0x168, "ILCE-6500" }, { 0x16a, "ILCE-7RM3" }, { 0x16b, "ILCE-7M3" }, { 0x16c, "DSC-RX0" }, { 0x16d, "DSC-RX10M4" }, }; static const char *orig, panalias[][12] = { "@@DC-FZ80", "DC-FZ82", "DC-FZ85", "@@DC-FZ81", "DC-FZ83", "@@DC-GF9", "DC-GX800", "DC-GX850", "@@DC-GF10", "DC-GF90", "@@DC-GX9", "DC-GX7MK3", "@@DC-ZS70", "DC-TZ90", "DC-TZ91", "DC-TZ92", "DC-TZ93", "@@DMC-FZ40", "DMC-FZ45", "@@DMC-FZ2500", "DMC-FZ2000", "DMC-FZH1", "@@DMC-G8", "DMC-G80", "DMC-G81", "DMC-G85", "@@DMC-GX85", "DMC-GX80", "DMC-GX7MK2", "@@DMC-LX9", "DMC-LX10", "DMC-LX15", "@@DMC-ZS40", "DMC-TZ60", "DMC-TZ61", "@@DMC-ZS50", "DMC-TZ70", "DMC-TZ71", "@@DMC-ZS60", "DMC-TZ80", "DMC-TZ81", "DMC-TZ85", "@@DMC-ZS100", "DMC-ZS110", "DMC-TZ100", "DMC-TZ101", "DMC-TZ110", "DMC-TX1", "@@DC-ZS200", "DC-TX2", "DC-TZ200", "DC-TZ202", "DC-TZ220", "DC-ZS220", }; static const struct { unsigned fsize; ushort rw, rh; uchar lm, tm, rm, bm, lf, cf, max, flags; char make[10], model[20]; ushort offset; } table[] = { { 786432,1024, 768, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-080C" }, { 1447680,1392,1040, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-145C" }, { 1920000,1600,1200, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-201C" }, { 5067304,2588,1958, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-510C" }, { 5067316,2588,1958, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-510C",12 }, { 10134608,2588,1958, 0, 0, 0, 0, 9,0x94,0,0,"AVT","F-510C" }, { 10134620,2588,1958, 0, 0, 0, 0, 9,0x94,0,0,"AVT","F-510C",12 }, { 16157136,3272,2469, 0, 0, 0, 0, 9,0x94,0,0,"AVT","F-810C" }, { 15980544,3264,2448, 0, 0, 0, 0, 8,0x61,0,1,"AgfaPhoto","DC-833m" }, { 9631728,2532,1902, 0, 0, 0, 0,96,0x61,0,0,"Alcatel","5035D" }, { 2868726,1384,1036, 0, 0, 0, 0,64,0x49,0,8,"Baumer","TXG14",1078 }, { 5298000,2400,1766,12,12,44, 2, 8,0x94,0,2,"Canon","PowerShot SD300" }, { 6553440,2664,1968, 4, 4,44, 4, 8,0x94,0,2,"Canon","PowerShot A460" }, { 6573120,2672,1968,12, 8,44, 0, 8,0x94,0,2,"Canon","PowerShot A610" }, { 6653280,2672,1992,10, 6,42, 2, 8,0x94,0,2,"Canon","PowerShot A530" }, { 7710960,2888,2136,44, 8, 4, 0, 8,0x94,0,2,"Canon","PowerShot S3 IS" }, { 9219600,3152,2340,36,12, 4, 0, 8,0x94,0,2,"Canon","PowerShot A620" }, { 9243240,3152,2346,12, 7,44,13, 8,0x49,0,2,"Canon","PowerShot A470" }, { 10341600,3336,2480, 6, 5,32, 3, 8,0x94,0,2,"Canon","PowerShot A720 IS" }, { 10383120,3344,2484,12, 6,44, 6, 8,0x94,0,2,"Canon","PowerShot A630" }, { 12945240,3736,2772,12, 6,52, 6, 8,0x94,0,2,"Canon","PowerShot A640" }, { 15636240,4104,3048,48,12,24,12, 8,0x94,0,2,"Canon","PowerShot A650" }, { 15467760,3720,2772, 6,12,30, 0, 8,0x94,0,2,"Canon","PowerShot SX110 IS" }, { 15534576,3728,2778,12, 9,44, 9, 8,0x94,0,2,"Canon","PowerShot SX120 IS" }, { 18653760,4080,3048,24,12,24,12, 8,0x94,0,2,"Canon","PowerShot SX20 IS" }, { 19131120,4168,3060,92,16, 4, 1, 8,0x94,0,2,"Canon","PowerShot SX220 HS" }, { 21936096,4464,3276,25,10,73,12, 8,0x16,0,2,"Canon","PowerShot SX30 IS" }, { 24724224,4704,3504, 8,16,56, 8, 8,0x94,0,2,"Canon","PowerShot A3300 IS" }, { 30858240,5248,3920, 8,16,56,16, 8,0x94,0,2,"Canon","IXUS 160" }, { 1976352,1632,1211, 0, 2, 0, 1, 0,0x94,0,1,"Casio","QV-2000UX" }, { 3217760,2080,1547, 0, 0,10, 1, 0,0x94,0,1,"Casio","QV-3*00EX" }, { 6218368,2585,1924, 0, 0, 9, 0, 0,0x94,0,1,"Casio","QV-5700" }, { 7816704,2867,2181, 0, 0,34,36, 0,0x16,0,1,"Casio","EX-Z60" }, { 2937856,1621,1208, 0, 0, 1, 0, 0,0x94,7,13,"Casio","EX-S20" }, { 4948608,2090,1578, 0, 0,32,34, 0,0x94,7,1,"Casio","EX-S100" }, { 6054400,2346,1720, 2, 0,32, 0, 0,0x94,7,1,"Casio","QV-R41" }, { 7426656,2568,1928, 0, 0, 0, 0, 0,0x94,0,1,"Casio","EX-P505" }, { 7530816,2602,1929, 0, 0,22, 0, 0,0x94,7,1,"Casio","QV-R51" }, { 7542528,2602,1932, 0, 0,32, 0, 0,0x94,7,1,"Casio","EX-Z50" }, { 7562048,2602,1937, 0, 0,25, 0, 0,0x16,7,1,"Casio","EX-Z500" }, { 7753344,2602,1986, 0, 0,32,26, 0,0x94,7,1,"Casio","EX-Z55" }, { 9313536,2858,2172, 0, 0,14,30, 0,0x94,7,1,"Casio","EX-P600" }, { 10834368,3114,2319, 0, 0,27, 0, 0,0x94,0,1,"Casio","EX-Z750" }, { 10843712,3114,2321, 0, 0,25, 0, 0,0x94,0,1,"Casio","EX-Z75" }, { 10979200,3114,2350, 0, 0,32,32, 0,0x94,7,1,"Casio","EX-P700" }, { 12310144,3285,2498, 0, 0, 6,30, 0,0x94,0,1,"Casio","EX-Z850" }, { 12489984,3328,2502, 0, 0,47,35, 0,0x94,0,1,"Casio","EX-Z8" }, { 15499264,3754,2752, 0, 0,82, 0, 0,0x94,0,1,"Casio","EX-Z1050" }, { 18702336,4096,3044, 0, 0,24, 0,80,0x94,7,1,"Casio","EX-ZR100" }, { 7684000,2260,1700, 0, 0, 0, 0,13,0x94,0,1,"Casio","QV-4000" }, { 787456,1024, 769, 0, 1, 0, 0, 0,0x49,0,0,"Creative","PC-CAM 600" }, { 28829184,4384,3288, 0, 0, 0, 0,36,0x61,0,0,"DJI" }, { 15151104,4608,3288, 0, 0, 0, 0, 0,0x94,0,0,"Matrix" }, { 3840000,1600,1200, 0, 0, 0, 0,65,0x49,0,0,"Foculus","531C" }, { 307200, 640, 480, 0, 0, 0, 0, 0,0x94,0,0,"Generic" }, { 62464, 256, 244, 1, 1, 6, 1, 0,0x8d,0,0,"Kodak","DC20" }, { 124928, 512, 244, 1, 1,10, 1, 0,0x8d,0,0,"Kodak","DC20" }, { 1652736,1536,1076, 0,52, 0, 0, 0,0x61,0,0,"Kodak","DCS200" }, { 4159302,2338,1779, 1,33, 1, 2, 0,0x94,0,0,"Kodak","C330" }, { 4162462,2338,1779, 1,33, 1, 2, 0,0x94,0,0,"Kodak","C330",3160 }, { 2247168,1232, 912, 0, 0,16, 0, 0,0x00,0,0,"Kodak","C330" }, { 3370752,1232, 912, 0, 0,16, 0, 0,0x00,0,0,"Kodak","C330" }, { 6163328,2864,2152, 0, 0, 0, 0, 0,0x94,0,0,"Kodak","C603" }, { 6166488,2864,2152, 0, 0, 0, 0, 0,0x94,0,0,"Kodak","C603",3160 }, { 460800, 640, 480, 0, 0, 0, 0, 0,0x00,0,0,"Kodak","C603" }, { 9116448,2848,2134, 0, 0, 0, 0, 0,0x00,0,0,"Kodak","C603" }, { 12241200,4040,3030, 2, 0, 0,13, 0,0x49,0,0,"Kodak","12MP" }, { 12272756,4040,3030, 2, 0, 0,13, 0,0x49,0,0,"Kodak","12MP",31556 }, { 18000000,4000,3000, 0, 0, 0, 0, 0,0x00,0,0,"Kodak","12MP" }, { 614400, 640, 480, 0, 3, 0, 0,64,0x94,0,0,"Kodak","KAI-0340" }, { 15360000,3200,2400, 0, 0, 0, 0,96,0x16,0,0,"Lenovo","A820" }, { 3884928,1608,1207, 0, 0, 0, 0,96,0x16,0,0,"Micron","2010",3212 }, { 1138688,1534, 986, 0, 0, 0, 0, 0,0x61,0,0,"Minolta","RD175",513 }, { 1581060,1305, 969, 0, 0,18, 6, 6,0x1e,4,1,"Nikon","E900" }, { 2465792,1638,1204, 0, 0,22, 1, 6,0x4b,5,1,"Nikon","E950" }, { 2940928,1616,1213, 0, 0, 0, 7,30,0x94,0,1,"Nikon","E2100" }, { 4771840,2064,1541, 0, 0, 0, 1, 6,0xe1,0,1,"Nikon","E990" }, { 4775936,2064,1542, 0, 0, 0, 0,30,0x94,0,1,"Nikon","E3700" }, { 5865472,2288,1709, 0, 0, 0, 1, 6,0xb4,0,1,"Nikon","E4500" }, { 5869568,2288,1710, 0, 0, 0, 0, 6,0x16,0,1,"Nikon","E4300" }, { 7438336,2576,1925, 0, 0, 0, 1, 6,0xb4,0,1,"Nikon","E5000" }, { 8998912,2832,2118, 0, 0, 0, 0,30,0x94,7,1,"Nikon","COOLPIX S6" }, { 5939200,2304,1718, 0, 0, 0, 0,30,0x16,0,0,"Olympus","C770UZ" }, { 3178560,2064,1540, 0, 0, 0, 0, 0,0x94,0,1,"Pentax","Optio S" }, { 4841984,2090,1544, 0, 0,22, 0, 0,0x94,7,1,"Pentax","Optio S" }, { 6114240,2346,1737, 0, 0,22, 0, 0,0x94,7,1,"Pentax","Optio S4" }, { 10702848,3072,2322, 0, 0, 0,21,30,0x94,0,1,"Pentax","Optio 750Z" }, { 4147200,1920,1080, 0, 0, 0, 0, 0,0x49,0,0,"Photron","BC2-HD" }, { 4151666,1920,1080, 0, 0, 0, 0, 0,0x49,0,0,"Photron","BC2-HD",8 }, { 13248000,2208,3000, 0, 0, 0, 0,13,0x61,0,0,"Pixelink","A782" }, { 6291456,2048,1536, 0, 0, 0, 0,96,0x61,0,0,"RoverShot","3320AF" }, { 311696, 644, 484, 0, 0, 0, 0, 0,0x16,0,8,"ST Micro","STV680 VGA" }, { 16098048,3288,2448, 0, 0,24, 0, 9,0x94,0,1,"Samsung","S85" }, { 16215552,3312,2448, 0, 0,48, 0, 9,0x94,0,1,"Samsung","S85" }, { 20487168,3648,2808, 0, 0, 0, 0,13,0x94,5,1,"Samsung","WB550" }, { 24000000,4000,3000, 0, 0, 0, 0,13,0x94,5,1,"Samsung","WB550" }, { 12582980,3072,2048, 0, 0, 0, 0,33,0x61,0,0,"Sinar","",68 }, { 33292868,4080,4080, 0, 0, 0, 0,33,0x61,0,0,"Sinar","",68 }, { 44390468,4080,5440, 0, 0, 0, 0,33,0x61,0,0,"Sinar","",68 }, { 1409024,1376,1024, 0, 0, 1, 0, 0,0x49,0,0,"Sony","XCD-SX910CR" }, { 2818048,1376,1024, 0, 0, 1, 0,97,0x49,0,0,"Sony","XCD-SX910CR" }, { 17496000,4320,3240, 0, 0, 0,0,224,0x94,0,0,"Xiro","Xplorer V" }, }; static const char *corp[] = { "AgfaPhoto", "Canon", "Casio", "Epson", "Fujifilm", "Mamiya", "Minolta", "Motorola", "Kodak", "Konica", "Leica", "Nikon", "Nokia", "Olympus", "Ricoh", "Pentax", "Phase One", "Samsung", "Sigma", "Sinar", "Sony", "YI" }; char head[32], *cp; int hlen, flen, fsize, zero_fsize=1, i, c; struct jhead jh; tiff_flip = flip = filters = UINT_MAX; /* 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; tiff_nifds = 0; memset (tiff_ifd, 0, sizeof tiff_ifd); memset (gpsdata, 0, sizeof gpsdata); memset (cblack, 0, sizeof cblack); memset (white, 0, sizeof white); memset (mask, 0, sizeof mask); thumb_offset = thumb_length = thumb_width = thumb_height = 0; load_raw = thumb_load_raw = 0; write_thumb = &CLASS jpeg_thumb; data_offset = meta_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 = 0; 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; for (i=0; i < 0x10000; i++) curve[i] = i; order = get2(); hlen = get4(); fseek (ifp, 0, SEEK_SET); fread (head, 1, 32, ifp); fseek (ifp, 0, SEEK_END); flen = 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)) apply_tiff(); } else if (order == 0x4949 || order == 0x4d4d) { if (!memcmp (head+6,"HEAPCCDR",8)) { data_offset = hlen; parse_ciff (hlen, flen-hlen, 0); load_raw = &CLASS canon_load_raw; } else if (parse_tiff(0)) apply_tiff(); } 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"); load_raw = &CLASS quicktake_100_load_raw; } else if (!strcmp (head, "qktn")) { strcpy (make, "Apple"); strcpy (model,"QuickTake 150"); load_raw = &CLASS kodak_radc_load_raw; } 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+28*(shot_select > 0), SEEK_SET); parse_tiff (data_offset = get4()); parse_tiff (thumb_offset+12); apply_tiff(); if (!load_raw) { load_raw = &CLASS unpacked_load_raw; tiff_bps = 14; } } else if (!memcmp (head,"RIFF",4)) { fseek (ifp, 0, SEEK_SET); parse_riff(); } else if (!memcmp (head+4,"ftypcrx ",8)) { fseek (ifp, 0, SEEK_SET); parse_crx (fsize); } else if (!memcmp (head+4,"ftypqt ",9)) { fseek (ifp, 0, SEEK_SET); parse_qt (fsize); is_raw = 0; } 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,"NOKIARAW",8)) { strcpy (make, "NOKIA"); order = 0x4949; fseek (ifp, 300, SEEK_SET); data_offset = get4(); i = get4(); width = get2(); height = get2(); switch (tiff_bps = i*8 / (width * height)) { case 8: load_raw = &CLASS eight_bit_load_raw; break; case 10: load_raw = &CLASS nokia_load_raw; } raw_height = height + (top_margin = i / (width * tiff_bps/8) - height); mask[0][3] = 1; filters = 0x61616161; } else if (!memcmp (head,"ARRI",4)) { order = 0x4949; fseek (ifp, 20, SEEK_SET); width = get4(); height = get4(); strcpy (make, "ARRI"); fseek (ifp, 668, SEEK_SET); fread (model, 1, 64, ifp); data_offset = 4096; load_raw = &CLASS packed_load_raw; load_flags = 88; filters = 0x61616161; } else if (!memcmp (head,"XPDS",4)) { order = 0x4949; fseek (ifp, 0x800, SEEK_SET); fread (make, 1, 41, ifp); raw_height = get2(); raw_width = get2(); fseek (ifp, 56, SEEK_CUR); fread (model, 1, 30, ifp); data_offset = 0x10000; load_raw = &CLASS canon_rmf_load_raw; gamma_curve (0, 12.25, 1, 1023); } else if (!memcmp (head+4,"RED1",4)) { strcpy (make, "Red"); strcpy (model,"One"); parse_redcine(); load_raw = &CLASS redcine_load_raw; gamma_curve (1/2.4, 12.92, 1, 4095); filters = 0x49494949; } 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(); if (make[0] == 0) for (zero_fsize=i=0; i < sizeof table / sizeof *table; i++) if (fsize == table[i].fsize) { strcpy (make, table[i].make ); strcpy (model, table[i].model); flip = table[i].flags >> 2; zero_is_bad = table[i].flags & 2; if (table[i].flags & 1) parse_external_jpeg(); data_offset = table[i].offset; raw_width = table[i].rw; raw_height = table[i].rh; left_margin = table[i].lm; top_margin = table[i].tm; width = raw_width - left_margin - table[i].rm; height = raw_height - top_margin - table[i].bm; filters = 0x1010101 * table[i].cf; colors = 4 - !((filters & filters >> 1) & 0x5555); load_flags = table[i].lf; switch (tiff_bps = (fsize-data_offset)*8 / (raw_width*raw_height)) { case 6: load_raw = &CLASS minolta_rd175_load_raw; break; case 8: load_raw = &CLASS eight_bit_load_raw; break; case 10: case 12: load_flags |= 512; if (!strcmp(make,"Canon")) load_flags |= 256; load_raw = &CLASS packed_load_raw; break; case 16: order = 0x4949 | 0x404 * (load_flags & 1); tiff_bps -= load_flags >> 4; tiff_bps -= load_flags = load_flags >> 1 & 7; load_raw = &CLASS unpacked_load_raw; } maximum = (1 << tiff_bps) - (1 << table[i].max); } if (zero_fsize) fsize = 0; if (make[0] == 0) parse_smal (0, flen); if (make[0] == 0) { parse_jpeg(0); if (!(strncmp(model,"ov",2) && strncmp(model,"RP_OV",5)) && !fseek (ifp, -6404096, SEEK_END) && fread (head, 1, 32, ifp) && !strcmp(head,"BRCMn")) { strcpy (make, "OmniVision"); data_offset = ftell(ifp) + 0x8000-32; width = raw_width; raw_width = 2611; load_raw = &CLASS nokia_load_raw; filters = 0x16161616; } else is_raw = 0; } for (i=0; i < sizeof corp / sizeof *corp; i++) if (strcasestr (make, corp[i])) /* Simplify company names */ strcpy (make, corp[i]); if ((!strcmp(make,"Kodak") || !strcmp(make,"Leica")) && ((cp = strcasestr(model," DIGITAL CAMERA")) || (cp = strstr(model,"FILE VERSION")))) *cp = 0; if (!strncasecmp(model,"PENTAX",6)) strcpy (make, "Pentax"); 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,"FinePix ",8)) strcpy (model, model+8); 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 (!height) height = raw_height; if (!width) width = raw_width; if (height == 2624 && width == 3936) /* Pentax K10D and Samsung GX10 */ { height = 2616; width = 3896; } if (height == 3136 && width == 4864) /* Pentax K20D and Samsung GX20 */ { height = 3124; width = 4688; filters = 0x16161616; } if (raw_height == 2868 && (!strcmp(model,"K-r") || !strcmp(model,"K-x"))) { width = 4309; filters = 0x16161616; } if (raw_height == 3136 && !strcmp(model,"K-7")) { height = 3122; width = 4684; filters = 0x16161616; top_margin = 2; } if (raw_height == 3284 && !strncmp(model,"K-5",3)) { left_margin = 10; width = 4950; filters = 0x16161616; } if (raw_height == 3300 && !strncmp(model,"K-50",4)) { height = 3288, width = 4952; left_margin = 0; top_margin = 12; } if (raw_height == 3664 && !strncmp(model,"K-S",3)) { width = 5492; left_margin = 0; } if (raw_height == 4032 && !strcmp(model,"K-3")) { height = 4032; width = 6040; left_margin = 4; } if (raw_height == 4060 && !strcmp(model,"KP")) { height = 4032; width = 6032; left_margin = 52; top_margin = 28; } if (raw_height == 4950 && !strcmp(model,"K-1")) { height = 4932; width = 7380; left_margin = 4; top_margin = 18; } if (raw_height == 5552 && !strcmp(model,"645D")) { height = 5502; width = 7328; left_margin = 48; top_margin = 29; filters = 0x61616161; } 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; switch (tiff_compress) { case 0: case 1: load_raw = &CLASS packed_dng_load_raw; break; case 7: load_raw = &CLASS lossless_dng_load_raw; break; case 34892: load_raw = &CLASS lossy_dng_load_raw; break; default: load_raw = 0; } goto dng_skip; } if (!strcmp(make,"Canon") && !fsize && tiff_bps != 15) { if (!load_raw) load_raw = &CLASS lossless_jpeg_load_raw; for (i=0; i < sizeof canon / sizeof *canon; i++) if (raw_width == canon[i][0] && raw_height == canon[i][1]) { width = raw_width - (left_margin = canon[i][2]); height = raw_height - (top_margin = canon[i][3]); width -= canon[i][4]; height -= canon[i][5]; mask[0][1] = canon[i][6]; mask[0][3] = -canon[i][7]; mask[1][1] = canon[i][8]; mask[1][3] = -canon[i][9]; if (canon[i][10]) filters = canon[i][10] * 0x01010101; } if ((unique_id | 0x20000) == 0x2720000) { left_margin = 8; top_margin = 16; } } for (i=0; i < sizeof unique / sizeof *unique; i++) if (unique_id == 0x80000000 + unique[i].id) { adobe_coeff ("Canon", unique[i].model); if (model[4] == 'K' && strlen(model) == 8) strcpy (model, unique[i].model); } for (i=0; i < sizeof sonique / sizeof *sonique; i++) if (unique_id == sonique[i].id) strcpy (model, sonique[i].model); for (i=0; i < sizeof panalias / sizeof *panalias; i++) if (panalias[i][0] == '@@') orig = panalias[i]+1; else if (!strcmp(model,panalias[i])) adobe_coeff ("Panasonic", orig); if (!strcmp(make,"Nikon")) { if (!load_raw) load_raw = &CLASS packed_load_raw; if (model[0] == 'E') load_flags |= !data_offset << 2 | 2; } /* Set parameters based on camera name (for non-DNG files). */ if (!strcmp(model,"KAI-0340") && find_green (16, 16, 3840, 5120) < 25) { height = 480; top_margin = filters = 0; strcpy (model,"C603"); } if (!strcmp(make,"Sony") && raw_width > 3888) black = 128 << (tiff_bps - 12); if (is_foveon) { if (height*2 < width) pixel_aspect = 0.5; if (height > width) pixel_aspect = 2; filters = 0; simple_coeff(0); } else if (!strcmp(make,"Canon") && tiff_bps == 15) { switch (width) { case 3344: width -= 66; case 3872: width -= 6; } if (height > width) { SWAP(height,width); SWAP(raw_height,raw_width); } if (width == 7200 && height == 3888) { raw_width = width = 6480; raw_height = height = 4320; } filters = 0; tiff_samples = colors = 3; load_raw = &CLASS canon_sraw_load_raw; } else if (!strcmp(model,"PowerShot 600")) { height = 613; width = 854; raw_width = 896; 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; filters = 0x1e4e1e4e; goto canon_a5; } else if (!strcmp(model,"PowerShot A50")) { height = 968; width = 1290; raw_width = 1320; filters = 0x1b4e4b1e; goto canon_a5; } else if (!strcmp(model,"PowerShot Pro70")) { height = 1024; width = 1552; filters = 0x1e4b4e1b; canon_a5: colors = 4; tiff_bps = 10; load_raw = &CLASS packed_load_raw; load_flags = 264; } else if (!strcmp(model,"PowerShot Pro90 IS") || !strcmp(model,"PowerShot G1")) { colors = 4; filters = 0xb4b4b4b4; } else if (!strcmp(model,"PowerShot A610")) { if (canon_s2is()) strcpy (model+10, "S2 IS"); } else if (!strcmp(model,"PowerShot SX220 HS")) { mask[1][3] = -4; } else if (!strcmp(model,"EOS D2000C")) { filters = 0x61616161; black = curve[200]; } else if (!strcmp(model,"EOS 80D")) { top_margin -= 2; height += 2; } 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") || !strcmp(model,"D3000")) { height -= 3; width -= 4; } else if (!strcmp(model,"D3") || !strcmp(model,"D3S") || !strcmp(model,"D700")) { width -= 4; left_margin = 2; } else if (!strcmp(model,"D3100")) { width -= 28; left_margin = 6; } else if (!strcmp(model,"D5000") || !strcmp(model,"D90")) { width -= 42; } else if (!strcmp(model,"D5100") || !strcmp(model,"D7000") || !strcmp(model,"COOLPIX A")) { width -= 44; } else if (!strcmp(model,"D3200") || !strncmp(model,"D6",2) || !strncmp(model,"D800",4)) { width -= 46; } else if (!strcmp(model,"D4") || !strcmp(model,"Df")) { width -= 52; left_margin = 2; } else if (!strncmp(model,"D40",3) || !strncmp(model,"D50",3) || !strncmp(model,"D70",3)) { width--; } else if (!strcmp(model,"D100")) { if (load_flags) 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 (!strncmp(model,"D300",4)) { width -= 32; } else if (!strncmp(model,"COOLPIX B",9)) { load_flags = 24; } else if (!strncmp(model,"COOLPIX P",9) && raw_width != 4032) { load_flags = 24; filters = 0x94949494; if (model[9] == '7' && iso_speed >= 400) black = 255; } else if (!strncmp(model,"1 ",2)) { height -= 2; } else if (fsize == 1581060) { simple_coeff(3); pre_mul[0] = 1.2085; pre_mul[1] = 1.0943; pre_mul[3] = 1.1103; } else if (fsize == 3178560) { cam_mul[0] *= 4; cam_mul[2] *= 4; } else if (fsize == 4771840) { 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 (fsize == 2940928) { if (!timestamp && !nikon_e2100()) strcpy (model,"E2500"); if (!strcmp(model,"E2500")) { height -= 2; load_flags = 6; colors = 4; filters = 0x4b4b4b4b; } } else if (fsize == 4775936) { if (!timestamp) nikon_3700(); if (model[0] == 'E' && atoi(model+1) < 3700) filters = 0x49494949; if (!strcmp(model,"Optio 33WR")) { flip = 1; filters = 0x16161616; } if (make[0] == 'O') { i = find_green (12, 32, 1188864, 3576832); c = find_green (12, 32, 2383920, 2387016); if (abs(i) < abs(c)) { SWAP(i,c); load_flags = 24; } if (i < 0) filters = 0x61616161; } } else if (fsize == 5869568) { if (!timestamp && minolta_z2()) { strcpy (make, "Minolta"); strcpy (model,"DiMAGE Z2"); } load_flags = 6 + 24*(make[0] == 'M'); } else if (fsize == 6291456) { 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,"Fujifilm")) { if (!strcmp(model+7,"S2Pro")) { strcpy (model,"S2Pro"); height = 2144; width = 2880; flip = 6; } top_margin = (raw_height - height) >> 2 << 1; left_margin = (raw_width - width ) >> 2 << 1; if (width == 2848 || width == 3664) filters = 0x16161616; if (width == 4032 || width == 4952 || width == 6032 || width == 8280) left_margin = 0; if (width == 3328 && (width -= 66)) left_margin = 34; if (width == 4936) left_margin = 4; if (!strcmp(model,"HS50EXR") || !strcmp(model,"F900EXR")) { width += 2; left_margin = 0; filters = 0x16161616; } if (fuji_layout) raw_width *= is_raw; if (filters == 9) FORC(36) ((char *)xtrans)[c] = xtrans_abs[(c/6+top_margin) % 6][(c+left_margin) % 6]; } 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")) { if (!load_raw && (maximum = 0xfff)) load_raw = &CLASS unpacked_load_raw; if (!strncmp(model,"DiMAGE A",8)) { if (!strcmp(model,"DiMAGE A200")) filters = 0x49494949; tiff_bps = 12; load_raw = &CLASS packed_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_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 D")) { load_raw = &CLASS unpacked_load_raw; data_error = -1; } else if (!strcmp(model,"*ist DS")) { height -= 2; } else if (!strcmp(make,"Samsung") && raw_width == 4704) { height -= top_margin = 8; width -= 2 * (left_margin = 8); load_flags = 256; } else if (!strcmp(make,"Samsung") && raw_height == 3714) { height -= top_margin = 18; left_margin = raw_width - (width = 5536); if (raw_width != 5600) left_margin = top_margin = 0; filters = 0x61616161; colors = 3; } else if (!strcmp(make,"Samsung") && raw_width == 5632) { order = 0x4949; height = 3694; top_margin = 2; width = 5574 - (left_margin = 32 + tiff_bps); if (tiff_bps == 12) load_flags = 80; } else if (!strcmp(make,"Samsung") && raw_width == 5664) { height -= top_margin = 17; left_margin = 96; width = 5544; filters = 0x49494949; } else if (!strcmp(make,"Samsung") && raw_width == 6496) { filters = 0x61616161; black = 1 << (tiff_bps - 7); } else if (!strcmp(model,"EX1")) { order = 0x4949; height -= 20; top_margin = 2; if ((width -= 6) > 3682) { height -= 10; width -= 46; top_margin = 8; } } else if (!strcmp(model,"WB2000")) { order = 0x4949; height -= 3; top_margin = 2; if ((width -= 10) > 3718) { height -= 28; width -= 56; top_margin = 8; } } else if (strstr(model,"WB550")) { strcpy (model, "WB550"); } else if (!strcmp(model,"EX2F")) { height = 3045; width = 4070; top_margin = 3; order = 0x4949; filters = 0x49494949; load_raw = &CLASS unpacked_load_raw; } else if (!strcmp(model,"STV680 VGA")) { black = 16; } else if (!strcmp(model,"N95")) { height = raw_height - (top_margin = 2); } else if (!strcmp(model,"640x480")) { gamma_curve (0.45, 4.5, 1, 255); } 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 == 7410 || raw_width == 8282) { height -= 84; width -= 82; top_margin = 4; left_margin = 41; filters = 0x61616161; } else if (raw_width == 8384) { height = 6208; width = 8280; top_margin = 96; left_margin = 46; } else if (raw_width == 9044) { height = 6716; width = 8964; top_margin = 8; left_margin = 40; black += load_flags = 256; maximum = 0x8101; } else if (raw_width == 4090) { strcpy (model, "V96C"); height -= (top_margin = 6); width -= (left_margin = 3) + 7; filters = 0x61616161; } if (tiff_samples > 1) { is_raw = tiff_samples+1; if (!shot_select && !half_size) filters = 0; } } else if (!strcmp(make,"Sinar")) { if (!load_raw) load_raw = &CLASS unpacked_load_raw; if (is_raw > 1 && !shot_select && !half_size) filters = 0; 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; raw_width = tile_width; } 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")) { if ((flen - data_offset) / (raw_width*8/7) == raw_height) load_raw = &CLASS panasonic_load_raw; if (!load_raw) { load_raw = &CLASS unpacked_load_raw; load_flags = 4; } zero_is_bad = 1; if ((height += 12) > raw_height) height = raw_height; for (i=0; i < sizeof pana / sizeof *pana; i++) if (raw_width == pana[i][0] && raw_height == pana[i][1]) { left_margin = pana[i][2]; top_margin = pana[i][3]; width += pana[i][4]; height += pana[i][5]; } filters = 0x01010101 * (uchar) "\x94\x61\x49\x16" [((filters-1) ^ (left_margin & 1) ^ (top_margin << 1)) & 3]; } else if (!strcmp(model,"C770UZ")) { height = 1718; width = 2304; filters = 0x16161616; load_raw = &CLASS packed_load_raw; load_flags = 30; } else if (!strcmp(make,"Olympus")) { height += height & 1; if (exif_cfa) filters = exif_cfa; if (width == 4100) width -= 4; if (width == 4080) width -= 24; if (width == 9280) { width -= 6; height -= 6; } if (load_raw == &CLASS unpacked_load_raw) load_flags = 4; tiff_bps = 12; if (!strcmp(model,"E-300") || !strcmp(model,"E-500")) { width -= 20; if (load_raw == &CLASS unpacked_load_raw) { maximum = 0xfc3; memset (cblack, 0, sizeof cblack); } } else if (!strcmp(model,"E-330")) { width -= 30; if (load_raw == &CLASS unpacked_load_raw) maximum = 0xf79; } else if (!strcmp(model,"SP550UZ")) { thumb_length = flen - (thumb_offset = 0xa39800); thumb_height = 480; thumb_width = 640; } else if (!strcmp(model,"TG-4")) { width -= 16; } else if (!strcmp(model,"TG-5")) { width -= 6; } } else if (!strcmp(model,"N Digital")) { height = 2047; width = 3072; filters = 0x61616161; data_offset = 0x1a00; load_raw = &CLASS packed_load_raw; } else if (!strcmp(model,"DSC-F828")) { width = 3288; left_margin = 5; mask[1][3] = -17; 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; mask[0][1] = 9; data_offset = 787392; load_raw = &CLASS sony_load_raw; } else if (!strcmp(make,"Sony") && raw_width == 3984) { width = 3925; order = 0x4d4d; } else if (!strcmp(make,"Sony") && raw_width == 4288) { width -= 32; } else if (!strcmp(make,"Sony") && raw_width == 4600) { if (!strcmp(model,"DSLR-A350")) height -= 4; black = 0; } else if (!strcmp(make,"Sony") && raw_width == 4928) { if (height < 3280) width -= 8; } else if (!strcmp(make,"Sony") && raw_width == 5504) { width -= height > 3664 ? 8 : 32; if (!strncmp(model,"DSC",3)) black = 200 << (tiff_bps - 12); } else if (!strcmp(make,"Sony") && raw_width == 6048) { width -= 24; if (strstr(model,"RX1") || strstr(model,"A99")) width -= 6; } else if (!strcmp(make,"Sony") && raw_width == 7392) { width -= 30; } else if (!strcmp(make,"Sony") && raw_width == 8000) { width -= 32; } else if (!strcmp(model,"DSLR-A100")) { if (width == 3880) { height--; width = ++raw_width; } else { height -= 4; width -= 4; order = 0x4d4d; load_flags = 2; } filters = 0x61616161; } else if (!strcmp(model,"PIXL")) { height -= top_margin = 4; width -= left_margin = 32; gamma_curve (0, 7, 1, 255); } else if (!strcmp(model,"C603") || !strcmp(model,"C330") || !strcmp(model,"12MP")) { order = 0x4949; if (filters && data_offset) { fseek (ifp, data_offset < 4096 ? 168 : 5252, SEEK_SET); read_shorts (curve, 256); } else gamma_curve (0, 3.875, 1, 255); load_raw = filters ? &CLASS eight_bit_load_raw : strcmp(model,"C330") ? &CLASS kodak_c603_load_raw : &CLASS kodak_c330_load_raw; load_flags = tiff_bps > 16; tiff_bps = 8; } else if (!strncasecmp(model,"EasyShare",9)) { data_offset = data_offset < 0x15000 ? 0x15000 : 0x17000; load_raw = &CLASS packed_load_raw; } else if (!strcasecmp(make,"Kodak")) { if (filters == UINT_MAX) filters = 0x61616161; if (!strncmp(model,"NC2000",6) || !strncmp(model,"EOSDCS",6) || !strncmp(model,"DCS4",4)) { width -= 4; left_margin = 2; if (model[6] == ' ') model[6] = 0; if (!strcmp(model,"DCS460A")) goto bw; } else if (!strcmp(model,"DCS660M")) { black = 214; goto bw; } else if (!strcmp(model,"DCS760M")) { bw: 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)) { raw_height = 2 + (height = 242); if (flen < 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); } top_margin = left_margin = 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; tiff_bps = 12; } 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; 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 (!strncmp(model,"QuickTake",9)) { if (head[5]) strcpy (model+10, "200"); 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; } 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; } if (!model[0]) sprintf (model, "%dx%d", width, height); if (filters == UINT_MAX) filters = 0x94949494; 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 ((use_camera_matrix & (use_camera_wb || dng_version)) && cmatrix[0][0] > 0.125) { memcpy (rgb_cam, cmatrix, sizeof cmatrix); raw_color = 0; } if (raw_color) adobe_coeff (make, model); if (load_raw == &CLASS kodak_radc_load_raw) if (raw_color) adobe_coeff ("Apple","Quicktake"); if (fuji_width) { fuji_width = width >> !fuji_layout; filters = fuji_width & 1 ? 0x94949494 : 0x49494949; width = (height >> fuji_layout) + fuji_width; height = width - 1; pixel_aspect = 1; } else { if (raw_height < height) raw_height = height; if (raw_width < width ) raw_width = width; } if (!tiff_bps) tiff_bps = 12; if (!maximum) maximum = (1 << tiff_bps) - 1; if (!load_raw || height < 22 || width < 22 || tiff_bps > 16 || tiff_samples > 6 || colors > 4) is_raw = 0; #ifdef NO_JASPER if (load_raw == &CLASS redcine_load_raw) { fprintf (stderr,_("%s: You must link dcraw with %s!!\n"), ifname, "libjasper"); is_raw = 0; } #endif #ifdef NO_JPEG if (load_raw == &CLASS kodak_jpeg_load_raw || load_raw == &CLASS lossy_dng_load_raw) { fprintf (stderr,_("%s: You must link dcraw with %s!!\n"), ifname, "libjpeg"); is_raw = 0; } #endif if (!cdesc[0]) strcpy (cdesc, colors == 3 ? "RGBG":"GMCY"); if (!raw_height) raw_height = height; if (!raw_width ) raw_width = width; if (filters > 999 && colors == 3) filters |= ((filters >> 2 & 0x22222222) | (filters << 2 & 0x88888888)) & filters << 1; notraw: if (flip == UINT_MAX) flip = tiff_flip; if (flip == UINT_MAX) 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; 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 aces_rgb[3][3] = { { 0.432996, 0.375380, 0.189317 }, { 0.089427, 0.816523, 0.102989 }, { 0.019165, 0.118150, 0.941914 } }; static const double (*out_rgb[])[3] = { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb, aces_rgb }; static const char *name[] = { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ", "ACES" }; 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 > 6; 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[fcol(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 (high, wide*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 (struct tiff_hdr *th, ushort *ntag, ushort tag, ushort type, int count, int val) { struct tiff_tag *tt; int c; tt = (struct tiff_tag *)(ntag+1) + (*ntag)++; tt->val.i = val; if (type == 1 && count <= 4) FORC(4) tt->val.c[c] = val >> (c << 3); else if (type == 2) { count = strnlen((char *)th + val, count-1) + 1; if (count <= 4) FORC(4) tt->val.c[c] = ((char *)th)[val+c]; } else if (type == 3 && count <= 2) FORC(2) tt->val.s[c] = val >> (c << 4); tt->count = count; tt->type = type; tt->tag = tag; } #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; 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"DCRAW_VERSION); t = localtime (×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); if (full) { tiff_set (th, &th->ntag, 254, 4, 1, 0); tiff_set (th, &th->ntag, 256, 4, 1, width); tiff_set (th, &th->ntag, 257, 4, 1, height); tiff_set (th, &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, &th->ntag, 259, 3, 1, 1); tiff_set (th, &th->ntag, 262, 3, 1, 1 + (colors > 1)); } tiff_set (th, &th->ntag, 270, 2, 512, TOFF(th->desc)); tiff_set (th, &th->ntag, 271, 2, 64, TOFF(th->make)); tiff_set (th, &th->ntag, 272, 2, 64, TOFF(th->model)); if (full) { if (oprof) psize = ntohl(oprof[0]); tiff_set (th, &th->ntag, 273, 4, 1, sizeof *th + psize); tiff_set (th, &th->ntag, 277, 3, 1, colors); tiff_set (th, &th->ntag, 278, 4, 1, height); tiff_set (th, &th->ntag, 279, 4, 1, height*width*colors*output_bps/8); } else tiff_set (th, &th->ntag, 274, 3, 1, "12435867"[flip]-'0'); tiff_set (th, &th->ntag, 282, 5, 1, TOFF(th->rat[0])); tiff_set (th, &th->ntag, 283, 5, 1, TOFF(th->rat[2])); tiff_set (th, &th->ntag, 284, 3, 1, 1); tiff_set (th, &th->ntag, 296, 3, 1, 2); tiff_set (th, &th->ntag, 305, 2, 32, TOFF(th->soft)); tiff_set (th, &th->ntag, 306, 2, 20, TOFF(th->date)); tiff_set (th, &th->ntag, 315, 2, 64, TOFF(th->artist)); tiff_set (th, &th->ntag, 34665, 4, 1, TOFF(th->nexif)); if (psize) tiff_set (th, &th->ntag, 34675, 7, psize, sizeof *th); tiff_set (th, &th->nexif, 33434, 5, 1, TOFF(th->rat[4])); tiff_set (th, &th->nexif, 33437, 5, 1, TOFF(th->rat[6])); tiff_set (th, &th->nexif, 34855, 3, 1, iso_speed); tiff_set (th, &th->nexif, 37386, 5, 1, TOFF(th->rat[8])); if (gpsdata[1]) { tiff_set (th, &th->ntag, 34853, 4, 1, TOFF(th->ngps)); tiff_set (th, &th->ngps, 0, 1, 4, 0x202); tiff_set (th, &th->ngps, 1, 2, 2, gpsdata[29]); tiff_set (th, &th->ngps, 2, 5, 3, TOFF(th->gps[0])); tiff_set (th, &th->ngps, 3, 2, 2, gpsdata[30]); tiff_set (th, &th->ngps, 4, 5, 3, TOFF(th->gps[6])); tiff_set (th, &th->ngps, 5, 1, 1, gpsdata[31]); tiff_set (th, &th->ngps, 6, 5, 1, TOFF(th->gps[18])); tiff_set (th, &th->ngps, 7, 5, 3, TOFF(th->gps[12])); tiff_set (th, &th->ngps, 18, 2, 12, TOFF(th->gps[20])); tiff_set (th, &th->ngps, 29, 2, 12, TOFF(th->gps[23])); memcpy (th->gps, gpsdata, sizeof th->gps); } } 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, quality, i, c; 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, read_from_stdin=0; 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"), DCRAW_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-6] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ,ACES)")); #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 = (char *) 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; break; 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 = 3 * (opm == '+'); break; case 'I': read_from_stdin = 1; break; case 'E': document_mode++; case 'D': document_mode++; case 'd': document_mode++; 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 (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; raw_image = 0; 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; colors = 3; } 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 || (!identify_only && (threshold || aber[0] != 1 || aber[2] != 1))); iheight = (height + shrink) >> shrink; iwidth = (width + shrink) >> shrink; if (identify_only) { if (verbose) { if (document_mode == 3) { top_margin = left_margin = fuji_width = 0; height = raw_height; width = raw_width; } iheight = (height + shrink) >> shrink; iwidth = (width + shrink) >> shrink; 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) { int fhigh = 2, fwide = 2; if ((filters ^ (filters >> 8)) & 0xff) fhigh = 4; if ((filters ^ (filters >> 16)) & 0xffff) fhigh = 8; if (filters == 1) fhigh = fwide = 16; if (filters == 9) fhigh = fwide = 6; printf (_("\nFilter pattern: ")); for (i=0; i < fhigh; i++) for (c = i && putchar('/') && 0; c < fwide; c++) putchar (cdesc[fcol(i,c)]); } 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 (meta_length) { meta_data = (char *) malloc (meta_length); merror (meta_data, "main()"); } if (filters || colors == 1) { raw_image = (ushort *) calloc ((raw_height+7), raw_width*2); merror (raw_image, "main()"); } else { image = (ushort (*)[4]) calloc (iheight, iwidth*sizeof *image); merror (image, "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); if (raw_image && read_from_stdin) fread (raw_image, 2, raw_height*raw_width, stdin); else (*load_raw)(); if (document_mode == 3) { top_margin = left_margin = fuji_width = 0; height = raw_height; width = raw_width; } iheight = (height + shrink) >> shrink; iwidth = (width + shrink) >> shrink; if (raw_image) { image = (ushort (*)[4]) calloc (iheight, iwidth*sizeof *image); merror (image, "main()"); crop_masked_pixels(); free (raw_image); } 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; i = cblack[3]; FORC3 if (i > cblack[c]) i = cblack[c]; FORC4 cblack[c] -= i; black += i; i = cblack[6]; FORC (cblack[4] * cblack[5]) if (i > cblack[6+c]) i = cblack[6+c]; FORC (cblack[4] * cblack[5]) cblack[6+c] -= i; black += i; if (user_black >= 0) black = user_black; FORC4 cblack[c] += black; if (user_sat > 0) maximum = user_sat; #ifdef COLORCHECK colorcheck(); #endif if (is_foveon) { if (document_mode || load_raw == &CLASS foveon_dp_load_raw) { for (i=0; i < height*width*4; i++) if ((short) image[0][i] < 0) image[0][i] = 0; } else foveon_interpolate(); } else if (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 && filters > 1000) ppg_interpolate(); else if (filters == 9) xtrans_interpolate (quality*2-3); 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.477 log @Added "-o 6" for ACES colorspace. Copied color matrices from DNG Converter 9.5.1. Support the Canon EOS 80D & IXUS 160, Fuji X-E2 & X-E2S & X-Pro2 @ text @d3 1 a3 1 Copyright 1997-2016 by Dave Coffin, dcoffin a cybercom o net d26 1 a26 1 #define DCRAW_VERSION "9.27" d101 3 a103 2 access them are prefixed with "CLASS". Note that a thread-safe C++ class cannot have non-const static local variables. d1927 1 a1927 1 bwide += bwide & load_flags >> 7; d1930 1 a1930 1 bite = 8 + (load_flags & 24); d1948 1 a1948 1 bitbuf |= (unsigned) (fgetc(ifp) << i); d1951 1 a1951 1 RAW(row,col ^ (load_flags >> 6 & 1)) = val; d2088 8 d3788 1 a3788 1 (load_raw == &CLASS packed_load_raw && (load_flags & 32))) { d5747 2 a5748 1 tiff_ifd[ifd].bps = getint(type); a5753 2 if (tiff_ifd[ifd].bps > 12) break; load_raw = &CLASS packed_load_raw; d6254 1 d6270 3 d6282 3 a6284 1 case 14: load_flags = 0; d6290 2 d6747 1 a6747 1 } else if (tag == 0xc000) { d6827 66 d7134 2 d7142 2 d7166 2 d7172 2 d7196 2 d7206 8 d7216 2 d7262 2 d7282 2 d7378 2 d7388 1 a7388 1 { "Fujifilm S2Pro", 128, 0, d7390 1 a7390 1 { "Fujifilm S3Pro", 0, 0, d7424 1 a7424 1 { "Fujifilm HS2", 0, 0, d7432 2 d7452 4 d7460 4 d7470 4 d7480 2 d7486 2 d7600 2 d7630 2 d7650 2 d7658 2 d7700 2 d7800 4 d7808 1 a7808 1 { "Olympus E-M10", 0, 0, /* also E-M10 Mark II */ d7810 2 d7840 2 d7877 1 a7877 1 { 8566,-2746,-1201,-3612,12204,1550,-893,1680,6264 } }, d7888 2 d7896 2 d7904 2 d7912 2 d7920 1 a7920 1 { "Panasonic DMC-FZ3", 15, 0, d7922 1 a7922 1 { "Panasonic DMC-FZ4", 15, 0, d7926 1 a7926 1 { "Panasonic DMC-FZ7", 15, 0, d7968 2 d8002 4 d8020 2 d8030 4 d8042 2 d8046 3 a8048 1 { "Panasonic DMC-TZ1", 15, 0, d8050 1 a8050 1 { "Panasonic DMC-ZS1", 15, 0, d8052 1 a8052 3 { "Panasonic DMC-TZ6", 15, 0, { 8607,-2822,-808,-3755,11930,2049,-820,2060,5224 } }, { "Panasonic DMC-ZS4", 15, 0, d8054 1 a8054 1 { "Panasonic DMC-TZ7", 15, 0, d8056 1 a8056 3 { "Panasonic DMC-ZS5", 15, 0, { 8802,-3135,-789,-3151,11468,1904,-550,1745,4810 } }, { "Panasonic DMC-TZ8", 15, 0, d8060 2 d8072 8 d8150 1 a8150 1 { "Sony DSC-RX100M", 0, 0, /* M2, M3, and M4 */ d8154 3 a8156 1 { "Sony DSC-RX10", 0, 0, /* also RX10M2 */ d8162 2 d8198 3 a8200 1 { "Sony ILCE-6300", 0, 0, d8204 2 d8208 2 d8216 2 d8260 2 d8417 1 d8419 3 a8421 1 { 6288, 4056, 264, 34, 0, 0 }, d8435 1 d8437 2 d8449 2 a8450 1 { 0x347, "EOS 760D" }, d8455 2 a8456 1 { 0x346, "EOS 100D" }, d8486 24 a8509 1 { 0x161, "ILCA-68" }, { 0x165, "ILCE-6300" }, d8529 18 a8546 18 { 5298000,2400,1766,12,12,44, 2,40,0x94,0,2,"Canon","PowerShot SD300" }, { 6553440,2664,1968, 4, 4,44, 4,40,0x94,0,2,"Canon","PowerShot A460" }, { 6573120,2672,1968,12, 8,44, 0,40,0x94,0,2,"Canon","PowerShot A610" }, { 6653280,2672,1992,10, 6,42, 2,40,0x94,0,2,"Canon","PowerShot A530" }, { 7710960,2888,2136,44, 8, 4, 0,40,0x94,0,2,"Canon","PowerShot S3 IS" }, { 9219600,3152,2340,36,12, 4, 0,40,0x94,0,2,"Canon","PowerShot A620" }, { 9243240,3152,2346,12, 7,44,13,40,0x49,0,2,"Canon","PowerShot A470" }, { 10341600,3336,2480, 6, 5,32, 3,40,0x94,0,2,"Canon","PowerShot A720 IS" }, { 10383120,3344,2484,12, 6,44, 6,40,0x94,0,2,"Canon","PowerShot A630" }, { 12945240,3736,2772,12, 6,52, 6,40,0x94,0,2,"Canon","PowerShot A640" }, { 15636240,4104,3048,48,12,24,12,40,0x94,0,2,"Canon","PowerShot A650" }, { 15467760,3720,2772, 6,12,30, 0,40,0x94,0,2,"Canon","PowerShot SX110 IS" }, { 15534576,3728,2778,12, 9,44, 9,40,0x94,0,2,"Canon","PowerShot SX120 IS" }, { 18653760,4080,3048,24,12,24,12,40,0x94,0,2,"Canon","PowerShot SX20 IS" }, { 19131120,4168,3060,92,16, 4, 1,40,0x94,0,2,"Canon","PowerShot SX220 HS" }, { 21936096,4464,3276,25,10,73,12,40,0x16,0,2,"Canon","PowerShot SX30 IS" }, { 24724224,4704,3504, 8,16,56, 8,40,0x94,0,2,"Canon","PowerShot A3300 IS" }, { 30858240,5248,3920, 8,16,56,16,40,0x94,0,2,"Canon","IXUS 160" }, d8619 1 d8625 1 a8625 1 "Samsung", "Sigma", "Sinar", "Sony" }; a8712 1 load_raw = &CLASS unpacked_load_raw; d8717 4 d8724 3 d8822 2 a8823 1 load_flags |= 128; d8878 1 a8878 1 if (width == 4352 && (!strcmp(model,"K-r") || !strcmp(model,"K-x"))) d8880 3 a8882 1 if (width >= 4960 && !strncmp(model,"K-5",3)) d8884 13 a8896 7 if (width == 4736 && !strcmp(model,"K-7")) { height = 3122; width = 4684; filters = 0x16161616; top_margin = 2; } if (width == 6080 && !strcmp(model,"K-3")) { left_margin = 4; width = 6040; } if (width == 7424 && !strcmp(model,"645D")) { height = 5502; width = 7328; filters = 0x61616161; top_margin = 29; left_margin = 48; } d8941 4 d9012 1 a9012 1 load_flags = 40; d9024 3 d9081 2 d9155 1 a9155 2 } else if (load_raw != &CLASS packed_load_raw) maximum = (is_raw == 2 && shot_select) ? 0x2f00 : 0x3e00; d9159 1 a9159 1 if (width == 4032 || width == 4952 || width == 6032) left_margin = 0; d9221 1 a9221 1 load_flags = 32; d9291 5 d9409 2 a9455 5 if (!strncmp(model,"DSC",3)) { tiff_bps = 14; load_raw = &CLASS unpacked_load_raw; black = 512; } @ 1.476 log @Support the Blackmagic URSA, Nokia N9, and Photron BC2-HD. Support the Canon EOS 750D, 760D, EOS M, and sRAW/mRAW for EOS 5DS R. When there's a tie for largest raw image, "-s" says which to decode. Fixed null-byte warnings in TIFF output. @ text @d3 1 a3 1 Copyright 1997-2015 by Dave Coffin, dcoffin a cybercom o net d26 1 a26 1 #define DCRAW_VERSION "9.26" d856 2 d859 1 a859 1 if (jh->clrs > 6 || !jh->huff[0]) return 0; d1772 1 a1772 1 i = (pixel[col] << 2) - ph1.black d2864 2 d5314 1 a5314 1 FORC4 cblack[c ^ c >> 1] = get2() >> (14-tiff_ifd[2].bps); d5425 1 a5425 1 if (tag == 0x2020) d5739 2 d6074 1 a6074 1 for (num=i=0; i < len; i++) d6215 4 d6313 2 a6314 2 || (tiff_bps == 8 && !strcasestr(make,"Kodak") && !strstr(model2,"DEBUG RAW"))) d6734 1 a6734 1 if ((tag = get4()) > 10000) tag = get4(); d6756 1 a6756 1 if (mark == 0xc0 || mark == 0xc3) { d7080 2 d7112 2 d7116 2 d7136 2 d7166 2 d7170 2 d7178 2 d7238 2 d7254 2 d7336 2 d7340 2 d7348 2 d7356 1 a7356 1 { "Fujifilm X-T1", 0, 0, d7502 2 d7506 2 d7584 2 a7585 2 { "Nikon 1 J5", 0, 0, /* DJC */ { 2621,-856,500,-4471,8761,5711,-1321,2644,11945 } }, d7596 2 d7668 1 a7668 1 { "Olympus E-M10", 0, 0, d7676 2 d7732 6 d7748 2 a7749 2 { "Pentax K-S2", 0, 0, /* DJC */ { 5322,-2195,41,-3689,8902,4788,-858,1831,7969 } }, d7762 4 d7846 2 d7860 2 d7878 6 d7892 14 d7924 4 d7936 2 d7972 1 a7972 1 { "Sony DSC-R1", 512, 0, d7976 1 a7976 1 { "Sony DSC-RX100M", 200, 0, /* M2 and M3 */ d7978 1 a7978 1 { "Sony DSC-RX100", 200, 0, d7980 1 a7980 1 { "Sony DSC-RX10", 200, 0, d7982 3 a7984 1 { "Sony DSC-RX1", 128, 0, d8002 1 a8002 1 { "Sony DSLR-A450", 128, 0xfeb, d8004 1 a8004 1 { "Sony DSLR-A580", 128, 0xfeb, d8006 1 a8006 1 { "Sony DSLR-A500", 128, 0xfeb, d8008 1 a8008 1 { "Sony DSLR-A5", 128, 0xfeb, d8010 1 a8010 1 { "Sony DSLR-A700", 128, 0, d8012 1 a8012 1 { "Sony DSLR-A850", 128, 0, d8014 1 a8014 1 { "Sony DSLR-A900", 128, 0, d8016 3 a8018 1 { "Sony ILCA-77M2", 128, 0, d8020 3 a8022 1 { "Sony ILCE-7M2", 128, 0, d8024 1 a8024 1 { "Sony ILCE-7S", 128, 0, d8026 3 a8028 1 { "Sony ILCE-7R", 128, 0, d8030 1 a8030 1 { "Sony ILCE-7", 128, 0, d8032 1 a8032 1 { "Sony ILCE", 128, 0, /* 3000, 5000, 5100, 6000, and QX1 */ d8034 1 a8034 1 { "Sony NEX-5N", 128, 0, d8036 1 a8036 1 { "Sony NEX-5R", 128, 0, d8038 1 a8038 1 { "Sony NEX-5T", 128, 0, d8040 1 a8040 1 { "Sony NEX-3N", 128, 0, d8046 1 a8046 1 { "Sony NEX-3", 128, 0, /* Adobe */ d8048 1 a8048 1 { "Sony NEX-5", 128, 0, /* Adobe */ d8050 1 a8050 1 { "Sony NEX-6", 128, 0, d8052 1 a8052 1 { "Sony NEX-7", 128, 0, d8054 1 a8054 1 { "Sony NEX", 128, 0, /* NEX-C3, NEX-F3 */ d8056 1 a8056 1 { "Sony SLT-A33", 128, 0, d8058 1 a8058 1 { "Sony SLT-A35", 128, 0, d8060 1 a8060 1 { "Sony SLT-A37", 128, 0, d8062 1 a8062 1 { "Sony SLT-A55", 128, 0, d8064 1 a8064 1 { "Sony SLT-A57", 128, 0, d8066 1 a8066 1 { "Sony SLT-A58", 128, 0, d8068 1 a8068 1 { "Sony SLT-A65", 128, 0, d8070 1 a8070 1 { "Sony SLT-A77", 128, 0, d8072 1 a8072 1 { "Sony SLT-A99", 128, 0, d8230 1 d8244 1 d8258 2 a8259 1 { 0x327, "EOS 1200D" }, d8287 4 a8290 1 { 0x15a, "ILCE-QX1" }, d8327 1 d8404 1 a8404 1 "Nikon", "Nokia", "Olympus", "Pentax", "Phase One", "Ricoh", d8721 2 d8916 1 a8916 1 if (width == 4032 || width == 4952) left_margin = 0; d9159 2 d9188 4 d9196 2 d9204 7 a9221 2 } else if (!strcmp(model,"DSLR-A350")) { height -= 4; d9286 1 d9479 4 d9484 1 a9484 1 { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb }; d9486 1 a9486 1 { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" }; d9507 1 a9507 1 output_color < 1 || output_color > 5; d9885 1 a9885 1 puts(_("-o [0-5] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)")); @ 1.475 log @Use typecasts instead of [0] to flatten multi-dimensional arrays. @ text @d26 1 a26 1 #define DCRAW_VERSION "9.25" a91 9 #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 d152 1 d174 1 a174 1 #define CLIP(x) LIM(x,0,65535) a807 4 /* Not a full implementation of Lossless JPEG, just enough to decode Canon, Kodak and Adobe DNG images. */ d809 2 a810 2 int bits, high, wide, clrs, sraw, psv, restart, vpred[6]; ushort *huff[6], *free[4], *row; d815 1 a815 1 int c, tag, len; d821 1 a821 2 fread (data, 2, 1, ifp); if (data[1] != 0xd8) return 0; d823 1 a823 1 fread (data, 2, 2, ifp); d831 1 d833 1 d842 1 a842 1 for (dp = data; dp < data+len && (c = *dp++) < 4; ) d849 3 d858 1 a858 1 FORC(5) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c]; d1037 1 a1037 1 if (is_raw == 2 && shot_select) (*rp)++; d1041 1 a1041 1 *rp += is_raw; d1048 37 a1084 1 if (is_raw == 2 && shot_select) (*rp)--; d1089 1 a1089 1 unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col; d1100 26 a1125 8 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); } d5340 2 a5341 1 goto get2_rggb; d5375 1 a5375 1 goto get2_rggb; a5431 1 get2_rggb: d5433 5 a5437 3 i = len >> 3 == 164 || len == 1506 ? 112:22; fseek (ifp, i, SEEK_CUR); FORC4 sraw_mul[c ^ (c >> 1)] = get2(); d5490 2 a5491 1 case 33434: shutter = getreal(type); break; d5497 1 d5896 1 a5896 1 shutter = getreal(type); d6024 8 d6045 1 a6045 4 if (get2() == 2) { fuji_width = 1; filters = 0x49494949; } d6186 1 a6186 1 int max_samp=0, raw=-1, thm=-1, i; d6198 5 d6207 2 d6211 2 a6212 1 tiff_ifd[i].width*tiff_ifd[i].height > raw_width*raw_height) { d6222 1 d6226 1 d6445 1 a6445 3 white[row][col] = bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp); vbits -= bpp; d7040 2 a7041 2 { "Canon EOS 5DS", 0, 0x3c96, /* DJC */ { 6885,-753,-856,-4416,11752,2665,-1266,2393,5468 } }, d7090 4 d7100 2 d7480 2 a7481 2 { "Nikon D7200", 0, 0, /* DJC */ { 6111,-2759,-358,-5108,10766,4343,-769,1691,8030 } }, d7636 2 d7654 2 d7700 4 d7844 2 d7872 2 a7873 2 { "Samsung NX500", 0, 0, /* DJC */ { 10196,-4532,-272,-3888,11489,2400,-1203,2424,9173 } }, d8139 1 d8162 2 d8289 2 d8474 1 a8474 1 else d8569 2 a8570 2 if (filters) is_raw = tiff_samples; else colors = tiff_samples; d8572 1 d8638 4 d9252 1 a9252 1 if (~fuji_width & 1) filters = 0x49494949; d9553 1 a9553 1 void CLASS tiff_set (ushort *ntag, d9560 2 a9561 4 tt->tag = tag; tt->type = type; tt->count = count; if (type < 3 && count <= 4) d9563 5 a9567 1 else if (type == 3 && count <= 2) d9569 3 a9571 1 else tt->val.i = val; a9584 49 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); } d9599 49 @ 1.474 log @Updated color matrices, support the Canon EOS 5DS. @ text @d2175 1 a2175 1 huff[0][s++] = src[i] << 8 | (uchar) src[i+1]; d2180 1 a2180 1 buf[0][0][i] = 2048; d2189 1 a2189 1 buf[c][0][i] = (buf[c][0][i] * val + x) >> s; d2764 1 a2764 1 FORC(6) lent[0][c] = row < 2 ? 7:4; d2921 1 a2921 1 nseg = fgetc(ifp); d2924 1 a2924 1 seg[0][i] = get4() + data_offset*(i & 1); d3387 2 a3388 2 ddft[0][0][i] = ddft[1][0][i] + row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]); d3433 2 a3434 2 ddft[0][0][i] = ddft[1][0][i] + row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]); d4214 1 a4214 1 if (!(val = image[0][i])) continue; d4220 1 a4220 1 image[0][i] = CLIP(val); d5532 1 a5532 1 romm_cam[0][i] = int_to_float(get4()); d5537 1 a5537 1 fscanf (ifp, "%f", &romm_cam[0][i]); d5827 1 a5827 1 FORC(36) xtrans[0][c] = fgetc(ifp) & 3; d6064 1 a6064 1 mask[0][i] = getint(type); d6588 1 a6588 1 romm_cam[0][i] = getreal(11); d6927 1 a6927 1 poff[0][i] = off + get4()*2; d7917 1 a7917 1 cam_xyz[0][j] = table[i].trans[j] / 10000.0; d8739 1 a8739 1 FORC(36) xtrans[0][c] = @ 1.473 log @Canon multi-exposure files are already white-balanced. @ text @d26 1 a26 1 #define DCRAW_VERSION "9.24" d952 1 a952 1 i = jidx / (cr2_slice[1]*jh.high); d955 1 a955 1 jidx -= i * (cr2_slice[1]*jh.high); d1538 1 a1538 1 int cx[18], cf[18]; d1545 2 a1546 2 cubic_spline(cx, cf, 18); d5506 1 a5506 1 "Aptus-II 7","","","Aptus-II 6","","","Aptus-II 10","Aptus-II 5", d5725 4 d6977 2 d7243 2 d7257 1 a7257 1 { "Fujifilm XQ1", 0, 0, d7397 2 a7398 2 { "Nikon D5500", 0, 0, /* DJC */ { 5765,-2176,184,-3736,9072,4664,-1028,2213,9259 } }, d7411 2 d7477 2 d7563 2 a7564 2 { "Olympus E-M5MarkII", 0, 0, /* DJC */ { 6617,-2589,139,-2917,8499,4419,-884,1913,6829 } }, d7727 2 a7728 2 { "Panasonic DMC-GF7", 15, 0, /* DJC */ { 6086,-2691,-18,-4207,9767,4441,-1486,2640,7441 } }, d7749 4 d7793 2 d7797 1 a7797 1 { "Samsung NX1", 128, 0, d8060 1 d8549 4 a8552 1 if (height > width) SWAP(height,width); d8811 1 @ 1.472 log @Moved border_interpolate() to the end of xtrans_interpolate(). @ text @d5391 2 @ 1.471 log @Support all format options of the Nikon D4S and D810. Guess which filter pattern OmniVision cameras use. @ text @a4608 1 border_interpolate(6); d4813 1 @ 1.470 log @Fixed data errors with Olympus E-M5MarkII HR images. @ text @d26 1 a26 1 #define DCRAW_VERSION "9.23" d1201 19 d1914 1 d1928 7 d5263 2 d6206 6 d7359 1 a7359 1 { "Nikon D3300", 150, 0, d7373 1 a7373 1 { "Nikon D4S", 768, 0, d7385 1 a7385 1 { "Nikon D5300", 600, 0, d7387 2 d7401 1 a7401 1 { "Nikon D750", 600, 0, d7407 1 a7407 1 { "Nikon D810", 600, 0, d7461 1 a7461 1 { "Nikon 1 V3", 200, 0, d7463 1 a7463 1 { "Nikon 1 J4", 200, 0, d7549 2 d7575 1 a7575 1 { "OmniVision ov5647", 0, 0, /* DJC */ d7713 2 @ 1.469 log @Support the Lenovo A820. @ text @d1884 2 a1885 2 if (load_flags & 1 && (col % 10) == 9 && fgetc(ifp) && col < width+left_margin) derror(); d8886 1 @ 1.468 log @Copied color matrices from DNG Converter 8.7.1. Support pre-release Sonys and Canons that lack a proper model name. Support the Samsung NX1 (yet another compression algorithm). Read camera white balance in all professional Kodak cameras. Reduced zippering in Fuji X-Trans interpolation. Support YCbCr files from the Kodak C330. Support Hasselblad multi-shot files. @ text @d8128 1 @ 1.467 log @Correctly handle Fuji X-Trans images in DNG format. @ text @d3 1 a3 1 Copyright 1997-2014 by Dave Coffin, dcoffin a cybercom o net d26 1 a26 1 #define DCRAW_VERSION "9.22" d1718 3 a1720 1 int row, col, pred[2], len[2], diff, c; d1725 5 d1731 1 a1731 1 pred[0] = pred[1] = 0x8000 + load_flags; d1733 30 a1762 7 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; RAW(row,col+c) = pred[c] += diff; d1766 1 d1768 1 a1768 1 maximum = 0xffff; d1818 2 a1819 3 if ((shot = shot_select) || half_size) { if (shot) shot--; if (shot > 3) shot = 3; a1824 6 free (raw_image); raw_image = 0; free (image); image = (ushort (*)[4]) calloc ((iheight=height), (iwidth=width)*sizeof *image); merror (image, "sinar_4shot_load_raw()"); d1835 1 a1835 1 image[r*width+c][FC(row,col)] = pixel[col]; d1840 1 a1840 1 shrink = filters = 0; d2370 26 a2395 1 void CLASS kodak_yrgb_load_raw() d2401 1 a2401 1 merror (pixel, "kodak_yrgb_load_raw()"); d2405 1 a2405 1 for (col=0; col < raw_width; col++) { d2724 49 d4696 2 a4697 2 for (row=top+1; row < mrow-1; row++) for (col=left+1; col < mcol-1; col++) { d4700 6 a4705 2 i = (row-sgrow) % 3 ? TS:1; for (d=0; d < 4; d++, rix += TS*TS) d4708 1 d5358 1 a5358 1 i = len >> 3 == 164 ? 112:22; d5366 2 d5564 2 d5869 1 d5970 2 d6671 1 a6671 1 while (ftell(ifp)+7 < end) d6697 20 d6944 2 d7042 2 d7078 2 d7134 2 d7186 2 d7194 2 d7364 2 d7370 2 a7371 2 { "Nikon D810", 596, 0, /* DJC */ { 6502,-2328,154,-4249,9943,4307,-1303,2538,8108 } }, d7502 2 d7572 2 d7576 2 d7606 4 d7634 4 a7637 2 { "Panasonic DMC-FZ1000", 15, 0, /* DJC */ { 5686,-2219,-68,-4143,9912,4232,-1244,2246,5917 } }, d7684 2 d7718 3 a7720 1 { "Samsung NX30", 0, 0, /* NX30, NX300 */ d7730 3 a7732 1 { "Samsung NX", 0, 0, /* NX5, NX10, NX11, NX100 */ d7734 4 d7754 1 a7754 1 { "Sony DSC-RX100M2", 200, 0, d7794 2 d7802 1 a7802 1 { "Sony ILCE", 128, 0, /* 3000, 5000, and 6000 */ d7985 1 d7995 1 d8024 27 d8118 2 d8257 4 d8366 2 a8367 1 if (!strncmp(model,"ov",2) && !fseek (ifp, -6404096, SEEK_END) && d8453 1 a8453 1 if (unique_id == 0x80000000 + unique[i].id) d8455 6 d8559 1 a8559 1 !strcmp(model,"D600") || d8585 1 a8585 3 } else if (!strcmp(make,"Nikon") && raw_width == 4032) { adobe_coeff ("Nikon","COOLPIX P7700"); } else if (!strncmp(model,"COOLPIX P",9)) { d8726 4 a8729 2 height -= 18; width = 5536; d8743 2 d8787 3 a8789 3 } else if (raw_width == 7410) { height = 5502; width = 7328; d8806 4 d8812 1 a8925 1 adobe_coeff ("Sony","DSC-R1"); d8964 5 a8968 2 load_raw = filters ? &CLASS eight_bit_load_raw : &CLASS kodak_yrgb_load_raw; d8974 3 a8976 7 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")) { d8979 2 a8980 12 } 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; d8983 1 a8983 2 colors = 1; filters = 0; d8985 1 a8985 1 colors = 1; d9106 1 a9106 1 tiff_bps > 16 || tiff_samples > 4 || colors > 4) d9829 5 d9835 3 a9837 2 for (i=0; i < 16; i++) putchar (cdesc[fcol(i >> 1,i & 1)]); @ 1.466 log @Copied color matrices from DNG Converter 8.5. @ text @d116 1 a116 1 char *meta_data, xtrans[6][6]; d257 1 a257 1 if (filters == 9) return xtrans[(row+top_margin+6)%6][(col+left_margin+6)%6]; d4460 1 a4460 1 #define fcol(row,col) xtrans[(row+top_margin+6)%6][(col+left_margin+6)%6] d5685 1 a5685 2 FORC(36) xtrans[(c/6+top_margin)%6][(c+left_margin)%6] = fgetc(ifp) & 3; d6504 1 a6504 1 FORC(36) xtrans[0][35-c] = fgetc(ifp) & 3; d7226 2 d7480 2 d8464 3 @ 1.465 log @In colorcheck(), darken sample squares and do a second pass for exact white balance. @ text @d26 1 a26 1 #define DCRAW_VERSION "9.21" d7280 5 a7284 1 { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } }, d7521 2 d7623 4 d8706 2 @ 1.464 log @Removed C99 dependency in Phase One code. Correctly dereference TIFF type 13 (SubIFD) tags. @ text @d3879 2 a3880 2 double inverse[NSQ][3], cam_xyz[4][3], num; int c, i, j, k, sq, row, col, count[4]; d3889 2 a3890 1 gmb_cam[sq][c] += BAYER(row,col); d3900 10 a3909 5 for (raw_color = 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 (rgb_cam, cam_xyz); @ 1.463 log @Removed redundant strings. @ text @d378 1 a378 2 float A[2*len][2*len], b[2*len], c[2*len], d[2*len]; float x[len], y[len]; d381 6 a386 4 memset (A, 0, sizeof(A)); memset (b, 0, sizeof(b)); memset (c, 0, sizeof(c)); memset (d, 0, sizeof(d)); d428 1 d4939 1 a4939 1 if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4) d5234 1 a5234 1 if ((tag | 0x70) == 0x2070 && type == 4) d5528 1 @ 1.462 log @Support Lossy DNG files that lack an OpcodeList2 tag. Decode DNG files made from Fuji X-Trans photos. Support the Canon G1 X Mark II, Nikon P340, Samsing NX mini. Patched in Anders Torger's code for Phase One correction. Correctly crop all Sony cameras, read Panasonic blacklevels. @ text @d7893 1 a7893 1 { 307200, 640, 480, 0, 0, 0, 0, 0,0x94,0,0,"Generic","640x480" }, d7930 3 a7932 3 { 12582980,3072,2048, 0, 0, 0, 0,33,0x61,0,0,"Sinar","3072x2048",68 }, { 33292868,4080,4080, 0, 0, 0, 0,33,0x61,0,0,"Sinar","4080x4080",68 }, { 44390468,4080,5440, 0, 0, 0, 0,33,0x61,0,0,"Sinar","4080x5440",68 }, @ 1.461 log @Fixed Sony A700 black level. @ text @d26 1 a26 1 #define DCRAW_VERSION "9.20" d164 2 a165 1 int format, key_off, black, black_off, split_col, tag_21a; d376 53 d1367 1 a1367 1 unsigned wide, y, x, c, rend, cend, row, col; d1371 3 a1373 1 wide = head[2] / head[4]; d1376 1 a1376 1 for (y=0; y < head[3] / head[5]; y++) { d1385 3 a1387 1 for (row = rend-head[5]; row < raw_height && row < rend; row++) { d1394 3 a1396 1 for (col = cend-head[4]; col < raw_width && col < cend; col++) { d1424 1 d1464 1 a1464 1 if (type == 131) /* Bad column */ d1501 77 d1664 1 a1664 1 short (*black)[2]; d1666 1 a1666 1 pixel = (ushort *) calloc (raw_width + raw_height*4, 2); d1672 8 a1679 4 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); d1703 3 a1705 1 i = (pixel[col] << 2) - ph1.black + black[row][col >= ph1.split_col]; d2246 2 d2256 1 a2256 1 ushort curve[3][256]; d2259 19 a2277 17 fseek (ifp, meta_offset, SEEK_SET); order = 0x4d4d; ntags = get4(); while (ntags--) { opcode = get4(); get4(); get4(); if (opcode != 8) { fseek (ifp, get4(), SEEK_CUR); continue; } fseek (ifp, 20, SEEK_CUR); if ((c = get4()) > 2) break; fseek (ifp, 12, SEEK_CUR); if ((deg = get4()) > 8) break; for (i=0; i <= deg && i < 9; i++) coeff[i] = getreal(12); for (i=0; i < 256; i++) { for (tot=j=0; j <= deg; j++) tot += coeff[j] * pow(i/255.0, j); curve[c][i] = tot*0xffff; d2279 4 a2283 1 order = sorder; d2300 1 a2300 1 FORC3 image[row*width+tcol+col][c] = curve[c][pixel[col][c]]; d2570 1 a2570 1 ushort huff[32768]; d2574 1 a2574 1 int i, c, n, col, row, len, diff, sum=0; d2576 1 d2578 1 a2578 1 FORC(32768 >> (tab[i] >> 8)) huff[n++] = tab[i]; d2583 1 a2583 5 len = getbithuff(15,huff); diff = getbits(len); if ((diff & (1 << (len-1))) == 0) diff -= (1 << len) - 1; if ((sum += diff) >> 12) derror(); d2651 22 d3628 1 a3628 1 } else if (zero < mblack[4] && mblack[5] && mblack[6] && mblack[7]) d3630 2 d5508 4 d5622 2 d5670 4 d5675 5 d5751 4 a5754 1 load_raw = &CLASS samsung_load_raw; d5824 1 d6057 2 d6078 1 a6078 1 tiff_compress != 32769 && tiff_compress != 32770) d6451 3 a6453 1 case 0x223: ph1.black_off = data+base; break; d6848 2 d7058 2 d7174 2 a7175 2 { "Nikon D3300", 147, 0, /* DJC */ { 6108,-2161,-13,-4091,9871,4220,-1222,2469,7907 } }, d7188 2 d7258 2 d7270 2 d7348 2 d7422 1 a7422 1 { "Panasonic DMC-FZ3", 143, 0, d7424 1 a7424 1 { "Panasonic DMC-FZ4", 143, 0, d7428 1 a7428 1 { "Panasonic DMC-FZ7", 144, 0, d7442 1 a7442 1 { "Panasonic DMC-LF1", 143, 0, d7444 1 a7444 1 { "Leica C (Typ 112)", 143, 0, d7458 1 a7458 1 { "Panasonic DMC-LX5", 143, 0, d7460 1 a7460 1 { "Leica D-LUX 5", 143, 0, d7462 1 a7462 1 { "Panasonic DMC-LX7", 143, 0, d7464 1 a7464 1 { "Leica D-LUX 6", 143, 0, d7466 1 a7466 1 { "Panasonic DMC-FZ100", 143, 0xfff, d7468 1 a7468 1 { "Leica V-LUX 2", 143, 0xfff, d7470 1 a7470 1 { "Panasonic DMC-FZ150", 143, 0xfff, d7472 1 a7472 1 { "Leica V-LUX 3", 143, 0xfff, d7474 1 a7474 1 { "Panasonic DMC-FZ200", 143, 0xfff, d7476 1 a7476 1 { "Leica V-LUX 4", 143, 0xfff, d7486 1 a7486 1 { "Panasonic DMC-G3", 143, 0xfff, d7488 1 a7488 1 { "Panasonic DMC-G5", 143, 0xfff, d7490 1 a7490 1 { "Panasonic DMC-G6", 142, 0xfff, d7494 1 a7494 1 { "Panasonic DMC-GF2", 143, 0xfff, d7496 1 a7496 1 { "Panasonic DMC-GF3", 143, 0xfff, d7498 1 a7498 1 { "Panasonic DMC-GF5", 143, 0xfff, d7500 1 a7500 1 { "Panasonic DMC-GF6", 143, 0, d7506 1 a7506 1 { "Panasonic DMC-GH3", 144, 0, d7508 1 a7508 1 { "Panasonic DMC-GM1", 143, 0, d7510 1 a7510 1 { "Panasonic DMC-GX1", 143, 0, d7512 1 a7512 1 { "Panasonic DMC-GX7", 143, 0, d7514 4 a7517 2 { "Panasonic DMC-TZ61", 143, 0, /* DJC */ { 6211,-2325,27,-3800,9449,4352,-943,2166,6293 } }, d7540 3 a7542 1 { "Samsung NX300", 0, 0, d7598 2 d7612 1 a7612 1 { "Sony ILCE-3000", 128, 0, a7613 2 { "Sony ILCE-5000", 128, 0, /* DJC */ { 4130,-1407,93,-4151,9566,4586,-1035,1976,7000 } }, d7793 1 d7830 1 d7959 1 a7959 1 data_offset = meta_length = tiff_bps = tiff_compress = 0; d8503 5 d8687 2 d8690 1 a8690 1 width -= 8; d8693 4 d8702 2 @ 1.460 log @Added three temporary color matrices. @ text @d7389 1 a7389 1 { "Sony DSLR-A700", 126, 0, @ 1.459 log @Use Little CMS version 2. @ text @d6975 2 d7307 2 d7401 2 @ 1.458 log @Support the Kodak 12-megapixel camera(s). @ text @d83 1 a83 1 #include /* Support color profiles */ a8680 1 cmsErrorAction (LCMS_ERROR_SHOW); @ 1.457 log @Can now use "-M" with a DNG file that embeds a bad color matrix. Improved support for Nokia cameraphones. Support the Alcatel 5235D, Powershot G16 and S120, Pentax K-3, etc. Added tone curve for Canon RMF files. Copied color matrices from DNG Converter 8.3. Support blacklevel patterns up to 64x64. @ text @d7684 3 d8482 2 a8483 1 } else if (!strcmp(model,"C603") || !strcmp(model,"C330")) { d8486 1 a8486 1 fseek (ifp, 168, SEEK_SET); @ 1.456 log @Fix green spots when half-sizing Fuji X-Trans images. Support the Baumer TXG14, OmniVision OV5647 (Raspberry Pi), and Samsung NX2000. @ text @d3 1 a3 1 Copyright 1997-2013 by Dave Coffin, dcoffin a cybercom o net d26 1 a26 1 #define DCRAW_VERSION "9.19" d126 1 a126 1 unsigned black, cblack[4], maximum, mix_green, raw_color, zero_is_bad; d132 1 a132 1 ushort *raw_image, (*image)[4]; d138 1 a138 1 int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=-1; d1754 1 a1754 1 RAW(orow,ocol) = bits >> (10*c+2) & 0x3ff; d1757 1 a1757 1 maximum = 0x3ff; a2353 2 if (raw_image) free (raw_image); raw_image = 0; d2387 2 a2388 2 while (len--) *data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127]; d2446 1 a2446 1 data = (uchar *) malloc (raw_width); d2498 3 d3421 1 a3421 1 if (mask[0][3]) goto mask_set; d3424 2 a3425 2 mask[0][1] = mask[1][1] = 2; mask[0][3] = -2; d3648 1 a3648 1 void CLASS cam_xyz_coeff (double cam_xyz[4][3]) d3666 1 a3666 1 for (raw_color = i=0; i < 3; i++) d3725 1 a3725 1 for (i=0; i < colors; i++) d3729 1 a3729 1 cam_xyz_coeff (cam_xyz); d3902 5 d3909 4 a3912 2 val = image[0][i]; if (!val) continue; d4852 2 a4853 1 } else if (!strcmp (buf,"OLYMPUS")) { d4856 2 a4857 1 order = get2(); get2(); d5190 2 a5191 1 "","","","","","","","","","","","","","","","","","AFi-II 12" }; a5304 1 int blrr=1, blrc=1, dblack[] = { 0,0,0,0 }; d5655 4 a5658 2 blrr = get2(); blrc = get2(); d5661 1 a5661 1 blrr = blrc = 2; d5663 2 a5664 10 black = getreal(type); if ((unsigned)(filters+1) < 1000) break; dblack[0] = black; dblack[1] = (blrc == 2) ? getreal(type):dblack[0]; dblack[2] = (blrr == 2) ? getreal(type):dblack[0]; dblack[3] = (blrc == 2 && blrr == 2) ? getreal(type):dblack[1]; if (colors == 3) filters |= ((filters >> 2 & 0x22222222) | (filters << 2 & 0x88888888)) & filters << 1; FORC4 cblack[filters >> (c << 1) & 3] = dblack[c]; d5759 1 a5759 1 cam_xyz_coeff (cam_xyz); d6627 2 d6675 2 d6691 2 d6733 2 a6792 2 { "Fujifilm S200EXR", 512, 0x3fff, { 11401,-4498,-1312,-5088,12751,2613,-838,1568,5941 } }, d6795 2 d6833 1 a6833 1 { "Fujifilm HS20EXR", 0, 0, d6839 2 d6851 2 d6855 6 d6863 2 a6864 2 { "Fujifilm X-S1", 0, 0, { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } }, d6989 2 d6997 2 d7003 2 d7063 2 d7069 2 d7123 2 d7135 2 d7141 2 d7159 2 d7195 2 d7219 2 d7233 4 d7281 2 a7282 2 { "Panasonic DMC-G6", 143, 0xfff, /* DJC */ { 6395,-2583,-40,-3677,9109,4569,-1502,2806,6431 } }, d7299 2 d7303 2 d7325 2 d7343 2 d7355 2 d7359 2 d7391 6 d7401 2 d7448 1 a7448 1 for (j=0; j < 12; j++) d7450 1 a7450 1 cam_xyz_coeff (cam_xyz); d7551 1 a7551 1 static const ushort canon[][6] = { d7553 1 a7553 1 { 2144, 1560, 4, 8, 52, 2 }, d7557 1 a7557 1 { 3152, 2068, 64, 12, 0, 0 }, d7565 1 a7565 1 { 3984, 2622, 76, 20, 0, 2 }, d7570 2 a7571 1 { 4176, 3062, 96, 17, 8, 0 }, d7575 1 a7575 1 { 4480, 3348, 12, 10, 36, 12 }, d7600 1 d7630 1 d7646 1 a7646 1 { 19131120,4168,3060,92,16, 4, 1, 8,0x94,0,2,"Canon","PowerShot SX220 HS" }, d7671 2 a7826 1 strcpy (model, "X2"); d7833 6 a7838 2 data_offset += i - width * 5 / 4 * height; load_raw = &CLASS nokia_load_raw; d7862 1 d7937 2 d7965 2 d7993 5 d8073 1 a8073 10 mask[0][0] = top_margin = 16; mask[0][2] = top_margin + height; mask[0][3] = left_margin = 92; } else if (!strcmp(model,"PowerShot SX50 HS")) { mask[0][0] = top_margin = 17; mask[0][2] = raw_height; mask[0][3] = 80; filters = 0x49494949; } else if (!strcmp(model,"PowerShot G10")) { filters = 0x49494949; d8108 2 a8109 1 } else if (!strcmp(model,"D4")) { d8213 2 a8214 1 if (!strcmp(model,"HS50EXR")) { d8273 2 a8274 1 filters = 0x49494949; a8609 3 if (raw_color) adobe_coeff (make, model); if (load_raw == &CLASS kodak_radc_load_raw) if (raw_color) adobe_coeff ("Apple","Quicktake"); d8618 8 d9213 1 a9213 1 case 'M': use_camera_matrix = (opm == '+'); break; a9228 2 if (use_camera_matrix < 0) use_camera_matrix = use_camera_wb; d9295 1 a9379 4 if (use_camera_matrix && cmatrix[0][0] > 0.25) { memcpy (rgb_cam, cmatrix, sizeof cmatrix); raw_color = 0; } d9422 6 @ 1.455 log @Support the Fuji HS50, X20, X100S, SL1000, Samsung NX300, Canon A3300 and EOS C500, and Olympus XZ-10. Added Frank Markesteijn's X-Trans demosaic algorithm. Lowercased the names of all camera makers. Hardened dcraw against corrupt input files. Tableized away large chunks of code in identify(). @ text @d26 1 a26 1 #define DCRAW_VERSION "9.18" d1727 1 a1727 1 dwide = raw_width * 5 / 4; d3881 1 d3946 12 d4901 2 a4902 4 if (tag == 0xc && len == 4) { cam_mul[0] = getreal(type); cam_mul[2] = getreal(type); } d6623 1 a6623 1 { "Canon EOS 100D", 0, 0x3806, d6663 2 d6993 2 d7127 2 d7275 2 d7281 2 d7533 1 a7533 1 { 0x189, "EOS 350D" }, d7548 2 a7549 1 char make[12], model[20]; d7555 1 a7555 1 { 5067316,2588,1958, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-510C" }, d7557 1 a7557 1 { 10134620,2588,1958, 0, 0, 0, 0, 9,0x94,0,0,"AVT","F-510C" }, d7560 1 d7604 1 a7604 1 { 1652736,1536,1076, 0, 0, 0, 0, 0,0x61,0,0,"Kodak","DCS200" }, d7606 1 a7606 1 { 4162462,2338,1779, 1,33, 1, 2, 0,0x94,0,0,"Kodak","C330" }, d7608 1 a7608 1 { 6166488,2864,2152, 0, 0, 0, 0, 0,0x94,0,0,"Kodak","C603" }, d7612 2 a7613 2 { 3884928,1608,1207, 0, 0, 0, 0,96,0x16,0,0,"Micron","2010" }, { 1138688,1534, 986, 0, 0, 0, 0, 0,0x61,0,0,"Minolta","RD175" }, d7635 3 a7637 3 { 12582980,3072,2048, 0, 0, 0, 0,33,0x61,0,0,"Sinar","3072x2048" }, { 33292868,4080,4080, 0, 0, 0, 0,33,0x61,0,0,"Sinar","4080x4080" }, { 44390468,4080,5440, 0, 0, 0, 0,33,0x61,0,0,"Sinar","4080x5440" }, d7812 1 d7822 3 a7824 1 switch (tiff_bps = fsize*8 / (raw_width*raw_height)) { d7840 12 a7851 1 if (make[0] == 0) parse_jpeg (is_raw = 0); a8061 3 } else if (fsize == 1138688) { data_offset = 513; load_raw = &CLASS minolta_rd175_load_raw; d8149 2 a8150 2 load_raw = &CLASS unpacked_load_raw; maximum = 0xfff; d8191 1 a8191 1 } else if (!strcmp(make,"Samsung") && raw_width == 5546) { d8193 1 a8193 1 width -= 10; a8233 4 } else if (!strcmp(model,"F-510C")) { data_offset = fsize - width*height*(fsize >> 22); } else if (!strcmp(model,"2010")) { data_offset = 3212; a8262 7 if (!memcmp(head,"8BPS",4)) { fseek (ifp, 14, SEEK_SET); height = get4(); width = get4(); filters = 0x61616161; data_offset = 68; } d8401 1 a8401 1 if (filters && (data_offset = fsize - raw_height*raw_width)) { a8488 4 height = 1024; width = 1536; data_offset = 79872; load_raw = &CLASS eight_bit_load_raw; @ 1.454 log @Copied color matrices from DNG Converter 7.3. @ text @d3 1 a3 1 Copyright 1997-2012 by Dave Coffin, dcoffin a cybercom o net d26 1 a26 1 #define DCRAW_VERSION "9.17" a44 21 #ifdef NODEPS #define NO_JASPER #define NO_JPEG #define NO_LCMS #endif #ifndef NO_JASPER #include /* Decode RED camera movies */ #endif #ifndef NO_JPEG #include /* Decode compressed Kodak DC120 photos */ #endif /* and Adobe Lossy DNGs */ #ifndef NO_LCMS #include /* Support color profiles */ #endif #ifdef LOCALEDIR #include #define _(String) gettext(String) #else #define _(String) (String) #endif d71 21 d116 1 a116 1 char *meta_data; d120 3 a122 3 unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id; off_t strip_offset, data_offset; off_t thumb_offset, meta_offset, profile_offset; d129 1 a133 1 int mask[8][4], flip, tiff_flip, colors; d136 1 a253 7 static const char filter2[6][6] = { { 1,1,0,1,1,2 }, { 1,1,2,1,1,0 }, { 2,0,1,0,2,1 }, { 1,1,2,1,1,0 }, { 1,1,0,1,1,2 }, { 0,2,1,2,0,1 } }; d256 1 a256 1 if (filters == 2) return filter2[(row+6) % 6][(col+6) % 6]; d271 9 a543 4 /* getbits(-1) initializes the buffer getbits(n) where 0 <= n <= 25 returns an n-bit integer */ d550 2 a551 1 if (nbits == -1) d809 1 d905 1 a905 1 if (row >= 0) RAW(row,col) = val; d921 1 a921 1 if (!ljpeg_start (&jh, 0)) return; d1037 1 a1037 1 pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel); d1189 4 a1192 4 { 0x00, "PENTAX", "Optio 33WR" }, { 0x03, "NIKON", "E3200" }, { 0x32, "NIKON", "E3700" }, { 0x33, "OLYMPUS", "C740UZ" } }; d1653 1 a1653 1 calloc ((iheight=height)*(iwidth=width), sizeof *image); d1677 1 d1685 1 a1685 1 int vbits=0, bwide, pwide, rbits, bite, half, irow, row, col, val, i; d1688 3 a1690 4 if (raw_width * 8 >= width * tiff_bps) /* Is raw_width in bytes? */ pwide = (bwide = raw_width) * 8 / tiff_bps; else bwide = (pwide = raw_width) * tiff_bps / 8; rbits = bwide * 8 - pwide * tiff_bps; d1706 1 a1706 1 for (col=0; col < pwide; col++) { d1713 1 a1713 1 RAW(row,col ^ (load_flags >> 6)) = val; d1740 20 d2326 1 d2474 28 d2654 1 a2654 1 img = (ushort *) calloc ((height+2)*(width+2), 2); d2812 1 a2812 1 ushort huff[258], vpred[2][2], hpred[2]; d3317 1 a3317 1 shrink = (short (*)[3]) calloc ((width/4) * (height/4), sizeof *shrink); d3446 2 a3447 2 for (row=mask[m][0]; row < mask[m][2]; row++) for (col=mask[m][1]; col < mask[m][3]; col++) { d3946 1 a3946 1 img = (ushort (*)[4]) calloc (height*width, sizeof *img); d3959 2 a3960 2 if (four_color_rgb && colors++) mix_green = !half_size; d4000 1 a4000 1 if (filters == 2) size = 6; d4081 1 a4081 1 if (filters == 2) prow = pcol = 6; d4227 259 a4489 2 #define TS 256 /* Tile Size */ d4492 1 a4492 2 int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2]; ushort (*pix)[4], (*rix)[3]; d4495 1 a4495 2 float r, cbrt[0x10000], xyz[3], xyz_cam[3][4]; ushort (*rgb)[TS][TS][3]; d4501 1 a4501 9 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]; d4503 1 a4503 1 buffer = (char *) malloc (26*TS*TS); /* 1664 kB */ d4547 1 a4547 12 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]); d4677 1 a4677 1 map = (float *) calloc (high*wide, sizeof *map); a5040 2 if (tag == 0x2010 && type != 7) load_raw = &CLASS olympus_load_raw; d5307 1 a5307 1 case 9: filters = get2(); break; d5344 1 d5346 1 a5346 1 load_flags = get4() && (filters=0x16161616) ? 24:80; d5475 1 a5475 1 for (colors=cfa=i=0; i < plen; i++) { d5541 4 d5621 1 d5641 1 a5641 1 if (!filters || !~filters) break; d5824 3 d5837 4 a5840 1 case 16: load_raw = &CLASS unpacked_load_raw; break; a5856 2 case 34892: load_raw = &CLASS lossy_dng_load_raw; break; d5865 1 a5865 1 case 32867: break; d5869 1 a5869 2 if ( (tiff_samples == 3 && tiff_ifd[raw].bytes && tiff_bps != 14 && tiff_bps != 2048 && d5871 1 a5871 1 || (tiff_bps == 8 && !strstr(make,"KODAK") && !strstr(make,"Kodak") && d5876 2 a5877 2 tiff_ifd[i].width * tiff_ifd[i].height / SQR(tiff_ifd[i].bps+1) > thumb_width * thumb_height / SQR(thumb_misc+1) d6022 1 a6022 1 void CLASS parse_ciff (int offset, int length) d6031 1 a6031 1 if (nrecs > 100) return; d6038 1 a6038 2 parse_ciff (ftell(ifp), len); /* Parse a sub-table */ d6047 3 a6049 1 fseek (ifp, 12, SEEK_CUR); d6284 3 d6292 2 a6293 1 if ((width = get4()) > 10000) width = get4(); d6322 1 a6322 1 parse_ciff (save+hlen, len-hlen); d6512 1 a6564 1 is_foveon = 1; d6576 1 a6576 1 { "AGFAPHOTO DC-833m", 0, 0, /* DJC */ d6612 2 d6630 2 a6655 2 { "Canon EOS", 0, 0, { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, d6714 2 d6736 1 a6736 1 { "CASIO EX-S20", 0, 0, /* DJC */ d6738 1 a6738 1 { "CASIO EX-Z750", 0, 0, /* DJC */ d6740 1 a6740 1 { "CASIO EX-Z10", 128, 0xfff, /* DJC */ d6750 1 a6750 1 { "EPSON R-D1", 0, 0, d6752 1 a6752 1 { "FUJIFILM E550", 0, 0, d6754 1 a6754 1 { "FUJIFILM E900", 0, 0, d6756 1 a6756 1 { "FUJIFILM F5", 0, 0, d6758 1 a6758 1 { "FUJIFILM F6", 0, 0, d6760 1 a6760 1 { "FUJIFILM F77", 0, 0xfe9, d6762 1 a6762 1 { "FUJIFILM F7", 0, 0, d6764 1 a6764 1 { "FUJIFILM F8", 0, 0, d6766 1 a6766 1 { "FUJIFILM S100FS", 514, 0, d6768 1 a6768 1 { "FUJIFILM S200EXR", 512, 0x3fff, d6770 1 a6770 1 { "FUJIFILM S20Pro", 0, 0, d6772 1 a6772 1 { "FUJIFILM S2Pro", 128, 0, d6774 1 a6774 1 { "FUJIFILM S3Pro", 0, 0, d6776 1 a6776 1 { "FUJIFILM S5Pro", 0, 0, d6778 1 a6778 1 { "FUJIFILM S5000", 0, 0, d6780 1 a6780 1 { "FUJIFILM S5100", 0, 0, d6782 1 a6782 1 { "FUJIFILM S5500", 0, 0, d6784 1 a6784 1 { "FUJIFILM S5200", 0, 0, d6786 1 a6786 1 { "FUJIFILM S5600", 0, 0, d6788 1 a6788 1 { "FUJIFILM S6", 0, 0, d6790 1 a6790 1 { "FUJIFILM S7000", 0, 0, d6792 1 a6792 1 { "FUJIFILM S9000", 0, 0, d6794 1 a6794 1 { "FUJIFILM S9500", 0, 0, d6796 1 a6796 1 { "FUJIFILM S9100", 0, 0, d6798 1 a6798 1 { "FUJIFILM S9600", 0, 0, d6800 3 a6802 1 { "FUJIFILM IS-1", 0, 0, d6804 1 a6804 1 { "FUJIFILM IS Pro", 0, 0, d6806 1 a6806 1 { "FUJIFILM HS10 HS11", 0, 0xf68, d6808 1 a6808 1 { "FUJIFILM HS20EXR", 0, 0, d6810 1 a6810 1 { "FUJIFILM HS3", 0, 0, d6812 5 a6816 1 { "FUJIFILM X100", 0, 0, d6818 1 a6818 1 { "FUJIFILM X10", 0, 0, d6820 3 a6822 1 { "FUJIFILM X-Pro1", 0, 0, d6824 1 a6824 1 { "FUJIFILM X-E1", 0, 0, d6826 1 a6826 1 { "FUJIFILM XF1", 0, 0, d6828 1 a6828 1 { "FUJIFILM X-S1", 0, 0, d6832 1 a6832 1 { "KODAK NC2000", 0, 0, d6838 1 a6838 1 { "KODAK DCS420", 0, 0, d6840 1 a6840 1 { "KODAK DCS460", 0, 0, d6842 1 a6842 1 { "KODAK EOSDCS1", 0, 0, d6844 1 a6844 1 { "KODAK EOSDCS3B", 0, 0, d6870 1 a6870 1 { "KODAK P712", 0, 0, d6872 1 a6872 1 { "KODAK P850", 0, 0xf7c, d6874 1 a6874 1 { "KODAK P880", 0, 0xfff, d6876 1 a6876 1 { "KODAK EasyShare Z980", 0, 0, d6878 1 a6878 1 { "KODAK EasyShare Z981", 0, 0, d6880 1 a6880 1 { "KODAK EasyShare Z990", 0, 0xfed, d6882 1 a6882 1 { "KODAK EASYSHARE Z1015", 0, 0xef1, d6908 1 a6908 1 { "MINOLTA DiMAGE A200", 0, 0, d6914 1 a6914 1 { "MINOLTA DYNAX 5", 0, 0xffb, d6916 1 a6916 1 { "MINOLTA DYNAX 7", 0, 0xffb, d6918 1 a6918 1 { "MOTOROLA PIXL", 0, 0, /* DJC */ d6920 1 a6920 1 { "NIKON D100", 0, 0, d6922 1 a6922 1 { "NIKON D1H", 0, 0, d6924 1 a6924 1 { "NIKON D1X", 0, 0, d6926 1 a6926 1 { "NIKON D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */ d6928 1 a6928 1 { "NIKON D200", 0, 0xfbc, d6930 1 a6930 1 { "NIKON D2H", 0, 0, d6932 1 a6932 1 { "NIKON D2X", 0, 0, d6934 1 a6934 1 { "NIKON D3000", 0, 0, d6936 1 a6936 1 { "NIKON D3100", 0, 0, d6938 1 a6938 1 { "NIKON D3200", 0, 0xfb9, d6940 1 a6940 1 { "NIKON D300", 0, 0, d6942 1 a6942 1 { "NIKON D3X", 0, 0, d6944 1 a6944 1 { "NIKON D3S", 0, 0, d6946 1 a6946 1 { "NIKON D3", 0, 0, d6948 1 a6948 1 { "NIKON D40X", 0, 0, d6950 1 a6950 1 { "NIKON D40", 0, 0, d6952 1 a6952 1 { "NIKON D4", 0, 0, d6954 1 a6954 1 { "NIKON D5000", 0, 0xf00, d6956 1 a6956 1 { "NIKON D5100", 0, 0x3de6, d6958 3 a6960 1 { "NIKON D50", 0, 0, d6962 1 a6962 1 { "NIKON D600", 0, 0x3e07, d6964 1 a6964 1 { "NIKON D60", 0, 0, d6966 1 a6966 1 { "NIKON D7000", 0, 0, d6968 3 a6970 1 { "NIKON D700", 0, 0, d6972 1 a6972 1 { "NIKON D70", 0, 0, d6974 1 a6974 1 { "NIKON D800", 0, 0, d6976 1 a6976 1 { "NIKON D80", 0, 0, d6978 1 a6978 1 { "NIKON D90", 0, 0xf00, d6980 1 a6980 1 { "NIKON E950", 0, 0x3dd, /* DJC */ d6982 3 a6984 1 { "NIKON E995", 0, 0, /* copied from E5000 */ d6986 1 a6986 1 { "NIKON E2100", 0, 0, /* copied from Z2, new white balance */ d6988 1 a6988 1 { "NIKON E2500", 0, 0, d6990 1 a6990 1 { "NIKON E3200", 0, 0, /* DJC */ d6992 1 a6992 1 { "NIKON E4300", 0, 0, /* copied from Minolta DiMAGE Z2 */ d6994 1 a6994 1 { "NIKON E4500", 0, 0, d6996 1 a6996 1 { "NIKON E5000", 0, 0, d6998 1 a6998 1 { "NIKON E5400", 0, 0, d7000 1 a7000 1 { "NIKON E5700", 0, 0, d7002 1 a7002 1 { "NIKON E8400", 0, 0, d7004 1 a7004 1 { "NIKON E8700", 0, 0, d7006 1 a7006 1 { "NIKON E8800", 0, 0, d7008 5 a7012 1 { "NIKON COOLPIX P6000", 0, 0, d7014 1 a7014 1 { "NIKON COOLPIX P7000", 0, 0, d7016 1 a7016 1 { "NIKON COOLPIX P7100", 0, 0, d7018 1 a7018 1 { "NIKON COOLPIX P7700", 200, 0, d7020 1 a7020 1 { "NIKON 1 V2", 0, 0, d7022 3 a7024 1 { "NIKON 1 ", 0, 0, d7026 1 a7026 1 { "OLYMPUS C5050", 0, 0, d7028 1 a7028 1 { "OLYMPUS C5060", 0, 0, d7030 1 a7030 1 { "OLYMPUS C7070", 0, 0, d7032 1 a7032 1 { "OLYMPUS C70", 0, 0, d7034 1 a7034 1 { "OLYMPUS C80", 0, 0, d7036 1 a7036 1 { "OLYMPUS E-10", 0, 0xffc, d7038 1 a7038 1 { "OLYMPUS E-1", 0, 0, d7040 1 a7040 1 { "OLYMPUS E-20", 0, 0xffc, d7042 1 a7042 1 { "OLYMPUS E-300", 0, 0, d7044 1 a7044 1 { "OLYMPUS E-330", 0, 0, d7046 1 a7046 1 { "OLYMPUS E-30", 0, 0xfbc, d7048 1 a7048 1 { "OLYMPUS E-3", 0, 0xf99, d7050 1 a7050 1 { "OLYMPUS E-400", 0, 0, d7052 1 a7052 1 { "OLYMPUS E-410", 0, 0xf6a, d7054 1 a7054 1 { "OLYMPUS E-420", 0, 0xfd7, d7056 1 a7056 1 { "OLYMPUS E-450", 0, 0xfd2, d7058 1 a7058 1 { "OLYMPUS E-500", 0, 0, d7060 1 a7060 1 { "OLYMPUS E-510", 0, 0xf6a, d7062 1 a7062 1 { "OLYMPUS E-520", 0, 0xfd2, d7064 1 a7064 1 { "OLYMPUS E-5", 0, 0xeec, d7066 1 a7066 1 { "OLYMPUS E-600", 0, 0xfaf, d7068 1 a7068 1 { "OLYMPUS E-620", 0, 0xfaf, d7070 1 a7070 1 { "OLYMPUS E-P1", 0, 0xffd, d7072 1 a7072 1 { "OLYMPUS E-P2", 0, 0xffd, d7074 1 a7074 1 { "OLYMPUS E-P3", 0, 0, d7076 1 a7076 1 { "OLYMPUS E-PL1s", 0, 0, d7078 1 a7078 1 { "OLYMPUS E-PL1", 0, 0, d7080 1 a7080 1 { "OLYMPUS E-PL2", 0, 0, d7082 1 a7082 1 { "OLYMPUS E-PL3", 0, 0, d7084 1 a7084 1 { "OLYMPUS E-PL5", 0, 0xfcb, d7086 1 a7086 1 { "OLYMPUS E-PM1", 0, 0, d7088 1 a7088 1 { "OLYMPUS E-PM2", 0, 0, d7090 1 a7090 1 { "OLYMPUS E-M5", 0, 0xfe1, d7092 1 a7092 1 { "OLYMPUS SP350", 0, 0, d7094 1 a7094 1 { "OLYMPUS SP3", 0, 0, d7096 1 a7096 1 { "OLYMPUS SP500UZ", 0, 0xfff, d7098 1 a7098 1 { "OLYMPUS SP510UZ", 0, 0xffe, d7100 1 a7100 1 { "OLYMPUS SP550UZ", 0, 0xffe, d7102 1 a7102 1 { "OLYMPUS SP560UZ", 0, 0xff9, d7104 1 a7104 1 { "OLYMPUS SP570UZ", 0, 0, d7106 3 a7108 1 { "OLYMPUS XZ-1", 0, 0, d7110 1 a7110 1 { "OLYMPUS XZ-2", 0, 0, d7112 1 a7112 1 { "PENTAX *ist DL2", 0, 0, d7114 1 a7114 1 { "PENTAX *ist DL", 0, 0, d7116 1 a7116 1 { "PENTAX *ist DS2", 0, 0, d7118 1 a7118 1 { "PENTAX *ist DS", 0, 0, d7120 1 a7120 1 { "PENTAX *ist D", 0, 0, d7122 1 a7122 1 { "PENTAX K10D", 0, 0, d7124 1 a7124 1 { "PENTAX K1", 0, 0, d7126 1 a7126 1 { "PENTAX K20D", 0, 0, d7128 1 a7128 1 { "PENTAX K200D", 0, 0, d7130 1 a7130 1 { "PENTAX K2000", 0, 0, d7132 1 a7132 1 { "PENTAX K-m", 0, 0, d7134 1 a7134 1 { "PENTAX K-x", 0, 0, d7136 1 a7136 1 { "PENTAX K-r", 0, 0, d7138 1 a7138 1 { "PENTAX K-5 II", 0, 0, d7140 1 a7140 1 { "PENTAX K-5", 0, 0, d7142 1 a7142 1 { "PENTAX K-7", 0, 0, d7144 1 a7144 1 { "PENTAX 645D", 0, 0x3e00, d7160 1 a7160 1 { "LEICA V-LUX1", 0, 0, d7166 1 a7166 1 { "LEICA DIGILUX 3", 0, 0xf7f, d7170 1 a7170 1 { "LEICA DIGILUX 2", 0, 0, d7174 1 a7174 1 { "LEICA D-LUX2", 0, 0xf7f, d7178 1 a7178 1 { "LEICA D-LUX3", 0, 0, d7182 1 a7182 1 { "LEICA D-LUX 4", 15, 0, d7186 1 a7186 1 { "LEICA D-LUX 5", 143, 0, d7190 1 a7190 1 { "LEICA D-LUX 6", 143, 0, d7194 1 a7194 1 { "LEICA V-LUX 2", 143, 0xfff, d7198 1 a7198 1 { "LEICA V-LUX 3", 143, 0xfff, d7202 1 a7202 1 { "LEICA V-LUX 4", 143, 0xfff, d7216 2 d7226 2 d7250 1 a7250 1 { "RED ONE", 704, 0xffff, /* DJC */ d7252 1 a7252 1 { "SAMSUNG EX1", 0, 0x3e00, d7254 1 a7254 1 { "SAMSUNG EX2F", 0, 0x7ff, d7256 3 a7258 1 { "SAMSUNG NX2", 0, 0xfff, /* NX20, NX200, NX210 */ d7260 1 a7260 1 { "SAMSUNG NX1000", 0, 0, d7262 1 a7262 1 { "SAMSUNG NX", 0, 0, /* NX5, NX10, NX11, NX100 */ d7264 1 a7264 1 { "SAMSUNG WB2000", 0, 0xfff, d7266 1 a7266 1 { "SAMSUNG GX-1", 0, 0, d7268 1 a7268 1 { "SAMSUNG S85", 0, 0xffff, /* DJC */ d7272 1 a7272 1 { "SONY DSC-F828", 0, 0, d7274 1 a7274 1 { "SONY DSC-R1", 512, 0, d7276 1 a7276 1 { "SONY DSC-V3", 0, 0, d7278 1 a7278 1 { "SONY DSC-RX100", 200, 0, d7280 1 a7280 1 { "SONY DSC-RX1", 128, 0, d7282 1 a7282 1 { "SONY DSLR-A100", 0, 0xfeb, d7284 1 a7284 1 { "SONY DSLR-A290", 0, 0, d7286 1 a7286 1 { "SONY DSLR-A2", 0, 0, d7288 1 a7288 1 { "SONY DSLR-A300", 0, 0, d7290 1 a7290 1 { "SONY DSLR-A330", 0, 0, d7292 1 a7292 1 { "SONY DSLR-A350", 0, 0xffc, d7294 1 a7294 1 { "SONY DSLR-A380", 0, 0, d7296 1 a7296 1 { "SONY DSLR-A390", 0, 0, d7298 1 a7298 1 { "SONY DSLR-A450", 128, 0xfeb, d7300 1 a7300 1 { "SONY DSLR-A580", 128, 0xfeb, d7302 1 a7302 1 { "SONY DSLR-A5", 128, 0xfeb, d7304 1 a7304 1 { "SONY DSLR-A700", 126, 0, d7306 1 a7306 1 { "SONY DSLR-A850", 128, 0, d7308 1 a7308 1 { "SONY DSLR-A900", 128, 0, d7310 1 a7310 1 { "SONY NEX-5N", 128, 0, d7312 1 a7312 1 { "SONY NEX-5R", 128, 0, d7314 3 a7316 1 { "SONY NEX-3", 138, 0, /* DJC */ d7318 1 a7318 1 { "SONY NEX-5", 116, 0, /* DJC */ d7320 1 a7320 1 { "SONY NEX-3", 128, 0, /* Adobe */ d7322 1 a7322 1 { "SONY NEX-5", 128, 0, /* Adobe */ d7324 1 a7324 1 { "SONY NEX-6", 128, 0, d7326 1 a7326 1 { "SONY NEX-7", 128, 0, d7328 1 a7328 1 { "SONY NEX", 128, 0, /* NEX-C3, NEX-F3 */ d7330 1 a7330 1 { "SONY SLT-A33", 128, 0, d7332 1 a7332 1 { "SONY SLT-A35", 128, 0, d7334 1 a7334 1 { "SONY SLT-A37", 128, 0, d7336 1 a7336 1 { "SONY SLT-A55", 128, 0, d7338 3 a7340 1 { "SONY SLT-A57", 128, 0, d7342 1 a7342 1 { "SONY SLT-A65", 128, 0, d7344 1 a7344 1 { "SONY SLT-A77", 128, 0, d7346 1 a7346 1 { "SONY SLT-A99", 128, 0, d7437 1 a7437 4 char head[32], *cp; int hlen, flen, fsize, zero_fsize=1, i, c, is_canon; struct jhead jh; short pana[][6] = { d7460 40 a7499 1 { 4508, 3330, 0, 0, -3, -6 } }; d7501 27 a7527 2 int fsize; char make[12], model[19], withjpeg; d7529 89 a7617 88 { 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 */ { 787456, "Creative", "PC-CAM 600" ,0 }, { 1138688, "Minolta", "RD175" ,0 }, { 3840000, "Foculus", "531C" ,0 }, { 307200, "Generic", "640x480" ,0 }, { 786432, "AVT", "F-080C" ,0 }, { 1447680, "AVT", "F-145C" ,0 }, { 1920000, "AVT", "F-201C" ,0 }, { 5067304, "AVT", "F-510C" ,0 }, { 5067316, "AVT", "F-510C" ,0 }, { 10134608, "AVT", "F-510C" ,0 }, { 10134620, "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 }, { 9243240, "Canon", "PowerShot A470" ,0 }, { 10341600, "Canon", "PowerShot A720 IS",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 }, { 15534576, "Canon", "PowerShot SX120 IS",0 }, { 18653760, "Canon", "PowerShot SX20 IS",0 }, { 19131120, "Canon", "PowerShot SX220 HS",0 }, { 21936096, "Canon", "PowerShot SX30 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 }, { 7562048, "CASIO", "EX-Z500" ,1 }, { 7753344, "CASIO", "EX-Z55" ,1 }, { 7816704, "CASIO", "EX-Z60" ,1 }, { 10843712, "CASIO", "EX-Z75" ,1 }, { 10834368, "CASIO", "EX-Z750" ,1 }, { 12310144, "CASIO", "EX-Z850" ,1 }, { 12489984, "CASIO", "EX-Z8" ,1 }, { 15499264, "CASIO", "EX-Z1050" ,1 }, { 18702336, "CASIO", "EX-ZR100" ,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 }, { 20487168, "SAMSUNG", "WB550" ,1 }, { 24000000, "SAMSUNG", "WB550" ,1 }, { 12582980, "Sinar", "" ,0 }, { 33292868, "Sinar", "" ,0 }, { 44390468, "Sinar", "" ,0 } }; d7619 7 a7625 3 { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX", "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One", "SAMSUNG", "Mamiya", "MOTOROLA", "LEICA" }; d7627 1 a7627 1 tiff_flip = flip = filters = -1; /* 0 is valid, so -1 is unknown */ d7669 2 a7670 1 parse_ciff (hlen, flen - hlen); d7753 10 d7764 2 a7765 2 strcpy (make, "RED"); strcpy (model,"ONE"); d7785 3 a7787 1 if (table[i].withjpeg) d7789 22 d7817 4 a7820 5 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," Digital Camera")) || d7858 6 a7863 4 if (tiff_compress == 1) load_raw = &CLASS packed_dng_load_raw; if (tiff_compress == 7) load_raw = &CLASS lossless_dng_load_raw; d7866 19 a7884 4 if ((is_canon = !strcmp(make,"Canon"))) load_raw = memcmp (head+6,"HEAPCCDR",8) ? &CLASS lossless_jpeg_load_raw : &CLASS canon_load_raw; if (!strcmp(make,"NIKON")) { a7889 4 if (!strcmp(make,"CASIO")) { load_raw = &CLASS packed_load_raw; maximum = 0xf7f; } d7893 6 d7904 1 a7904 1 } else if (is_canon && tiff_bps == 15) { d7911 1 a7916 1 pixel_aspect = 607/628.0; a7925 1 colors = 4; a7931 1 colors = 4; a7936 1 colors = 4; a7937 89 goto canon_a5; } else if (!strcmp(model,"PowerShot SD300")) { height = 1752; width = 2344; raw_height = 1766; raw_width = 2400; top_margin = 12; left_margin = 12; goto canon_a5; } else if (!strcmp(model,"PowerShot A460")) { height = 1960; width = 2616; raw_height = 1968; raw_width = 2664; top_margin = 4; left_margin = 4; goto canon_a5; } else if (!strcmp(model,"PowerShot A530")) { height = 1984; width = 2620; raw_height = 1992; raw_width = 2672; top_margin = 6; left_margin = 10; goto canon_a5; } 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; goto canon_a5; } else if (!strcmp(model,"PowerShot A620")) { height = 2328; width = 3112; raw_height = 2340; raw_width = 3152; top_margin = 12; left_margin = 36; goto canon_a5; } else if (!strcmp(model,"PowerShot A470")) { height = 2328; width = 3096; raw_height = 2346; raw_width = 3152; top_margin = 6; left_margin = 12; goto canon_a5; } else if (!strcmp(model,"PowerShot A720 IS")) { height = 2472; width = 3298; raw_height = 2480; raw_width = 3336; top_margin = 5; left_margin = 6; goto canon_a5; } else if (!strcmp(model,"PowerShot A630")) { height = 2472; width = 3288; raw_height = 2484; raw_width = 3344; top_margin = 6; left_margin = 12; goto canon_a5; } else if (!strcmp(model,"PowerShot A640")) { height = 2760; width = 3672; raw_height = 2772; raw_width = 3736; top_margin = 6; left_margin = 12; goto canon_a5; } else if (!strcmp(model,"PowerShot A650")) { height = 3024; width = 4032; raw_height = 3048; raw_width = 4104; top_margin = 12; left_margin = 48; goto canon_a5; } else if (!strcmp(model,"PowerShot S3 IS")) { height = 2128; width = 2840; raw_height = 2136; raw_width = 2888; top_margin = 8; left_margin = 44; d7939 1 d7943 6 a7948 32 if (raw_width > 1600) zero_is_bad = 1; } 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_load_raw; load_flags = 40; zero_is_bad = 1; } else if (!strcmp(model,"PowerShot SX120 IS")) { height = 2742; width = 3664; raw_height = 2778; raw_width = 3728; top_margin = 18; left_margin = 16; filters = 0x49494949; load_raw = &CLASS packed_load_raw; load_flags = 40; zero_is_bad = 1; } else if (!strcmp(model,"PowerShot SX20 IS")) { height = 3024; width = 4032; raw_height = 3048; raw_width = 4080; top_margin = 12; left_margin = 24; load_raw = &CLASS packed_load_raw; load_flags = 40; zero_is_bad = 1; a7949 4 height = 3043; width = 4072; raw_height = 3060; raw_width = 4168; d7953 1 a7953 118 load_raw = &CLASS packed_load_raw; load_flags = 8; zero_is_bad = 1; } else if (!strcmp(model,"PowerShot SX30 IS")) { height = 3254; width = 4366; raw_height = 3276; raw_width = 4464; top_margin = 10; left_margin = 25; filters = 0x16161616; load_raw = &CLASS packed_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 == 3744) { height = 2760; width = 3684; top_margin = 16; left_margin = 8; if (unique_id > 0x2720000) { top_margin = 12; left_margin = 52; } } 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 == 4160) { height = 3048; width = 4048; top_margin = 11; left_margin = 104; } else if (is_canon && raw_width == 4176) { height = 3045; width = 4072; left_margin = 96; d7958 1 a7958 22 } 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 == 4352) { top_margin = 18; left_margin = 62; if (unique_id == 0x80000288) adobe_coeff ("Canon","EOS 1100D"); 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; d7960 3 a7962 63 } else if (is_canon && raw_width == 4496) { height = 3316; width = 4404; top_margin = 50; left_margin = 80; } else if (is_canon && raw_width == 4832) { top_margin = unique_id == 0x80000261 ? 51:26; left_margin = 62; if (unique_id == 0x80000252) adobe_coeff ("Canon","EOS 500D"); goto canon_cr2; } else if (is_canon && raw_width == 5108) { top_margin = 13; left_margin = 98; goto canon_cr2; } else if (is_canon && raw_width == 5120) { height -= top_margin = 45; left_margin = 142; width = 4916; } else if (is_canon && raw_width == 5280) { top_margin = 52; left_margin = 72; if (unique_id == 0x80000301) adobe_coeff ("Canon","EOS 650D"); goto canon_cr2; } else if (is_canon && raw_width == 5344) { top_margin = 51; left_margin = 142; if (unique_id == 0x80000269) { top_margin = 100; left_margin = 126; height -= 2; adobe_coeff ("Canon","EOS-1D X"); } if (unique_id == 0x80000270) adobe_coeff ("Canon","EOS 550D"); if (unique_id == 0x80000286) adobe_coeff ("Canon","EOS 600D"); goto canon_cr2; } else if (is_canon && raw_width == 5360) { top_margin = 51; left_margin = 158; goto canon_cr2; } else if (is_canon && raw_width == 5568) { top_margin = 38; left_margin = 72; goto canon_cr2; } else if (is_canon && raw_width == 5712) { height = 3752; width = 5640; top_margin = 20; left_margin = 62; } else if (is_canon && raw_width == 5792) { top_margin = 51; left_margin = 158; canon_cr2: height -= top_margin; width -= left_margin; } else if (is_canon && raw_width == 5920) { height = 3870; width = 5796; top_margin = 80; left_margin = 122; d7987 2 a7988 1 !strcmp(model,"D7000")) { d7992 1 a7992 1 !strcmp(model,"D800")) { d8016 2 a8017 2 } else if (!strcmp(make,"NIKON") && raw_width == 4032) { adobe_coeff ("NIKON","COOLPIX P7700"); d8025 3 a8028 6 height = 963; width = 1287; raw_width = 1632; maximum = 0x3f4; colors = 4; filters = 0x1e1e1e1e; d8033 3 a8035 12 goto e900; } else if (fsize == 2465792) { height = 1203; width = 1616; raw_width = 2048; colors = 4; filters = 0x4b4b4b4b; adobe_coeff ("NIKON","E950"); e900: tiff_bps = 10; load_raw = &CLASS packed_load_raw; load_flags = 6; a8036 6 height = 1540; width = 2064; colors = 4; filters = 0xe1e1e1e1; load_raw = &CLASS packed_load_raw; load_flags = 6; d8046 9 a8054 12 } 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; a8055 4 height = 1542; width = 2064; load_raw = &CLASS packed_load_raw; load_flags = 30; a8072 3 height = 1710; width = 2288; filters = 0x16161616; a8076 1 load_raw = &CLASS packed_load_raw; d8078 10 a8087 17 } 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_load_raw; load_flags = 30; } else if (!strcmp(make,"FUJIFILM")) { d8097 6 a8102 6 if (width == 2848) filters = 0x16161616; if (width == 3328) { width = 3262; left_margin = 34; } if (width == 4952) { d8104 1 a8104 1 filters = 2; a8106 6 } else if (!strcmp(model,"RD175")) { height = 986; width = 1534; data_offset = 513; filters = 0x61616161; load_raw = &CLASS minolta_rd175_load_raw; d8114 1 a8114 1 } else if (!strcasecmp(make,"MINOLTA")) { d8153 1 a8153 39 } 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_load_raw; maximum = 0xf7c; } } else if (fsize == 6114240) { height = 1737; width = 2324; raw_width = 3520; load_raw = &CLASS packed_load_raw; maximum = 0xf7a; } else if (!strcmp(model,"Optio 750Z")) { height = 2302; width = 3072; load_raw = &CLASS packed_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; } else if (!strcmp(make,"SAMSUNG") && raw_width == 4704) { d8157 5 a8161 1 } else if (!strcmp(make,"SAMSUNG") && raw_width == 5632) { d8185 1 a8185 8 } else if (fsize == 20487168) { height = 2808; width = 3648; goto wb550; } else if (fsize == 24000000) { height = 3000; width = 4000; wb550: a8186 4 order = 0x4d4d; load_raw = &CLASS unpacked_load_raw; load_flags = 6; maximum = 0x3df; a8194 5 height = 484; width = 644; load_raw = &CLASS eight_bit_load_raw; flip = 2; filters = 0x16161616; a8197 5 } else if (!strcmp(model,"531C")) { height = 1200; width = 1600; load_raw = &CLASS unpacked_load_raw; filters = 0x49494949; a8198 3 height = 480; width = 640; load_raw = &CLASS eight_bit_load_raw; a8199 12 } 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; a8200 4 height = 1958; width = 2588; load_raw = fsize < 7500000 ? &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw; a8201 14 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; a8202 4 height = 1207; width = 1608; order = 0x4949; filters = 0x16161616; a8203 23 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; } d8284 1 a8284 1 } else if (!strcmp(make,"LEICA") || !strcmp(make,"Panasonic")) { d8308 1 a8308 1 } else if (!strcmp(make,"OLYMPUS")) { d8310 1 a8310 1 filters = exif_cfa; a8330 3 } else if (!strcmp(model,"XZ-2")) { load_raw = &CLASS packed_load_raw; load_flags = 24; d8353 2 a8354 2 } else if (!strcmp(make,"SONY") && raw_width == 3984) { adobe_coeff ("SONY","DSC-R1"); d8357 1 a8357 1 } else if (!strcmp(make,"SONY") && raw_width == 5504) { d8359 1 a8359 1 } else if (!strcmp(make,"SONY") && raw_width == 6048) { d8376 1 a8376 7 } else if (!strcmp(model,"C603v")) { height = 480; width = 640; if (fsize < 614400 || find_green (16, 16, 3840, 5120) < 25) goto c603v; strcpy (model,"KAI-0340"); height -= 3; data_offset = 3840; d8378 1 a8378 22 load_raw = &CLASS unpacked_load_raw; } 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)) { d8382 2 a8383 1 load_raw = &CLASS eight_bit_load_raw; d8387 1 a8387 1 } else if (!strcasecmp(make,"KODAK")) { d8425 1 a8425 1 raw_height = height = 242; d8433 1 a8433 1 data_offset += raw_width + 1; a8506 105 } 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; raw_width = 3232; tiff_bps = 10; } 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-Z500")) { height = 1937; width = 2577; raw_width = 3904; filters = 0x16161616; } else if (!strcmp(model,"EX-Z55")) { height = 1960; width = 2570; raw_width = 3904; } else if (!strcmp(model,"EX-Z60")) { height = 2145; width = 2833; raw_width = 3584; filters = 0x16161616; tiff_bps = 10; } else if (!strcmp(model,"EX-Z75")) { height = 2321; width = 3089; raw_width = 4672; maximum = 0xfff; } else if (!strcmp(model,"EX-Z750")) { height = 2319; width = 3087; raw_width = 4672; maximum = 0xfff; } else if (!strcmp(model,"EX-Z850")) { height = 2468; width = 3279; raw_width = 4928; maximum = 0xfff; } else if (!strcmp(model,"EX-Z8")) { height = 2467; width = 3281; raw_height = 2502; raw_width = 4992; maximum = 0xfff; } else if (fsize == 15499264) { /* EX-Z1050 or EX-Z1080 */ height = 2752; width = 3672; raw_width = 5632; } else if (!strcmp(model,"EX-ZR100")) { height = 3044; width = 4072; raw_width = 4096; load_flags = 80; } 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; d8534 3 a8536 1 if (!load_raw || height < 22) is_raw = 0; d8556 1 a8556 1 if (filters && colors == 3) d8560 2 a8561 2 if (flip == -1) flip = tiff_flip; if (flip == -1) flip = 0; d8736 1 a8736 1 img = (ushort (*)[4]) calloc (wide*high, sizeof *img); d8769 1 a8769 1 img = (ushort (*)[4]) calloc (width*newdim, sizeof *img); d8781 1 a8781 1 img = (ushort (*)[4]) calloc (height*newdim, sizeof *img); d9104 1 a9104 1 case 'h': half_size = 1; /* "-h" implies "-f" */ d9240 1 a9240 3 if (width <= raw_width * 8 / tiff_bps) width = raw_width * 8 / tiff_bps; else width = raw_width; d9286 1 a9286 1 raw_image = (ushort *) calloc ((raw_height+7)*raw_width, 2); d9289 1 a9289 1 image = (ushort (*)[4]) calloc (iheight*iwidth, sizeof *image); d9305 1 a9305 3 if (width <= raw_width * 8 / tiff_bps) width = raw_width * 8 / tiff_bps; else width = raw_width; d9310 1 a9310 1 image = (ushort (*)[4]) calloc (iheight*iwidth, sizeof *image); d9341 1 a9341 1 else if (quality == 1 || colors > 3 || filters < 1000) d9343 1 a9343 1 else if (quality == 2) d9345 4 a9348 1 else ahd_interpolate(); @ 1.453 log @Support the Canon EOS 6D, 1DX, SX50, Casio EX-ZR100, Fuji X-E1 & XF1, Pentax K-5 II (s), and Samsung EX2F. @ text @d6296 2 a6297 2 { "Canon EOS 6D", 0, 0x3c82, /* DJC */ { 5305,-1175,-247,-4398,10046,4353,-1177,2269,7174 } }, d6368 2 a6369 2 { "Canon PowerShot G15", 0, 0, /* DJC */ { 6122,-2591,310,-3649,8603,5047,-212,621,4435 } }, d6408 2 a6409 2 { "Canon PowerShot S110", 0, 0, /* DJC */ { 6150,-2362,-24,-3958,9498,4462,-234,827,4451 } }, d6412 2 a6413 2 { "Canon PowerShot SX50 HS", 0, 0, /* DJC */ { 11743,-5718,-170,-1881,7849,4034,-415,1610,5972 } }, d6651 1 a6651 1 { 7866,-2108,-555,-4869,12483,2681,-1176,2069,7501 } }, d6700 2 d6762 2 a6763 2 { "OLYMPUS E-PL5", 0, 0xfcb, /* DJC */ { 7222,-2971,102,-2890,8534,4358,-1007,1962,6299 } }, d6766 2 d6786 2 d6814 2 a6815 2 { "PENTAX K-5 II", 0, 0, /* DJC */ { 6735,-2869,84,-3906,9222,4684,-1048,1897,7248 } }, d6904 2 d6950 2 a6951 2 { "SONY DSC-RX1", 128, 0, /* DJC */ { 4582,-1507,259,-4355,9689,4667,-1160,2083,7342 } }, d6982 2 @ 1.452 log @Measured saturation level on the Canon EOS-1D X. @ text @d26 1 a26 1 #define DCRAW_VERSION "9.16" d962 5 a966 8 if (unique_id < 0x80000218) { rp[0] -= 512; goto next; } else if (unique_id == 0x80000285) { next: pix[0] = rp[0] + rp[2]; pix[2] = rp[0] + rp[1]; pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12); } else { d972 5 a1144 17 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; } /* d1585 1 a1585 3 pred[c] += diff; if (row >= 0 && (unsigned)(col+c) < width) RAW(row,col+c) = pred[c]; d1773 1 a1773 2 if (col < width) if ((RAW(row,col) = pred[col & 1]) > 4098) derror(); d2445 1 a2445 1 if (col < width) RAW(row,col) = curve[pix[i] << 1] >> 2; a3376 4 if (load_raw == &CLASS sony_load_raw) { mask[0][3] = 9; goto sides; } d3378 1 d4770 1 a4770 1 i = len == 1312 ? 112:22; d5552 9 a5560 1 load_raw = &CLASS nikon_load_raw; break; d5576 2 a5577 1 tiff_bps != 14 && tiff_bps != 2048 && tiff_compress != 32770) d5995 1 a5995 1 width = get4(); d6296 2 d6334 2 d6368 2 d6408 6 a6429 2 { "Canon PowerShot SX1 IS", 0, 0, { 6578,-259,-502,-5974,13030,3309,-308,1058,4970 } }, d6458 1 a6458 1 { "FUJIFILM F77", 0, 0, d6463 1 a6463 1 { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } }, d6514 4 d6536 1 a6536 1 { "Kodak DCS520C", 180, 0, d6538 1 a6538 1 { "Kodak DCS560C", 188, 0, d6540 1 a6540 1 { "Kodak DCS620C", 180, 0, d6542 1 a6542 1 { "Kodak DCS620X", 185, 0, d6544 1 a6544 1 { "Kodak DCS660C", 214, 0, d6628 1 a6628 1 { "NIKON D3200", 0, 0, d6650 2 d6698 2 d6740 1 a6740 1 { "OLYMPUS E-5", 0, 0, d6760 2 d6764 1 a6764 1 { "OLYMPUS E-M5", 0, 0, d6808 2 d6858 4 d6870 4 d6884 2 d6918 2 d6934 1 a6934 1 { "SONY DSC-F828", 491, 0, d6940 4 a6943 2 { "SONY DSC-RX100", 192, 0, /* DJC */ { 7329,-2746,-405,-2691,9338,3354,-136,1259,5051 } }, d6982 2 d7002 2 d7196 1 d7401 1 a7401 1 if (width >= 4960 && !strcmp(model,"K-5")) d7446 1 d7725 8 d7799 4 d7846 1 d7857 1 a7857 3 if (tiff_compress == 34713 && !nikon_is_compressed()) { load_raw = &CLASS packed_load_raw; load_flags |= 1; a7858 1 } d7871 2 d7988 1 d7993 1 a7993 3 if (!strcmp(model,"X10") || !strcmp(model,"X-S1")) filters = 0x16161616; if (!strcmp(model,"X-Pro1")) { d8129 7 d8343 3 d8356 1 d8365 1 d8635 5 a9376 7 if (document_mode == 3) { top_margin = left_margin = fuji_width = 0; height = raw_height; if (width <= raw_width * 8 / tiff_bps) width = raw_width * 8 / tiff_bps; else width = raw_width; } d9381 9 a9426 2 image = (ushort (*)[4]) calloc (iheight*iwidth, sizeof *image); merror (image, "main()"); d9434 3 d9448 9 d9458 2 @ 1.451 log @Support the Samsung NX1000 and Sony RX100. @ text @d6358 1 a6358 1 { "Canon EOS-1D X", 0, 0, @ 1.450 log @Support the Canon EOS 650D, Samsung NX20, and Sigma SD1. @ text @d6900 2 d6918 2 d8047 1 a8047 1 } else if (!strncmp(model,"NX1",3)) { d8051 1 a8051 1 } else if (!strncmp(model,"NX2",3)) { d8319 2 @ 1.449 log @Fixed gravity sensor for Canon 5D Mark III with Firmware Version 1.1.x. @ text @d26 1 a26 1 #define DCRAW_VERSION "9.15" d2780 1 a2780 1 ushort huff[258], vpred, hpred; d2789 1 a2789 1 vpred = 1024; d2793 3 a2795 3 if (col) hpred += diff; else hpred = vpred += diff; image[row*width+col][c] = hpred; d6338 2 d7733 6 d8047 1 a8047 1 } else if (!strcmp(model,"NX200")) { d9401 1 a9401 1 if (document_mode || model[0] == 'D') { @ 1.448 log @Decode CAMF and IMAG blocks from Sigma SD15 and DP cameras. Added "-E" and "-I" options to support raw pixel substitution. Support Adobe Lossy DNG and the Imacon Flexframe 3f format. Support the Canon G1-X, 1D-X, 5D Mark III, the Fuji X-Pro1, X-S1, and many others. @ text @d4628 5 a4632 4 fread (buf97, 1, sizeof buf97, ifp); i = (uchar *) memmem (buf97, sizeof buf97,"\xbb\xbb",2) - buf97 + 10; if (i < 70 && buf97[i] < 3) flip = "065"[buf97[i]]-'0'; @ 1.447 log @Support the Casio EX-Z500. @ text @d3 1 a3 1 Copyright 1997-2011 by Dave Coffin, dcoffin a cybercom o net d26 1 a26 1 #define DCRAW_VERSION "9.12" d55 1 a55 1 #endif d126 1 a126 1 unsigned black, cblack[8], maximum, mix_green, raw_color, zero_is_bad; d131 3 a133 1 int flip, tiff_flip, colors; a134 1 ushort (*image)[4], white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4]; d159 1 d222 3 d232 1 a232 1 image[((row) >> shrink)*iwidth + ((col) >> shrink)][fc(row,col)] d234 1 a234 1 int CLASS fc (int row, int col) d253 11 a263 3 if (filters != 1) return FC(row,col); return filter[(row+top_margin) & 15][(col+left_margin) & 15]; d491 2 a492 4 ushort pixel[896], *pix; int irow, row, col, val; static const short mul[4][2] = { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } }; d495 3 a497 2 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) { a506 4 for (col=0; col < width; col++) BAYER(row,col) = pixel[col]; for (col=width; col < raw_width; col++) black += pixel[col]; d509 8 a516 2 if (raw_width > width) black = black / ((raw_width - width) * height) - 4; a529 17 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; } } d705 1 a705 1 void CLASS canon_compressed_load_raw() d708 1 a708 2 int nblocks, lowbits, i, c, row, r, col, save, val; unsigned irow, icol; a711 2 pixel = (ushort *) calloc (raw_width*8, sizeof *pixel); merror (pixel, "canon_compressed_load_raw()"); d718 1 a755 12 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; c = FC(irow,icol); if (icol < width) BAYER(irow,icol) = pixel[r*raw_width+col]; else if (col > 1 && (unsigned) (col-left_margin+2) > width+3) cblack[c] += (cblack[4+c]++,pixel[r*raw_width+col]); } } a756 1 free (pixel); a757 1 FORC4 if (cblack[4+c]) cblack[c] /= cblack[4+c]; d880 1 a880 1 int jwide, jrow, jcol, val, jidx, c, i, j, row=0, col=0; a881 1 int min=INT_MAX; d892 1 a892 3 val = *rp++; if (jh.bits <= 12) val = curve[val & 0xfff]; d904 1 a904 8 if ((unsigned) (row-top_margin) < height) { c = FC(row-top_margin,col-left_margin); 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) cblack[c] += (cblack[4+c]++,val); } a909 3 FORC4 if (cblack[4+c]) cblack[c] /= cblack[4+c]; if (!strcasecmp(make,"KODAK")) black = min; d963 6 a968 3 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; d982 1 a982 1 void CLASS adobe_copy_pixel (int row, int col, ushort **rp) d984 1 a984 1 unsigned r, c; a985 2 r = row -= top_margin; c = col -= left_margin; d987 3 a989 7 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; d992 1 a992 1 if (r < height && c < width) d994 1 a994 1 image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c]; d1000 1 a1000 1 void CLASS adobe_dng_load_raw_lj() d1029 1 a1029 1 void CLASS adobe_dng_load_raw_nc() d1035 1 a1035 1 merror (pixel, "adobe_dng_load_raw_nc()"); d1072 1 a1072 3 if ((unsigned) (row-top_margin) < height && (unsigned) (col-left_margin) < width) BAYER(row-top_margin,col-left_margin) = hpred[col & 1]; d1077 1 a1077 1 void CLASS nikon_compressed_load_raw() d1136 1 a1136 2 if ((unsigned) (col-left_margin) < width) BAYER(row,col-left_margin) = curve[LIM((short)hpred[col & 1],0,0x3fff)]; a1232 29 /* 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); } d1247 15 d1300 1 a1300 1 unsigned iten=0, isix, i, buffer=0, row, col, todo[16]; d1313 2 a1314 6 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); } d1319 1 a1319 1 int CLASS bayer (unsigned row, unsigned col) d1321 1 a1321 1 return (row < height && col < width) ? BAYER(row,col) : 0; d1342 2 a1343 2 rend = head[1]-top_margin + y*head[5]; for (row = rend-head[5]; row < height && row < rend; row++) { d1349 3 a1351 3 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; d1353 2 a1354 2 c = BAYER(row,col) * mult[c]; BAYER(row,col) = LIM(c,0,65535); d1408 3 a1410 3 for (row=0; row < height; row++) for (col = (tag & 1)*ph1.split_col; col < width; col++) BAYER(row,col) = curve[BAYER(row,col)]; d1413 2 a1414 2 col = get2() - left_margin; row = get2() - top_margin; d1416 1 a1416 1 if (col >= width) continue; d1418 2 a1419 2 for (row=0; row < height; row++) if (FC(row,col) == 1) { d1421 1 a1421 1 sum += val[i] = bayer (row+dir[i][0], col+dir[i][1]); d1426 1 a1426 1 BAYER(row,col) = (sum - val[max])/3.0 + 0.5; d1429 3 a1431 3 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; d1434 2 a1435 2 if (row >= height) continue; j = (FC(row,col) != 1) * 4; d1437 2 a1438 2 sum += bayer (row+dir[i][0], col+dir[i][1]); BAYER(row,col) = (sum + 4) >> 3; d1472 2 a1473 2 for (row=0; row < height; row++) for (col=0; col < width; col++) { d1476 1 a1476 1 num = BAYER(row,col) * 0.5; d1484 2 a1485 3 i = ((mult[0] * (1-cfrac) + mult[1] * cfrac) * (row + top_margin) + num) * 2; BAYER(row,col) = LIM(i,0,65535); d1493 2 a1494 2 int row, col, a, b; ushort *pixel, akey, bkey, mask; d1500 9 a1508 17 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); if (ph1.format) 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(); d1574 4 a1577 6 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; } a1579 1 phase_one_correct(); d1591 1 a1591 1 for (row=-top_margin; row < height; row++) { d1593 1 a1593 1 for (col=-left_margin; col < raw_width-left_margin; col+=2) { d1602 1 a1602 1 BAYER(row,col+c) = pred[c]; d1612 1 a1612 1 ushort *pixel; d1615 4 a1618 2 pixel = (ushort *) calloc (raw_width, sizeof *pixel); merror (pixel, "leaf_hdr_load_raw()"); d1623 1 a1623 1 fseek (ifp, get4() + 2*left_margin, SEEK_SET); d1626 1 d1628 3 a1630 4 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]; a1631 1 free (pixel); d1635 1 d1639 12 a1650 1 void CLASS unpacked_load_raw(); d1665 2 a1700 1 int zero=0; a1707 1 fseek (ifp, top_margin*bwide, SEEK_CUR); d1709 2 a1710 2 half = (height+1) >> 1; for (irow=0; irow < height; irow++) { d1729 1 a1729 7 i = (col ^ (load_flags >> 6)) - left_margin; if ((unsigned) i < width) BAYER(row,i) = val; else if (load_flags & 32) { black += val; zero += !val; } a1734 22 if (load_flags & 32 && pwide > width) black /= (pwide - width) * height; if (zero*4 > (pwide - width) * height) black = 0; } 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] >> load_flags) >> bits) derror(); } free (pixel); d1740 1 a1740 2 ushort *pixel, *pix; int rev, dwide, row, c; d1744 1 a1744 1 data = (uchar *) malloc (dwide + raw_width*2); a1745 1 pixel = (ushort *) (data + dwide); d1749 2 a1750 6 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]; a1752 1 if (top_margin) black /= top_margin * width; d1791 1 a1791 1 if ((BAYER(row,col) = pred[col & 1]) > 4098) derror(); d1822 2 a1823 2 else if (row < 2) pred = BAYER(row,col-2); else if (col < 2) pred = BAYER(row-2,col); d1825 3 a1827 3 w = BAYER(row,col-2); n = BAYER(row-2,col); nw = BAYER(row-2,col-2); d1834 1 a1834 1 if ((BAYER(row,col) = pred + ((diff << 2) | low)) >> 12) derror(); d1856 1 a1856 1 if (col != 1) BAYER(row,col) = (col+1) & 2 ? d1858 2 a1859 2 BAYER(row,1) = pixel[1] << 1; BAYER(row,1533) = pixel[765] << 1; d1862 1 a1862 1 BAYER(row,col) = pixel[col/2] << 1; d1930 1 a1930 1 BAYER(row,col) = curve[pixel[row+2][col+2]]; d2017 2 a2018 2 if (c) BAYER(row+y*2+c-1,x*2+2-c) = val; else BAYER(row+r*2+y,x*2+y) = val; d2028 1 a2028 1 val = (BAYER(y,x)-2048)*2 + (BAYER(y,r)+BAYER(y,s))/2; d2030 1 a2030 1 BAYER(y,x) = val; d2033 2 a2034 2 for (i=0; i < iheight*iwidth*4; i++) image[0][i] = curve[image[0][i]]; d2043 1 d2088 4 a2091 4 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]; d2098 58 d2169 1 a2169 1 BAYER(row,col) = (ushort) pixel[(col + shift) % 848]; d2177 1 a2177 1 unsigned row, col, val, lblack=0; d2181 1 a2181 2 fseek (ifp, top_margin*raw_width, SEEK_CUR); for (row=0; row < height; row++) { d2183 2 a2184 6 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; } a2186 4 if (raw_width > width+1) black = lblack / ((raw_width - width) * height); if (!strncmp(model,"DC2",3)) black = 0; d2248 1 a2248 3 if ((unsigned) (col-left_margin) < width) BAYER(row,col-left_margin) = val; else black += val; a2252 2 if (raw_width > width) black /= (raw_width - width) * height; d2312 1 a2312 1 if ((BAYER(row,col+i) = curve[ret ? buf[i] : d2350 2 d2405 2 a2406 3 pixel = (ushort *) calloc (raw_width, sizeof *pixel); merror (pixel, "sony_load_raw()"); for (row=0; row < height; row++) { d2409 2 a2410 5 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(); a2411 3 free (pixel); if (left_margin > 9) black /= (left_margin-9) * height; d2434 1 a2434 1 if (row < height) BAYER(row,col) = sum; d2463 1 a2463 1 if (col < width) BAYER(row,col) = curve[pix[i] << 1] >> 2; d2480 1 a2480 1 int s, count, bin, next, i, sym[3]; a2482 1 unsigned pix, row, col; d2528 2 a2529 6 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; d2566 5 a2570 5 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); d2574 1 a2574 1 BAYER(row,col) = (BAYER(row,col-2) + BAYER(row,col+2)) >> 1; d2576 5 a2580 5 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); d2649 1 a2649 1 BAYER(row,col) = curve[img[(row+1)*(width+2)+col+1]]; d2730 1 a2730 15 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() d2735 1 a2735 1 int pred[3], fixed, row, col, bit=-1, c, i; a2736 1 fixed = get4(); d2738 1 a2738 1 if (!fixed) foveon_decoder (1024, 0); d2742 1 a2742 1 if (!bit && !fixed && atoi(model+2) < 14) get4(); d2744 1 a2744 1 if (fixed) { d2761 77 a2837 4 if (document_mode) for (i=0; i < height*width*4; i++) if ((short) image[0][i] < 0) image[0][i] = 0; foveon_load_camf(); d2901 1 d2982 1 d3361 88 d3497 1 a3497 1 (r != row || c != col) && fc(r,c) == fc(row,col)) { a3807 1 FORC4 cblack[c] += black; d3821 2 a3822 2 c = FC(y,x); val = BAYER(y,x); d3921 1 a3921 1 c = fc(row,col); d3929 1 a3929 1 if (filters && colors == 3) { d3954 1 a3954 1 f = fc(y,x); d3958 1 a3958 1 f = fc(row,col); d3966 2 a3967 2 int code[16][16][32], *ip, sum[4]; int c, i, x, y, row, col, shift, color; d3971 1 a3971 1 d3973 4 a3976 3 for (row=0; row < 16; row++) for (col=0; col < 16; col++) { ip = code[row][col]; d3981 2 a3982 2 if (shift == 2) continue; color = fc(row+y,col+x); d3988 1 d3990 1 a3990 1 if (c != fc(row,col)) { d3998 1 a3998 1 ip = code[row & 15][col & 15]; d4000 1 a4000 1 for (i=8; i--; ip+=3) d4044 1 a4044 1 int prow=7, pcol=1, *ip, *code[16][16], gval[8], gmin, gmax, sum[4]; d4051 3 a4053 2 if (filters == 1) prow = pcol = 15; ip = (int *) calloc ((prow+1)*(pcol+1), 1280); d4055 2 a4056 2 for (row=0; row <= prow; row++) /* Precalculate for VNG */ for (col=0; col <= pcol; col++) { d4063 3 a4065 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; d4078 2 a4079 2 color = fc(row,col); if (fc(row+y,col+x) != color && fc(row+y*2,col+x*2) == color) d4092 1 a4092 1 ip = code[row & prow][col & pcol]; d4115 1 a4115 1 color = fc(row,col); d4790 2 a4791 1 fseek (ifp, 22, SEEK_CUR); d5084 1 a5084 1 tiff_ifd[ifd].comp = get2(); d5153 1 a5153 1 tile_width = getint(type); d5156 1 a5156 1 tile_length = getint(type); d5283 3 a5285 1 fseek (ifp, 78, SEEK_CUR); d5303 3 a5305 1 filters = flip = 0; d5433 8 d5528 2 d5533 2 a5538 20 case 0: case 1: switch (tiff_bps) { case 8: load_raw = &CLASS eight_bit_load_raw; break; case 12: load_raw = &CLASS packed_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) { tiff_bps = 12; load_raw = &CLASS packed_load_raw; load_flags = 81; } 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; d5552 19 a5570 2 case 32773: load_raw = &CLASS packed_load_raw; break; d5572 3 a5574 1 load_raw = &CLASS nikon_compressed_load_raw; break; d5588 1 a5588 1 tiff_bps != 14 && tiff_bps != 2048) d5595 2 a5596 1 thumb_width * thumb_height / SQR(thumb_misc+1)) { d5611 5 a5615 1 if (tiff_ifd[thm].bps > 8) a5616 2 else write_thumb = &CLASS ppm_thumb; d5959 1 a5959 1 case 0x222: ph1.split_col = data - left_margin; break; d6000 1 a6000 2 load_raw = fgetc(ifp) & 8 ? &CLASS unpacked_load_raw : &CLASS fuji_load_raw; d6211 2 a6212 1 fseek (ifp, 12, SEEK_CUR); d6216 6 d6224 1 a6224 1 data_offset = off+24; d6241 1 a6241 1 meta_offset = off+24; a6242 2 if (meta_length > 0x20000) meta_length = 0x20000; d6301 2 d6355 2 d6373 2 d6431 2 d6449 1 a6449 1 { "FUJIFILM FinePix E550", 0, 0, d6451 1 a6451 1 { "FUJIFILM FinePix E900", 0, 0, d6453 9 a6461 1 { "FUJIFILM FinePix F8", 0, 0, d6463 1 a6463 3 { "FUJIFILM FinePix F7", 0, 0, { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, { "FUJIFILM FinePix S100FS", 514, 0, d6465 1 a6465 1 { "FUJIFILM FinePix S200EXR", 512, 0x3fff, d6467 1 a6467 1 { "FUJIFILM FinePix S20Pro", 0, 0, d6469 1 a6469 1 { "FUJIFILM FinePix S2Pro", 128, 0, d6471 1 a6471 1 { "FUJIFILM FinePix S3Pro", 0, 0, d6473 1 a6473 1 { "FUJIFILM FinePix S5Pro", 0, 0, d6475 1 a6475 1 { "FUJIFILM FinePix S5000", 0, 0, d6477 1 a6477 1 { "FUJIFILM FinePix S5100", 0, 0, d6479 1 a6479 1 { "FUJIFILM FinePix S5500", 0, 0, d6481 1 a6481 1 { "FUJIFILM FinePix S5200", 0, 0, d6483 1 a6483 1 { "FUJIFILM FinePix S5600", 0, 0, d6485 1 a6485 1 { "FUJIFILM FinePix S6", 0, 0, d6487 1 a6487 1 { "FUJIFILM FinePix S7000", 0, 0, d6489 1 a6489 1 { "FUJIFILM FinePix S9000", 0, 0, d6491 1 a6491 1 { "FUJIFILM FinePix S9500", 0, 0, d6493 1 a6493 1 { "FUJIFILM FinePix S9100", 0, 0, d6495 1 a6495 1 { "FUJIFILM FinePix S9600", 0, 0, d6501 1 a6501 1 { "FUJIFILM FinePix HS10 HS11", 0, 0xf68, d6503 1 a6503 1 { "FUJIFILM FinePix HS20EXR", 0, 0, d6505 1 a6505 1 { "FUJIFILM FinePix F550EXR", 0, 0, d6507 1 a6507 3 { "FUJIFILM FinePix F600EXR", 0, 0, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, { "FUJIFILM FinePix X100", 0, 0, d6511 4 d6623 2 d6637 2 d6653 2 d6753 2 d6869 2 d6895 1 a6895 1 { "SAMSUNG NX200", 0, 0xfff, a6942 2 { "SONY NEX-C3", 128, 0, { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, d6953 2 d6959 2 d6963 2 d7103 1 d7132 1 d7159 1 d7179 1 a7179 1 "SAMSUNG", "Mamiya", "MOTOROLA" }; d7191 1 d7200 1 a7200 1 tile_width = tile_length = INT_MAX; d7208 1 a7208 1 for (i=0; i < 0x4000; i++) curve[i] = i; d7263 1 d7350 2 a7358 6 if (fuji_width) { fuji_width = (raw_width+1)/2; width = height + fuji_width; height = width - 1; pixel_aspect = 1; } d7379 1 a7379 1 load_raw = &CLASS adobe_dng_load_raw_nc; d7381 1 a7381 1 load_raw = &CLASS adobe_dng_load_raw_lj; d7386 1 a7386 1 &CLASS lossless_jpeg_load_raw : &CLASS canon_compressed_load_raw; a7403 1 load_raw = &CLASS foveon_load_raw; d7566 11 d7711 5 d7722 4 d7733 6 d7748 5 a7755 4 goto canon_cr2; } else if (is_canon && raw_width == 5108) { top_margin = 13; left_margin = 98; d7759 5 a7763 5 } else if (is_canon && raw_width == 5712) { height = 3752; width = 5640; top_margin = 20; left_margin = 62; d7781 5 a7785 1 } else if (!strcmp(model,"D5000")) { d7790 6 a7795 3 } else if (!strcmp(model,"D3100")) { width -= 28; left_margin = 6; a7799 2 } else if (!strcmp(model,"D90")) { width -= 42; d7925 1 a7925 1 strcpy (model+7," S2Pro"); d7937 1 a7937 1 if (!strcmp(model,"X10")) d7939 4 a7943 7 if (load_raw == &CLASS fuji_load_raw) { fuji_width = width >> !fuji_layout; width = (height >> fuji_layout) + fuji_width; raw_height = height; height = width - 1; if (~fuji_width & 1) filters = 0x49494949; } d7992 1 d8040 1 a8040 2 height = 3662; width = 5528; d8042 2 a8043 1 left_margin = 46; d8089 5 d8398 1 a8398 1 height = 242; d8557 6 d8595 10 d8616 2 a8617 1 if (load_raw == &CLASS kodak_jpeg_load_raw) { d8785 1 a8785 1 img[0] = img[FC(row,col)]; d9064 1 a9064 1 int arg, status=0; d9067 1 a9067 1 int use_fuji_rotate=1, write_to_stdout=0, quality, i, c; d9181 4 a9184 2 case 'D': case 'd': document_mode = 1 + (opt == 'D'); d9216 1 d9304 7 d9333 1 a9333 1 putchar (cdesc[fc(i >> 1,i & 1)]); d9358 4 d9369 7 a9375 1 (*load_raw)(); d9386 1 d9391 7 a9397 2 if (is_foveon && !document_mode) foveon_interpolate(); if (!is_foveon && document_mode < 2) scale_colors(); d9402 1 a9402 1 else if (quality == 1 || colors > 3) @ 1.446 log @Support the Canon S100, Nikon 1 J1 and V1, Panasonic GX1, Fuji X10, and Samsung NX200 with color matrices from DNG Converter 6.6. @ text @d7002 1 d8343 5 @ 1.445 log @Copied new color matrices from DNG Converter 6.5. @ text @d26 1 a26 1 #define DCRAW_VERSION "9.11" d3837 2 a3838 1 if ((mix_green = four_color_rgb)) colors++; d6284 2 d6378 2 d6550 2 d6670 1 a6670 1 { "Panasonic DMC-FZ40", 143, 0, d6708 2 d6730 2 d6750 3 a6752 1 { "SAMSUNG NX1", 0, 0, d6808 2 d7522 5 d7641 2 d7755 2 d7858 6 @ 1.444 log @Support ARRIRAW and Redcode R3D raw formats (video only). Support the Leica D-LUX 5 and V-LUX 2, Panasonic G3 and GF3, Olympus E-P3, Sony NEX-C3 and SLT-A35, and Canon SX30. Updated support for Nikon encrypted WB and Canon sRAW/mRAW. @ text @d3 1 a3 1 Copyright 1997-2010 by Dave Coffin, dcoffin a cybercom o net d26 1 a26 1 #define DCRAW_VERSION "9.10" d2497 1 a2497 1 for (dp=data, col=0; col < width-30; dp+=16) { d2512 1 a2512 1 BAYER(row,col) = curve[pix[i] << 1] >> 2; d4445 1 d6371 2 d6543 2 d6593 2 a6594 2 { "OLYMPUS E-P3", 0, 0, /* DJC */ { 7488,-3021,-55,-2377,8348,4029,-816,2405,6327 } }, d6601 4 d6699 2 d6709 2 a6710 2 { "Panasonic DMC-G3", 143, 0xfff, /* DJC */ { 6460,-2578,-366,-2786,8728,4059,-1073,2525,6254 } }, d6715 2 a6716 2 { "Panasonic DMC-GF3", 143, 0xfff, /* DJC */ { 8407,-3261,-502,-3997,10651,3347,-1095,2742,7294 } }, d6723 2 d6731 2 d6734 1 a6734 1 { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, d6783 4 d6791 3 a6793 3 { "SONY NEX-C3", 128, 0, /* DJC */ { 5171,-1786,-46,-3375,9315,4061,-611,1865,6473 } }, { "SONY NEX", 128, 0, /* Adobe's matrix */ d6797 2 a6798 2 { "SONY SLT-A35", 128, 0, /* DJC */ { 4504,-1495,115,-3507,9101,4407,-669,1844,6806 } }, d6801 4 d7197 1 a7197 1 if (!strcmp(model,"K-r") || !strcmp(model,"K-x")) d7199 1 a7199 1 if (!strcmp(model,"K-5")) d7201 1 a7201 1 if (!strcmp(model,"K-7")) d7203 1 a7203 1 if (!strcmp(model,"645D")) d8091 2 @ 1.443 log @Support the Fuji HS20EXR/F550EXR, Kodak Z990, Leaf AFi-II 12, Nikon D5100, and Samsung NX11 and NX100. @ text @d26 1 a26 1 #define VERSION "9.08" d44 9 a52 4 /* NO_JPEG disables decoding of compressed Kodak DC120 files. NO_LCMS disables the "-p" option. */ d54 1 a54 1 #include d57 1 a57 1 #include d65 1 d101 6 a106 3 #define ushort UshORt typedef unsigned char uchar; typedef unsigned short ushort; d976 1 a976 1 if (unique_id == 0x80000218 && ver > 1000006 && ver < 3000000) d1001 1 a1001 1 pix[0] = rp[0] + (( 200*rp[1] + 22929*rp[2]) >> 14); d1784 1 a1784 1 i = (col ^ (bite == 24)) - left_margin; d2659 52 d4439 1 a4439 1 short sorder=order; d4494 1 d4496 1 a4607 1 type = order; a4610 1 order = type; d4616 1 a4616 1 if (tag == 0xa7 && (unsigned) (ver97-200) < 12 && !cam_mul[0]) { d4622 1 a4622 1 i = "66666>666;6A"[ver97-200] - '0'; a4636 1 type = order; a4645 1 order = type; d4982 1 a4982 1 load_flags = 16 | (get4() && (filters=0x16161616)) << 3; d5437 1 a5437 1 load_flags = 17; d5453 1 a5453 1 load_flags = 15; d6034 29 d6588 2 d6684 2 d6688 2 d6698 2 d6704 2 d6720 2 d6772 2 d6778 2 d6944 1 d7101 19 d7378 11 d8025 1 d8347 7 d8356 2 a8357 1 fprintf (stderr,_("%s: You must link dcraw with libjpeg!!\n"), ifname); d8721 1 a8721 1 strcpy (th->soft, "dcraw v"VERSION); d8824 1 a8824 1 printf(_("\nRaw photo decoder \"dcraw\" v%s"), VERSION); d9037 2 a9038 2 shrink = filters && (half_size || ((threshold || aber[0] != 1 || aber[2] != 1) && !identify_only)); @ 1.442 log @Support the Hasselblad 9044x6732 back, Leaf 1068x1464 back, Fuji X100, and Canon 600D and 1100D. @ text @d26 1 a26 1 #define VERSION "9.07" d900 2 d4411 1 a4411 2 } else if (!strncmp (buf,"FUJIFILM",8) || !strncmp (buf,"SONY",4) || d4413 4 a4416 1 order = 0x4949; d4436 1 a4436 1 if (tag == 2 && strstr(make,"NIKON")) d4746 2 a4747 1 "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7" }; d4797 2 d4920 5 d5829 1 a5829 1 raw_height = order; d5833 1 a5833 4 order = raw_height; raw_height = 1; load_raw = &CLASS packed_load_raw; load_flags = 16; a5836 5 if (!raw_height) { filters = 0x16161616; load_raw = &CLASS packed_load_raw; load_flags = 24; } d6124 2 a6125 2 { "Canon EOS 600D", 0, 0x3510, /* DJC */ { 5589,-1476,-292,-3401,9372,4030,-706,2038,6350 } }, d6128 2 a6129 2 { "Canon EOS 1100D", 0, 0x3510, /* DJC */ { 5193,-1423,-226,-3414,9273,4142,-679,2103,6808 } }, d6241 1 a6241 1 { 0 } }, d6278 6 d6334 2 d6406 2 d6500 2 d6504 2 d6520 2 d6624 1 a6624 1 { "SAMSUNG NX10", 0, 0, d6642 2 d6949 1 d6953 1 d6966 1 a6966 1 fseek (ifp, 100, SEEK_SET); d7428 2 a7429 1 } else if (!strcmp(model,"D7000")) { d7461 2 d7568 1 a7568 3 maximum = 0x3e00; if (is_raw == 2 && shot_select) maximum = 0x2f00; d7571 5 a7575 3 if (is_raw == 2) data_offset += (shot_select > 0) * ( fuji_layout ? (raw_width *= 2) : raw_height*raw_width*2 ); d7672 2 a7673 2 } else if (!strcmp(model,"NX10")) { height -= top_margin = 4; d7982 1 a7982 1 data_offset = 0x15000; d8076 2 a8077 1 } else if (!strcmp(model,"QuickTake 100")) { a8086 8 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; @ 1.441 log @Support high-ISO images from the Samsung WB2000. @ text @d26 1 a26 1 #define VERSION "9.06" d1649 1 a1649 1 pred[0] = pred[1] = 0x8000; d5814 11 a5825 2 if (tag == 0x2ff0) FORC4 cam_mul[c ^ 1] = get2(); d6120 2 d6124 2 d6570 1 a6570 1 { "LEICA D-LUX4", 15, 0, d6632 2 d7332 6 d7363 2 d7544 2 a7545 2 top_margin = (raw_height - height)/2; left_margin = (raw_width - width )/2; d7770 7 d7799 1 a7799 1 if (tiff_samples > 1 || tile_length < raw_height) d7801 2 @ 1.440 log @Read correct camera WB from Nikon NRW and Samsung SRW files. Copied color matrices from Adobe DNG Converter 6.3. @ text @d4936 1 a4936 1 if (!tiff_ifd[ifd].bps) { d7628 1 a7628 1 height = 2760; d7631 2 a7632 2 height = 2750; width = 3668; a7637 1 width -= 10; d7639 5 @ 1.439 log @Support the Nikon D3100 & D7000 & P7000, Panasonic FZ40 & FZ100 & LX5, Samsung WB2000, Nokia X2, Canon SX120 & PowerShot G12, Hasselblad H4D, Pentax 645D & K-5 & K-r, Sony SLT-A33 & SLT-A55V. @ text @d26 1 a26 1 #define VERSION "9.05" d60 1 a60 1 #ifdef DJGPP d1551 7 a1557 6 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); } d1743 1 d1776 1 a1776 1 else if (load_flags & 32) d1778 2 d1787 2 d4422 5 a4426 2 else fseek (ifp, -10, SEEK_CUR); d4474 12 a4485 3 if (tag == 0x14 && len == 2560 && type == 7) { fseek (ifp, 1248, SEEK_CUR); goto get2_256; d4632 4 d4664 1 d6142 1 a6142 1 { 0 } }, d6175 2 d6201 2 d6365 2 d6385 2 a6386 2 { "NIKON D7000", 0, 0, /* DJC */ { 6629,-2254,-2,-3468,9387,4081,-760,2102,7574 } }, d6423 2 d6463 2 a6464 2 { "OLYMPUS E-5", 0, 0, /* DJC */ { 10033,-4067,-600,-3784,10494,3291,-923,2594,7744 } }, d6513 4 a6516 4 { "PENTAX K-r", 0, 0, /* Pentax DNG */ { 21746,-6684,-1521,-10014,26601,6573,-1920,3062,19415 } }, { "PENTAX K-5", 0, 0, /* Pentax DNG */ { 19331,-5842,-2589,-9103,28027,4285,-2216,3884,14767 } }, d6573 2 d6577 2 d6591 1 a6591 1 { "SAMSUNG NX10", 20, 0xea6, d6594 1 a6594 1 { 0 } }, d6621 2 d7625 1 d8120 1 a8120 1 } else if (!strcmp(model,"EX-Z1050")) { a8123 1 maximum = 0xffc; d8162 1 a8162 1 strcpy (cdesc, colors == 3 ? "RGB":"GMCY"); d8522 1 a8522 1 t = gmtime (×tamp); a8859 1 if (!cdesc[3]) cdesc[3] = 'G'; @ 1.438 log @Fixed rotation for Kodak EasyShare and some Canon EOS photos. @ text @d26 1 a26 1 #define VERSION "9.04" d1076 2 a1077 2 ushort bit[2][13], huff[4097]; int row, col, diff, c, i; d1081 5 a1085 3 FORC(13) bit[0][c] = get2(); FORC(13) bit[1][c] = fgetc(ifp); FORC(13) d1096 4 a1099 3 if ((unsigned) (row-top_margin) < height && col < width) BAYER(row-top_margin,col) = hpred[col & 1]; if (hpred[col & 1] >> 12) derror(); d1807 1 a1807 1 int dwide, row, c; d1809 1 d1815 2 a1816 1 if (fread (data, 1, dwide, ifp) < dwide) derror(); d4522 7 d4549 2 a4550 2 if (tag == 0x220 && len == 53) meta_offset = ftell(ifp) + 14; d4852 4 d6074 2 d6118 2 d6232 2 a6233 2 { "FUJIFILM FinePix HS10 HS11", 0, 0xf68, /* DJC */ { 12164,-3169,-1662,-1020,10358,662,-224,2108,3106 } }, d6356 2 d6374 2 d6432 2 d6482 4 d6488 2 d6494 1 a6494 1 { "Panasonic DMC-FZ28", 15, 0xfff, d6498 1 a6498 1 { "Panasonic DMC-FZ35", 147, 0xfff, d6500 5 a6504 1 { "Panasonic DMC-FZ50", 0, 0xfff, /* aka "LEICA V-LUX1" */ d6508 1 a6508 1 { "Panasonic DMC-L1", 0, 0x3dff, /* aka "LEICA DIGILUX 3" */ d6510 5 a6514 1 { "Panasonic DMC-LC1", 0, 0, /* aka "LEICA DIGILUX 2" */ d6516 3 a6518 1 { "Panasonic DMC-LX1", 0, 0x3dfc, /* aka "LEICA D-LUX2" */ d6520 1 a6520 1 { "Panasonic DMC-LX2", 0, 0, /* aka "LEICA D-LUX3" */ d6522 5 a6526 1 { "Panasonic DMC-LX3", 15, 0xfff, /* aka "LEICA D-LUX4" */ d6528 4 d6536 1 a6536 1 { "Panasonic DMC-G1", 15, 0xfff, d6554 6 d6562 1 a6562 1 { "SAMSUNG S85", 0, 0, /* DJC */ d6598 6 d6696 24 d6764 1 d6908 12 d6972 11 a6982 5 if (height == 3136 && width == 4864) /* Pentax K20D */ { height = 3124; width = 4688; } if (height == 3136 && width == 4736) /* Pentax K-7 */ { height = 3122; width = 4684; top_margin = 2; filters = 0x16161616; } d7157 11 d7241 4 d7344 5 d7373 1 a7373 1 } else if (!strcmp(model,"COOLPIX P6000")) { a7546 5 } else if (!strcmp(model,"K20D")) { filters = 0x16161616; } else if (!strcmp(model,"K-x")) { width = 4309; filters = 0x16161616; a7584 1 maximum = 0xffff; d7597 5 a7601 1 maximum = 0x3e00; d7699 6 d7762 1 a7762 1 if ((flen - data_offset) / (width*8/7) == height) d7769 10 a7778 96 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; } adobe_coeff ("Panasonic","DMC-FZ8"); break; case 3213: width -= 27; case 3177: width -= 10; load_flags = 2; filters = 0x49494949; adobe_coeff ("Panasonic","DMC-L1"); break; case 3304: width -= 17; adobe_coeff ("Panasonic","DMC-FZ30"); break; case 3330: width += 43; left_margin = -6; maximum = 0xf7f; case 3370: width -= 82; left_margin += 15; if (height > 2480) height = 2480 - (top_margin = 10); filters = 0x49494949; 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; 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; load_flags = 2; adobe_coeff ("Panasonic","DMC-LX1"); break; case 4060: width = 3982; if (height == 2250) goto lx3; width = 4018; filters = 0x16161616; if (!strncmp(model,"DMC-FZ3",7)) { height -= 2; adobe_coeff ("Panasonic","DMC-FZ35"); break; } filters = 0x49494949; break; case 4172: case 4396: 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; } @ 1.437 log @Support the Canon SX20 IS. Get Fuji HS10 black level from the metadata. @ text @d26 1 a26 1 #define VERSION "9.03" d4448 6 d4639 1 a4639 1 kodak = !strncmp(make,"EASTMAN",7); d4813 1 d4894 1 a4894 1 case 513: d4907 3 d5264 1 a5264 1 void CLASS parse_tiff (int base) d5266 1 a5266 2 int doff, max_samp=0, raw=-1, thm=-1, i; struct jhead jh; d5270 1 a5270 1 if (order != 0x4949 && order != 0x4d4d) return; a5271 2 memset (tiff_ifd, 0, sizeof tiff_ifd); tiff_nifds = 0; d5276 8 d5310 2 a5311 2 fuji_width *= (raw_width+1)/2; if (tiff_ifd[0].flip) tiff_flip = tiff_ifd[0].flip; d5809 1 a5809 1 parse_tiff (save+6); d6671 1 a6671 1 { 10341600, "Canon", "PowerShot A720" ,0 }, d6729 2 d6761 1 a6761 1 if (cp-head) parse_tiff(0); d6766 1 a6766 3 } else { parse_tiff(0); } d6806 1 d6866 1 d6998 1 a6998 1 } else if (!strcmp(model,"PowerShot A720")) { @ 1.436 log @Support the Samsung EX1. @ text @d26 1 a26 1 #define VERSION "9.02" d4894 1 a4894 1 tiff_ifd[ifd].width = jh.wide << (jh.clrs == 2); d4898 2 d5144 2 d6197 2 a6198 2 { "FUJIFILM FinePix HS10 HS11", 79, 0xf68, /* DJC */ { 12123,-3090,-1806,-1486,10894,593,-683,2369,3114 } }, d6663 1 d7035 10 d7153 1 a7153 1 } else if (is_canon && raw_width == 1208) { a7155 1 raw_width = width *= 4; d7159 1 a7159 1 } else if (is_canon && raw_width == 1280) { a7161 1 raw_width *= 4; d7163 1 a7163 1 } else if (is_canon && raw_width == 1336) { a7165 1 raw_width = width *= 4; d7169 1 a7169 1 } else if (is_canon && raw_width == 1340) { a7171 1 raw_width = width *= 4; d7173 1 a7173 1 } else if (is_canon && raw_width == 1448) { a7175 1 raw_width = width *= 4; @ 1.435 log @Support the Sony A450, Kodak Z981, Olympus E-P2, and Panasonic G2 & GF1. @ text @d7442 10 @ 1.434 log @Built color matrices for the Sony NEX-3 and NEX-5. @ text @d26 1 a26 1 #define VERSION "9.01" d4774 1 a4774 1 static const int wbtag[]={ 0xfa25,0xfa28,0xfa27,0xfa29,-1,-1,0xfa2a }; d4797 1 a4797 1 if (tag == 0xfa0d) wbi = fgetc(ifp); d4800 2 d5155 6 d6389 3 a6391 1 { "OLYMPUS E-620", 0, 0xfb9, d6395 2 d6469 1 a6469 1 { "Panasonic DMC-G2", 0, 0, d6509 3 a6511 1 { "SONY DSLR-A5", 126, 0, d7602 1 a7615 1 zero_is_bad = 1; a7622 1 zero_is_bad = 1; a7625 1 zero_is_bad = 1; a7636 1 zero_is_bad = 1; a7647 1 zero_is_bad = 1; a7665 1 zero_is_bad = 1; d7677 1 a7677 3 if (!strcmp(model,"DMC-GH1")) break; zero_is_bad = 1; adobe_coeff ("Panasonic","DMC-G1"); break; d7800 1 a7800 8 } else if (!strcmp(model,"EASYSHARE Z1015 IS")) { height = 2742; width = 3664; goto ezshare; } else if (!strcmp(model,"EasyShare Z980")) { height = 3006; width = 4016; ezshare: d8720 2 a8721 2 shrink = filters && (half_size || threshold || aber[0] != 1 || aber[2] != 1); @ 1.433 log @Support the Samsung WB550 and NX10, Casio EX-Z1050, and Fuji HS10. Support the Canon EOS 550D / Digital Rebel T2i / Kiss Digital X4. Support A100 images modified by Sony software. Split the darkness level into four separate color channels. @ text @d26 1 a26 1 #define VERSION "9.00" d3842 1 a3842 1 described in http://scien.stanford.edu/class/psych221/projects/99/tingchen/algodep/vargra.html d6505 4 @ 1.432 log @Support the Canon EOS-1D Mark IV and PowerShots G11 and S90. Support the Casio EX-Z750, Pentax K-x, Fuji S200EXR, Sony A550. @ text @d3 1 a3 1 Copyright 1997-2009 by Dave Coffin, dcoffin a cybercom o net d26 1 a26 1 #define VERSION "8.99" d117 1 a117 1 unsigned black, maximum, mix_green, raw_color, zero_is_bad; d170 1 a170 1 #define SWAP(a,b) { a ^= b; a ^= (b ^= a); } a349 14 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; } d702 1 a702 1 int nblocks, lowbits, i, c, row, r, col, save, val, nblack=0; a704 1 double dark[2] = { 0,0 }; d757 1 d761 1 a761 1 dark[icol & 1] += (nblack++,pixel[r*raw_width+col]); d767 1 a767 1 canon_black (dark, nblack); d890 1 a890 2 int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0, nblack=0; double dark[2] = { 0,0 }; d916 1 d921 1 a921 1 dark[(col-left_margin) & 1] += (nblack++,val); d928 1 a928 1 canon_black (dark, nblack); d1770 1 a1770 1 BAYER(row,i) = val << (load_flags >> 6); d1795 1 a1795 1 if ((BAYER2(row,col) = pixel[col]) >> bits) derror(); d2490 1 a2490 1 BAYER(row,col) = curve[pix[i] << 1] >> 1; d3381 2 d3557 1 a3557 1 int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast; d3567 1 d3602 1 a3602 1 for (row=0; row < 2; row++) d3604 2 d3618 2 a3619 2 window[2][col-1] + window[2][col+1] - black*4 ) * mul[row & 1] + (window[1][col] - black) * 0.5 + black; d3640 1 d3659 1 a3659 1 if ((val -= black) < 0) val = 0; d3674 1 a3674 1 if ((val = white[row][col] - black) > 0) d3708 1 a3708 1 val -= black; d4528 1 a4528 1 black = (get2()+get2()+get2()+get2())/4; d4533 2 a4534 3 if (tag == 0x401 && type == 4 && len == 4) { black = (get4()+get4()+get4()+get4())/4; } d4565 1 a4565 2 for (black = i=0; i < 4; i++) black += get2() << 2; d4585 1 a4585 1 fseek (ifp, get4(), SEEK_SET); d4810 1 d4813 1 a4813 1 double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num; d4851 4 a4854 1 case 2: case 256: /* ImageWidth */ d4857 1 a4857 1 case 3: case 257: /* ImageHeight */ d4861 1 d4863 1 a4863 1 tiff_ifd[ifd].bps = get2(); d4886 1 d4907 1 d4910 3 d4976 3 a4978 1 FORC4 cam_mul[c ^ (c >> 1)] = get2(); d5136 4 d5141 11 a5151 5 case 50715: /* BlackLevelDeltaH */ case 50716: /* BlackLevelDeltaV */ for (dblack=i=0; i < len; i++) dblack += getreal(type); black += dblack/len + 0.5; a5298 1 maximum = 0xffff; d5300 1 a5300 1 load_flags = 273; d5316 1 a5316 1 load_flags = 79; d5319 1 d5753 5 d6041 2 d6149 2 d6161 1 a6161 1 { "FUJIFILM FinePix S5100", 0, 0x3e00, d6163 1 a6163 1 { "FUJIFILM FinePix S5500", 0, 0x3e00, d6185 2 d6235 2 d6353 1 a6353 1 { "OLYMPUS E-10", 0, 0xffc0, d6355 1 a6355 1 { "OLYMPUS E-1", 0, 0xfff0, d6357 1 a6357 1 { "OLYMPUS E-20", 0, 0xffc0, d6367 1 a6367 1 { "OLYMPUS E-400", 0, 0xfff0, d6375 1 a6375 1 { "OLYMPUS E-500", 0, 0xfff0, d6385 2 d6427 1 a6427 1 { "Panasonic DMC-FZ8", 0, 0xf7f0, d6433 1 a6433 1 { "Panasonic DMC-FZ30", 0, 0xf94c, d6437 1 a6437 1 { "Panasonic DMC-FZ50", 0, 0xfff0, /* aka "LEICA V-LUX1" */ d6441 1 a6441 1 { "Panasonic DMC-L1", 0, 0xf7fc, /* aka "LEICA DIGILUX 3" */ d6445 1 a6445 1 { "Panasonic DMC-LX1", 0, 0xf7f0, /* aka "LEICA D-LUX2" */ d6453 2 d6457 2 d6471 2 a6472 2 { "Phase One P65", 0, 0, /* DJC */ { 8522,1268,-1916,-7706,16350,1358,-2397,4344,4923 } }, d6487 1 a6487 3 { "SONY DSLR-A200", 0, 0, { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } }, { "SONY DSLR-A230", 0, 0, /* copied */ d6497 1 a6497 1 { "SONY DSLR-A5", 254, 0x1ffe, d6499 1 a6499 1 { "SONY DSLR-A700", 254, 0x1ffe, d6501 1 a6501 1 { "SONY DSLR-A850", 256, 0x1ffe, d6503 1 a6503 1 { "SONY DSLR-A900", 254, 0x1ffe, d6595 1 a6595 1 int hlen, fsize, i, c, is_canon; d6619 1 d6621 1 d6665 1 d6676 2 d6692 1 d6717 1 a6717 1 fsize = ftell(ifp); d6725 1 a6725 1 parse_ciff (hlen, fsize - hlen); d6766 1 a6766 1 data_offset = get4(); d6793 1 a6793 1 for (i=0; i < sizeof table / sizeof *table; i++) d6800 2 a6801 1 if (make[0] == 0) parse_smal (0, fsize); d7132 7 d7270 2 a7271 2 i = find_green (12, 32, 0, fsize/2); c = find_green (12, 32, 0, 3096); d7310 1 a7310 1 } else d7421 16 d7468 1 d7578 1 a7578 2 maximum = 0xfff0; if ((fsize-data_offset) / (width*8/7) == height) d7580 4 a7583 1 if (!load_raw) load_raw = &CLASS unpacked_load_raw; d7603 1 d7614 1 a7614 1 maximum = 0xf7f0; d7651 1 d7698 5 a7702 8 if (load_raw == &CLASS olympus_load_raw) { tiff_bps = 12; 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")) { d7705 2 a7706 2 maximum = 0xfc30; black = 0; d7711 1 a7711 1 maximum = 0xf790; d7713 1 a7713 1 thumb_length = fsize - (thumb_offset = 0xa39800); d7741 7 a7747 2 height--; width = ++raw_width; d7838 1 a7838 1 if (fsize < 100000) { d7998 5 d8045 2 a8046 6 for (i=0; i < 32; i+=4) { if ((filters >> i & 15) == 9) filters |= 2 << i; if ((filters >> i & 15) == 6) filters |= 8 << i; } d8779 4 @ 1.431 log @Ignore the first data error in a Pentax *ist D file. @ text @d26 1 a26 1 #define VERSION "8.98" d997 1 a997 1 if (unique_id < 0x80000200) { d4541 1 a4541 1 if (tag == 0x401 && len == 4) { d4783 1 a4783 1 float mul[3], num; d5158 1 d5297 4 a5304 4 if (tiff_bps == 8) { tiff_bps = 12; load_raw = &CLASS sony_arw2_load_raw; break; } d5732 1 a5732 1 } else if (tag == 0x130) d5734 3 d6000 2 a6001 2 { "Canon EOS 7D", 0, 0x3510, /* DJC */ { 7956,-1490,-850,-2896,10428,2469,-827,1800,5680 } }, d6030 4 a6035 2 { "Canon EOS-1D Mark III", 0, 0x3bb0, { 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } }, d6053 1 a6053 1 { 0 } }, /* don't want the G1 matrix */ d6084 2 d6108 2 d6270 2 d6396 2 d6468 2 d6473 1 a6473 1 { 5209,-1072,-397,-8845,16121,2919,-1618,1802,8654 } }, d6632 1 d7091 5 d7130 1 a7260 3 } else if (!strcmp(model,"FinePix S5100") || !strcmp(model,"FinePix S5500")) { load_raw = &CLASS unpacked_load_raw; d7276 7 a7282 6 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; d7336 3 d7920 5 @ 1.430 log @Support the Sony DSLR-A850. @ text @d273 1 a273 1 data_error = 1; d7309 2 @ 1.429 log @Support the Canon EOS 7D and the Casio EX-Z850. @ text @d6414 3 a6416 1 { "Panasonic DMC-GH1", 15, 0xfff, d6452 2 a6453 2 { "SONY DSLR-A380", 0, 0, /* copied */ { 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } }, d6456 2 @ 1.428 log @Correctly crop Nikon D300S photos. @ text @d26 1 a26 1 #define VERSION "8.97" d5996 2 d6612 1 d7070 5 d7891 6 @ 1.427 log @Support the Canon A470, G11, Nikon D3000, and Panasonic FZ35/FZ38. Support camera WB for the Kodak EasyShare Z980 and Z1015. @ text @d7123 1 a7123 1 } else if (!strcmp(model,"D300")) { @ 1.426 log @Decode all packed 10-bit and 12-bit formats in one function. Support the Casio Z60, Casio Z75, Kodak Z980, and Pentax K-7. Support the Olympus X200,D560Z,C350Z with or without JPEG files. Copied color matrices from Adobe DNG Converter 5.4. @ text @d26 1 a26 1 #define VERSION "8.96" d1088 1 a1088 1 void CLASS pentax_k10_load_raw() a1270 17 /* 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); } } d1752 1 a1752 1 int vbits=0, bwide, pwide, rbits, bite, irow, row, col, val, i; d1762 1 d1766 1 a1766 1 (row = irow * 2 % height + irow / (height/2)) == 1 && d1769 1 a1769 1 fseek (ifp, data_offset - (-width*height*3/4 & -2048), SEEK_SET); d1772 1 a1772 1 fseek (ifp, ftell(ifp)/2, SEEK_SET); d1877 1 a1877 1 void CLASS olympus_e410_load_raw() d4589 1 a4589 1 load_raw = &CLASS olympus_e410_load_raw; d4784 1 d4807 3 d4993 1 d5312 1 a5312 1 load_raw = &CLASS pentax_k10_load_raw; break; d6036 2 d6044 2 d6076 2 d6252 2 d6324 1 a6324 1 { "OLYMPUS E-30", 0, 0, d6344 2 d6392 2 d6464 5 a6468 3 for (j=0; j < 12; j++) cam_xyz[0][j] = table[i].trans[j] / 10000.0; cam_xyz_coeff (cam_xyz); d6512 1 a6512 1 float CLASS find_green (int off0, int off1) d6515 1 a6515 1 int vbits, bite, col, i, c; a6518 1 bite = 8 + (load_flags & 24); d6522 1 a6522 1 for (vbits -= 12; vbits < 0; vbits += bite) { d6527 1 a6527 1 img[c][col] = bitbuf << (52-vbits) >> 52; a6560 1 { 614400, "Kodak", "KAI-0340" ,0 }, d6580 1 d6748 2 a6749 1 ((cp = strcasestr(model," DIGITAL CAMERA")) || a6871 1 raw_color = 0; d6890 8 d7010 5 d7091 2 a7092 1 !strcmp(model,"D80")) { a7131 1 load_raw = &CLASS nikon_e900_load_raw; d7139 1 a7143 1 load_raw = &CLASS nikon_e900_load_raw; d7147 4 d7192 2 a7193 2 i = find_green (0, fsize/2); c = find_green (0, 3096); a7346 6 } else if (!strcmp(model,"KAI-0340")) { height = 477; width = 640; order = 0x4949; data_offset = 3840; load_raw = &CLASS unpacked_load_raw; d7556 5 a7560 1 if (!strcmp(model,"DMC-GH1")) goto gh1; d7562 1 d7568 1 a7568 1 gh1: filters = 0x49494949; d7596 2 a7597 1 if (load_raw == &CLASS olympus_e410_load_raw) { d7654 6 a7659 1 goto c603v; @ 1.425 log @Support the Phase One P45+. @ text @d26 1 a26 1 #define VERSION "8.95" a548 23 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(); } d1103 1 a1103 1 for (row=0; row < height; row++) d1108 2 a1109 2 if (col < width) BAYER(row,col) = hpred[col & 1]; d1767 1 a1767 1 void CLASS packed_12_load_raw() d1769 1 a1769 1 int vbits=0, rbits=0, bwide, bite, irow, row, col, val, i; d1772 4 a1775 5 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; d1791 2 a1792 2 for (col=0; col < raw_width; col++) { for (vbits -= 12; vbits < 0; vbits += bite) { d1797 1 a1797 1 val = bitbuf << (52-vbits) >> 52; d1808 2 a1809 2 if (load_flags & 32 && raw_width > width) black /= (raw_width - width) * height; a1964 20 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; } d4454 8 d5202 1 a5202 1 load_raw = &CLASS packed_12_load_raw; d5288 1 a5288 1 case 12: load_raw = &CLASS packed_12_load_raw; d5296 3 a5298 1 load_raw = &CLASS packed_12_load_raw; d5319 1 a5319 1 load_raw = &CLASS packed_12_load_raw; break; d5983 1 a5983 1 Thanks to Adobe for providing these excellent CAM -> XYZ matrices! d6027 2 d6097 2 a6098 2 { "Canon PowerShot SX1 IS", 0, 0, /* DJC */ { 10013,-2214,-1111,-3650,11589,2062,342,685,3617 } }, d6203 4 d6251 2 d6257 6 d6267 2 a6280 8 { "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 } }, d6337 3 a6339 1 { "OLYMPUS E-500", 0, 0, d6345 2 d6383 2 d6411 2 a6412 2 { "Panasonic DMC-GH1", 15, 0xfff, /* DJC */ { 7808,-2387,-480,-2859,10002,2857,-1001,2012,4915 } }, d6439 2 d6443 2 d6447 2 d6509 26 d6542 1 a6542 1 unsigned hlen, fsize, i, c, is_canon; d6606 2 a6648 1 tiff_bps = 12; d6746 1 a6746 1 ((cp = strstr(model,"DIGITAL CAMERA")) || a6760 1 if (!maximum) maximum = (1 << tiff_bps) - 1; d6772 3 d6792 1 a6792 1 load_raw = &CLASS packed_12_load_raw; d6797 1 a6797 1 load_raw = &CLASS packed_12_load_raw; d6832 1 a6832 1 load_raw = &CLASS canon_a5_load_raw; d6839 1 a6839 1 load_raw = &CLASS canon_a5_load_raw; d6845 1 a6845 1 load_raw = &CLASS canon_a5_load_raw; d6853 1 a6853 1 load_raw = &CLASS canon_a5_load_raw; d6861 1 a6861 1 load_raw = &CLASS canon_a5_load_raw; a6868 1 load_raw = &CLASS canon_a5_load_raw; d6870 1 d6879 1 a6879 1 load_raw = &CLASS canon_a5_load_raw; d6887 1 a6887 1 load_raw = &CLASS canon_a5_load_raw; d6895 1 a6895 1 load_raw = &CLASS canon_a5_load_raw; d6903 1 a6903 1 load_raw = &CLASS canon_a5_load_raw; d6911 1 a6911 1 load_raw = &CLASS canon_a5_load_raw; d6919 1 a6919 1 load_raw = &CLASS canon_a5_load_raw; d6927 5 a6931 1 load_raw = &CLASS canon_a5_load_raw; d6939 1 a6939 1 load_raw = &CLASS packed_12_load_raw; d7049 2 d7083 2 d7093 1 a7093 1 load_raw = &CLASS packed_12_load_raw; d7137 1 a7137 1 load_raw = &CLASS packed_12_load_raw; d7163 1 a7163 1 load_raw = &CLASS packed_12_load_raw; d7172 9 d7189 1 a7189 1 load_raw = &CLASS packed_12_load_raw; d7205 1 a7205 1 load_raw = &CLASS packed_12_load_raw; d7250 2 a7251 1 load_raw = &CLASS packed_12_load_raw; d7257 1 a7257 1 load_raw = &CLASS packed_12_load_raw; d7293 1 a7293 1 load_raw = &CLASS packed_12_load_raw; d7300 1 a7300 1 load_raw = &CLASS packed_12_load_raw; d7305 1 a7305 1 load_raw = &CLASS packed_12_load_raw; a7539 1 if (!strcmp(model,"DMC-GH1")) goto gh1; d7543 1 d7549 2 a7550 2 gh1: width -= 28; filters = 0x49494949; d7572 1 a7572 1 load_raw = &CLASS packed_12_load_raw; d7604 1 a7604 1 load_raw = &CLASS packed_12_load_raw; d7624 2 d7664 5 d7670 1 a7670 1 load_raw = &CLASS packed_12_load_raw; d7821 2 a7822 1 load_raw = &CLASS casio_qv5700_load_raw; d7849 10 d7887 2 d8410 1 a8410 1 if ((cp = strchr (sp="nbrkStqmHACg", opt))) @ 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 d7351 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 d6386 2 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" d7383 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; d4479 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 d6253 2 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 d7838 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; d6045 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 3 a6117 4 if (width == 3880) { left_margin = 6; maximum = 0xf7f0; width -= 22; d6121 14 a6134 1 } 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 d5211 2 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 2 a3656 4 case 0x24: case 0x25: case 0x26: cam_mul[tag-0x24] = get2(); 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; r++) histogram[r][img[r] >> 3]++; d5565 3 d5569 1 d5648 1 a5648 1 int arg, status=0, user_flip=-1; d5662 1 a5662 1 "\nRaw Photo Decoder \"dcraw\" v7.53" d5675 1 d5698 1 a5698 1 if (strchr ("brlt", opt) && !isdigit(argv[arg][0])) { d5707 1 d5809 1 d5813 5 a5817 1 if ((trim = filters && !document_mode)) vng_interpolate(); @ 1.278 log @Added the Panasonic DMC-FZ30. @ text @d4183 2 d4802 3 a4804 5 } else if (!strcmp(model,"*ist D")) { load_raw = unpacked_load_raw; } else if (!strcmp(model,"*ist DS")) { height--; load_raw = packed_12_load_raw; d5505 1 a5505 1 "\nRaw Photo Decoder \"dcraw\" v7.52" @ 1.277 log @Added the Olympus C740UZ. @ text @d3301 3 a3303 1 camera_red = get4() / 256.0; d3305 4 a3308 2 case 0x12: camera_blue = get4() / 256.0; d3310 1 d3312 1 a3312 1 if (strcmp(make,"Canon") || level) d3315 1 d3317 1 a3317 1 if (strcmp(make,"Canon") || level) d4187 2 d4913 2 a4914 4 } else if (!strcmp(model,"DIGILUX 2") || !strcmp(model,"DMC-LC1")) { height = 1928; width = 2568; data_offset = 1024; d5505 1 a5505 1 "\nRaw Photo Decoder \"dcraw\" v7.51" @ 1.276 log @Added the Minolta RD175. @ text @d1008 3 a1010 1 Separates a Pentax Optio 33WR from a Nikon E3700. d1012 1 a1012 1 int CLASS pentax_optio33() d1021 2 a1022 1 return sum[0] < sum[1]*4; d4631 1 a4631 2 } else if (!strcmp(model,"E3700")) { if (!timestamp && pentax_optio33()) goto optio_33wr; d4637 11 a4647 11 } else if (!strcmp(model,"Optio 33WR")) { optio_33wr: strcpy (make, "PENTAX"); strcpy (model,"Optio 33WR"); height = 1542; width = 2064; load_raw = nikon_e2100_load_raw; flip = 1; filters = 0x16161616; pre_mul[0] = 1.331; pre_mul[2] = 1.820; d5210 1 a5210 2 for (i=0; i < 3; i++) coeff[i][3] = coeff[i][1] /= 2; d5499 1 a5499 1 "\nRaw Photo Decoder \"dcraw\" v7.50" @ 1.275 log @Added the Olympus C770UZ. @ text @d1347 28 d4251 1 d4725 6 d4837 1 a4837 1 height = 1210; d5498 1 a5498 1 "\nRaw Photo Decoder \"dcraw\" v7.49" @ 1.274 log @Fixed the Kodak NC2000F, and improved the Minolta DYNAX 5D. Correctly flip NEF files that Nikon Capture has modified. @ text @d4231 1 d4895 5 d5463 1 a5463 1 "\nRaw Photo Decoder \"dcraw\" v7.48" @ 1.273 log @Support Adobe DNG version 1.1.0.0. @ text @d2714 5 a2718 5 for (col=cut[sq][2]; col < cut[sq][2]+cut[sq][0]; col++) FORCC if (image[row*width+col][c]) { gmb_cam[sq][c] += image[row*width+col][c]; count[c]++; } d3149 13 d4038 2 d4092 2 d4719 1 d4921 1 a4921 5 left_margin = 1; for (i=176; i < 0x1000; i++) curve[i] = curve[i-1]; pre_mul[0] = 1.509; pre_mul[2] = 2.686; d5457 1 a5457 1 "\nRaw Photo Decoder \"dcraw\" v7.46" @ 1.272 log @Added the Leaf Aptus 17. @ text @d94 1 a94 1 int is_dng, is_canon, is_foveon, use_coeff, use_gamma; d734 4 a737 1 diff = getbits (len = dindex->leaf); d814 1 a814 1 unsigned r=row, c=col; d816 2 d827 6 a832 5 } else for (c=0; c < tiff_samples; c++) { image[row*width+col][c] = **rp < 0x1000 ? curve[**rp] : **rp; (*rp)++; } a3238 1 ushort scale[4]; d3312 1 a3312 1 if (len > 2 && !is_dng && !strcmp(make,"Kodak")) d3349 1 a3349 1 is_dng = 1; d3386 5 a3390 3 for (i=0; i < 4; i++) scale[i] = get4(); if (scale[1]*scale[2] == 2*scale[0]*scale[3]) ymag = 2; d3412 6 d3448 1 a3448 1 if (!is_dng && !strncmp(make,"Kodak",5)) { d4250 1 a4250 1 zero_after_ff = is_dng = fuji_secondary = 0; d4280 1 a4280 1 if (!is_dng && !strncmp(make,"NIKON",5) && filters == UINT_MAX) d4374 1 a4374 1 ymag = 1; d4376 1 a4376 1 if (is_dng) { d5443 1 a5443 1 "\nRaw Photo Decoder \"dcraw\" v7.45" @ 1.271 log @Fixed gcc warning. @ text @d435 1 a435 1 static int vbits=0; d438 1 a438 1 if (nbits == 0) return 0; d442 1 a442 1 ret = bitbuf = vbits = 0; d447 1 a447 1 while (vbits < LONG_BIT - 7) { d449 1 a450 2 if (c == 0xff && zero_after_ff) fgetc(ifp); d683 1 a683 1 int bits, high, wide, clrs, vpred[4]; d696 1 d717 3 a723 2 for (i=0; i < 4; i++) jh->vpred[i] = 1 << (jh->bits-1); a724 1 getbits(-1); d740 1 a740 1 void CLASS ljpeg_row (struct jhead *jh) d745 4 d767 1 a767 1 ljpeg_row (&jh); d769 3 a771 1 val = curve[jh.row[jcol]]; d851 1 a851 1 ljpeg_row (&jh); d3223 2 d3329 3 d4827 2 d5430 1 a5430 1 "\nRaw Photo Decoder \"dcraw\" v7.43" @ 1.270 log @Fixed serious problems with the Imacon Ixpress. Moved most verbose messages out of main(). @ text @d226 1 a226 1 float CLASS get_float() d228 3 a230 2 int i = get4(); return *((float *) &i); d3631 1 a3631 1 flash_used = *((float *) &len); d3633 1 a3633 1 canon_5814 = *((float *) &len); d3752 1 a3752 1 FORC3 coeff[i][c] = get_float(); d3754 1 a3754 1 cam_mul[i] = pre_mul[i] = get_float(); @ 1.269 log @Various changes regarding headerless raw photos. Support the Nikon D50 with camera white balance. @ text @d2138 3 d2863 4 d3324 7 a3407 9 if (is_dng || level) return done; if ((raw_height & 1) && !strncmp (make,"OLYMPUS",7)) raw_height++; if (make[0] == 0 && raw_width == 680) strcpy (make, "Imacon"); d3802 1 a3802 1 void CLASS parse_jpeg (int offset) d3807 1 a3807 1 if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return; d3820 1 a3820 1 strcat (model," JPEG"); d4172 1 a4172 1 unsigned hlen, fsize, i, c; a4320 1 if (make[0] == 0) parse_jpeg(0); d4322 1 d4372 2 d4795 4 a4798 11 height = 5444; width = 4080; raw_width = 4090; data_offset = 314 + raw_width*12; flip = 5; if (raw_height == 680) { order = 0x4949; height = 4084; data_offset -= 10; flip = 3; } d5094 1 a5094 1 if (!load_raw || !height || strstr(model,"JPEG")) { d5096 2 a5097 2 fprintf (stderr, "%s: Cannot decode %s %s images.\n", ifname, make, model); d5176 4 d5254 4 d5368 1 a5368 1 for (row = trim; row < height-trim; row++) { a5372 1 } d5416 1 a5416 1 "\nRaw Photo Decoder \"dcraw\" v7.42" a5557 5 if (is_foveon) { if (verbose) fprintf (stderr, "Foveon interpolation...\n"); foveon_interpolate(); } else { d5559 1 a5559 1 colorcheck(); d5561 2 a5562 2 scale_colors(); } d5564 1 a5564 8 trim = 0; if (filters && !document_mode) { trim = 1; if (verbose) fprintf (stderr, "%s interpolation...\n", quick_interpolate ? "Bilinear":"VNG"); vng_interpolate(); } a5568 2 if (verbose) fprintf (stderr, "Converting to RGB colorspace...\n"); d5570 1 a5570 6 if (flip) { if (verbose) fprintf (stderr, "Flipping image %c:%c:%c...\n", flip & 1 ? 'H':'0', flip & 2 ? 'V':'0', flip & 4 ? 'T':'0'); flip_image(); } @ 1.268 log @Added AVT and ISG cameras. @ text @d3082 2 a3083 1 fscanf (ifp, "%d", &serial); d3104 1 a3104 1 fseek (ifp, 280, SEEK_CUR); d3114 2 a3115 1 FORC4 cam_mul[c ^ (c >> 1)] = sget2 (buf97+6+c*2); d4061 2 d4176 1 a4176 1 { 3840000, "Foculus", "503c" ,0 }, d4190 1 a4190 1 { 5865472, "NIKON", "E4500" ,0 }, d4192 3 a4194 3 { 1976352, "CASIO", "QV-2000UX" ,0 }, { 3217760, "CASIO", "QV-3*00EX" ,0 }, { 6218368, "CASIO", "QV-5700" ,0 }, d4196 2 a4197 2 { 7684000, "CASIO", "QV-4000" ,0 }, { 4948608, "CASIO", "EX-S100" ,0 }, d4744 1 a4744 1 } else if (!strcmp(model,"503c")) { d5020 1 a5020 1 } else if (!strcmp(model,"QV-3*00EX")) { d5046 2 d5409 1 a5409 1 "\nRaw Photo Decoder \"dcraw\" v7.40" @ 1.267 log @Added the Casio EX-S100, Pixelink 782c1, and RoverShot 3320af. @ text @d4137 19 d4173 7 a4201 2 { 13248000, "Pixelink", "782c1" ,0 }, { 6291456, "RoverShot","3320af" ,0 }, d4746 15 a4760 1 } else if (!strcmp(model,"782c1")) { d4764 1 a4764 1 load_raw = unpacked_load_raw; d4766 1 a4766 1 } else if (!strcmp(model,"3320af")) { d4768 1 a4768 2 width = 2048; order = 0x4949; d4774 9 d5403 1 a5403 1 "\nRaw Photo Decoder \"dcraw\" v7.39" @ 1.266 log @Decode the raw formats used by SMaL cameras. @ text @d4167 1 d4176 2 d4222 1 a4222 1 if (!strncmp(make,"NIKON",5) && filters == UINT_MAX) d4722 15 d4991 5 d5357 1 a5357 1 "\nRaw Photo Decoder \"dcraw\" v7.38" @ 1.265 log @Improved support for Phase One files. @ text @d438 2 d1785 141 d3818 1 a3818 1 int i, ver; a3824 2 else if (ver >> 1 != 4) return; d3826 1 a3826 1 if (ver > 6) get4(); a3828 5 if (ver > 6) { i = get2(); height = get2(); width = get2(); } d3831 2 d5334 1 a5334 1 "\nRaw Photo Decoder \"dcraw\" v7.36" @ 1.264 log @Added the Polaroid x530 and Phase One P 25. @ text @d1182 1 a1182 1 mask = model[0] == 'P' ? 0x1354:0x5555; d3584 1 a3584 4 i = get4(); if (i == 0x52617754) load_raw = phase_one_load_raw; /* RawT */ if (i == 0x52617743) load_raw = phase_one_load_raw_c; /* RawC */ if (!load_raw) return; d3611 1 d3622 2 d5196 1 a5196 1 "\nRaw Photo Decoder \"dcraw\" v7.35" @ 1.263 log @Added the Foculus 503c. Don't assume that Nikon D2X/D2Hs files are big-endian. Added special auto white balance for the PowerShot 600. Fixed camera white balance for the PowerShot G1 and Pro90. @ text @d56 1 d62 1 d1198 49 d1829 1 a1829 1 int row, col, bit=-1, c, i; d1831 1 d1833 6 a1838 6 for (i=0; i < 1024; i++) huff[i] = get4(); init_decoder(); foveon_decoder (huff, 0); d1841 1 a1841 1 if (!bit) get4(); d1843 5 a1847 1 FORC3 { d1949 1 d1982 1 a1982 1 float cfilt=0.8, ddft[3][3][2], ppm[3][3][3]; d1988 1 a1988 1 int dim[3], dscr[2][2], (*smrow[7])[3], total[4], ipix[3]; a1996 2 foveon_fixed (ddft[1][0], 12, "DarkDrift"); foveon_fixed (&cfilt, 1, "ColumnFilter"); d2004 13 d2166 2 a2167 1 FORC3 fsum[c] += image[(row+hood[j*2])*width+col+hood[j*2+1]][c]; d2209 1 d2212 1 a2212 1 if (maximum > i) maximum = i; d2214 1 a2214 2 clip_max = maximum; limit = maximum * 9 >> 4; d2223 8 a2230 4 i = 0x4000 - ((min - limit) << 14) / limit; i = 0x4000 - (i*i >> 14); i = i*i >> 14; FORC3 pix[c] += (max - pix[c]) * i >> 14; a3173 1 if (flip == 7) flip = 4; /* Adobe didn't read the TIFF spec. */ d3582 6 a3587 1 fseek (ifp, base+8, SEEK_SET); d3709 1 a3709 1 int entries, off, len, tag, save, i, pent, poff[256][2]; d3729 1 a3729 2 if (data_offset) break; data_offset = off + 28; d3731 7 a3737 2 raw_width = get4(); raw_height = get4(); d4044 1 d4072 2 a4073 2 if ((cp = memmem (head, 32, "MMMMRawT", 8)) || (cp = memmem (head, 32, "IIIITwaR", 8))) a4167 4 /* File format is OK. Do we support this camera? */ /* Start with some useful defaults: */ a4176 1 load_raw = NULL; d4203 1 a4203 1 if (width < height) xmag = 2; a4580 3 } else if (!strcmp(make,"Phase One")) { load_raw = phase_one_load_raw; maximum = 0xffff; d5196 1 a5196 1 "\nRaw Photo Decoder \"dcraw\" v7.30" @ 1.262 log @Added support for the Phase One P 20. Changed maximums for the Nikon D70 and D100. @ text @d84 1 d188 8 a195 4 /* Get a 2-byte integer, making no assumptions about CPU byte order. Nor should we assume that the compiler evaluates left-to-right. */ d198 4 a201 1 uchar a, b; d203 6 a208 6 a = fgetc(ifp); b = fgetc(ifp); if (order == 0x4949) /* "II" means little-endian */ return a | b << 8; else /* "MM" means big-endian */ return a << 8 | b; a210 3 /* Same for a 4-byte integer. */ d213 4 a216 1 uchar a, b, c, d; d218 5 a222 2 a = fgetc(ifp); b = fgetc(ifp); c = fgetc(ifp); d = fgetc(ifp); d224 4 a227 4 if (order == 0x4949) return a | b << 8 | c << 16 | d << 24; else return a << 24 | b << 16 | c << 8 | d; a229 3 /* Faster than calling get2() multiple times. */ d237 117 d358 3 a360 1 int irow, orow, col; d362 1 a362 1 for (irow=orow=0; irow < height; irow++) d377 1 a377 1 BAYER(orow,col) = pixel[col]; d380 1 a380 2 if ((orow+=2) > height) orow = 1; d382 12 a393 2 black /= (896 - width) * height; maximum = 0x3ff; a1806 5 int CLASS sget4 (uchar *s) { return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; } a2775 6 double getrat() { double num = get4(); return num / get4(); } d2897 1 a2897 1 FORC4 cam_mul[c ^ (c >> 1)] = (buf97[c*2+6] << 8) + buf97[c*2+7]; d3316 1 a3316 1 int tboff, nrecs, i, type, len, roff, aoff, save, wbi=-1; d3355 1 a3355 4 white[0][1] = get2(); white[0][0] = get2(); white[1][0] = get2(); white[1][1] = get2(); d3407 4 a3504 6 float CLASS get_float() { int i = get4(); return *((float *) &i); } a3719 2 { "Canon PowerShot 600", { -3822,10019,1311,4085,-157,3386,-5341,10829,4812,-1969,10969,1126 } }, d3934 1 d4498 6 d5122 1 a5122 1 "\nRaw Photo Decoder \"dcraw\" v7.24" @ 1.261 log @Phase One gives me coeff[][] in the metadata. Nice! @ text @a768 1 maximum = curve[csize-1]; d1039 1 a1039 1 ushort *pixel, akey, bkey; d1044 1 d1053 2 a1054 2 pixel[col+0] = (b & 0xaaaa) | (a & 0x5555); pixel[col+1] = (a & 0xaaaa) | (b & 0x5555); d3388 1 d3399 2 a3404 2 save = ftell(ifp); fseek (ifp, base+data, SEEK_SET); a3409 1 fseek (ifp, save, SEEK_SET); d3419 5 a3423 1 nikon_curve_offset = ftell(ifp) - 4; d3425 1 d3428 8 d4117 2 d4122 1 a4122 1 maximum = 0xd2c; a4379 7 sprintf (model, "%dx%d", width, height); switch (raw_height) { /* purely cosmetic */ case 2060: strcpy (model,"LightPhase"); break; case 2682: strcpy (model,"H10"); break; case 4128: strcpy (model,"H20"); break; case 5488: strcpy (model,"H25"); break; } d4997 1 a4997 1 "\nRaw Photo Decoder \"dcraw\" v7.23" @ 1.260 log @Added color matrices for the Canon EOS D6000 and NIKON D2X. Identify SMaL raw files, but still can't decode them. @ text @d3379 6 d3387 1 a3387 1 unsigned entries, tag, type, len, data; d3399 12 d4365 6 a4370 18 switch (raw_height) { case 2060: strcpy (model, "LightPhase"); pre_mul[0] = 1.331; pre_mul[2] = 1.154; break; case 2682: strcpy (model, "H10"); break; case 4128: strcpy (model, "H20"); pre_mul[0] = 1.963; pre_mul[2] = 1.430; break; case 5488: strcpy (model, "H25"); pre_mul[0] = 2.80; pre_mul[2] = 1.20; d4703 1 d4989 1 a4989 1 "\nRaw Photo Decoder \"dcraw\" v7.22" @ 1.259 log @Set "filters" based on rotation for Leaf Valeo backs. @ text @d3445 24 d3547 1 a3547 1 { "Canon EOS D2000C", d3549 2 d3689 2 d3916 1 a4094 2 pre_mul[0] = 1.514; pre_mul[2] = 1.727; d4982 1 a4982 1 "\nRaw Photo Decoder \"dcraw\" v7.21" @ 1.258 log @Added "-z" option to fix timestamps. @ text @a38 1 #include d51 1 d58 1 d2279 1 a2279 1 pseudoinverse ((void *) cam_rgb, inverse, colors); d3344 2 d3360 8 d3791 1 a3791 1 zero_after_ff = is_dng = fuji_secondary = filters = 0; d3794 1 d3821 1 a3821 1 if (!strncmp(make,"NIKON",5) && filters == 0) d3923 1 d3935 1 a3935 1 if (!filters) filters = 0x94949494; a4367 2 if (height > width) filters = 0x16161616; d4371 1 a4371 2 if (raw_width == 2060) { filters = 0; d4955 1 a4955 1 "\nRaw Photo Decoder \"dcraw\" v7.20" @ 1.257 log @Refactored to reduce the line count. @ text @d39 1 d2819 1 a2819 1 void CLASS get_timestamp() d2823 2 d2826 6 a2831 1 if (fscanf (ifp, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon, d2854 1 a2854 1 get_timestamp(); d2936 1 a2936 1 get_timestamp(); d3413 21 d3734 1 a3734 1 int CLASS identify() d3812 1 a3812 3 } else if (!memcmp (head,"\0MRM",4)) parse_minolta(); else if (!memcmp (head,"\xff\xd8\xff\xe1",4) && d3844 2 d3861 2 d3875 1 d4631 3 a4633 2 if (!load_raw || !height) { fprintf (stderr, "%s: %s %s is not yet supported.\n", d4932 2 a4933 1 int identify_only=0, write_to_stdout=0, half_size=0, use_fuji_rotate=1; d4935 1 d4945 1 a4945 1 "\nRaw Photo Decoder \"dcraw\" v7.19" d4949 3 a4951 1 "\n-i Identify files but don't decode them" a4952 1 "\n-v Print verbose messages while decoding" d4993 1 d5048 11 a5058 3 if ((status = identify())) { fclose(ifp); continue; d5060 1 d5070 1 @ 1.256 log @Added colorcheck() function, and used it to create a color matrix for the MINOLTA DiMAGE Z2. @ text @d2227 57 a2284 2 void CLASS dng_coeff (double[4][4], double[4][3], double[3]); d2290 1 a2290 1 int cut[NSQ][4] = { d2316 1 a2316 1 float gmb_xyz[NSQ][3] = { d2341 2 d2344 1 a2344 7 double invert[3][6], num, error, minerr=DBL_MAX; double gmb_cam[NSQ][4], xyz_gmb[3][NSQ], cam_xyz[4][3]; double cc[4][4], cm[4][3], xyz[] = { 1,1,1 }; for (i=0; i < 4; i++) for (j=0; j < 4; j++) cc[i][j] = i == j; d2357 1 a2357 29 /* Compute: xyz_gmb = inverse(transpose(gmb_xyz)*gmb_xyz) * transpose(gmb_xyz) cam_xyz = transpose(gmb_cam) * transpose(xyz_gmb) */ for (i=0; i < 3; i++) { for (j=0; j < 6; j++) invert[i][j] = j == i+3; for (j=0; j < 3; j++) for (k=0; k < NSQ; k++) invert[i][j] += gmb_xyz[k][i] * gmb_xyz[k][j]; } for (i=0; i < 3; i++) { num = invert[i][i]; for (j=0; j < 6; j++) // Normalize row i invert[i][j] /= num; for (k=0; k < 3; k++) { // Subtract it from the other rows if (k==i) continue; num = invert[k][i]; for (j=0; j < 6; j++) invert[k][j] -= invert[i][j] * num; } } memset (xyz_gmb, 0, sizeof xyz_gmb); for (i=0; i < 3; i++) for (j=0; j < NSQ; j++) for (k=0; k < 3; k++) xyz_gmb[i][j] += invert[i][k+3] * gmb_xyz[j][k]; memset (cam_xyz, 0, sizeof cam_xyz); d2360 2 a2361 2 for (k=0; k < NSQ; k++) cam_xyz[i][j] += gmb_cam[k][i] * xyz_gmb[j][k]; d2374 1 a2374 1 memcpy (cm, cam_xyz, sizeof cm); d2377 1 a2377 1 dng_coeff (cc, cm, xyz); d2380 1 a2380 1 num = 10000 / (cm[1][0] + cm[1][1] + cm[1][2]); d2382 1 a2382 1 fprintf (stderr, "%d,", (int) (cm[c][j] * num + 0.5)); a2856 57 void CLASS dng_coeff (double cc[4][4], double cm[4][3], double xyz[3]) { 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 } }; double cam_xyz[4][3], cam_rgb[4][3], invert[3][6], num; int i, j, k; memset (cam_xyz, 0, sizeof cam_xyz); for (i=0; i < colors; i++) for (j=0; j < 3; j++) for (k=0; k < colors; k++) cam_xyz[i][j] += cc[i][k] * cm[k][j] * xyz[j]; memset (cam_rgb, 0, sizeof cam_rgb); /* Multiply out XYZ colorspace */ for (i=0; i < colors; i++) for (j=0; j < 3; j++) for (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; } /* Compute coeff = pseudoinverse(cam_rgb), or coeff = inverse (transpose(cam_rgb) * cam_rgb) * transpose(cam_rgb) */ for (i=0; i < 3; i++) { for (j=0; j < 6; j++) invert[i][j] = j == i+3; for (j=0; j < 3; j++) for (k=0; k < colors; k++) invert[i][j] += cam_rgb[k][i] * cam_rgb[k][j]; } for (i=0; i < 3; i++) { num = invert[i][i]; for (j=0; j < 6; j++) /* Normalize row i */ invert[i][j] /= num; for (k=0; k < 3; k++) { /* Subtract it from other rows */ if (k==i) continue; num = invert[k][i]; for (j=0; j < 6; j++) invert[k][j] -= invert[i][j] * num; } } use_coeff = 1; memset (coeff, 0, sizeof coeff); for (i=0; i < 3; i++) for (j=0; j < colors; j++) for (k=0; k < 3; k++) coeff[i][j] += invert[i][k+3] * cam_rgb[j][k]; } d2866 1 a2866 1 double dblack, cc[4][4], cm[4][3]; d3033 6 a3038 2 if (use_cm) dng_coeff (cc, cm, xyz); d3668 1 a3668 1 double cc[4][4], cm[4][3], xyz[] = { 1,1,1 }; a3671 3 for (i=0; i < 4; i++) for (j=0; j < 4; j++) cc[i][j] = i == j; d3676 2 a3677 2 cm[0][j] = table[i].trans[j]; dng_coeff (cc, cm, xyz); d4910 1 a4910 1 "\nRaw Photo Decoder \"dcraw\" v7.18" @ 1.255 log @Added "-j" option, check for corrupt CRW files. @ text @d2227 139 d3639 2 d4146 1 a4146 3 pre_mul[0] = 508; pre_mul[1] = 256; pre_mul[2] = 450; d4943 1 a4943 1 "\nRaw Photo Decoder \"dcraw\" v7.17" d5078 3 @ 1.254 log @Added the Nikon E880. @ text @d3088 1 d4793 1 a4793 1 int identify_only=0, write_to_stdout=0, half_size=0; d4804 1 a4804 1 "\nRaw Photo Decoder \"dcraw\" v7.16" d4825 1 d4860 1 d4950 1 a4950 1 fuji_rotate(); @ 1.253 log @Added the Casio EX-P505. @ text @d3938 2 a3939 1 } else if (!strcmp(model,"E990")) { @ 1.252 log @Support little-endian Phase One images. @ text @d3623 1 d4459 7 d4802 1 a4802 1 "\nRaw Photo Decoder \"dcraw\" v7.15" @ 1.251 log @Added camera white balance for the Nikon D2Hs. @ text @d1040 1 a1040 2 fseek (ifp, 8, SEEK_CUR); fseek (ifp, get4() + 296, SEEK_CUR); d1043 1 a1043 1 fseek (ifp, data_offset + 12 + top_margin*raw_width*2, SEEK_SET); d3250 28 d3636 1 d3661 4 a3664 9 if ((cp = memmem (head, 32, "MMMMRawT", 8))) { strcpy (make, "Phase One"); data_offset = cp - head; fseek (ifp, data_offset + 8, SEEK_SET); fseek (ifp, get4() + 136, SEEK_CUR); raw_width = get4(); fseek (ifp, 12, SEEK_CUR); raw_height = get4(); } else if (order == 0x4949 || order == 0x4d4d) { a3756 1 top_margin = left_margin = 0; d3759 2 a3760 2 height = raw_height; width = raw_width; a4168 4 height = 2048; width = 3080; top_margin = 5; left_margin = 22; a4173 4 height = 2672; width = 4012; top_margin = 5; left_margin = 26; a4176 4 height = 4098; width = 4098; top_margin = 20; left_margin = 26; a4181 4 height = 5458; width = 4098; top_margin = 20; left_margin = 26; a4184 1 filters = top_margin & 1 ? 0x94949494 : 0x49494949; d4794 1 a4794 1 "\nRaw Photo Decoder \"dcraw\" v7.14" @ 1.250 log @Added camera white balance for the Nikon D2X. @ text @d2597 4 a2600 4 break; case 0x204: fseek (ifp, 280, SEEK_CUR); fread (buf97, 324, 1, ifp); d2603 1 a2603 1 if (tag == 0xa7 && ver97 == 0x204) { d4789 1 a4789 1 "\nRaw Photo Decoder \"dcraw\" v7.13" @ 1.249 log @Added camera WB for the Canon S60 and all Fuji cameras. @ text @d2490 33 d2524 2 d2577 2 d2584 17 a2600 9 if (!strcmp(model,"NIKON D100 ")) { fseek (ifp, 72, SEEK_CUR); FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2(); } else if (!strcmp(model,"NIKON D2H")) { fseek (ifp, 10, SEEK_CUR); goto get2_rggb; } else if (!strcmp(model,"NIKON D70")) { fseek (ifp, 20, SEEK_CUR); FORC4 cam_mul[c] = get2(); d2603 8 d4789 1 a4789 1 "\nRaw Photo Decoder \"dcraw\" v7.12" @ 1.248 log @Added support for 22-megapixel Imacon Ixpress. Moved some flip logic and adjusted the Casio EX-Z50. @ text @d120 1 d2490 1 a2490 1 unsigned base=0, offset=0, entries, tag, type, len, save; d2549 1 a2549 2 camera_red = get2() / 256.0; camera_blue = get2() / 256.0; d2555 1 a2555 4 camera_red = get2(); camera_red /= get2(); camera_blue = get2(); camera_blue/= get2(); d2565 2 a2566 6 if (tag == 0x201 && len == 4) { camera_red = get2(); camera_red /= get2(); camera_blue = get2(); camera_blue = get2() / camera_blue; } d2592 1 a2592 4 camera_red = get2(); camera_red /= get2(); camera_blue = get2(); camera_blue = get2() / camera_blue; d2914 1 a2914 1 int save, tag, len, offset, high=0, wide=0; d2929 2 a2930 4 camera_red = get2(); camera_red /= get2(); camera_blue = get2(); camera_blue = get2() / camera_blue; d3028 1 d3077 1 d3198 17 d3518 2 a3519 2 char head[32], *c; unsigned hlen, fsize, i; a3551 1 float tmp; d3580 1 a3580 1 if ((c = memmem (head, 32, "MMMMRawT", 8))) { d3582 1 a3582 1 data_offset = c - head; d3632 1 a3632 4 camera_red = get4(); camera_red /= get4(); camera_blue = get4(); camera_blue = get4() / camera_blue; d3637 2 d3664 4 a3667 4 c = make + strlen(make); /* Remove trailing spaces */ while (*--c == ' ') *c = 0; c = model + strlen(model); while (*--c == ' ') *c = 0; d4009 1 a4009 1 if (!strcmp(model,"DiMAGE A200")) { a4010 4 tmp = camera_red; camera_red = 1 / camera_blue; camera_blue = 1 / tmp; } d4044 1 a4044 4 camera_red = get2(); camera_blue = get2(); camera_red /= get2(); camera_blue /= get2(); d4736 1 a4736 1 "\nRaw Photo Decoder \"dcraw\" v7.10" @ 1.247 log @Added the Logitech Fotoman Pixtura, matrix for Fuji F810. @ text @a1059 14 void CLASS ixpress_load_raw() { ushort pixel[4090]; int row, col; order = 0x4949; fseek (ifp, 304 + 6*2*4090, SEEK_SET); for (row=height; --row >= 0; ) { read_shorts (pixel, 4090); for (col=0; col < width; col++) BAYER(row,col) = pixel[width-1-col]; } } d2898 1 a2898 1 if (make[0] == 0 && raw_width == 680 && raw_height == 680) { d2900 1 a2900 2 strcpy (model,"Ixpress"); } d4131 2 a4132 2 } else if (!strcmp(model,"Ixpress")) { height = 4084; d4134 12 a4145 2 filters = 0x49494949; load_raw = ixpress_load_raw; d4389 2 a4390 2 height = 1932; width = 2602; d4393 2 a4394 2 pre_mul[0] = 1.969; pre_mul[2] = 1.570; a4580 5 switch ((flip+3600) % 360) { case 270: flip = 5; break; case 180: flip = 3; break; case 90: flip = 6; } d4738 1 a4738 1 "\nRaw Photo Decoder \"dcraw\" v7.09" d4841 7 a4888 2 if (user_flip >= 0) flip = user_flip; @ 1.246 log @Added the Fuji F710 and F800. @ text @d1257 2 a1258 2 if (model[2] == '4') return (getbits(5) << 3) + 4; /* DC40 */ d1260 1 a1260 1 return (getbits(6) << 2) + 2; /* DC50 */ d3361 2 d3645 3 d4336 6 d4748 1 a4748 1 "\nRaw Photo Decoder \"dcraw\" v7.08" @ 1.245 log @Added the Nikon E900 and Casio EX-Z50. Rewrote dng_coeff() to show saturated pixels as pure white. @ text @d3361 1 a3361 1 { "FUJIFILM FinePix F700", d3981 1 a3981 1 !strcmp(model,"FinePix F810") || d3989 1 a3989 1 } else if (!strcmp(model,"FinePix F700") || @ 1.244 log @Fixed the maximum for the FinePix S3Pro. @ text @d779 1 a779 1 if (row == 1 && atoi(model+1) < 5000) { d882 17 a925 15 void CLASS nikon_e950_load_raw() { int irow, row, col; getbits(-1); for (irow=0; irow < height; irow++) { row = irow * 2 % height; for (col=0; col < width; col++) BAYER(row,col) = getbits(10); for (col=28; col--; ) getbits(8); } maximum = 0x3dd; } d1090 1 a1090 3 /* For this function only, raw_width is in bytes, not pixels! */ a2668 5 static const double rgb_xyz[3][3] = { /* RGB from XYZ */ { 3.240479, -1.537150, -0.498535 }, { -0.969256, 1.875992, 0.041556 }, { 0.055648, -0.204043, 1.057311 } }; #if 0 d2673 1 a2673 2 #endif double cam_xyz[4][3], xyz_cam[3][4], invert[3][6], num; d2682 2 a2683 3 for (i=0; i < colors; i++) { for (num=j=0; j < 3; j++) num += cam_xyz[i][j]; d2685 8 a2692 1 cam_xyz[i][j] /= num; d2695 3 d2703 1 a2703 1 invert[i][j] += cam_xyz[k][i] * cam_xyz[k][j]; d2716 1 a2716 6 memset (xyz_cam, 0, sizeof xyz_cam); for (i=0; i < 3; i++) for (j=0; j < colors; j++) for (k=0; k < 3; k++) xyz_cam[i][j] += invert[i][k+3] * cam_xyz[j][k]; d2721 1 a2721 8 coeff[i][j] += rgb_xyz[i][k] * xyz_cam[k][j]; for (num=j=0; j < colors; j++) num += coeff[1][j]; for (i=0; i < 3; i++) for (j=0; j < colors; j++) coeff[i][j] /= num; use_coeff = 1; d3534 1 d3541 1 d3547 1 d3835 1 d3843 12 d3858 3 a3863 1 load_raw = nikon_e950_load_raw; a3885 1 width = 1616; d3887 1 a3893 1 width = 1616; d3895 1 d3940 5 d4313 1 a4313 1 width = 768; d4319 1 a4319 1 width = 768; d4325 1 a4325 1 width = 848; d4382 7 d4737 1 a4737 1 "\nRaw Photo Decoder \"dcraw\" v7.06" @ 1.243 log @Added color matrix for the PowerShot S60. @ text @d3950 1 a3950 1 maximum = 0xffff; @ 1.242 log @Fixed Kodak DC25 color and condensed three functions into simple_coeff(). @ text @d2727 1 a2727 1 for (i=0; i < 3; i++) { a2729 1 } d3360 2 d4716 1 a4716 1 "\nRaw Photo Decoder \"dcraw\" v7.05" @ 1.241 log @Added the Canon EOS 350D with more general CR2 support. @ text @d27 1 a1414 18 void CLASS kodak_dc20_coeff (float juice) { static const float my_coeff[3][4] = { { 2.25, 0.75, -1.75, -0.25 }, { -0.25, 0.75, 0.75, -0.25 }, { -0.25, -1.75, 0.75, 2.25 } }; static const float flat[3][4] = { { 1, 0, 0, 0 }, { 0, 0.5, 0.5, 0 }, { 0, 0, 0, 1 } }; int r, g; for (r=0; r < 3; r++) for (g=0; g < 4; g++) coeff[r][g] = my_coeff[r][g] * juice + flat[r][g] * (1-juice); use_coeff = 1; } a3301 28 void CLASS foveon_coeff() { static const float foveon[3][3] = { { 1.4032, -0.2231, -0.1016 }, { -0.5263, 1.4816, 0.0170 }, { -0.0112, 0.0183, 0.9113 } }; int i, j; for (i=0; i < 3; i++) for (j=0; j < 3; j++) coeff[i][j] = foveon[i][j]; use_coeff = 1; } void CLASS nikon_e950_coeff() { int r, g; static const float my_coeff[3][4] = { { -1.936280, 1.800443, -1.448486, 2.584324 }, { 1.405365, -0.524955, -0.289090, 0.408680 }, { -1.204965, 1.082304, 2.941367, -1.818705 } }; for (r=0; r < 3; r++) for (g=0; g < 4; g++) coeff[r][g] = my_coeff[r][g]; use_coeff = 1; } d3507 19 d3730 1 a3730 1 foveon_coeff(); d3850 1 d3852 1 a3852 1 colors = 4; a3853 1 nikon_e950_coeff(); d3863 1 a3863 1 nikon_e950_coeff(); d4276 5 a4280 1 if (!strcmp(model,"DC20")) { d4283 1 a4283 2 width = 249; raw_width = 256; d4285 1 a4285 2 width = 501; raw_width = 512; d4287 1 a4287 1 data_offset = raw_width + 1; d4290 1 a4290 1 kodak_dc20_coeff (1.0); a4294 15 } else if (strstr(model,"DC25")) { strcpy (model, "DC25"); height = 242; if (fsize < 100000) { width = 249; raw_width = 256; data_offset = 15681; } else { width = 501; raw_width = 512; data_offset = 15937; } colors = 4; filters = 0xb4b4b4b4; load_raw = kodak_easy_load_raw; d4715 1 a4715 1 "\nRaw Photo Decoder \"dcraw\" v7.04" @ 1.240 log @Support "-w" for Canon CR2 and Contax N Digital images. New cam_mul[] array will support 4-color cameras in the future. @ text @d2592 5 d2784 2 a2785 1 raw_width = type==3 ? get2() : get4(); d2788 2 a2789 1 raw_height = type==3 ? get2() : get4(); a2938 3 if (!strcmp(make,"Canon") && strcmp(model,"EOS D2000C")) raw_width = raw_height = 0; d3742 3 a3744 7 if ((is_canon = !strcmp(make,"Canon"))) { if (memcmp (head+6,"HEAPCCDR",8)) { filters = 0x61616161; load_raw = lossless_jpeg_load_raw; } else if (raw_width) load_raw = canon_compressed_load_raw; } d3829 3 d3833 2 a3834 2 height = 1662; width = 2496; d3836 1 d3838 2 a3839 2 height = 2718; width = 4082; d3841 6 a3846 4 } else if (!strcmp(model,"EOS-1D Mark II") || !strcmp(model,"EOS 20D")) { raw_height = 2360; raw_width = 3596; d3850 1 a3850 3 } else if (!strcmp(model,"EOS-1Ds Mark II")) { raw_height = 3349; raw_width = 5108; a3853 6 goto canon_cr2; } else if (!strcmp(model,"EOS DIGITAL REBEL XT")) { raw_height = 2328; raw_width = 3516; top_margin = 14; left_margin = 42; a3856 3 filters = 0x94949494; } else if (!strcmp(model,"EOS D2000C")) { black = curve[200]; d4754 1 a4754 1 "\nRaw Photo Decoder \"dcraw\" v7.03" @ 1.239 log @Fixed array bounds error in foveon_interpolate(). Don't use snprintf(), but keep strings safe anyway. @ text @d98 3 a100 2 float camera_red, camera_blue; float pre_mul[4], coeff[3][4]; d2296 3 a2298 5 else if (camera_red && camera_blue) { pre_mul[0] = camera_red; pre_mul[2] = camera_blue; pre_mul[1] = pre_mul[3] = 1.0; } else d2583 1 a2583 4 camera_red = get2(); camera_red /= get2(); camera_blue = get2(); camera_blue = get2() / camera_blue; d2622 8 d3592 1 a3592 1 camera_red = camera_blue = timestamp = tiff_samples = 0; a3595 1 pre_mul[0] = pre_mul[1] = pre_mul[2] = pre_mul[3] = 1; d3597 4 d3665 5 d4759 1 a4759 1 "\nRaw Photo Decoder \"dcraw\" v7.02" @ 1.238 log @Added the Canon EOS DIGITAL REBEL XT. @ text @d11 1 d13 2 a14 2 All the code currently under GPL is specific to Foveon cameras. This began in Revision 1.237. d1858 1 a1858 1 snprintf (str, 128, "%sRGBNeutral", model2); d1908 1 a1908 1 memcpy (black+1520, black+1509, sizeof *black*11); a2850 1 strcat (model," DNG"); d3528 1 a3528 1 char name[96]; d3534 1 a3534 1 snprintf (name, 96, "%s %s", make, model); d3691 1 d3713 1 d3741 1 d4747 1 a4747 1 "\nRaw Photo Decoder \"dcraw\" v7.01" @ 1.237 log @Dcraw 7.00 is a major rewrite: * It decodes all Adobe DNG files, and applies the same color matrices to non-DNG files. Color science replaces black magic. * It correctly decodes all Foveon images based on encrypted metadata. * It decodes the Casio QV-R51, Casio EX-Z55, Minolta Alpha-7, Nikon D2X, and ST Micro STV680. @ text @d630 7 d3828 1 a3828 3 height = raw_height - top_margin; width = raw_width - left_margin; filters = 0x94949494; d3834 8 a3844 1 maximum = 0xe80; d4744 1 a4744 1 "\nRaw Photo Decoder \"dcraw\" v7.00" @ 1.236 log @Fixed divide by zero error. @ text @d5 2 a6 5 This is a portable ANSI C program to convert raw image files from any digital camera into PPM format. TIFF and CIFF parsing are based upon public specifications, but no such documentation is available for the raw sensor data, so writing this program has been an immense effort. d8 12 a19 2 This code is freely licensed for all uses, commercial and otherwise. Comments, questions, and encouragement are welcome. d45 3 d79 1 a79 1 char *ifname, make[64], model[64], model2[64]; d81 1 a81 1 int data_offset, curve_offset, curve_length; d84 2 a85 1 int height, width, fuji_width, colors, black, rgb_max; d87 1 a87 1 int is_canon, is_cmy, is_foveon, use_coeff, use_gamma; d91 1 a91 1 ushort (*image)[4], white[8][8]; d95 2 a96 1 int verbose=0, use_auto_wb=0, use_camera_wb=0, use_secondary=0; d99 1 a99 1 int histogram[0x2000]; d116 3 d133 2 a134 9 PowerShot 600 uses 0xe1e4e1e4: 0 1 2 3 4 5 0 G M G M G M 1 C Y C Y C Y 2 M G M G M G 3 C Y C Y C Y PowerShot A5 uses 0x1e4e1e4e: d136 9 a150 30 PowerShot A50 uses 0x1b4e4b1e: 0 1 2 3 4 5 0 C Y C Y C Y 1 M G M G M G 2 Y C Y C Y C 3 G M G M G M 4 C Y C Y C Y 5 G M G M G M 6 Y C Y C Y C 7 M G M G M G PowerShot Pro70 uses 0x1e4b4e1b: 0 1 2 3 4 5 0 Y C Y C Y C 1 M G M G M G 2 C Y C Y C Y 3 G M G M G M 4 Y C Y C Y C 5 G M G M G M 6 C Y C Y C Y 7 M G M G M G PowerShots Pro90 and G1 use 0xb4b4b4b4: 0 1 2 3 4 5 0 G M G M G M 1 Y C Y C Y C a159 1 d185 1 a185 1 ushort CLASS fget2 (FILE *f) d189 1 a189 1 a = fgetc(f); b = fgetc(f); d200 1 a200 1 int CLASS fget4 (FILE *f) d204 2 a205 1 a = fgetc(f); b = fgetc(f); c = fgetc(f); d = fgetc(f); d214 1 a214 1 Faster than calling fget2() multiple times. d244 1 a244 1 BAYER(orow,col) = pixel[col] << 4; d250 2 a251 1 black = ((INT64) black << 4) / ((896 - width) * height); d274 1 a274 1 BAYER(row,col) = (pixel[col] & 0x3ff) << 4; d279 2 a280 1 black = ((INT64) black << 4) / ((raw_width - width) * height); d462 1 a462 1 int lowbits, shift, i, row, r, col, save, val; a466 1 INT64 bblack=0; d471 1 a471 1 shift = 4 - lowbits*2; d503 1 a503 1 save = ftell(ifp); /* Don't lose our place */ d521 1 a521 1 BAYER(irow,icol) = pixel[r*raw_width+col] << shift; d523 1 a523 1 bblack += pixel[r*raw_width+col]; d529 1 a529 33 black = (bblack << shift) / ((raw_width - width) * height); } void CLASS kodak_curve (ushort *curve) { int i, entries, tag, type, len, val; for (i=0; i < 0x1000; i++) curve[i] = i; if (strcasecmp(make,"KODAK")) return; if (!curve_offset) { fseek (ifp, 12, SEEK_SET); entries = fget2(ifp); while (entries--) { tag = fget2(ifp); type = fget2(ifp); len = fget4(ifp); val = fget4(ifp); if (tag == 0x90d) { curve_offset = val; curve_length = len; } } } if (curve_offset) { fseek (ifp, curve_offset, SEEK_SET); for (i=0; i < curve_length && i < 0x1000; i++) curve[i] = fget2(ifp); for ( ; i < 0x1000; i++) curve[i] = curve[i-1]; rgb_max = curve[i-1] << 2; } fseek (ifp, data_offset, SEEK_SET); d533 2 a534 2 Not a full implementation of Lossless JPEG, just enough to decode Canon and Kodak images. d536 7 a542 1 void CLASS lossless_jpeg_load_raw() d544 1 a544 1 int tag, len, jhigh=0, jwide=0, jrow, jcol, jidx, diff, i, row, col; a545 5 int vpred[2] = { 0x800, 0x800 }, hpred[2]; struct decode *dstart[2], *dindex; ushort curve[0x1000]; INT64 bblack=0; int min=INT_MAX; d547 5 a551 3 kodak_curve (curve); order = 0x4d4d; if (fget2(ifp) != 0xffd8) return; d553 4 a556 3 tag = fget2(ifp); len = fget2(ifp) - 2; if (tag <= 0xff00 || len > 255) return; d560 4 a563 2 jhigh = (data[1] << 8) + data[2]; jwide =((data[3] << 8) + data[4])*2; d566 2 a567 4 init_decoder(); dstart[0] = dstart[1] = free_decode; for (dp = data; dp < data+len && *dp < 2; ) { dstart[*dp] = free_decode; d572 4 a575 1 d578 41 a618 17 for (jrow=0; jrow < jhigh; jrow++) for (jcol=0; jcol < jwide; jcol++) { for (dindex = dstart[jcol & 1]; dindex->branch[0]; ) dindex = dindex->branch[getbits(1)]; len = dindex->leaf; diff = getbits(len); if ((diff & (1 << (len-1))) == 0) diff -= (1 << len) - 1; if (jcol < 2) { vpred[jcol] += diff; hpred[jcol] = vpred[jcol]; } else hpred[jcol & 1] += diff; diff = hpred[jcol & 1]; if (diff < 0) diff = 0; if (diff > 0xfff) diff = 0xfff; d621 1 a621 1 i = jidx / (1680*jhigh); d623 1 a623 1 row = jidx / 1680 % jhigh; d626 1 a626 1 jidx -= 2*1680*jhigh; d634 1 a634 2 if ((unsigned) (row-top_margin) >= height) continue; d636 2 a637 3 BAYER(row-top_margin,col-left_margin) = curve[diff] << 2; if (min > curve[diff]) min = curve[diff]; d639 1 a639 1 bblack += curve[diff]; d641 2 d644 1 a644 1 black = (bblack << 2) / ((raw_width - width) * height); d646 71 a716 1 black = min << 2; d725 2 a726 3 int vpred[4], hpred[2], csize, row, col, i, len, diff; ushort *curve; struct decode *dindex; d731 3 a733 4 fseek (ifp, curve_offset, SEEK_SET); for (i=0; i < 4; i++) vpred[i] = fget2(ifp); csize = fget2(ifp); d736 1 a736 2 for (i=0; i < csize; i++) curve[i] = fget2(ifp); d744 1 a744 6 for (dindex=first_decode; dindex->branch[0]; ) dindex = dindex->branch[getbits(1)]; len = dindex->leaf; diff = getbits(len); if ((diff & (1 << (len-1))) == 0) diff -= (1 << len) - 1; a752 1 if (diff < 0) diff = 0; d754 1 a754 1 BAYER(row,col-left_margin) = curve[diff] << 2; d756 1 d778 1 a778 1 BAYER(row,col-left_margin) = i << 2; d895 1 a895 1 BAYER(row,col) = (pixel[col] & 0xfff) << 2; d907 1 a907 1 BAYER(row,col) = getbits(10) << 4; d911 1 d928 1 a928 1 BAYER(r,c) = pixel[col] << 2; d944 1 a944 1 BAYER(r,c) = pixel[col] << 2; d959 1 a959 1 BAYER(r,c) = pixel[col] << 2; d1016 1 a1016 1 BAYER(row,col) = (todo[i+1] & 0x3ff) << 4; d1019 1 d1028 3 a1030 3 fseek (ifp, fget4(ifp) + 296, SEEK_CUR); akey = fget2(ifp); bkey = fget2(ifp); d1070 5 a1074 6 for (c=0; c < 3; c++) for (row=r; row < r+32; row++) { read_shorts (pixel, raw_width); for (col=0; col < width; col++) image[row*width+col][c] = pixel[col]; } d1078 3 a1080 1 /* For this function only, raw_width is in bytes, not pixels! */ d1088 1 a1088 1 BAYER(row,col) = getbits(12) << 2; d1094 1 a1094 1 void CLASS unpacked_load_raw (int rsh) d1104 1 a1104 1 BAYER(row,col) = pixel[col] << 8 >> (8+rsh); a1108 20 void CLASS all_16_load_raw() { unpacked_load_raw (0); } void CLASS high_12_load_raw() { unpacked_load_raw (2); } void CLASS low_12_load_raw() { unpacked_load_raw (-2); } void CLASS low_10_load_raw() { unpacked_load_raw (-4); } d1127 1 a1127 1 BAYER(row,col) = (pixel[col] & 0xfff) << 2; d1143 1 a1143 1 BAYER(row,col) = getbits(12) << 2; d1157 1 a1157 1 BAYER(row,col) = pixel[col] << 6; d1160 1 d1178 1 a1178 1 BAYER(row,col) = (pixel[col] & 0x3ff) << 4; d1180 1 d1194 1 a1194 1 BAYER(row,col) = pixel[col] << 2; d1274 1 a1274 1 for (c=0; c < 3; c++) { d1324 1 d1376 4 a1379 4 BAYER(row+0,col+0) = pixel[col+0][1] << 6; BAYER(row+1,col+1) = pixel[col+1][1] << 6; BAYER(row+0,col+1) = (pixel[col][0] + pixel[col+1][0]) << 5; BAYER(row+1,col+0) = (pixel[col][2] + pixel[col+1][2]) << 5; d1384 1 d1396 1 a1396 2 for (row=0; row < height; row++) { d1400 1 a1400 1 BAYER(row,col) = (ushort) pixel[(col + shift) % 848] << 6; d1402 1 a1425 1 ushort curve[0x1000]; a1427 1 kodak_curve (curve); d1437 1 a1437 1 BAYER(row,icol) = (ushort) curve[pixel[col]] << 2; d1442 1 d1444 1 a1444 1 black = ((INT64) black << 2) / ((raw_width - width) * height); d1447 1 a1447 1 free (pixel); d1453 1 a1453 1 ushort raw[6], curve[0x1000]; a1457 1 kodak_curve (curve); d1507 1 a1507 1 BAYER(row,col) = curve[diff] << 2; d1517 1 a1517 1 ushort *ip, curve[0x1000]; a1518 1 kodak_curve (curve); d1561 1 a1561 2 for (c=0; c < 3; c++) if (rgb[c] > 0) ip[c] = curve[rgb[c]] << 2; d1564 1 a1588 1 INT64 bblack=0; d1593 1 a1593 1 key = fget4(ifp); d1606 1 a1606 1 bblack += ntohs(pixel[col]); d1611 3 a1613 2 if (bblack) black = bblack / ((left_margin-9) * height); d1616 1 a1616 13 void CLASS sony_rgbe_coeff() { int r, g; static const float my_coeff[3][4] = { { 1.321918, -0.471747, 0.149829, 0.000000 }, { -0.288764, 0.646067, -0.486517, 1.129213 }, { 0.061336, 0.000000, 1.138007, -0.199343 } }; for (r=0; r < 3; r++) for (g=0; g < 4; g++) coeff[r][g] = my_coeff[r][g]; use_coeff = 1; } d1628 1 a1628 1 if (code) { a1633 1 } d1643 14 d1664 1 a1664 3 fseek (ifp, 260, SEEK_SET); for (i=0; i < 1024; i++) diff[i] = fget2(ifp); d1666 1 a1666 1 huff[i] = fget4(ifp); d1671 1 a1671 1 for (row=0; row < raw_height; row++) { d1673 3 a1675 3 if (!bit) fget4(ifp); for (col=bit=0; col < raw_width; col++) { for (c=0; c < 3; c++) { d1684 1 a1684 5 if ((unsigned) (row-top_margin) >= height || (unsigned) (col-left_margin) >= width ) continue; for (c=0; c < 3; c++) if (pred[c] > 0) image[(row-top_margin)*width+(col-left_margin)][c] = pred[c]; d1687 7 d1696 1 a1696 1 int CLASS apply_curve (int i, const int *curve) d1698 110 a1807 8 if (i <= -curve[0]) return -curve[curve[0]]-1; else if (i < 0) return -curve[1-i]; else if (i < curve[0]) return curve[1+i]; else return curve[curve[0]]+1; d1812 123 a1934 42 float mul[3] = { 1.0321, 1.0, 1.1124 }; static const int weight[3][3][3] = { { { 4141, 37726, 11265 }, { -30437, 16066, -41102 }, { 326, -413, 362 } }, { { 1770, -1316, 3480 }, { -2139, 213, -4998 }, { -2381, 3496, -2008 } }, { { -3838, -24025, -12968 }, { 20144, -12195, 30272 }, { -631, -2025, 822 } } }, curve1[73] = { 72, 0,1,2,2,3,4,5,6,6,7,8,9,9,10,11,11,12,13,13,14,14, 15,16,16,17,17,18,18,18,19,19,20,20,20,21,21,21,22, 22,22,23,23,23,23,23,24,24,24,24,24,25,25,25,25,25, 25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26 }, curve2[21] = { 20, 0,1,1,2,3,3,4,4,5,5,6,6,6,7,7,7,7,7,7,7 }, curve3[73] = { 72, 0,1,1,2,2,3,4,4,5,5,6,6,7,7,8,8,8,9,9,10,10,10,10, 11,11,11,12,12,12,12,12,12,13,13,13,13,13,13,13,13, 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14 }, curve4[37] = { 36, 0,1,1,2,3,3,4,4,5,6,6,7,7,7,8,8,9,9,9,10,10,10, 11,11,11,11,11,12,12,12,12,12,12,12,12,12 }, curve5[111] = { 110, 0,1,1,2,3,3,4,5,6,6,7,7,8,9,9,10,11,11,12,12,13,13, 14,14,15,15,16,16,17,17,18,18,18,19,19,19,20,20,20, 21,21,21,21,22,22,22,22,22,23,23,23,23,23,24,24,24,24, 24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,26,26, 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26 }, *curves[3] = { curve3, curve4, curve5 }, trans[3][3] = { { 7576, -2933, 1279 }, { -11594, 29911, -12394 }, { 4000, -18850, 20772 } }; ushort *pix, prev[3], (*shrink)[3]; int row, col, c, i, j, diff, sum, ipix[3], work[3][3], total[4]; int (*smrow[7])[3], smlast, smred, smred_p=0, hood[7], min, max; a1935 1 /* Sharpen all colors */ d1937 3 d1942 6 d1949 1 a1949 1 for (c=0; c < 3; c++) { d1952 7 a1958 5 ipix[c] = pix[c] + ((diff + (diff*diff >> 14)) * 0x3333 >> 14); } for (c=0; c < 3; c++) { work[0][c] = ipix[c]*ipix[c] >> 14; work[2][c] = ipix[c]*work[0][c] >> 14; d1961 2 a1962 2 for (c=0; c < 3; c++) { for (sum=i=0; i < 3; i++) d1964 4 a1967 3 sum += weight[c][i][j] * work[i][j]; ipix[c] = (ipix[c] + (sum >> 14)) * mul[c]; if (ipix[c] < 0) ipix[c] = 0; d1974 21 d2015 3 a2017 2 smred = (smrow[2][col][0]*6 + (smrow[1][col][0]+smrow[3][col][0])*4 + smrow[0][col][0]+smrow[4][col][0] + 8) >> 4; d2020 2 a2021 3 i = pix[0] + ((pix[0] - ((smred*7 + smred_p) >> 3)) >> 2); if (i < 0) i = 0; if (i > 10000) i = 10000; d2027 20 a2046 23 /* Limit each color value to the range of its neighbors */ hood[0] = 4; for (i=0; i < 3; i++) { hood[i+1] = (i-width-1)*4; hood[i+4] = (i+width-1)*4; } for (row=1; row < height-1; row++) { pix = image[row*width+1]; memcpy (prev, pix-4, sizeof prev); for (col=1; col < width-1; col++) { for (c=0; c < 3; c++) { for (min=max=prev[c], i=0; i < 7; i++) { j = pix[hood[i]]; if (min > j) min = j; if (max < j) max = j; } prev[c] = *pix; if (*pix < min) *pix = min; if (*pix > max) *pix = max; pix++; } pix++; } d2059 1 a2059 2 for (c=0; c < 3; c++) smrow[4][col][c] = pix[c-8]+pix[c-4]+pix[c]+pix[c+4]+pix[c+8]; d2065 21 a2085 1 for (total[3]=1500, sum=60, c=0; c < 3; c++) { d2091 4 a2094 12 j = (sum << 16) / total[3]; for (c=0; c < 3; c++) { i = apply_curve ((total[c] * j >> 16) - pix[c], curve1); i += pix[c] - 13 - (c==1); ipix[c] = i - apply_curve (i, curve2); } sum = (ipix[0]+ipix[1]+ipix[1]+ipix[2]) >> 2; for (c=0; c < 3; c++) { i = ipix[c] - apply_curve (ipix[c] - sum, curve2); if (i < 0) i = 0; pix[c] = i; } d2098 12 a2109 9 /* Translate the image to a different colorspace */ for (pix=image[0]; pix < image[height*width]; pix+=4) { for (c=0; c < 3; c++) { for (i=j=0; j < 3; j++) i += trans[c][j] * pix[j]; i = (i+0x1000) >> 13; if (i < 0) i = 0; if (i > 24000) i = 24000; ipix[c] = i; d2111 1 a2111 2 for (c=0; c < 3; c++) pix[c] = ipix[c]; d2113 1 d2122 2 a2123 3 for (c=0; c < 3; c++) ipix[c] += image[(row*4+i)*width+col*4+j][c]; for (c=0; c < 3; c++) d2128 1 a2128 1 (shrink[(row+1)*(width/4)+col][c]*1840 + ipix[c]*141) >> 12; a2129 1 d2135 2 a2136 3 for (c=0; c < 3; c++) smrow[0][col][c] = ipix[c] = (shrink[(row/4)*(width/4)+col/4][c]*1485 + ipix[c]*6707) >> 13; d2141 2 a2142 3 for (c=0; c < 3; c++) smrow[1][col][c] = ipix[c] = (smrow[0][col][c]*1485 + ipix[c]*6707) >> 13; d2149 2 a2150 3 for (c=0; c < 3; c++) smrow[2][col][c] = (smrow[2][col][c]*6707 + smrow[1][col][c]*1485) >> 13; d2154 1 a2154 1 for (i=j=60, c=0; c < 3; c++) { d2160 2 a2161 2 i = (smrow[2][col][c] * j >> 16) - image[row*width+col][c]; ipix[c] = apply_curve (i, curves[c]); d2165 1 a2165 1 for (c=0; c < 3; c++) { d2174 12 d2188 2 d2251 1 a2251 1 int row, col, c, val; d2253 1 a2253 1 double sum[4], dmin, dmax; d2255 1 a2255 1 rgb_max -= black; d2257 2 a2258 4 for (c=0; c < 4; c++) { min[c] = INT_MAX; max[c] = count[c] = sum[c] = 0; } d2261 1 a2261 1 for (c=0; c < colors; c++) { d2267 1 a2267 1 if (val > rgb_max-100) continue; d2272 1 a2272 6 for (dmax=c=0; c < colors; c++) { sum[c] /= count[c]; if (dmax < sum[c]) dmax = sum[c]; } for (c=0; c < colors; c++) pre_mul[c] = dmax / sum[c]; d2275 1 a2275 2 for (c=0; c < 4; c++) count[c] = sum[c] = 0; d2283 4 a2286 8 for (dmin=DBL_MAX, dmax=c=0; c < colors; c++) { sum[c] /= count[c]; if (dmin > sum[c]) dmin = sum[c]; if (dmax < sum[c]) dmax = sum[c]; } if (dmin > 0) for (c=0; c < colors; c++) pre_mul[c] = dmax / sum[c]; d2298 15 d2315 1 a2315 2 for (c=0; c < colors; c++) fprintf (stderr, " %f", pre_mul[c]); d2318 1 d2321 1 a2321 1 for (c=0; c < colors; c++) { d2327 1 a2327 1 if (val > rgb_max) val = rgb_max; d2387 1 a2387 1 for (c=0; c < colors; c++) d2477 1 a2477 1 for (c=0; c < colors; c++) d2485 1 a2485 1 for (c=0; c < colors; c++) { /* Save to buffer */ d2490 1 a2490 1 if (t > rgb_max) t = rgb_max; d2505 1 a2505 1 void CLASS tiff_parse_subifd (int base) d2507 2 a2508 47 int entries, tag, type, len, val, save; entries = fget2(ifp); while (entries--) { tag = fget2(ifp); type = fget2(ifp); len = fget4(ifp); if (type == 3 && len < 3) { val = fget2(ifp); fget2(ifp); } else val = fget4(ifp); switch (tag) { case 0x100: /* ImageWidth */ raw_width = val; break; case 0x101: /* ImageHeight */ raw_height = val; break; case 0x102: /* Bits per sample */ break; case 0x103: /* Compression */ tiff_data_compression = val; break; case 0x106: /* Kodak color format */ kodak_data_compression = val; break; case 0x111: /* StripOffset */ if (len == 1) data_offset = val; else { save = ftell(ifp); fseek (ifp, base+val, SEEK_SET); data_offset = fget4(ifp); fseek (ifp, save, SEEK_SET); } break; case 0x115: /* SamplesPerRow */ break; case 0x116: /* RowsPerStrip */ break; case 0x117: /* StripByteCounts */ break; case 0x123: curve_offset = val; curve_length = len; } } d2513 2 a2514 1 int base=0, offset=0, entries, tag, type, len, val, save; a2516 1 d2523 3 a2525 1 if (!strcmp (buf,"Nikon")) { /* starts with "Nikon\0\2\0\0\0" ? */ d2527 3 a2529 3 order = fget2(ifp); /* might differ from file-wide byteorder */ val = fget2(ifp); /* should be 42 decimal */ offset = fget4(ifp); d2531 2 a2532 1 } else if (!strncmp (buf,"FUJIFILM",8)) { d2535 3 a2537 1 } else if (!strcmp (buf,"OLYMP")) d2539 2 a2540 1 else if (!strcmp (buf,"AOC")) d2542 1 a2542 2 else fseek (ifp, -10, SEEK_CUR); d2544 1 a2544 1 entries = fget2(ifp); d2546 3 a2548 7 tag = fget2(ifp); type = fget2(ifp); len = fget4(ifp); if (type == 3 && len < 3) { val = fget2(ifp); fget2(ifp); } else val = fget4(ifp); d2550 3 d2554 10 a2563 5 fseek (ifp, base+val, SEEK_SET); camera_red = fget4(ifp); camera_red /= fget4(ifp); camera_blue = fget4(ifp); camera_blue/= fget4(ifp); d2566 1 a2566 1 curve_offset = base+val + 2112; d2568 1 a2568 1 curve_offset = base+val + 2; d2571 3 a2573 3 fseek (ifp, base+val + 72, SEEK_SET); camera_red = fget2(ifp) / 256.0; camera_blue = fget2(ifp) / 256.0; d2575 5 a2579 5 fseek (ifp, base+val + 10, SEEK_SET); camera_red = fget2(ifp); camera_red /= fget2(ifp); camera_blue = fget2(ifp); camera_blue = fget2(ifp) / camera_blue; d2581 26 a2606 13 fseek (ifp, base+val + 20, SEEK_SET); camera_red = fget2(ifp); camera_red /= fget2(ifp); camera_blue = fget2(ifp); camera_blue/= fget2(ifp); } } if (tag == 0x201 && len == 4) { /* Pentax */ fseek (ifp, base+val, SEEK_SET); camera_red = fget2(ifp); camera_red /= fget2(ifp); camera_blue = fget2(ifp); camera_blue = fget2(ifp) / camera_blue; d2608 2 a2609 2 if (tag == 0x1017) /* Olympus */ camera_red = val / 256.0; d2611 8 a2618 2 camera_blue = val / 256.0; fseek (ifp, save, SEEK_SET); d2620 1 d2647 1 a2647 1 entries = fget2(ifp); d2649 4 a2652 4 tag = fget2(ifp); type = fget2(ifp); len = fget4(ifp); val = fget4(ifp); d2667 68 a2734 4 /* Parse a TIFF file looking for camera model and decompress offsets. */ void CLASS parse_tiff (int base) d2736 3 a2738 1 int doff, entries, tag, type, len, val, save; a2739 1 int wide=0, high=0, offset=0, i; d2741 174 a2914 1 static const char *corp[] = { "OLYMPUS", "PENTAX", "SONY" }; d2916 4 a2919 95 fseek (ifp, base, SEEK_SET); order = fget2(ifp); val = fget2(ifp); /* Should be 42 for standard TIFF */ while ((doff = fget4(ifp))) { fseek (ifp, doff+base, SEEK_SET); entries = fget2(ifp); while (entries--) { tag = fget2(ifp); type = fget2(ifp); len = fget4(ifp); if (type == 3 && len < 3) { val = fget2(ifp); fget2(ifp); } else val = fget4(ifp); save = ftell(ifp); fseek (ifp, base+val, SEEK_SET); switch (tag) { case 0x11: camera_red = val / 256.0; break; case 0x12: camera_blue = val / 256.0; break; case 0x100: /* ImageWidth */ wide = val; break; case 0x101: /* ImageHeight */ high = val; break; case 0x10f: /* Make tag */ fgets (make, 64, ifp); break; case 0x110: /* Model tag */ fgets (model, 64, ifp); break; case 0x111: /* StripOffset */ if (len == 1) offset = val; else offset = fget4(ifp); break; case 0x112: /* Rotation */ flip = flip_map[(val-1) & 7]; break; case 0x123: curve_offset = val; curve_length = len; break; case 0x827d: /* Model2 tag */ fgets (model2, 64, ifp); break; case 0x131: /* Software tag */ fgets (software, 64, ifp); if (!strncmp(software,"Adobe",5)) make[0] = 0; break; case 0x132: /* DateTime tag */ get_timestamp(); break; case 0x144: strcpy (make, "Leaf"); raw_width = wide; raw_height = high; if (len > 1) data_offset = fget4(ifp); else data_offset = val; break; case 0x14a: /* SubIFD tag */ if (len > 2 && !strcmp(make,"Kodak")) len = 2; if (len > 1) while (len--) { fseek (ifp, base+val, SEEK_SET); fseek (ifp, fget4(ifp)+base, SEEK_SET); tiff_parse_subifd(base); val += 4; } else tiff_parse_subifd(base); break; case 0x8769: /* EXIF tag */ parse_exif (base); break; } fseek (ifp, save, SEEK_SET); } } for (i=0; i < sizeof corp / sizeof *corp; i++) if (!strncmp (make, corp[i], strlen(corp[i]))) { if ((high & 1) && make[0] == 'O') high++; raw_width = wide; raw_height = high; if (offset) data_offset = offset; } d2922 1 a2922 1 data_offset = offset; d2924 1 a2924 1 if (make[0] == 0 && wide == 680 && high == 680) { d2928 19 d2951 1 a2951 1 int save, tag, len; d2954 4 a2957 4 data_offset = fget4(ifp) + 8; while ((save=ftell(ifp)) < data_offset) { tag = fget4(ifp); len = fget4(ifp); d2961 2 a2962 2 raw_height = fget2(ifp); raw_width = fget2(ifp); d2965 5 a2969 5 fget4(ifp); camera_red = fget2(ifp); camera_red /= fget2(ifp); camera_blue = fget2(ifp); camera_blue = fget2(ifp) / camera_blue; d2976 50 d3038 4 a3041 4 fget2(ifp); if (fget4(ifp) != 0x80008) return; if (fget4(ifp) == 0) return; bpp = fget2(ifp); d3046 1 a3046 1 bitbuf = bitbuf << 16 | (fget2(ifp) ^ key[i++ & 1]); d3050 1 a3050 1 bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp) << (14-bpp); d3056 1 a3056 2 Parse the CIFF structure looking for two pieces of information: The camera model, and the decode table number. d3071 1 a3071 1 tboff = fget4(ifp) + offset; d3073 1 a3073 1 nrecs = fget2(ifp); d3075 3 a3077 3 type = fget2(ifp); len = fget4(ifp); roff = fget4(ifp); d3088 1 a3088 1 wbi = fget2(ifp); d3097 4 a3100 4 white[0][1] = fget2(ifp) << 4; white[0][0] = fget2(ifp) << 4; white[1][0] = fget2(ifp) << 4; white[1][1] = fget2(ifp) << 4; d3110 4 a3113 4 camera_red = fget2(ifp) ^ key[0]; camera_red =(fget2(ifp) ^ key[1]) / camera_red; camera_blue = fget2(ifp) ^ key[0]; camera_blue /= fget2(ifp) ^ key[1]; d3131 4 a3134 4 camera_red = fget2(ifp); camera_red /= fget2(ifp); camera_blue = fget2(ifp); camera_blue = fget2(ifp) / camera_blue; d3142 2 a3143 2 raw_width = fget2(ifp); raw_height = fget2(ifp); d3147 1 a3147 1 timestamp = fget4(ifp); d3153 1 a3153 1 flip = fget4(ifp); d3157 1 a3157 1 crw_init_tables (fget4(ifp)); d3216 1 a3216 1 skip = fget4(ifp); d3224 2 a3225 2 if (!strcmp(data,"NeutObj_neutrals")) for (i=0; i < 4; i++) { d3227 3 a3229 2 if (i) pre_mul[i-1] = (float) neut[0] / neut[i]; } d3235 10 d3247 2 a3248 2 char *buf, *bp, *np; int off1, off2, len, i; d3251 2 d3254 48 a3301 28 off2 = fget4(ifp); fseek (ifp, off2, SEEK_SET); while (fget4(ifp) != 0x464d4143) /* Search for "CAMF" */ if (feof(ifp)) return; off1 = fget4(ifp); fseek (ifp, off1+8, SEEK_SET); off1 += (fget4(ifp)+3) * 8; len = (off2 - off1)/2; fseek (ifp, off1, SEEK_SET); buf = malloc (len); merror (buf, "parse_foveon()"); for (i=0; i < len; i++) /* Convert Unicode to ASCII */ buf[i] = fget2(ifp); for (bp=buf; bp < buf+len; bp=np) { np = bp + strlen(bp) + 1; if (!strcmp(bp,"CAMMANUF")) strcpy (make, np); if (!strcmp(bp,"CAMMODEL")) strcpy (model, np); if (!strcmp(bp,"TIME")) timestamp = atoi(np); } fseek (ifp, 248, SEEK_SET); raw_width = fget4(ifp); raw_height = fget4(ifp); fseek (ifp, 36, SEEK_SET); flip = fget4(ifp); free (buf); d3306 4 a3309 5 static const float foveon[3][3] = { { 2.0343955, -0.727533, -0.3067457 }, { -0.2287194, 1.231793, -0.0028293 }, { -0.0086152, -0.153336, 1.1617814 } }; d3314 1 a3314 1 coeff[i][j] = foveon[i][j] * pre_mul[i]; d3333 1 a3333 4 Given a matrix that converts RGB to GMCY, create a matrix to do the opposite. Only square matrices can be inverted, so I create four 3x3 matrices by omitting a different GMCY color in each one. The final coeff[][] matrix is the sum of these four. d3335 1 a3335 1 void CLASS gmcy_coeff() d3337 182 a3518 6 static const float gmcy[4][3] = { /* red green blue */ { 0.11, 0.86, 0.08 }, /* green */ { 0.50, 0.29, 0.51 }, /* magenta */ { 0.11, 0.92, 0.75 }, /* cyan */ { 0.81, 0.98, 0.08 } /* yellow */ d3520 3 a3522 2 double invert[3][6], num; int ignore, i, j, k, r, g; d3524 10 a3533 24 memset (coeff, 0, sizeof coeff); for (ignore=0; ignore < 4; ignore++) { for (j=0; j < 3; j++) { g = (j < ignore) ? j : j+1; for (r=0; r < 3; r++) { invert[j][r] = gmcy[g][r]; /* 3x3 matrix to invert */ invert[j][r+3] = (r == j); /* Identity matrix */ } } for (j=0; j < 3; j++) { num = invert[j][j]; /* Normalize this row */ for (i=0; i < 6; i++) invert[j][i] /= num; for (k=0; k < 3; k++) { /* Subtract it from the other rows */ if (k==j) continue; num = invert[k][j]; for (i=0; i < 6; i++) invert[k][i] -= invert[j][i] * num; } } for (j=0; j < 3; j++) { /* Add the result to coeff[][] */ g = (j < ignore) ? j : j+1; for (r=0; r < 3; r++) coeff[r][g] += invert[r][j+3]; a3534 8 } for (r=0; r < 3; r++) { /* Normalize such that: */ for (num=g=0; g < 4; g++) /* (1,1,1,1) x coeff = (1,1,1) */ num += coeff[r][g]; for (g=0; g < 4; g++) coeff[r][g] /= num; } use_coeff = 1; d3547 1 a3547 1 char make[12], model[16]; d3549 22 a3570 18 { 62464, "Kodak", "DC20" }, { 124928, "Kodak", "DC20" }, { 2465792, "NIKON", "E950" }, { 2940928, "NIKON", "E2100" }, { 4771840, "NIKON", "E990" }, { 4775936, "NIKON", "E3700" }, { 5865472, "NIKON", "E4500" }, { 5869568, "NIKON", "E4300" }, { 787456, "Creative", "PC-CAM 600" }, { 1976352, "Casio", "QV-2000UX" }, { 3217760, "Casio", "QV-3*00EX" }, { 6218368, "Casio", "QV-5700" }, { 7684000, "Casio", "QV-4000" }, { 9313536, "Casio", "EX-P600" }, { 10979200, "Casio", "EX-P700" }, { 4841984, "Pentax", "Optio S" }, { 6114240, "Pentax", "Optio S4" }, { 12582980, "Sinar", "" } }; d3573 1 a3573 1 "MINOLTA", "Minolta", "Konica" }; d3578 1 a3578 1 raw_height = raw_width = flip = 0; d3581 4 a3584 1 camera_red = camera_blue = timestamp = 0; d3586 4 a3589 2 data_offset = curve_offset = tiff_data_compression = 0; zero_after_ff = 0; d3594 2 a3595 2 order = fget2(ifp); hlen = fget4(ifp); d3604 2 a3605 2 fseek (ifp, fget4(ifp) + 136, SEEK_CUR); raw_width = fget4(ifp); d3607 1 a3607 1 raw_height = fget4(ifp); d3614 1 a3614 1 if (!strncmp(make,"NIKON",5) && raw_width == 0) d3622 1 a3622 1 fseek (ifp, 4 + fget2(ifp), SEEK_SET); d3629 1 a3629 1 if (fget4(ifp) == 2834 && fget4(ifp) == 2834) { d3640 4 a3643 4 data_offset += fget4(ifp); fget4(ifp); raw_width = fget4(ifp); raw_height = fget4(ifp); d3649 2 a3650 2 strcpy (make, "CONTAX"); strcpy (model,"N DIGITAL"); d3653 1 a3653 1 parse_tiff (fget4(ifp)+12); d3666 2 d3693 3 a3695 1 load_raw = NULL; d3698 15 a3712 6 fuji_width = top_margin = left_margin = 0; colors = 3; filters = 0x94949494; black = is_cmy = is_foveon = use_coeff = 0; use_gamma = xmag = ymag = 1; rgb_max = 0x3fff; d3716 1 d3728 8 a3735 1 if (!strcmp(model,"PowerShot 600")) { a3740 2 pre_mul[0] = 1.137; pre_mul[1] = 1.257; d3743 1 a3743 1 height = 776; a3748 3 pre_mul[0] = 1.5842; pre_mul[1] = 1.2966; pre_mul[2] = 1.0419; a3755 3 pre_mul[0] = 1.750; pre_mul[1] = 1.381; pre_mul[3] = 1.182; d3762 1 a3762 3 pre_mul[0] = 1.389; pre_mul[1] = 1.343; pre_mul[3] = 1.034; a3766 3 pre_mul[0] = 1.496; pre_mul[1] = 1.509; pre_mul[3] = 1.009; a3774 6 pre_mul[0] = 1.446; pre_mul[1] = 1.405; pre_mul[2] = 1.016; } else { pre_mul[0] = 1.785; pre_mul[2] = 1.266; a3780 2 pre_mul[0] = 1.592; pre_mul[2] = 1.261; a3785 8 if (!strcmp(model,"PowerShot G2") || !strcmp(model,"PowerShot S40")) { pre_mul[0] = 1.965; pre_mul[2] = 1.208; } else { /* G3 and S45 */ pre_mul[0] = 1.855; pre_mul[2] = 1.339; } a3790 2 pre_mul[0] = 1.895; pre_mul[2] = 1.403; d3796 1 a3796 7 pre_mul[0] = 2.242; pre_mul[2] = 1.245; if (!strcmp(model,"EOS Kiss Digital")) { pre_mul[0] = 1.882; pre_mul[2] = 1.094; } rgb_max = 16000; a3801 2 pre_mul[0] = 1.85; pre_mul[2] = 1.53; a3806 2 pre_mul[0] = 1.621; pre_mul[2] = 1.528; a3810 2 pre_mul[0] = 1.976; pre_mul[2] = 1.282; a3814 3 pre_mul[0] = 1.66; pre_mul[2] = 1.13; rgb_max = 14464; a3823 2 pre_mul[0] = 1.95; pre_mul[2] = 1.36; d3832 1 a3832 3 pre_mul[0] = 1.609; pre_mul[2] = 1.848; rgb_max = 0x3a00; d3834 1 a3834 2 black = 800; pre_mul[2] = 1.25; d3836 2 a3837 7 filters = 0x16161616; pre_mul[0] = 0.838; pre_mul[2] = 1.095; } else if (!strcmp(model,"D1H")) { filters = 0x16161616; pre_mul[0] = 2.301; pre_mul[2] = 1.129; a3839 1 filters = 0x16161616; a3840 2 pre_mul[0] = 1.910; pre_mul[2] = 1.220; a3843 4 filters = 0x61616161; pre_mul[0] = 2.374; pre_mul[2] = 1.677; rgb_max = 15632; d3847 5 a3851 8 filters = 0x49494949; pre_mul[0] = 2.8; pre_mul[2] = 1.2; } else if (!strcmp(model,"D70")) { filters = 0x16161616; pre_mul[0] = 2.043; pre_mul[2] = 1.625; } else if (!strcmp(model,"E950")) { d3862 1 d3866 12 a3877 13 if (nikon_e990()) { filters = 0xb4b4b4b4; nikon_e950_coeff(); pre_mul[0] = 1.196; pre_mul[1] = 1.246; pre_mul[2] = 1.018; } else { strcpy (model, "E995"); filters = 0xe1e1e1e1; pre_mul[0] = 1.253; pre_mul[1] = 1.178; pre_mul[3] = 1.035; } d3879 9 d3889 3 a3891 11 if (nikon_e2100()) { height = 1206; load_raw = nikon_e2100_load_raw; pre_mul[0] = 1.945; pre_mul[2] = 1.040; } else { strcpy (model, "E2500"); height = 1204; filters = 0x4b4b4b4b; goto coolpix; } d3893 1 d3899 11 a3909 8 if (pentax_optio33()) { strcpy (make, "Pentax"); strcpy (model,"Optio 33WR"); flip = 1; filters = 0x16161616; pre_mul[0] = 1.331; pre_mul[2] = 1.820; } d3911 11 d3925 4 a3928 5 if (minolta_z2()) { strcpy (make, "Minolta"); strcpy (model,"DiMAGE Z2"); load_raw = nikon_e2100_load_raw; } d3932 1 a3933 18 goto coolpix; } else if (!strcmp(model,"E5000") || !strcmp(model,"E5700")) { filters = 0xb4b4b4b4; coolpix: colors = 4; pre_mul[0] = 1.300; pre_mul[1] = 1.300; pre_mul[3] = 1.148; } else if (!strcmp(model,"E5400")) { filters = 0x16161616; pre_mul[0] = 1.700; pre_mul[2] = 1.344; } else if (!strcmp(model,"E8400") || !strcmp(model,"E8700") || !strcmp(model,"E8800")) { filters = 0x16161616; pre_mul[0] = 2.131; pre_mul[2] = 1.400; a3936 3 black = 256; pre_mul[0] = 2.322; pre_mul[2] = 1.404; d3943 1 a3943 3 black = 512; pre_mul[0] = 1.424; pre_mul[2] = 1.718; d3953 1 a3953 1 rgb_max = 0xffff; d3960 1 a3960 3 pre_mul[0] = 1.639; pre_mul[2] = 1.438; rgb_max = 0xf800; d3967 2 a3968 8 load_raw = low_12_load_raw; pre_mul[0] = 1.755; pre_mul[2] = 1.542; rgb_max = 0xffff; } else if (!strcmp(model,"FinePix S7000")) { pre_mul[0] = 1.62; pre_mul[2] = 1.38; goto fuji_s7000; d3970 2 a3971 4 !strcmp(model,"FinePix F810")) { pre_mul[0] = 1.65; pre_mul[2] = 1.29; fuji_s7000: d3977 1 a3977 1 rgb_max = 0xf800; d3985 1 a3985 3 pre_mul[0] = 1.639; pre_mul[2] = 1.438; rgb_max = 0x3e00; d3995 2 d4000 2 a4001 2 load_raw = low_12_load_raw; rgb_max = 15860; d4010 3 a4012 2 rgb_max = model[8] == '1' ? 15916:16380; } else if (!strncmp(model,"DYNAX",5) || d4015 1 a4015 1 rgb_max = 16364; d4019 2 d4039 2 a4040 2 load_raw = low_10_load_raw; rgb_max = 15856; d4042 8 a4049 4 camera_red = fget2(ifp); camera_blue = fget2(ifp); camera_red /= fget2(ifp); camera_blue /= fget2(ifp); a4050 2 pre_mul[0] = 1.42; pre_mul[2] = 1.25; d4052 1 a4052 3 load_raw = low_12_load_raw; pre_mul[0] = 1.76; pre_mul[1] = 1.07; d4057 18 a4074 7 height = 1544; width = 2068; raw_width = 3136; load_raw = packed_12_load_raw; pre_mul[0] = 1.506; pre_mul[2] = 1.152; } else if (!strcmp(model,"Optio S4")) { d4079 12 a4090 2 pre_mul[0] = 1.308; pre_mul[2] = 1.275; d4129 1 a4129 1 rgb_max = 0xffff; d4135 1 a4137 1 rgb_max = 0xffff; d4140 2 a4141 2 height = fget4(ifp); width = fget4(ifp); d4144 2 a4145 2 load_raw = all_16_load_raw; rgb_max = 0xffff; d4149 2 a4150 1 load_raw = low_12_load_raw; d4155 1 a4157 1 rgb_max = 0xffff; d4162 2 a4163 3 load_raw = high_12_load_raw; pre_mul[0] = 1.883; pre_mul[2] = 1.367; d4166 3 a4168 3 load_raw = high_12_load_raw; pre_mul[0] = 1.57; pre_mul[2] = 1.48; d4170 3 a4172 3 load_raw = high_12_load_raw; pre_mul[0] = 1.43; pre_mul[2] = 1.77; d4174 3 a4176 4 load_raw = high_12_load_raw; black = 640; pre_mul[0] = 1.43; pre_mul[2] = 1.77; d4181 2 a4182 2 load_raw = all_16_load_raw; rgb_max = 64560; d4184 2 a4185 5 black = 248; pre_mul[0] = 1.718; pre_mul[2] = 1.235; } else if (!strcmp(model,"C5050Z")) { filters = 0x16161616; d4187 4 a4190 16 pre_mul[0] = 1.533; pre_mul[2] = 1.880; } else if (!strcmp(model,"C5060WZ")) { load_raw = olympus_cseries_load_raw; pre_mul[0] = 2.285; pre_mul[2] = 1.023; } else if (!strncmp(model,"C70Z",4)) { load_raw = olympus_cseries_load_raw; pre_mul[0] = 1.648; pre_mul[2] = 1.660; } else if (!strcmp(model,"C8080WZ")) { filters = 0x16161616; load_raw = olympus_cseries_load_raw; pre_mul[0] = 2.335; pre_mul[2] = 1.323; } else if (!strcmp(model,"N DIGITAL")) { d4196 1 a4196 2 pre_mul[0] = 1.366; pre_mul[2] = 1.251; d4201 1 a4201 2 sony_rgbe_coeff(); filters = 0xb4b4b4b4; a4202 3 pre_mul[0] = 1.512; pre_mul[1] = 1.020; pre_mul[2] = 1.405; a4207 2 pre_mul[0] = 2.014; pre_mul[2] = 1.744; d4213 2 a4214 1 curve_length = 176; a4219 2 pre_mul[0] = 1.629; pre_mul[2] = 2.767; a4222 2 pre_mul[0] = 1.386; pre_mul[2] = 2.405; d4224 1 a4224 3 black = 32; pre_mul[1] = 1.068; pre_mul[2] = 1.036; d4226 1 a4226 3 black = 32; pre_mul[1] = 1.012; pre_mul[2] = 1.804; a4229 2 pre_mul[0] = 1.327; pre_mul[2] = 2.074; a4232 2 pre_mul[0] = 1.724; pre_mul[2] = 2.411; d4239 1 a4239 3 black = 720; pre_mul[0] = 1.006; pre_mul[2] = 1.858; d4241 1 a4241 3 black = 750; pre_mul[1] = 1.053; pre_mul[2] = 1.703; d4243 1 a4243 3 black = 720; pre_mul[1] = 1.002; pre_mul[2] = 1.818; d4245 1 a4245 4 black = 740; pre_mul[0] = 1.486; pre_mul[2] = 1.280; is_cmy = 1; d4247 1 a4247 3 black = 855; pre_mul[0] = 1.156; pre_mul[2] = 1.626; d4249 1 a4249 1 black = 855; a4251 7 } else if (!strcmp(model,"DCS720X")) { pre_mul[0] = 1.35; pre_mul[2] = 1.18; is_cmy = 1; } else if (!strcmp(model,"DCS760C")) { pre_mul[0] = 1.06; pre_mul[2] = 1.72; a4254 24 } else if (!strcmp(model,"ProBack")) { pre_mul[0] = 1.06; pre_mul[2] = 1.385; } else if (!strncmp(model2,"PB645C",6)) { pre_mul[0] = 1.0497; pre_mul[2] = 1.3306; } else if (!strncmp(model2,"PB645H",6)) { pre_mul[0] = 1.2010; pre_mul[2] = 1.5061; } else if (!strncmp(model2,"PB645M",6)) { pre_mul[0] = 1.01755; pre_mul[2] = 1.5424; } else if (!strcasecmp(model,"DCS Pro 14n")) { pre_mul[1] = 1.0323; pre_mul[2] = 1.258; } else if (!strcasecmp(model,"DCS Pro 14nx")) { pre_mul[0] = 1.336; pre_mul[2] = 1.3155; } else if (!strcasecmp(model,"DCS Pro SLR/c")) { pre_mul[0] = 1.425; pre_mul[2] = 1.293; } else if (!strcasecmp(model,"DCS Pro SLR/n")) { pre_mul[0] = 1.324; pre_mul[2] = 1.483; d4292 1 a4292 1 kodak_dc20_coeff (0.5); a4350 21 } else if (!strcmp(make,"SIGMA")) { switch (raw_height) { case 763: height = 756; top_margin = 2; break; case 1531: height = 1514; top_margin = 7; break; } switch (raw_width) { case 1152: width = 1136; left_margin = 8; break; case 2304: width = 2271; left_margin = 17; break; } if (height*2 < width) ymag = 2; filters = 0; load_raw = foveon_load_raw; is_foveon = 1; pre_mul[0] = 1.179; pre_mul[2] = 0.713; if (!strcmp(model,"SD10")) { pre_mul[0] *= 2.07; pre_mul[2] *= 2.30; } foveon_coeff(); rgb_max = 5600; d4371 2 a4372 1 load_raw = high_12_load_raw; d4377 14 d4396 2 a4397 2 pre_mul[0] = 2.356; pre_mul[1] = 1.069; d4403 2 a4404 2 pre_mul[0] = 2.34; pre_mul[2] = 1.24; d4407 1 a4407 1 load_raw = low_12_load_raw; d4414 2 d4429 2 a4430 2 if (colors == 4 && !use_coeff) gmcy_coeff(); a4455 1 int shift=0, size, i; d4473 2 a4474 8 while (rgb_max << shift < 0x8000) shift++; size = width * height * 4; if (shift) for (i=0; i < size; i++) image[0][i] <<= shift; rgb_max = 0xffff; use_gamma = use_coeff = is_cmy = 0; d4494 1 a4494 1 float rgb[3], mag; d4509 1 a4509 1 else if (use_coeff) { /* RGB from GMCY or Foveon */ a4512 4 } else if (is_cmy) { /* RGB from CMY */ rgb[0] = img[0] + img[1] - img[2]; rgb[1] = img[1] + img[2] - img[0]; rgb[2] = img[2] + img[0] - img[1]; d4516 2 a4517 4 if (rgb[r] < 0) rgb[r] = 0; if (rgb[r] > rgb_max) rgb[r] = rgb_max; d4521 2 a4522 9 if (write_fun == write_ppm) { for (mag=r=0; r < 3; r++) mag += (unsigned) img[r]*img[r]; mag = sqrt(mag)/2; if (mag > 0xffff) mag = 0xffff; img[3] = mag; histogram[img[3] >> 3]++; } d4552 1 a4552 1 for (i=0; i < 4; i++) d4616 1 a4616 1 Write the image to a 24-bpp PPM file. d4620 3 a4622 12 int row, col, i, c, val, total; float white, r, scale[0x10000]; ushort *rgb; uchar (*ppm)[3]; /* Set the white point to the 99th percentile. */ i = width * height * 0.01; if (fuji_width) i /= 2; for (val=0x2000, total=0; --val; ) if ((total += histogram[val]) > i) break; white = (val << 3) / bright; a4625 1 d4628 10 a4637 2 scale[0] = 0; for (i=1; i < 0x10000; i++) { d4639 1 a4639 1 scale[i] = 221.7025 / i * ( !use_gamma ? r : d4641 2 d4645 3 a4647 9 for (col=trim; col < width-trim; col++) { rgb = image[row*width+col]; for (c=0; c < 3; c++) { val = rgb[c] * scale[rgb[3]]; if (val > 255) val=255; for (i=0; i < xmag; i++) ppm[xmag*(col-trim)+i][c] = val; } } d4655 1 a4655 1 Write the image to a 48-bpp Photoshop file. d4672 2 a4673 2 int hw[2], psize, row, col, c, val; ushort *buffer, *pred, *rgb; d4687 1 a4687 7 rgb = image[row*width+col]; for (c=0; c < 3; c++) { val = rgb[c] * bright; if (val > 0xffff) val = 0xffff; pred[c*psize] = htons(val); } d4696 1 a4696 1 Write the image to a 48-bpp PPM file. d4700 2 a4701 2 int row, col, c, val; ushort *rgb, (*ppm)[3]; d4703 1 a4703 5 val = rgb_max * bright; if (val < 256) val = 256; if (val > 0xffff) val = 0xffff; d4705 1 a4705 1 width-trim*2, height-trim*2, val); d4711 2 a4712 9 for (col = trim; col < width-trim; col++) { rgb = image[row*width+col]; for (c=0; c < 3; c++) { val = rgb[c] * bright; if (val > 0xffff) val = 0xffff; ppm[col-trim][c] = htons(val); } } d4732 1 a4732 1 "\nRaw Photo Decoder \"dcraw\" v6.35" d4744 2 d4788 2 d4809 1 a4809 1 #if defined(WIN32) || defined(DJGPP) d4816 1 a4816 3 for ( ; arg < argc; arg++) { d4843 1 a4843 1 image = calloc (iheight * iwidth, sizeof *image); d4845 1 @ 1.235 log @Added the Casio EX-P700. Fixed three potential buffer overruns. @ text @d4111 2 a4112 1 for (i=0; i < 0x10000; i++) { @ 1.234 log @Call fuji_rotate() before apply_profile(). Do not use the gamma curve after applying a profile. @ text @d567 1 a567 1 for (i=0; i < curve_length; i++) d974 1 a974 1 ushort pixel[4134], akey, bkey; d981 2 d994 1 d1554 1 a1554 1 ushort pixel[3360]; d1568 2 d1578 1 d2907 1 d3853 7 d3932 1 a3932 1 image[0][i] <<= 2; d4227 1 a4227 1 "\nRaw Photo Decoder \"dcraw\" v6.34" @ 1.233 log @Improved Pentax Optio 33WR detection. @ text @d76 2 a77 1 int is_canon, is_cmy, is_foveon, use_coeff, trim, flip, xmag, ymag; d3026 1 a3026 1 xmag = ymag = 1; d3920 1 a3920 1 use_coeff = is_cmy = 0; d4099 2 a4100 1 scale[i] = (r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099) * 221.7025 / i; d4213 1 a4213 1 "\nRaw Photo Decoder \"dcraw\" v6.33" d4347 1 a4350 1 fuji_rotate(); @ 1.232 log @Changed default rgb_max from 0x4000 to 0x3fff. @ text @d797 2 a798 2 int i; char tail[952]; d803 2 a804 2 if (!tail[i]) return 0; return 1; @ 1.231 log @Added the Pentax Optio 33WR. Flip the Nucore images to proper orientation. Do fuji_rotate() before convert_to_rgb(). @ text @d3026 1 a3026 1 rgb_max = 0x4000; @ 1.230 log @For Leaf cameras, get pre_mul[] values from the metadata. Added preliminary support for color profiles using LCMS. @ text @d793 15 d1154 1 a1154 4 if (model[0] == 'B' && width == 2598) row = height - 1 - irow/2 - height/2 * (irow & 1); else row = irow; d2958 1 d3269 8 d3847 6 a3852 1 load_raw = nucore_load_raw; d4019 1 d4211 1 a4211 1 "\nRaw Photo Decoder \"dcraw\" v6.32" d4348 1 a4351 1 fuji_rotate(); @ 1.229 log @Added the Nikon E8400. Tweaked the gamma curve yet again. @ text @d91 5 d2715 28 d2902 1 d2905 3 d2981 2 a3011 1 pre_mul[0] = pre_mul[1] = pre_mul[2] = pre_mul[3] = 1; d3493 1 a3493 3 load_raw = all_16_load_raw; pre_mul[0] = 1.1629; pre_mul[2] = 1.3556; a3497 3 pre_mul[0] = 2.103; pre_mul[1] = 1.256; pre_mul[2] = 1.0; d3865 41 d4177 3 d4184 1 a4184 1 "\nRaw Photo Decoder \"dcraw\" v6.31" d4191 8 a4198 1 "\n-f Interpolate RGBG as four colors" d4202 1 a4203 5 "\n-b Set brightness (1.0 by default)" "\n-a Use automatic white balance" "\n-w Use camera white balance, if possible" "\n-r Set red multiplier (daylight = 1.0)" "\n-l Set blue multiplier (daylight = 1.0)" d4225 3 a4227 1 a4298 1 fclose(ifp); d4318 3 d4333 1 @ 1.228 log @Use the standard video gamma function -- no more "-g". Enable "-s" option for the Fuji S3. Fixed segfault in fuji_rotate(). Added the Leaf Volare. Removed unused canon_rgb_coeff() function. @ text @d3243 2 a3244 1 } else if (!strcmp(model,"E8700") || d3248 1 a3248 1 pre_mul[2] = 1.300; d3988 1 a3988 1 white = (val << 4) / bright; d3997 1 a3997 1 scale[i] = (r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099) * 256 / i; d4107 1 a4107 1 "\nRaw Photo Decoder \"dcraw\" v6.30" @ 1.227 log @Added fuji_rotate() function; fujiturn is no longer needed. @ text @d81 1 a81 1 float gamma_val=0.6, bright=1.0, red_scale=1.0, blue_scale=1.0; d987 17 a2761 18 /* The grass is always greener in my PowerShot G2 when this function is called. Use at your own risk! */ void CLASS canon_rgb_coeff (float juice) { static const float my_coeff[3][3] = { { 1.116187, -0.107427, -0.008760 }, { -1.551374, 4.157144, -1.605770 }, { 0.090939, -0.399727, 1.308788 } }; int i, j; for (i=0; i < 3; i++) for (j=0; j < 3; j++) coeff[i][j] = my_coeff[i][j] * juice + (i==j) * (1-juice); use_coeff = 1; } a3061 4 #ifdef CUSTOM if (write_fun == write_ppm) /* Pro users may not want my matrix */ canon_rgb_coeff (0.1); #endif d3268 2 d3457 9 d3905 1 a3905 1 if (ur >= height || uc >= width) continue; d3977 1 a3977 1 float max, mul, scale[0x10000]; d3987 1 a3987 1 max = val << 4; d3994 4 a3997 5 mul = bright * 442 / max; scale[0] = 0; for (i=1; i < 0x10000; i++) scale[i] = mul * pow (i*2/max, gamma_val-1); d4106 1 a4106 1 "\nRaw Photo Decoder \"dcraw\" v6.25" a4117 1 "\n-g Set gamma (0.6 by default, only for 24-bpp output)" d4124 3 a4126 3 "\n-2 Write 24-bpp PPM (default)" "\n-3 Write 48-bpp PSD (Adobe Photoshop)" "\n-4 Write 48-bpp PPM" d4134 1 a4134 1 if (strchr ("gbrl", opt) && !isdigit(argv[arg][0])) { a4139 1 case 'g': gamma_val = atof(argv[arg++]); break; @ 1.226 log @Added the Epson R-D1. Added the read_shorts() function and refactored. @ text @d74 1 a74 1 int height, width, colors, black, rgb_max; d2970 1 a2970 1 top_margin = left_margin = 0; d3262 1 d3272 1 d3279 1 d3306 1 d3314 1 d3877 37 d3978 1 a3978 1 if (!strcmp(make,"FUJIFILM") && abs(width-height) < 2) i /= 2; d4101 1 a4101 1 "\nRaw Photo Decoder \"dcraw\" v6.23" d4236 1 @ 1.225 log @Added the Fuji FinePix S3Pro and Minolta DiMAGE A200. @ text @d197 2 a198 2 a = fgetc(f); b = fgetc(f); d200 1 a200 1 return a + (b << 8); d202 1 a202 1 return (a << 8) + b; d212 2 a213 4 a = fgetc(f); b = fgetc(f); c = fgetc(f); d = fgetc(f); d215 1 a215 1 return a + (b << 8) + (c << 16) + (d << 24); d217 11 a227 1 return (a << 24) + (b << 16) + (c << 8) + d; d853 1 a853 1 fread (pixel, 2, 2944, ifp); d857 1 a857 1 BAYER(r,c) = ntohs(pixel[col]) << 2; d869 1 a869 3 fread (pixel, 2, 4352, ifp); if (ntohs(0xaa55) == 0xaa55) /* data is little-endian */ swab (pixel, pixel, 4352*2); d884 1 a884 3 fread (pixel, 2, ncol, ifp); if (ntohs(0xaa55) == 0xaa55) /* data is little-endian */ swab (pixel, pixel, ncol*2); d915 1 a915 3 fread (pixel, 2, 2944, ifp); if (ntohs(0xaa55) == 0xaa55) /* data is little-endian */ swab (pixel, pixel, 2944*2); d961 1 a961 1 fread (pixel, 2, raw_width, ifp); d963 2 a964 2 a = ntohs(pixel[col+0]) ^ akey; b = ntohs(pixel[col+1]) ^ bkey; d978 1 d981 1 a981 3 fread (pixel, 2, 4090, ifp); if (ntohs(0xaa55) == 0xaa55) /* data is little-endian */ swab (pixel, pixel, 4090*2); d1001 1 a1001 1 void CLASS unpacked_load_raw (int order, int rsh) d1009 1 a1009 3 fread (pixel, 2, raw_width, ifp); if (order != ntohs(0x55aa)) swab (pixel, pixel, width*2); d1016 1 a1016 1 void CLASS be_16_load_raw() /* "be" = "big-endian" */ d1018 1 a1018 1 unpacked_load_raw (0x55aa, 0); d1021 1 a1021 1 void CLASS be_high_12_load_raw() d1023 1 a1023 1 unpacked_load_raw (0x55aa, 2); d1026 1 a1026 1 void CLASS be_low_12_load_raw() d1028 1 a1028 1 unpacked_load_raw (0x55aa,-2); d1031 1 a1031 1 void CLASS be_low_10_load_raw() d1033 1 a1033 16 unpacked_load_raw (0x55aa,-4); } void CLASS le_16_load_raw() /* "le" = "little-endian" */ { unpacked_load_raw (0xaa55, 0); } void CLASS le_high_12_load_raw() { unpacked_load_raw (0xaa55, 2); } void CLASS le_low_12_load_raw() { unpacked_load_raw (0xaa55,-2); d1110 1 a1110 1 uchar *data, *dp; d1113 2 a1114 2 data = calloc (width, 2); merror (data, "nucore_load_raw()"); d1116 1 a1116 1 fread (data, 2, width, ifp); d1121 2 a1122 2 for (dp=data, col=0; col < width; col++, dp+=2) BAYER(row,col) = (dp[0] << 2) + (dp[1] << 10); d1124 1 a1124 1 free (data); d1411 1 a1411 3 fread (raw, 2, 6, ifp); for (i=0; i < 6; i++) raw[i] = ntohs(raw[i]); d2860 1 a2860 1 { "Canon", "NIKON", "Kodak", "OLYMPUS", "PENTAX", a2931 1 order = 0x4d4d; d2933 2 a2934 1 data_offset = fget4(ifp); d3253 6 d3288 1 a3288 1 load_raw = le_low_12_load_raw; d3327 1 a3327 1 load_raw = be_low_12_load_raw; d3363 1 a3363 1 load_raw = be_low_10_load_raw; d3374 1 a3374 1 load_raw = be_low_12_load_raw; d3447 1 a3447 1 load_raw = be_16_load_raw; d3452 1 a3452 1 load_raw = be_16_load_raw; d3460 1 a3460 1 load_raw = le_high_12_load_raw; d3465 1 a3465 1 load_raw = le_high_12_load_raw; d3469 1 a3469 1 load_raw = be_high_12_load_raw; d3473 1 a3473 1 load_raw = be_high_12_load_raw; d3481 1 a3481 1 load_raw = le_16_load_raw; d3767 1 a3767 1 load_raw = be_high_12_load_raw; d4059 1 a4059 1 "\nRaw Photo Decoder \"dcraw\" v6.22" @ 1.224 log @Improved support for the Canon S70 and Olympus E-300. @ text @d854 18 d2880 1 d3279 7 d3342 6 d4071 1 a4071 1 "\nRaw Photo Decoder \"dcraw\" v6.21" @ 1.223 log @Fixed camera white balance for the PowerShots G6, S70, and Pro1. @ text @d3 1 a3 1 Copyright 1997-2004 by Dave Coffin, dcoffin a cybercom o net d1019 6 a1024 1 void CLASS le_high_12_load_raw() /* "le" = "little-endian" */ d2550 1 d2603 1 a2603 1 fseek (ifp, aoff+104 + wbi*8, SEEK_SET); d2623 1 a2623 1 if (type == 0x1030 && (wbi == 6 || wbi > 14)) { d3460 5 d3913 2 a3914 3 /* Set the white point to the 99th percentile */ d4039 1 a4039 1 "\nRaw Photo Decoder \"dcraw\" v6.20" @ 1.222 log @Added the Olympus C70Z,C7000Z. @ text @d2545 1 d2547 4 d2584 1 a2584 6 if (wbi == 6 && fget4(ifp) == 0) wbi = 15; else { fseek (ifp, aoff+100, SEEK_SET); goto common; } d2591 11 a2601 4 camera_red = fget2(ifp); camera_red = fget2(ifp) / camera_red; camera_blue = fget2(ifp); camera_blue /= fget2(ifp); d2617 2 a2618 2 if (type == 0x1030 && wbi > 14) { /* Get white sample */ fseek (ifp, aoff, SEEK_SET); d4029 1 a4029 1 "\nRaw Photo Decoder \"dcraw\" v6.19" @ 1.221 log @Added the Nikon E3700 and Olympus E-300. @ text @d3458 4 d4022 1 a4022 1 "\nRaw Photo Decoder \"dcraw\" v6.18" @ 1.220 log @Minolta "MAXXUM" is the same as "DYNAX". @ text @d802 1 a802 1 fseek (ifp, width==1616 ? 8792:424, SEEK_CUR); d1029 23 d2834 1 d3203 6 d3444 5 d4018 1 a4018 1 "\nRaw Photo Decoder \"dcraw\" v6.17" @ 1.219 log @Added the Fuji FinePix F810. @ text @d3275 2 a3276 1 } else if (!strncmp(model,"DYNAX",5)) { @ 1.218 log @Added the Pentax *ist DS. @ text @d3239 4 a3242 3 } else if (!strcmp(model,"FinePix E550")) { pre_mul[0] = 1.45; pre_mul[2] = 1.25; d3982 1 a3982 1 "\nRaw Photo Decoder \"dcraw\" v6.16" @ 1.217 log @Flip Foveon images, allow camera white balance for the Pentax *ist D. Added the Fuji FinePix S5100/S5500, Minolta Dynax 7D, and Sony DSC-V3. @ text @d2287 1 a2287 1 camera_blue/= fget2(ifp); d2348 1 a2348 1 int wide=0, high=0, cr2_offset=0, offset=0; d2350 1 d2388 4 a2391 2 cr2_offset = val; offset = fget4(ifp); d2440 9 a2448 4 if (!strncmp(make,"OLYMPUS",7)) { make[7] = 0; raw_width = wide; raw_height = - (-high & -2); a2449 7 } if (!strncmp(make,"SONY",4)) { raw_width = wide; raw_height = high; } if (!strcmp(make,"Canon") && strcmp(model,"EOS D2000C")) data_offset = cr2_offset; d2823 2 a2824 1 { "Canon", "NIKON", "Kodak", "PENTAX", "MINOLTA", "Minolta", "Konica" }; a3308 3 height = 2024; width = 3040; data_offset = 0x10000; d3312 3 d3981 1 a3981 1 "\nRaw Photo Decoder \"dcraw\" v6.15" @ 1.216 log @Sony DSC-F828 matrix had green and emerald swapped. Oops. @ text @d1024 5 d1489 1 a1489 1 unsigned i, key, row, col, icol; d1501 1 a1501 1 fseek (ifp, 862144, SEEK_SET); d1505 4 a1508 5 for (col=0; col < 3343; col++) if ((icol = col-left_margin) < width) BAYER(row,icol) = ntohs(pixel[col]); else bblack += ntohs(pixel[col]); d1510 2 a1511 1 black = bblack / ((3343 - width) * height); d2196 1 a2196 1 fseek (ifp, val+base, SEEK_SET); d2214 1 a2214 1 void CLASS nef_parse_makernote() d2232 3 d2237 2 d2247 1 a2247 1 if (type == 3) { /* short int */ d2252 1 a2252 1 if (tag == 0xc) { d2282 8 a2289 1 if (tag == 0x1017) /* Olympus */ d2317 1 a2317 1 void CLASS nef_parse_exif (int base) d2328 1 a2328 1 fseek (ifp, val+base, SEEK_SET); d2331 6 a2336 3 if (tag == 0x927c && (!strncmp(make,"NIKON",5) || !strncmp(make,"OLYMPUS",7))) nef_parse_makernote(); d2366 1 a2366 1 fseek (ifp, val+base, SEEK_SET); d2422 1 a2422 1 fseek (ifp, val+base, SEEK_SET); d2430 2 a2431 2 case 0x8769: /* Nikon EXIF tag */ nef_parse_exif(base); d2443 4 d2456 29 d2603 1 a2603 5 switch (fget4(ifp)) { case 270: flip = 5; break; case 180: flip = 3; break; case 90: flip = 6; } d2688 2 d2856 3 a2858 15 } else if (!memcmp (head,"\0MRM",4)) { parse_tiff(48); fseek (ifp, 4, SEEK_SET); data_offset = fget4(ifp) + 8; fseek (ifp, 24, SEEK_SET); raw_height = fget2(ifp); raw_width = fget2(ifp); fseek (ifp, 12, SEEK_SET); /* PRD */ fseek (ifp, fget4(ifp) + 4, SEEK_CUR); /* TTW */ fseek (ifp, fget4(ifp) + 12, SEEK_CUR); /* WBG */ camera_red = fget2(ifp); camera_red /= fget2(ifp); camera_blue = fget2(ifp); camera_blue = fget2(ifp) / camera_blue; } else if (!memcmp (head,"\xff\xd8\xff\xe1",4) && d3223 10 d3272 3 a3432 1 height = 2460; a3433 1 raw_width = 3360; d3442 7 d3797 5 d3855 2 a3856 1 i = width * height * (strcmp(make,"FUJIFILM") ? 0.01 : 0.005); d3979 1 a3979 1 "\nRaw Photo Decoder \"dcraw\" v6.12" @ 1.215 log @Don't segfault when lossless JPEG data is corrupt. @ text @d1513 3 a1515 3 { { 1.321918, 0.000000, 0.149829, -0.471747 }, { -0.288764, 1.129213, -0.486517, 0.646067 }, { 0.061336, -0.199343, 1.138007, 0.000000 } }; d3916 1 a3916 1 "\nRaw Photo Decoder \"dcraw\" v6.11" @ 1.214 log @Macintosh mktime() chokes on "TZ=". Better to use "TZ=UTC". @ text @d572 1 a572 1 ushort curve[0x10000]; d617 1 d3916 1 a3916 1 "\nRaw Photo Decoder \"dcraw\" v6.10" @ 1.213 log @Added the Canon EOS-1Ds Mark II. @ text @d2294 1 a2294 1 putenv ("TZ="); /* Remove this to assume local time */ @ 1.212 log @Added the Minolta DiMAGE G400 and Fuji FinePix S20Pro. Added the "-s" option for Fuji secondary sensors. @ text @d568 1 a568 1 int tag, len, jhigh=0, jwide=0, trick, row, col, diff; d587 1 a587 1 jwide = (data[3] << 8) + data[4]; a598 1 trick = 2 * jwide / width; d601 2 a602 2 for (row=0; row < raw_height; row++) for (col=0; col < raw_width; col++) d604 1 a604 1 for (dindex = dstart[col & 1]; dindex->branch[0]; ) d610 3 a612 3 if (col < 2 && (row % trick == 0)) { vpred[col] += diff; hpred[col] = vpred[col]; d614 2 a615 2 hpred[col & 1] += diff; diff = hpred[col & 1]; d617 15 d3052 11 d3915 1 a3915 1 "\nRaw Photo Decoder \"dcraw\" v6.09" @ 1.211 log @Added the Nikon E8800. @ text @d83 1 a83 1 int verbose=0, use_auto_wb=0, use_camera_wb=0; d884 1 a884 7 val = pixel[col+16]; if (val == 0x3fff) { /* If the primary is maxed, */ val = pixel[col+1488] << 4; /* use the secondary. */ rgb_max = 0xffff; } if (val > 0xffff) val = 0xffff; d2756 1 a2756 1 { "Canon", "NIKON", "Kodak", "PENTAX", "Minolta", "Konica" }; d3157 1 a3157 1 rgb_max = 0xf7ff; d3170 3 a3172 2 rgb_max = 0xf7ff; } else if (!strcmp(model,"FinePix F700")) { d3179 1 a3179 1 rgb_max = 14000; d3191 1 a3191 1 } else if (!strcmp(make,"Minolta")) { d3198 6 a3203 1 if (model[8] <= '5') { d3890 1 a3890 1 "\nRaw Photo Decoder \"dcraw\" v6.08" d3901 1 d3940 1 @ 1.210 log @Added the Minolta DiMAGE Z2. @ text @d3143 2 a3144 1 } else if (!strcmp(model,"E8700")) { d3890 1 a3890 1 "\nRaw Photo Decoder \"dcraw\" v6.07" @ 1.209 log @Added the Minolta DiMAGE G600. Changed Fuji E550, Fuji S7000, and Minolta white balances. @ text @d764 15 d781 2 a782 2 uchar data[2424], *dp; ushort pixel[1616], *pix; d787 1 a787 1 fseek (ifp, 8792, SEEK_CUR); d790 10 a799 11 fread (data, 2424, 1, ifp); for (dp=data, pix=pixel; dp < data+2424; dp+=12, pix+=8) { pix[0] = (dp[ 3] << 2) + (dp[2] >> 6); pix[1] = (dp[ 1] >> 2) + (dp[2] << 6); pix[2] = (dp[ 0] << 2) + (dp[7] >> 6); pix[3] = (dp[ 6] >> 2) + (dp[7] << 6); pix[4] = (dp[ 5] << 2) + (dp[4] >> 6); pix[5] = (dp[11] >> 2) + (dp[4] << 6); pix[6] = (dp[10] << 2) + (dp[9] >> 6); pix[7] = (dp[ 8] >> 2) + (dp[9] << 6); d802 1 a802 1 BAYER(row,col) = (pixel[col] & 0x3ff) << 4; d3122 5 d3889 1 a3889 1 "\nRaw Photo Decoder \"dcraw\" v6.06" @ 1.208 log @Added the Konica KD-400Z. Fixed rgb_max for all Minolta cameras. Range of tm_mon is 0 to 11, not 1 to 12! @ text @d3144 8 a3151 2 } else if (!strcmp(model,"FinePix S7000") || !strcmp(model,"FinePix E550")) { a3155 2 pre_mul[0] = 1.81; pre_mul[2] = 1.38; a3168 1 filters = 0x94949494; d3183 3 a3185 2 data_offset = 4016; fseek (ifp, 1936, SEEK_SET); d3187 9 a3195 3 height = 1956; width = 2607; raw_width = 2624; d3206 1 a3206 1 pre_mul[0] = 2.00; d3870 1 a3870 1 "\nRaw Photo Decoder \"dcraw\" v6.05" @ 1.207 log @Fixed vng_interpolate() to match Ting Chen's vargra.m. Use putenv() instead of setenv() for portability. Correctly parse .badpixels when it lacks a final newline. Added the FUJIFILM FinePix E550. @ text @d1899 2 a1903 2 if (min[c] > val) min[c] = val; if (max[c] < val) max[c] = val; d2271 1 d2575 1 d2748 1 a2748 1 { "Canon", "NIKON", "Kodak", "PENTAX", "Minolta" }; d3161 8 d3175 2 a3176 1 if (!strncmp(model,"DiMAGE A",8)) d3178 2 a3179 1 else if (!strncmp(model,"DiMAGE G",8)) { a3182 1 load_raw = be_low_10_load_raw; d3187 2 d3860 1 a3860 1 "\nRaw Photo Decoder \"dcraw\" v6.04" @ 1.206 log @Added "CLASS" macro for easier conversion to C++. @ text @d1857 1 a1857 3 while (1) { fgets (line, 128, fp); if (feof(fp)) break; d1976 1 a1976 1 -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,0,0x01, d1978 1 a1978 1 -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,0,0x04, -2,+1,+0,+0,0,0x06, d1981 1 a1981 1 -1,-2,+1,+0,0,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40, d1984 2 a1985 2 -1,+0,+1,-2,0,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22, -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,0,0x10, -1,+1,+1,-1,1,0x44, d1987 1 a1987 1 -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,0,0x04, -1,+2,+1,+1,0,0x04, d1990 1 a1990 1 +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,0,0x10, +0,+0,+0,+2,1,0x08, d1993 1 a1993 1 +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,0,0x40, +0,+1,+2,+0,0,0x60, d1999 1 a1999 1 int code[8][640], *ip, gval[8], gmin, gmax, sum[4]; a2003 1 ip = code[row]; d2005 1 a2024 1 pix = image[row*width+1]; d2026 2 a2027 2 if (col & 1) ip = code[row & 7]; a2037 1 pix += 4; a2043 1 ip = code[row]; d2045 1 d2067 1 a2067 2 if ((g & 1) == 0 && FC(row+y,col+x) != color && FC(row+y*2,col+x*2) == color) a2078 1 pix = image[row*width+2]; d2080 2 a2081 2 if ((col & 1) == 0) ip = code[row & 7]; d2098 4 a2123 1 pix += 4; d2271 1 a2271 1 setenv ("TZ", "", 1); /* Remove this to assume local time */ d2574 1 a2574 1 setenv ("TZ", "", 1); d3142 2 a3143 1 } else if (!strcmp(model,"FinePix S7000")) { d3604 1 d3847 1 a3847 1 "\nRaw Photo Decoder \"dcraw\" v6.02" @ 1.205 log @Get UNIX timestamps from all image formats. Added the Konica KD-510Z. @ text @d62 5 a66 2 /* Global Variables */ d96 2 d182 1 a182 1 void merror (void *ptr, char *where) d193 1 a193 1 ushort fget2 (FILE *f) d208 1 a208 1 int fget4 (FILE *f) d222 1 a222 1 void canon_600_load_raw() d252 1 a252 1 void canon_a5_load_raw() d284 1 a284 1 unsigned getbits (int nbits) d307 1 a307 1 void init_decoder() d339 1 a339 1 uchar *make_decoder (const uchar *source, int level) d365 1 a365 1 void crw_init_tables (unsigned table) d441 1 a441 1 int canon_has_lowbits() d456 1 a456 1 void canon_compressed_load_raw() d530 1 a530 1 void kodak_curve (ushort *curve) d566 1 a566 1 void lossless_jpeg_load_raw() d633 1 a633 1 void nikon_compressed_load_raw() d682 1 a682 1 void nikon_load_raw() d712 1 a712 1 int nikon_is_compressed() d731 1 a731 1 int nikon_e990() d749 1 a749 1 int nikon_e2100() d764 1 a764 1 void nikon_e2100_load_raw() d792 1 a792 1 void nikon_e950_load_raw() d809 1 a809 1 void fuji_s2_load_raw() d825 1 a825 1 void fuji_common_load_raw (int ncol, int icol, int nrow) d842 1 a842 1 void fuji_s5000_load_raw() d848 1 a848 1 void fuji_s7000_load_raw() d858 1 a858 1 void fuji_f700_load_raw() d882 1 a882 1 void rollei_load_raw() d907 1 a907 1 void phase_one_load_raw() d930 1 a930 1 void ixpress_load_raw() d946 1 a946 1 void packed_12_load_raw() d959 1 a959 1 void unpacked_load_raw (int order, int rsh) d976 1 a976 1 void be_16_load_raw() /* "be" = "big-endian" */ d981 1 a981 1 void be_high_12_load_raw() d986 1 a986 1 void be_low_12_load_raw() d991 1 a991 1 void be_low_10_load_raw() d996 1 a996 1 void le_high_12_load_raw() /* "le" = "little-endian" */ d1001 1 a1001 1 void olympus_cseries_load_raw() d1016 1 a1016 1 void eight_bit_load_raw() d1031 1 a1031 1 void casio_qv5700_load_raw() d1050 1 a1050 1 void nucore_load_raw() d1069 1 a1069 1 const int *make_decoder_int (const int *source, int level) d1086 1 a1086 1 int radc_token (int tree) d1132 1 a1132 1 void kodak_radc_load_raw() d1200 1 a1200 1 void kodak_jpeg_load_raw() {} d1216 1 a1216 1 void kodak_jpeg_load_raw() d1257 1 a1257 1 void kodak_dc120_load_raw() d1273 1 a1273 1 void kodak_dc20_coeff (float juice) d1291 1 a1291 1 void kodak_easy_load_raw() d1319 1 a1319 1 void kodak_compressed_load_raw() d1383 1 a1383 1 void kodak_yuv_load_raw() d1440 1 a1440 1 void sony_decrypt (unsigned *data, int len, int start, int key) d1457 1 a1457 1 void sony_load_raw() d1486 1 a1486 1 void sony_rgbe_coeff() d1500 1 a1500 1 void foveon_decoder (unsigned huff[1024], unsigned code) d1526 1 a1526 1 void foveon_load_raw() d1564 1 a1564 1 int apply_curve(int i, const int *curve) d1576 1 a1576 1 void foveon_interpolate() d1827 1 a1827 1 void bad_pixels() d1884 1 a1884 1 void scale_colors() d1974 1 a1974 1 void vng_interpolate() d2138 1 a2138 1 void tiff_parse_subifd(int base) d2189 1 a2189 1 void nef_parse_makernote() d2265 1 a2265 1 void get_timestamp() d2279 1 a2279 1 void nef_parse_exif(int base) d2303 1 a2303 1 void parse_tiff(int base) d2415 1 a2415 1 void ciff_block_1030() d2442 1 a2442 1 void parse_ciff(int offset, int length) d2547 1 a2547 1 void parse_rollei() d2585 1 a2585 1 void parse_foveon() d2620 1 a2620 1 void foveon_coeff() d2639 1 a2639 1 void canon_rgb_coeff (float juice) d2653 1 a2653 1 void nikon_e950_coeff() d2673 1 a2673 1 void gmcy_coeff() d2724 1 a2724 1 int identify() d3617 1 a3617 1 void convert_to_rgb() d3666 1 a3666 1 void flip_image() d3715 1 a3715 1 void write_ppm(FILE *ofp) d3759 1 a3759 1 void write_psd(FILE *ofp) d3806 1 a3806 1 void write_ppm16(FILE *ofp) d3837 1 a3837 1 int main(int argc, char **argv) @ 1.204 log @Handle Windows paths in bad_pixels(). @ text @d29 1 d67 2 a68 1 int data_offset, curve_offset, curve_length, timestamp; d2256 19 a2274 1 void nef_parse_exif() d2285 3 d2289 1 a2289 2 (!strncmp(make,"NIKON",5) || !strncmp(make,"OLYMPUS",7))) { fseek (ifp, val, SEEK_SET); d2291 1 a2291 2 fseek (ifp, save, SEEK_SET); } d2359 3 d2385 1 a2385 1 nef_parse_exif(); d2520 2 d2546 2 d2556 4 d2571 4 d2606 2 d2743 2 d2840 4 a2843 8 /* Remove excess wordage */ if (!strncmp(make,"NIKON",5) || !strncmp(make,"Canon",5)) make[5] = 0; if (!strncmp(make,"PENTAX",6)) make[6] = 0; if (strstr(make,"Minolta")) strcpy (make, "Minolta"); if (!strncmp(make,"KODAK",5)) d2845 1 a2845 8 if (!strcmp(make,"Eastman Kodak Company")) strcpy (make, "Kodak"); i = strlen(make); if (!strncmp(model,make,i++)) memmove (model, model+i, 64-i); /* Remove trailing spaces */ c = make + strlen(make); d2849 3 d3156 4 d3165 3 a3172 1 data_offset = 4016; a3174 1 fseek (ifp, 1936, SEEK_SET); d3843 1 a3843 1 "\nRaw Photo Decoder \"dcraw\" v6.00" @ 1.203 log @Fixed the Nikon D70 color balance. @ text @d1834 6 @ 1.202 log @Added automatic image flipping, with manual override. @ text @d3020 2 a3021 2 pre_mul[0] = 2.8; pre_mul[2] = 1.2; @ 1.201 log @Added the PowerShot G6/S70 and the EOS 20D. @ text @d71 1 a71 1 int is_canon, is_cmy, is_foveon, use_coeff, trim, ymag; d2276 1 d2317 3 d2490 8 d2702 1 a2702 1 raw_height = raw_width = 0; d2830 2 a2831 1 pre_mul[0] = pre_mul[1] = pre_mul[2] = pre_mul[3] = ymag = 1; d3618 46 d3683 1 a3683 1 width-trim*2, ymag*(height-trim*2)); d3685 1 a3685 1 ppm = calloc (width-trim*2, 3); d3698 2 a3699 1 ppm[col-trim][c] = val; d3703 1 a3703 1 fwrite (ppm, width-trim*2, 3, ofp); d3791 2 a3792 1 int arg, status=0, identify_only=0, write_to_stdout=0, half_size=0; d3800 1 a3800 1 "\nRaw Photo Decoder \"dcraw\" v5.90" d3817 1 d3838 1 d3933 8 @ 1.200 log @Eliminated the crw_decompress() function. @ text @d57 1 d2363 1 a2363 1 if (!strcmp(model,"Canon EOS-1D Mark II")) d2937 7 d2964 2 a2965 1 } else if (!strcmp(model,"EOS-1D Mark II")) { d2973 2 a2974 2 pre_mul[0] = 2.248; pre_mul[2] = 1.174; d3517 1 a3517 1 if (!load_raw) { d3739 1 a3739 1 "\nRaw Photo Decoder \"dcraw\" v5.88" d3780 1 a3780 1 case 'h': half_size = 1; @ 1.199 log @Added the Canon PowerShot A5 Zoom. @ text @a427 47 Decompress "count" blocks of 64 samples each. */ void crw_decompress (ushort *outbuf, int count) { struct decode *decode, *dindex; int i, leaf, len, diff, diffbuf[64]; static int carry, pixel, base[2]; zero_after_ff = 1; if (!outbuf) { /* Initialize */ carry = pixel = 0; fseek (ifp, count, SEEK_SET); getbits(-1); return; } while (count--) { memset(diffbuf,0,sizeof diffbuf); decode = first_decode; for (i=0; i < 64; i++ ) { for (dindex=decode; dindex->branch[0]; ) dindex = dindex->branch[getbits(1)]; leaf = dindex->leaf; decode = second_decode; 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 (pixel++ % raw_width == 0) base[0] = base[1] = 512; outbuf[i] = ( base[i & 1] += diffbuf[i] ); } outbuf += 64; } } /* d453 2 d462 3 a464 1 crw_decompress (0, 540 + lowbits*raw_height*raw_width/4); d466 26 a491 1 crw_decompress (pixel, raw_width/8); /* Get eight rows */ @ 1.198 log @Don't be fooled by camera-generated Nikon TIFFs. @ text @d2844 1 a2844 1 } else d2859 2 a2860 1 } else if (!strcmp(model,"PowerShot A5")) { d3748 1 a3748 1 "\nRaw Photo Decoder \"dcraw\" v5.87" @ 1.197 log @Allocate enough bytes for the G500. @ text @d2732 1 a2732 1 } else d2734 3 d3747 1 a3747 1 "\nRaw Photo Decoder \"dcraw\" v5.86" @ 1.196 log @Added the Minolta DiMAGE G500. Set black=640 for the Olympus E-20. @ text @d974 1 a974 1 pixel = calloc (width, sizeof *pixel); @ 1.195 log @Fixed color problems with the Nikon E995, Nikon E5400, and Leaf Valeo 22. @ text @d977 1 a977 1 fread (pixel, 2, width, ifp); d1001 5 d2748 6 d3114 15 d3232 1 d3744 1 a3744 1 "\nRaw Photo Decoder \"dcraw\" v5.85" @ 1.194 log @vng_interpolate() must clip to rgb_max, not 0xffff. @ text @d739 18 d2687 1 a2687 1 { 4771840, "NIKON", "E990/995" }, d3013 1 a3013 1 } else if (!strcmp(model,"E990/995")) { a3015 1 filters = 0xb4b4b4b4; d3017 13 a3029 4 nikon_e950_coeff(); pre_mul[0] = 1.196; pre_mul[1] = 1.246; pre_mul[2] = 1.018; d3059 4 d3182 2 d3717 1 a3717 1 "\nRaw Photo Decoder \"dcraw\" v5.84" @ 1.193 log @Found the curve tables for all Kodak cameras, and re-balanced the colors accordingly. @ text @d2103 1 a2103 1 if (t > 0xffff) t = 0xffff; d3685 1 a3685 1 "\nRaw Photo Decoder \"dcraw\" v5.83" @ 1.192 log @Major speed increase in convert_to_rgb(). @ text @d65 1 a65 1 int data_offset, nef_curve_offset, timestamp; d181 33 d540 31 a570 2 ushort fget2 (FILE *); int fget4 (FILE *); d578 1 a578 1 int tag, len, jhigh=0, jwide=0, trick, row, col, irow, icol, diff; d582 1 d584 1 d586 1 d628 1 a628 1 if ((unsigned) (irow = row-top_margin) >= height) d630 6 a635 4 if ((unsigned) (icol = col-left_margin) < width) BAYER(irow,icol) = diff << 2; else bblack += diff; d639 2 d656 1 a656 1 fseek (ifp, nef_curve_offset, SEEK_SET); a1180 1 black = 0; d1281 1 d1284 2 a1285 1 if (width < raw_width) d1294 1 a1294 1 BAYER(row,icol) = (ushort) pixel[col] << 6; d1296 1 a1296 1 black += pixel[col]; d1300 1 a1300 1 black = ((INT64) black << 6) / ((raw_width - width) * height); a1305 19 void kodak_dcr_curve (ushort *curve) { int i, j; for (i=0; i < 0x1000; i++) curve[i] = i; if (strncmp(model,"DCS Pro",7)) return; fseek (ifp, 0x4000, SEEK_SET); for (i=j=0; j < 100; i++) { if (i > 0x10000) return; if (fget2(ifp) == j) j++; else j=0; } fseek (ifp, 7992, SEEK_CUR); for (i=0; i < 0x400; i++) curve[i] = fget2(ifp); rgb_max = curve[i-1] << 2; } d1314 1 a1314 3 kodak_dcr_curve (curve); fseek (ifp, data_offset, SEEK_SET); d1378 1 a1378 3 kodak_dcr_curve (curve); fseek (ifp, data_offset, SEEK_SET); a2118 33 /* Get a 2-byte integer, making no assumptions about CPU byte order. Nor should we assume that the compiler evaluates left-to-right. */ ushort fget2 (FILE *f) { uchar a, b; a = fgetc(f); b = fgetc(f); if (order == 0x4949) /* "II" means little-endian */ return a + (b << 8); else /* "MM" means big-endian */ return (a << 8) + b; } /* Same for a 4-byte integer. */ int fget4 (FILE *f) { uchar a, b, c, d; a = fgetc(f); b = fgetc(f); c = fgetc(f); d = fgetc(f); if (order == 0x4949) return a + (b << 8) + (c << 16) + (d << 24); else return (a << 24) + (b << 16) + (c << 8) + d; } d2128 1 a2128 1 if (type == 3) { /* short int */ d2163 3 a2165 4 case 0x828d: /* Unknown */ case 0x828e: /* Unknown */ case 0x9217: /* Unknown */ break; d2211 1 a2211 1 nef_curve_offset = base+val + 2112; d2213 1 a2213 1 nef_curve_offset = base+val + 2; a2270 1 nef_curve_offset = 0; d2281 1 a2281 1 if (type == 3) { /* short int */ d2310 4 d2688 1 a2688 1 data_offset = tiff_data_compression = 0; d3068 1 a3068 1 rgb_max = 0x3e00; a3211 1 black = 400; d3215 3 a3217 2 pre_mul[0] = 1.327; pre_mul[2] = 2.093; d3221 2 a3222 2 pre_mul[0] = 1.43; pre_mul[2] = 2.16; d3226 2 a3227 2 pre_mul[0] = 1.28; pre_mul[2] = 2.00; d3229 3 a3231 3 black = 0; pre_mul[0] = 0.973; pre_mul[2] = 0.987; d3233 3 a3235 3 black = 0; pre_mul[0] = 0.996; pre_mul[2] = 1.279; d3239 2 a3240 2 pre_mul[0] = 1.21; pre_mul[2] = 1.63; d3244 2 a3245 2 pre_mul[0] = 1.46; pre_mul[2] = 1.84; d3252 3 a3254 2 pre_mul[0] = 1.00; pre_mul[2] = 1.20; d3256 3 a3258 2 pre_mul[0] = 0.985; pre_mul[2] = 1.15; d3260 3 a3262 2 pre_mul[0] = 1.00; pre_mul[2] = 1.20; d3264 3 a3266 2 pre_mul[0] = 1.12; pre_mul[2] = 1.07; d3269 3 a3271 2 pre_mul[0] = 1.05; pre_mul[2] = 1.17; d3273 1 a3313 1 rgb_max = 0x3fc0; a3320 1 black = 0; d3685 1 a3685 1 "\nRaw Photo Decoder \"dcraw\" v5.82" @ 1.191 log @Added camera white balance for all Olympus models. @ text @d3486 1 a3486 1 float rgb[4]; d3510 17 a3526 6 for (r=0; r < 3; r++) rgb[r] = img[r]; for (rgb[3]=r=0; r < 3; r++) { /* Compute the magnitude */ if (rgb[r] < 0) rgb[r] = 0; if (rgb[r] > rgb_max) rgb[r] = rgb_max; rgb[3] += rgb[r]*rgb[r]; a3527 6 rgb[3] = sqrt(rgb[3])/2; if (rgb[3] > 0xffff) rgb[3] = 0xffff; for (r=0; r < 4; r++) img[r] = rgb[r]; histogram[img[3] >> 3]++; /* bin width is 8 */ d3665 1 a3665 1 "\nRaw Photo Decoder \"dcraw\" v5.81" @ 1.190 log @Figured out how to get linear data from the Kodak DCS Pros. Improved support for the Fuji S2 and F700. Closed a histogram gap in the Canon S50 and G5. @ text @d2175 3 a2177 1 } else d2185 4 a2188 1 val = fget4(ifp); d2220 4 d2240 2 a2241 1 if (tag == 0x927c && !strncmp(make,"NIKON",5)) { d3167 2 d3660 1 a3660 1 "\nRaw Photo Decoder \"dcraw\" v5.80" @ 1.189 log @Fixed Kodak YUV code for widths not divisible by 8. Discovered that Kodak DCS Pro files are 10-bpp. @ text @d465 1 a465 1 int lowbits, shift, i, row, r, col, save; d482 5 a486 2 for (r=0; r < 8; r+=2, prow++) *prow = (*prow << 2) + ((c >> r) & 3); d794 1 a794 1 if (val == 0x3fff) /* If the primary is maxed, */ d796 2 d1236 19 d1258 1 a1258 1 ushort raw[6]; d1261 4 a1264 1 int diff, shift; a1265 6 /* Kodak claims that their "DCS Pro" cameras are all 12-bit, but their raw data values never exceed 1023. Thus I treat them as 10-bit cameras. */ shift = strncmp(model,"DCS Pro",7) ? 2 : 4; d1317 1 a1317 1 BAYER(row,col) = diff << shift; d1326 5 a1330 2 int i, li=0, si, diff, shift, six[6], y[4], cb=0, cr=0, rgb[3]; ushort *ip; a1331 1 shift = strncmp(model,"DCS Pro",7) ? 2 : 4; d1361 1 a1361 1 six[si] = diff << shift; d1371 3 a1373 3 rgb[0] = y[i] + 1.40200/2 * cr; rgb[1] = y[i] - 0.34414/2 * cb - 0.71414/2 * cr; rgb[2] = y[i] + 1.77200/2 * cb; d1375 1 a1375 1 if (rgb[c] > 0) ip[c] = rgb[c]; d3016 1 d3042 1 a3042 1 rgb_max = 0xffff; d3265 2 a3266 2 pre_mul[1] = 1.0191; pre_mul[2] = 1.1567; d3268 2 a3269 2 pre_mul[0] = 1.25; pre_mul[2] = 1.225; d3271 2 a3272 2 pre_mul[0] = 1.24; pre_mul[2] = 1.16; d3274 2 a3275 2 pre_mul[0] = 1.273; pre_mul[2] = 1.235; a3295 4 if (pre_mul[1] == 1) { pre_mul[0] *= 1.05; pre_mul[2] *= 1.10; } d3648 1 a3648 1 "\nRaw Photo Decoder \"dcraw\" v5.79" @ 1.188 log @Don't use canon_rgb_coeff() by default, other minor fixes. @ text @d1237 1 a1237 1 int diff; d1239 6 d1296 1 a1296 1 BAYER(row,col) = diff << 2; d1305 1 a1305 1 int i, li=0, si, diff, six[6], y[4], cb=0, cr=0, rgb[3]; d1308 1 d1320 5 d1338 1 a1338 1 six[si] = diff << 2; d3593 2 d3628 1 a3628 1 "\nRaw Photo Decoder \"dcraw\" v5.78" @ 1.187 log @Added the Panasonic DMC-LC1. @ text @d2829 1 d2832 1 d3257 2 d3474 2 a3475 1 if (rgb[3] > 0xffff) rgb[3] = 0xffff; d3561 2 a3562 1 if (val > 0xffff) val=0xffff; d3580 3 d3584 1 a3584 1 width-trim*2, height-trim*2, rgb_max); d3594 2 a3595 1 if (val > 0xffff) val=0xffff; d3614 1 a3614 1 "\nRaw Photo Decoder \"dcraw\" v5.77" @ 1.186 log @Minor optimizations in vng_interpolate() @ text @d3092 1 a3092 1 } else if (!strcmp(model,"DIGILUX 2")) { @ 1.185 log @Added the Kodak DCS Pro 14nx and SLR/c. @ text @d1945 1 d1998 2 a1999 3 gmin = INT_MAX; /* Choose a threshold */ gmax = 0; for (g=0; g < 8; g++) { d2017 7 a2023 2 t = pix[color] + (sum[c] - sum[color])/num; brow[2][col][c] = t > 0 ? (t < 0xffff ? t : 0xffff) : 0; @ 1.184 log @Added default white balance for the Canon EOS Kiss Digital. @ text @d3224 6 d3231 2 a3232 2 pre_mul[0] = 1.168; pre_mul[2] = 1.230; d3251 4 d3599 1 a3599 1 "\nRaw Photo Decoder \"dcraw\" v5.76" @ 1.183 log @In 16-bit PPM output, replace 65535 with rgb_max. @ text @d2848 4 @ 1.182 log @Added the Casio Exlim Pro 600, Creo Leaf Valeo 22, and Leica Digilux 2. Changed TIFF tags to hex. @ text @d3555 2 a3556 2 fprintf (ofp, "P6\n%d %d\n65535\n", width-trim*2, height-trim*2); d3585 1 a3585 1 "\nRaw Photo Decoder \"dcraw\" v5.75" @ 1.181 log @Allow "-w" flag to work with "-h" and "-f". Added camera white balance for all Minolta raw files. Fixed white balance for the Canon EOS 300D DIGITAL. Read all SubIFDs for non-Kodak cameras. @ text @d863 2 a864 1 void pentax_optio_load_raw() d872 2 a873 2 for (col=0; col < 17; col++) getbits(16); a876 10 void packed_12_load_raw() { int row, col; getbits(-1); for (row=0; row < height; row++) for (col=0; col < width; col++) BAYER(row,col) = getbits(12) << 2; } d2219 4 a2222 1 val = fget4(ifp); d2226 7 a2232 1 case 256: /* ImageWidth */ d2235 1 a2235 1 case 257: /* ImageHeight */ d2238 1 a2238 1 case 271: /* Make tag */ d2241 1 a2241 1 case 272: /* Model tag */ d2244 1 a2244 1 case 273: /* StripOffset */ d2248 1 a2248 1 case 33405: /* Model2 tag */ d2251 1 a2251 1 case 305: /* Software tag */ d2256 10 a2265 1 case 330: /* SubIFD tag */ d2294 1 a2294 1 if (make[0] == 0 && wide == 0x2a80000 && high == 0x2a80000) { d2611 1 d3012 2 a3013 1 load_raw = pentax_optio_load_raw; d3019 2 a3020 1 load_raw = pentax_optio_load_raw; d3078 12 d3365 7 d3585 1 a3585 1 "\nRaw Photo Decoder \"dcraw\" v5.73" @ 1.180 log @Added the Kodak DCS Pro SLR/n. @ text @d1842 1 a1842 1 else if (camera_red && camera_blue && colors == 3) { a1843 1 pre_mul[1] = 1.0; d1845 1 d2257 2 a2258 1 if (len > 2) len=2; d2347 2 a2348 1 if (!strcmp(model,"Canon EOS DIGITAL REBEL") && wbi == 6) d2642 7 d2990 2 a2991 2 pre_mul[0] = 1.57; pre_mul[2] = 1.42; d3554 1 a3554 1 "\nRaw Photo Decoder \"dcraw\" v5.71" @ 1.179 log @Added the Kodaks DC20, DC25, DC40, DC50, and DC120. Added the Nikon Coolpix 8700. @ text @d3187 3 d3545 1 a3545 1 "\nRaw Photo Decoder \"dcraw\" v5.70" @ 1.179.1.1 log @Version 5.72 changes abandoned in this side branch. @ text @d1842 1 a1842 1 else if (camera_red && camera_blue) { d1844 1 a1845 1 pre_mul[1] = pre_mul[3] = 1.0; d2189 1 a2189 1 void mrw_parse_makernote(int base) d2200 3 a2202 27 if (tag == 3) { fseek (ifp, base+val + 112, SEEK_SET); camera_red = fget4(ifp); camera_red /= (camera_blue = fget4(ifp)); camera_blue = fget4(ifp) / camera_blue; } fseek (ifp, save, SEEK_SET); } } void nef_parse_exif(int base) { int entries, tag, type, len, val, save; entries = fget2(ifp); while (entries--) { tag = fget2(ifp); type = fget2(ifp); len = fget4(ifp); val = fget4(ifp); save = ftell(ifp); if (tag == 0x927c) { fseek (ifp, val+base, SEEK_SET); if (!strncmp(make,"NIKON",5)) nef_parse_makernote(); else if (strstr(make,"Minolta")) mrw_parse_makernote(base); d2269 1 a2269 1 nef_parse_exif(base); d2346 1 a2346 2 if (((!strcmp(model,"Canon EOS DIGITAL REBEL") || !strcmp(model,"Canon EOS 300D DIGITAL"))) && wbi == 6) d3542 1 a3542 1 "\nRaw Photo Decoder \"dcraw\" v5.72" @ 1.178 log @Added option for half-size output. @ text @d29 7 d991 223 d1235 2 d2588 2 d2691 2 d2942 4 d3196 1 d3212 53 d3338 6 d3542 1 a3542 1 "\nRaw Photo Decoder v5.62" @ 1.177 log @Added the Canon PowerShot Pro1 and EOS-1D Mark II. Never exit() -- always return from main(). @ text @d62 1 d92 4 d195 1 a195 1 image[orow*width+col][FC(orow,col)] = pixel[col] << 4; d224 1 a224 1 image[row*width+col][FC(row,col)] = (pixel[col] & 0x3ff) << 4; d486 1 a486 2 image[irow*width+icol][FC(irow,icol)] = pixel[r*raw_width+col] << shift; d516 1 a516 1 len = fget2(ifp); d518 1 a518 1 fread (data, 1, len-2, ifp); d556 1 a556 1 image[irow*width+icol][FC(irow,icol)] = diff << 2; d608 1 a608 1 image[row*width+col-left_margin][FC(row,col)] = curve[diff] << 2; d631 1 a631 1 image[row*width+col-left_margin][FC(row,col)] = i << 2; d701 1 a701 1 image[row*width+col][FC(row,col)] = (pixel[col] & 0x3ff) << 4; d713 1 a713 1 image[row*width+col][FC(row,col)] = getbits(10) << 4; d733 1 a733 1 image[r*width+c][FC(r,c)] = ntohs(pixel[col]) << 2; d750 1 a750 1 image[r*width+c][FC(r,c)] = pixel[col] << 2; d788 1 a788 1 image[r*width+c][FC(r,c)] = val; d813 1 a813 1 image[row*width+col][FC(row,col)] = (todo[i+1] & 0x3ff) << 4; d837 1 a837 1 image[row*width+col][FC(row,col)] = pixel[col+left_margin]; d852 1 a852 1 image[row*width+col][FC(row,col)] = pixel[width-1-col]; d863 1 a863 1 image[row*width+col][FC(row,col)] = getbits(12) << 2; d876 1 a876 1 image[row*width+col][FC(row,col)] = getbits(12) << 2; d891 1 a891 1 image[row*width+col][FC(row,col)] = pixel[col] << 8 >> (8+rsh); d927 1 a927 1 image[row*width+col][FC(row,col)] = getbits(12) << 2; d941 1 a941 1 image[row*width+col][FC(row,col)] = pixel[col] << 6; d961 1 a961 1 image[row*width+col][FC(row,col)] = (pixel[col] & 0x3ff) << 4; d979 1 a979 1 image[row*width+col][FC(row,col)] = (dp[0] << 2) + (dp[1] << 10); d998 1 a998 1 image[row*width+icol][FC(row,icol)] = (ushort) pixel[col] << 6; d1067 1 a1067 1 image[row*width+col][FC(row,col)] = diff << 2; d1161 1 a1161 1 image[row*width+icol][FC(row,icol)] = ntohs(pixel[col]); d1515 1 d1546 1 a1546 1 tot += image[r*width+c][FC(r,c)]; d1549 1 a1549 1 image[row*width+col][FC(row,col)] = tot/n; d3234 1 a3234 1 int arg, status=0, identify_only=0, write_to_stdout=0; d3242 1 a3242 1 "\nRaw Photo Decoder v5.60" d3252 1 d3283 1 d3341 4 a3344 1 image = calloc (height * width, sizeof *image); d3351 3 a3358 1 bad_pixels(); d3361 1 @ 1.176 log @Added the Pentax Optio S. @ text @d25 1 d75 1 d166 1 a166 1 exit(1); d286 1 a286 1 void make_decoder (const uchar *source, int level) d296 1 a296 1 exit(1); d300 10 a309 7 if (level < next && i > leaf) { 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++]; d456 1 d484 1 a484 1 black += pixel[r*raw_width+col]; d489 2 a490 1 black = ((INT64) black << shift) / ((raw_width - width) * height); d493 3 d502 2 a503 2 uchar head[64]; int jwide, trick, row, col, len, diff; d505 24 a528 1 struct decode *dindex; a529 4 fread (head, 1, 64, ifp); init_decoder(); make_decoder (head+7, 0); jwide = (head[43] << 8) + head[44]; d533 2 a534 2 for (row=0; row < height; row++) for (col=0; col < width; col++) d536 1 a536 1 for (dindex=first_decode; dindex->branch[0]; ) d549 6 a554 1 image[row*width+col][FC(row,col)] = diff << 2; d556 2 a559 3 ushort fget2 (FILE *); int fget4 (FILE *); d999 1 a999 1 if (width < raw_width) d1186 1 a1186 1 exit(1); d1978 1 a1978 1 int wide=0, high=0, offset=0; d2008 1 d2044 3 d2589 7 d2609 10 d3229 1 a3229 1 int arg, id, identify_only=0, write_to_stdout=0; d3232 1 a3232 1 FILE *ofp; d3237 1 a3237 1 "\nRaw Photo Decoder v5.58" d3257 1 a3257 1 exit(1); d3265 1 a3265 1 exit(1); d3289 1 a3289 1 exit(1); d3294 1 a3294 1 exit(1); d3299 1 a3299 1 exit(1); d3304 1 a3304 1 exit(1); d3311 9 d3321 8 a3328 2 ifp = fopen (ifname, "rb"); if (!ifp) perror(ifname); d3330 1 a3330 8 if (!(id = !ifp || identify())) fprintf (stderr, "%s is a %s %s image.\n", ifname, make, model); if (ifp) fclose(ifp); if (arg+1 < argc) continue; exit(id); } if (!ifp) continue; if (identify()) { d3362 1 a3362 1 if (write_to_stdout) { d3364 1 a3364 2 ofp = stdout; } else { d3370 1 d3384 1 a3384 1 return 0; @ 1.175 log @Added the Kodak NC2000F. @ text @d819 1 a819 1 void pentax_optio_s4_load_raw() d2324 1 d2691 6 d2700 1 a2700 1 load_raw = pentax_optio_s4_load_raw; d3183 1 a3183 1 "\nRaw Photo Decoder v5.57" @ 1.174 log @Check array bounds when building a Huffman tree. Fixed the Canon EOS 10D camera white balance. @ text @d950 1 a950 1 int row, col, margin; d952 1 a952 1 if ((margin = (raw_width - width)/2)) d958 7 a964 4 for (col=0; col < width; col++) image[row*width+col][FC(row,col)] = (ushort) pixel[col+margin] << 6; if (margin == 2) black += pixel[0] + pixel[1] + pixel[raw_width-2] + pixel[raw_width-1]; d966 2 a967 2 if (margin) black = ((INT64) black << 6) / (4 * height); d2799 17 a2815 1 if (!strcmp(model,"DCS315C")) { d2818 1 a2819 1 } else if (!strcmp(model,"DCS330C")) { a2821 1 black = 0; d2823 2 d2827 1 d2829 1 a2829 1 } else if (!strcmp(model,"DCS460")) { d2832 1 d2834 1 a2834 1 } else if (!strcmp(model,"DCS460A")) { a2836 9 width -= 4; } else if (!strcmp(model,"EOSDCS3B")) { pre_mul[0] = 1.43; pre_mul[2] = 2.16; width -= 4; } else if (!strcmp(model,"EOSDCS1")) { pre_mul[0] = 1.28; pre_mul[2] = 2.00; width -= 4; d2886 2 a2887 1 load_raw = kodak_easy_load_raw; break; d2889 2 a2890 1 load_raw = lossless_jpeg_load_raw; break; d3176 1 a3176 1 "\nRaw Photo Decoder v5.56" @ 1.173 log @Fixed Custom WB for the Canon EOS DIGITAL REBEL. @ text @d62 1 d78 1 a78 1 } first_decode[32], second_decode[512]; d163 1 a163 1 fprintf (stderr, "Out of memory in %s\n", where); d226 8 a233 1 A rough description of Canon's compression algorithm: d235 16 a250 12 + Each pixel outputs a 10-bit sample, from 0 to 1023. + Split the data into blocks of 64 samples each. + Subtract from each sample the value of the sample two positions to the left, which has the same color filter. From the two leftmost samples in each row, subtract 512. + For each nonzero sample, make a token consisting of two four-bit numbers. The low nibble is the number of bits required to represent the sample, and the high nibble is the number of zero samples preceding this sample. + Output this token as a variable-length bitstring using one of three tablesets. Follow it with a fixed-length bitstring containing the sample. d252 5 a256 3 The "first_decode" table is used for the first sample in each block, and the "second_decode" table is used for the others. */ d284 1 a284 1 void make_decoder(struct decode *dest, const uchar *source, int level) d286 2 a287 2 static struct decode *free; /* Next unused node */ static int leaf; /* number of leaves already added */ d290 5 a294 3 if (level==0) { free = dest; leaf = 0; a295 4 free++; /* At what level should the next leaf appear? */ a297 1 d299 4 a302 4 dest->branch[0] = free; make_decoder (free, source, level+1); dest->branch[1] = free; make_decoder (free, source, level+1); d304 1 a304 1 dest->leaf = source[16 + leaf++]; d307 1 a307 1 void init_tables(unsigned table) d371 4 a374 31 memset ( first_decode, 0, sizeof first_decode); memset (second_decode, 0, sizeof second_decode); make_decoder ( first_decode, first_tree[table], 0); make_decoder (second_decode, second_tree[table], 0); } /* getbits(-1) initializes the buffer getbits(n) where 0 <= n <= 25 returns an n-bit integer */ unsigned getbits(int nbits) { static unsigned long bitbuf=0; static int vbits=0; unsigned c, ret; if (nbits == 0) return 0; if (nbits == -1) ret = bitbuf = vbits = 0; else { ret = bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - nbits); vbits -= nbits; } while (vbits < LONG_BIT - 7) { c = fgetc(ifp); bitbuf = (bitbuf << 8) + c; if (c == 0xff && is_canon) /* Canon puts an extra 0 after 0xff */ fgetc(ifp); vbits += 8; } return ret; a378 4 Note that the width passed to this function is slightly larger than the global width, because it includes some blank pixels that (*load_raw) will strip off. d380 1 a380 1 void decompress(ushort *outbuf, int count) d386 1 d456 1 a456 1 decompress(0, 540 + lowbits*raw_height*raw_width/4); d458 1 a458 1 decompress(pixel, raw_width/8); /* Get eight rows */ d498 2 a499 2 memset (first_decode, 0, sizeof first_decode); make_decoder (first_decode, head+7, 0); d502 1 a502 1 is_canon = 1; d537 2 a538 2 memset (first_decode, 0, sizeof first_decode); make_decoder (first_decode, nikon_tree, 0); d1142 1 a1142 1 void foveon_decoder(struct decode *dest, unsigned huff[1024], unsigned code) d1144 1 a1144 1 static struct decode *free; d1147 5 a1151 1 free++; d1155 1 a1155 1 dest->leaf = i; d1158 1 a1158 3 } else free = dest + 1; d1162 4 a1165 4 dest->branch[0] = free; foveon_decoder (free, huff, code); dest->branch[1] = free; foveon_decoder (free, huff, code+1); d1170 1 a1170 1 struct decode decode[2048], *dindex; d1181 2 a1182 2 memset (decode, 0, sizeof decode); foveon_decoder (decode, huff, 0); d1189 1 a1189 1 for (dindex=decode; dindex->branch[0]; ) { d2046 3 a2048 2 int tboff, nrecs, i, type, len, roff, aoff, save; int wbi=-1, remap[] = { 1,2,3,4,5,1 }; d2105 2 d2128 1 a2128 1 init_tables (fget4(ifp)); d2331 1 d3161 1 a3161 1 "\nRaw Photo Decoder v5.54" @ 1.172 log @Simplified the CRW decompression logic. @ text @d2085 2 @ 1.171 log @Fixed the Nikon D1H default white balance. @ text @d403 1 a403 1 int i, leaf, len, sign, diff, diffbuf[64]; d427 3 a429 6 sign=(getbits(1)); /* 1 is positive, 0 is negative */ diff=getbits(len-1); if (sign) diff += 1 << (len-1); else diff += (-1 << len) + 1; d3172 1 a3172 1 "\nRaw Photo Decoder v5.53" @ 1.170 log @Save time by precomputing all possible "scale" values. @ text @d2584 2 a2585 2 pre_mul[0] = 1.347; pre_mul[2] = 3.279; @ 1.169 log @Added the Minolta DiMAGE A2 and Olympus C8080WZ. @ text @d3054 1 a3054 1 float max, mul, scale; d3072 3 a3078 2 /* In some math libraries, pow(0,expo) doesn't return zero */ scale = rgb[3] ? mul * pow (rgb[3]*2/max, gamma_val-1) : 0; d3080 1 a3080 1 val = rgb[c] * scale; d3175 1 a3175 1 "\nRaw Photo Decoder v5.52" @ 1.168 log @dcraw.c no longer calls external code to read lossless JPEG. @ text @d908 1 a908 1 fseek (ifp, 15360 - row*(-width*height*3/4 & -2048), SEEK_SET); d1962 1 a1962 1 int wide=0, high=0; d1980 1 a1980 1 wide = val >> 16; d1983 1 a1983 1 high = val >> 16; d1991 3 d2021 7 a2027 1 if (make[0] == 0 && wide == 680 && high == 680) { d2421 2 a2422 2 if (!strncmp(make,"OLYMPUS",7) || !strncmp(make,"Minolta",7)) make[7] = 0; d2690 1 a2690 1 if (!strcmp(model,"DiMAGE A1")) a2762 2 height = 1966; width = 2624; a2763 1 data_offset = 0x54000; a2767 3 height = 1684; width = 2256; data_offset = 0x4000; a2771 3 height = 1924; width = 2576; data_offset = 0x4000; a2775 2 height = 1926; width = 2576; a2780 2 height = 1950; width = 2608; d2782 5 d3174 1 a3174 1 "\nRaw Photo Decoder v5.50" @ 1.167 log @Added the Nikon D70. @ text @a15 5 The Canon EOS-1D and some Kodak cameras compress their raw data with lossless JPEG. To read such images, you must also download: http://www.cybercom.net/~dcoffin/dcraw/ljpeg_decode.tar.gz d41 2 a42 3 #include "jpeg.h" #include "mcu.h" #include "proto.h" d287 1 a287 1 if (level < next) { /* Are we there yet? */ a507 1 #ifdef LJPEG_DECODE d509 2 a510 1 Lossless JPEG code calls this function to get data. d512 1 a512 1 int ReadJpegData (char *buffer, int numBytes) d514 4 a517 2 return fread(buffer, 1, numBytes, ifp); } d519 24 a542 19 /* Called from DecodeImage() in huffd.c to write one row. Notice that one row of the JPEG data is two rows for us. Canon did this so that the predictors could work against like colors. Quite clever! Kodak didn't think of that. 8-/ */ void PmPutRow(ushort **buf, int numComp, int numCol, int row) { int r, col, trick=1; trick = numComp * numCol / width; row *= trick; for (r = row; r < row+trick; r++) for (col=0; col < width; col+=2) { image[r*width+col+0][FC(r,col+0)] = buf[0][0] << 2; image[r*width+col+1][FC(r,col+1)] = buf[0][1] << 2; buf++; d546 2 a547 19 void lossless_jpeg_load_raw() { DecompressInfo dcInfo; MEMSET(&dcInfo, 0, sizeof(dcInfo)); ReadFileHeader (&dcInfo); ReadScanHeader (&dcInfo); DecoderStructInit (&dcInfo); HuffDecoderInit (&dcInfo); DecodeImage (&dcInfo); FreeArray2D (mcuROW1); FreeArray2D (mcuROW2); } #else void lossless_jpeg_load_raw() { } #endif /* LJPEG_DECODE */ ushort fget2 (FILE *f); int fget4 (FILE *f); d586 1 a586 1 hpred[col & 1] = vpred[i]; a2975 7 #ifndef LJPEG_DECODE if (load_raw == lossless_jpeg_load_raw) { fprintf (stderr, "%s: %s %s requires lossless JPEG decoder.\n", ifname, make, model); return 1; } #endif d3173 1 a3173 4 "\nRaw Photo Decoder v5.47" #ifdef LJPEG_DECODE " with Lossless JPEG support" #endif @ 1.166 log @Changed "bit" to "bpp" for clarity. @ text @d1939 6 d2612 4 d3196 1 a3196 1 "\nRaw Photo Decoder v5.46" @ 1.165 log @Fixed the Pentax Optio S4 white balance. @ text @d3061 1 a3061 1 Write the image to a 24-bit PPM file. d3103 1 a3103 1 Write the image to a 48-bit Photoshop file. d3149 1 a3149 1 Write the image to a 48-bit PPM file. d3199 1 a3199 1 "\n-g Set gamma (0.6 by default, only for 24-bit output)" d3205 3 a3207 3 "\n-2 Write 24-bit PPM (default)" "\n-3 Write 48-bit PSD (Adobe Photoshop)" "\n-4 Write 48-bit PPM" @ 1.164 log @When finding the white point, consider that half of a Fuji output image is black space. @ text @d2702 2 a2703 2 pre_mul[0] = 2.09; pre_mul[1] = 1.06; @ 1.163 log @Reduced vng_interpolate() execution time by one-third. (thanks to Ahti Heinla for this fix) @ text @d3073 1 d3075 1 a3075 1 if ((total+=histogram[val]) > (int)(width*height*0.01)) break; d3186 1 a3186 1 "\nRaw Photo Decoder v5.45" @ 1.162 log @Added the Pentax Optio S4. @ text @d1759 6 a1764 3 while ((g = *ip++) != INT_MAX) { /* Calculate gradients */ diff = abs(pix[g] - pix[*ip++]); diff <<= *ip++; d1768 1 d3185 1 a3185 1 "\nRaw Photo Decoder v5.44" @ 1.161 log @Added camera white balance for Nikon D100 and D2H. (Thanks, Eric!) @ text @d857 13 d2333 1 d2694 6 d3181 1 a3181 1 "\nRaw Photo Decoder v5.43" @ 1.160 log @Added the Sony DSC-F828. @ text @d1899 1 a1900 1 save = ftell(ifp); a1905 1 fseek (ifp, save, SEEK_SET); d1911 14 d3161 1 a3161 1 "\nRaw Photo Decoder v5.42" @ 1.159 log @Don't include values.h. @ text @d3 1 a3 1 Copyright 1997-2003 by Dave Coffin, dcoffin a cybercom o net d1107 60 d2763 12 d3148 1 a3148 1 "\nRaw Photo Decoder v5.40" @ 1.158 log @Added "-a" option for automatic white balance. Vastly improved camera white balance for CRW files. Changed default gamma to 0.6. Added the Creative PC-CAM 600. @ text @d27 2 a32 1 #include @ 1.157 log @Set black=0 for all Phase One cameras, added the Phase One H25. @ text @d24 3 d31 1 a31 4 #include #include #include #include d50 4 d61 3 a63 5 char make[64], model[64], model2[64]; int timestamp; int tiff_data_offset, tiff_data_compression; int kodak_data_compression; int nef_curve_offset; d68 1 a68 1 ushort (*image)[4]; d70 3 a72 3 float gamma_val=0.8, bright=1.0, red_scale=1.0, blue_scale=1.0; int verbose=0, four_color_rgb=0, use_camera_wb=0; int document_mode=0, quick_interpolate=0; d152 12 a176 5 /* Immediately after the 26-byte header come the data rows. First the even rows 0..612, then the odd rows 1..611. Each row is 896 pixels, ten bits per pixel, packed into 1120 bytes (8960 bits). */ a190 5 /* Copy 854 pixels into the image[] array. The other 42 pixels are black. Left-shift by 4 for extra precision in upcoming calculations. */ d195 2 a196 3 if ((orow+=2) > height) /* Once we've read all the even rows, */ orow = 1; /* read the odd rows. */ d377 1 a377 1 static unsigned bitbuf=0, ret=0; d379 1 a379 1 unsigned char c; d385 1 a385 1 ret = bitbuf << (8*sizeof(int) - vbits) >> (8*sizeof(int) - nbits); d388 1 a388 1 while (vbits < 25) { d491 2 a492 2 for (r=0; r < 8; r+=2) *prow++ = (*prow << 2) + ((c >> r) & 3); a547 2 fseek (ifp, tiff_data_offset, SEEK_SET); d586 1 a586 1 fseek (ifp, tiff_data_offset, SEEK_SET); a616 1 fseek (ifp, tiff_data_offset, SEEK_SET); d652 1 a652 1 fseek (ifp, tiff_data_offset, SEEK_SET); a682 1 fseek (ifp, 0, SEEK_SET); a708 1 fseek (ifp, 0, SEEK_SET); d727 1 a727 1 fseek (ifp, tiff_data_offset + (2944*24+32)*2, SEEK_SET); a742 1 fseek (ifp, tiff_data_offset, SEEK_SET); d757 1 a757 1 tiff_data_offset += (1472*4+24)*2; a775 1 fseek (ifp, tiff_data_offset, SEEK_SET); a798 1 fseek (ifp, tiff_data_offset, SEEK_SET); d823 1 a823 1 fseek (ifp, tiff_data_offset + 8, SEEK_SET); d827 1 a827 1 fseek (ifp, tiff_data_offset + 12 + top_margin*raw_width*2, SEEK_SET); a859 1 fseek (ifp, tiff_data_offset, SEEK_SET); a872 1 fseek (ifp, tiff_data_offset, SEEK_SET); d918 1 a918 1 void casio_easy_load_raw() d924 1 a924 2 merror (pixel, "casio_easy_load_raw()"); fseek (ifp, tiff_data_offset, SEEK_SET); a938 1 fseek (ifp, 0, SEEK_SET); a958 1 fseek (ifp, tiff_data_offset, SEEK_SET); a979 1 fseek (ifp, tiff_data_offset, SEEK_SET); a999 2 fseek (ifp, tiff_data_offset, SEEK_SET); a1062 2 fseek (ifp, tiff_data_offset, SEEK_SET); d1481 1 a1481 4 /* Automatic color balance, currently used only in Document Mode. */ void auto_scale() d1485 1 a1485 1 double sum[4], maxd=0; d1487 34 a1520 14 for (c=0; c < 4; c++) { min[c] = INT_MAX; sum[c] = max[c] = count[c] = 0; } for (row=0; row < height; row++) for (col=0; col < width; col++) for (c=0; c < colors; c++) { val = image[row*width+col][c]; if (!val) continue; val -= black; if (val < 0) val = 0; if (min[c] > val) min[c] = val; if (max[c] < val) max[c] = val; sum[c] += val; d1523 24 a1546 4 for (c=0; c < colors; c++) { /* Smallest pre_mul[] value */ pre_mul[c] = sum[c]/count[c]; /* should be 1.0 */ if (maxd < pre_mul[c]) maxd = pre_mul[c]; a1547 9 for (c=0; c < colors; c++) pre_mul[c] = maxd / pre_mul[c]; } void scale_colors() { int row, col, c, val; rgb_max -= black; d1789 1 a1789 1 tiff_data_offset = val; d1793 1 a1793 1 tiff_data_offset = fget4(ifp); d1944 27 d1977 1 a1977 1 int wbi=0; d2000 30 a2029 14 fseek (ifp, aoff+100, SEEK_SET); /* could use 100, 108 or 116 */ camera_red = fget2(ifp); camera_red = fget2(ifp) / camera_red; camera_blue = fget2(ifp); camera_blue /= fget2(ifp); } if (type == 0x0032 && !strcmp(model,"Canon EOS D30")) { fseek (ifp, aoff+72, SEEK_SET); /* Get white balance (D30) */ camera_red = fget2(ifp); camera_red = fget2(ifp) / camera_red; camera_blue = fget2(ifp); camera_blue /= fget2(ifp); if (wbi==0) /* AWB doesn't work here */ camera_red = camera_blue = 0; d2038 4 d2059 2 d2076 1 a2076 1 tiff_data_offset = atoi(val); d2086 1 a2086 1 tiff_data_offset += tx * ty * 2; d2228 1 a2228 1 int identify(char *fname) d2241 1 d2252 1 d2254 1 a2254 1 tiff_data_offset = tiff_data_compression = 0; d2264 2 a2265 2 tiff_data_offset = c - head; fseek (ifp, tiff_data_offset + 8, SEEK_SET); d2272 1 a2273 1 fseek (ifp, hlen, SEEK_SET); d2279 1 a2279 1 tiff_data_offset = fget4(ifp) + 8; d2284 1 a2284 1 tiff_data_offset = 0x1000; d2297 1 a2297 1 tiff_data_offset += fget4(ifp); d2303 1 a2303 1 tiff_data_offset -= 0x1000; d2313 1 a2313 1 tiff_data_offset = fget4(ifp); d2345 1 a2345 1 fprintf (stderr, "%s: unsupported file format.\n", fname); d2474 1 a2474 1 tiff_data_offset = 288912; d2480 1 a2480 1 tiff_data_offset = 289168; d2602 1 a2602 1 tiff_data_offset = 0x10000; d2658 1 a2658 1 tiff_data_offset = 68; d2665 1 a2665 1 tiff_data_offset = 0x54000; d2672 1 a2672 1 tiff_data_offset = 0x4000; d2679 1 a2679 1 tiff_data_offset = 0x4000; d2698 1 a2698 1 tiff_data_offset = 0x1a00; d2796 1 a2796 1 fname, make, model, tiff_data_compression); d2838 7 d2848 2 a2849 2 tiff_data_offset = width * 2; load_raw = casio_easy_load_raw; d2854 1 a2854 1 load_raw = casio_easy_load_raw; d2869 1 a2869 1 fname, make, model); d2875 1 a2875 1 fname, make, model); a2880 7 if (use_camera_wb) { if (camera_red && camera_blue && colors == 3) { pre_mul[0] = camera_red; pre_mul[2] = camera_blue; } else fprintf (stderr, "%s: Cannot use camera white balance.\n",fname); } a2887 4 else { pre_mul[0] *= red_scale; pre_mul[2] *= blue_scale; } d2900 1 d3075 1 a3075 1 "\nRaw Photo Decoder v5.27" d3088 1 a3088 1 "\n-g Set gamma (0.8 by default, only for 24-bit output)" d3090 2 a3091 1 "\n-w Use camera white balance settings if possible" d3121 1 d3152 3 a3154 2 ifp = fopen(argv[arg],"rb"); if (!ifp) perror(argv[arg]); d3156 2 a3157 2 if (!(id = !ifp || identify(argv[arg]))) fprintf (stderr, "%s is a %s %s image.\n", argv[arg], make, model); d3163 1 a3163 1 if (identify(argv[arg])) { d3171 1 a3171 1 "Loading %s %s image from %s...\n", make, model, argv[arg]); a3179 4 if (verbose) fprintf (stderr, "Scaling raw data (black=%d)...\n", black); if (document_mode) auto_scale(); d3193 1 a3193 1 ofname = malloc (strlen(argv[arg]) + 16); d3199 1 a3199 1 strcpy (ofname, argv[arg]); @ 1.156 log @Don't print informational messages unless "-v" flag is set. Fixed a bug in kodak_yuv_load_raw(). @ text @d23 1 a38 1 #define __USE_XOPEN a826 1 INT64 bblack=0; d828 2 a829 2 fseek (ifp, 8, SEEK_SET); fseek (ifp, fget4(ifp) + 308, SEEK_SET); d832 1 a832 1 fseek (ifp, 12 + top_margin*raw_width*2, SEEK_SET); a842 2 for (col=left_margin+width; col < raw_width-1; col++) bblack += pixel[col]; a843 2 black = bblack / (height * (raw_width-1-width-left_margin)); if (raw_width == 3120) black = 0; d2198 1 a2198 1 if (!memcmp (head,"MMMMRawT",8)) { d2200 3 a2202 2 fseek (ifp, 8, SEEK_SET); fseek (ifp, fget4(ifp) + 148, SEEK_SET); d2543 2 a2544 2 switch (raw_width) { case 3120: d2553 1 a2553 1 case 4056: d2560 1 a2560 1 case 4134: d2568 9 d3014 1 a3014 1 "\nRaw Photo Decoder v5.26" @ 1.155 log @DJGPP does not #define WIN32 @ text @d69 2 a70 1 int four_color_rgb=0, use_camera_wb=0, document_mode=0, quick_interpolate=0; d1086 1 a1086 1 len = (width - col) * 3; d1491 5 a1495 3 if (!fixed++) fprintf (stderr, "Fixed bad pixels at:"); fprintf (stderr, " %d,%d", col, row); d3009 1 a3009 1 "\nRaw Photo Decoder v5.25" d3018 1 d3050 1 d3100 3 a3102 2 fprintf (stderr, "Loading %s %s image from %s...\n", make, model, argv[arg]); d3106 2 a3107 1 fprintf (stderr, "Foveon interpolation...\n"); d3111 2 a3112 1 fprintf (stderr, "Scaling raw data (black=%d)...\n", black); d3120 3 a3122 2 fprintf (stderr, "%s interpolation...\n", quick_interpolate ? "Bilinear":"VNG"); d3125 2 a3126 1 fprintf (stderr, "Converting to RGB colorspace...\n"); d3143 2 a3144 1 fprintf (stderr, "Writing data to %s...\n", ofname); @ 1.154 log @Added the Phase One LightPhase and a Sinar camera. Try to decode unknown Canon, Nikon, and Phase One models. Created new global variables top_margin and left_margin. Refactored extensively. @ text @d3069 1 a3069 1 #ifdef WIN32 @ 1.153 log @Added the Sigma SD10. @ text @a57 1 int raw_height, raw_width; /* Including black borders */ d62 1 d156 1 a156 1 void ps600_load_raw() d197 1 a197 71 void a5_load_raw() { uchar data[1240], *dp; ushort pixel[992], *pix; int row, col; /* Each data row is 992 ten-bit pixels, packed into 1240 bytes. */ for (row=0; row < height; row++) { fread (data, 1240, 1, ifp); for (dp=data, pix=pixel; dp < data+1240; 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] ); } /* Copy 960 pixels into the image[] array. The other 32 pixels are black. Left-shift by 4 for extra precision in upcoming calculations. */ for (col=0; col < width; col++) image[row*width+col][FC(row,col)] = (pixel[col] & 0x3ff) << 4; for (col=width; col < 992; col++) black += pixel[col] & 0x3ff; } black = ((INT64) black << 4) / ((992 - width) * height); } void a50_load_raw() { uchar data[1650], *dp; ushort pixel[1320], *pix; int row, col; /* Each row is 1320 ten-bit pixels, packed into 1650 bytes. */ for (row=0; row < height; row++) { fread (data, 1650, 1, ifp); for (dp=data, pix=pixel; dp < data+1650; 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] ); } /* Copy 1290 pixels into the image[] array. The other 30 pixels are black. Left-shift by 4 for extra precision in upcoming calculations. */ for (col=0; col < width; col++) image[row*width+col][FC(row,col)] = (pixel[col] & 0x3ff) << 4; for (col=width; col < 1320; col++) black += pixel[col] & 0x3ff; } black = ((INT64) black << 4) / ((1320 - width) * height); } void pro70_load_raw() a202 3 /* Each row is 1552 ten-bit pixels, packed into 1940 bytes. */ d204 2 a205 2 fread (data, 1940, 1, ifp); for (dp=data, pix=pixel; dp < data+1940; dp+=10, pix+=8) a215 4 /* Copy all pixels into the image[] array. Left-shift by 4 for extra precision in upcoming calculations. No black pixels? */ d218 2 d221 2 d472 1 a472 1 unsigned top=0, left=0, irow, icol; a474 8 /* Set the width of the black borders */ switch (raw_width) { case 2144: top = 8; left = 4; break; /* G1 */ case 2224: top = 6; left = 48; break; /* EOS D30 */ case 2376: top = 6; left = 12; break; /* G2 or G3 */ case 2672: top = 6; left = 12; break; /* S50 */ case 3152: top =12; left = 64; break; /* EOS D60 */ } d492 3 a494 1 for (r=0; r < 8; r++) d496 1 a496 3 irow = row+r-top; icol = col-left; if (irow >= height) continue; d503 1 a563 1 int left=0, right=0; a571 7 if (!strcmp(model,"D1X")) right = 4; if (!strcmp(model,"D2H")) { left = 6; right = 8; } d588 1 a588 1 for (col=-left; col < width+right; col++) d596 1 a596 1 if (col+left < 2) { d602 1 a602 1 if ((unsigned) col >= width) continue; d606 1 a606 1 image[row*width+col][FC(row,col)] = curve[diff] << 2; a610 21 /* 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 nikon_is_compressed() { uchar test[256]; int i; if (tiff_data_compression != 34713) return 0; if (strcmp(model,"D100")) return 1; fseek (ifp, tiff_data_offset, SEEK_SET); fread (test, 1, 256, ifp); for (i=15; i < 256; i+=16) if (test[i]) return 1; return 0; } a612 1 int left=0, right=0, skip16=0; a614 18 if (!strcmp(model,"D100")) width = 3034; if (nikon_is_compressed()) { nikon_compressed_load_raw(); return; } if (!strcmp(model,"D1X")) right = 4; if (!strcmp(model,"D100") && tiff_data_compression == 34713) { right = 3; skip16 = 1; width = 3037; } if (!strcmp(model,"D2H")) { left = 6; right = 8; } d627 1 a627 1 for (col=-left; col < width+right; col++) { d629 3 a631 3 if ((unsigned) col < width) image[row*width+col][FC(row,col)] = i << 2; if (skip16 && (col % 10) == 9) d638 21 d799 1 a799 1 unsigned left=0, top=0, iten=0, isix, i, buffer=0, row, col, todo[16]; a800 4 switch (raw_width) { case 1316: left = 6; top = 1; width = 1300; height = 1030; break; case 2568: left = 8; top = 2; width = 2560; height = 1960; break; } d814 2 a815 2 row = todo[i] / raw_width - top; col = todo[i] % raw_width - left; d824 1 a824 1 int left=0, top=0, row, col, a, b; a827 4 switch (raw_width) { case 4056: left = 26; top = 5; break; case 4134: left = 26; top = 20; break; } d832 1 a832 1 fseek (ifp, 12 + top*raw_width*2, SEEK_SET); d842 2 a843 2 image[row*width+col][FC(row,col)] = pixel[col+left]; for (col=left+width; col < raw_width-1; col++) d846 2 a847 1 black = bblack / (height * (raw_width-1-width-left)); d894 6 a899 1 void high_12_load_raw() d904 1 a904 1 void low_12_load_raw() d909 1 a909 1 void le_high_12_load_raw() d1153 1 a1153 1 unsigned huff[1024], bitbuf=0, top=0, left=0; a1155 9 /* Set the width of the black borders */ switch (raw_height) { case 763: top = 2; break; case 1531: top = 7; break; } switch (raw_width) { case 1152: left = 8; break; case 2304: left = 17; break; } d1178 2 a1179 2 if ((unsigned) row-top >= height || (unsigned) col-left >= width ) continue; d1182 1 a1182 1 image[(row-top)*width+(col-left)][c] = pred[c]; a1871 2 tiff_data_offset = 0; tiff_data_compression = 0; d1905 1 a1905 1 model[0] = 0; d1926 1 a1926 1 if (model[0] == 0 && wide == 680 && high == 680) { d2172 21 a2193 10 pre_mul[0] = pre_mul[1] = pre_mul[2] = pre_mul[3] = 1; camera_red = camera_blue = black = timestamp = 0; rgb_max = 0x4000; colors = 3; is_cmy = is_foveon = use_coeff = 0; ymag = 1; strcpy (make, "NIKON"); /* wild guess */ model[0] = model2[0] = 0; tiff_data_offset = 0; a2206 4 switch (raw_width) { case 4056: strcpy (model, "H10"); break; case 4134: strcpy (model, "H20"); break; } d2255 6 a2260 21 else if (fsize == 2465792) /* Nikon "DIAG RAW" formats */ strcpy (model,"E950"); else if (fsize == 2940928) strcpy (model, nikon_e2100() ? "E2100":"E2500"); else if (fsize == 4771840) strcpy (model,"E990/995"); else if (fsize == 5865472) strcpy (model,"E4500"); else if (fsize == 5869568) strcpy (model,"E4300"); else { strcpy (make, "Casio"); /* Casio has similar formats */ if (fsize == 1976352) strcpy (model, "QV-2000UX"); else if (fsize == 3217760) strcpy (model, "QV-3*00EX"); else if (fsize == 7684000) strcpy (model, "QV-4000"); else if (fsize == 6218368) strcpy (model, "QV-5700"); } d2280 2 a2281 1 if (model[0] == 0) { d2285 27 a2311 1 is_canon = !strcmp(make,"Canon"); d2317 1 a2317 1 load_raw = ps600_load_raw; d2323 1 d2326 1 a2326 1 load_raw = a5_load_raw; d2333 1 d2336 1 a2336 1 load_raw = a50_load_raw; d2345 1 a2345 1 load_raw = pro70_load_raw; a2349 1 height = 1416; a2352 1 load_raw = canon_compressed_load_raw; d2356 1 a2356 1 } else if (!strcmp(model,"PowerShot G1")) { d2359 19 a2377 13 colors = 4; filters = 0xb4b4b4b4; load_raw = canon_compressed_load_raw; pre_mul[0] = 1.446; pre_mul[1] = 1.405; pre_mul[2] = 1.016; } else if (!strcmp(model,"PowerShot S30")) { height = 1550; width = 2088; filters = 0x94949494; load_raw = canon_compressed_load_raw; pre_mul[0] = 1.785; pre_mul[2] = 1.266; d2381 2 a2382 2 filters = 0x94949494; load_raw = canon_compressed_load_raw; d2396 2 a2397 2 filters = 0x94949494; load_raw = canon_compressed_load_raw; a2399 7 } else if (!strcmp(model,"EOS D30")) { height = 1448; width = 2176; filters = 0x94949494; load_raw = canon_compressed_load_raw; pre_mul[0] = 1.592; pre_mul[2] = 1.261; d2403 2 a2404 2 filters = 0x94949494; load_raw = canon_compressed_load_raw; a2410 2 filters = 0x61616161; load_raw = lossless_jpeg_load_raw; a2416 2 filters = 0x61616161; load_raw = lossless_jpeg_load_raw; a2421 4 height = raw_height; width = raw_width; filters = 0x61616161; load_raw = lossless_jpeg_load_raw; a2424 2 height = 1324; width = 2012; a2425 1 load_raw = nikon_load_raw; a2428 2 height = 1324; width = 2012; a2429 1 load_raw = nikon_load_raw; a2432 1 height = 1324; a2435 1 load_raw = nikon_load_raw; d2439 2 a2440 2 height = 2024; width = 3037; a2441 1 load_raw = nikon_load_raw; a2445 1 height = 1648; d2447 1 a2448 1 load_raw = nikon_load_raw; a2465 1 load_raw = nikon_load_raw; d2471 12 a2482 11 height = 1206; width = 1616; filters = 0x94949494; load_raw = nikon_e2100_load_raw; pre_mul[0] = 1.945; pre_mul[2] = 1.040; } else if (!strcmp(model,"E2500")) { height = 1204; width = 1616; filters = 0x4b4b4b4b; goto coolpix; a2486 1 load_raw = nikon_load_raw; a2492 2 height = 1924; width = 2576; a2495 1 load_raw = nikon_load_raw; d2531 1 a2531 4 height = raw_height; width = raw_width; filters = 0x94949494; load_raw = low_12_load_raw; a2538 1 filters = 0x94949494; d2540 1 a2540 1 load_raw = low_12_load_raw; d2543 28 a2570 4 } else if (!strcmp(model,"H10")) { height = 2672; width = 4012; filters = 0x94949494; a2572 8 } else if (!strcmp(model,"H20")) { height = 4098; width = 4098; filters = 0x49494949; load_raw = phase_one_load_raw; pre_mul[0] = 1.963; pre_mul[2] = 1.430; rgb_max = 0xffff; d2581 8 a2599 1 filters = 0x94949494; d2601 1 a2601 1 load_raw = high_12_load_raw; a2606 1 filters = 0x94949494; d2608 1 a2608 1 load_raw = high_12_load_raw; a2620 1 filters = 0x94949494; a2630 2 height = raw_height; width = raw_width; d2728 13 a2740 2 height = raw_height; width = raw_width; d2746 7 a2752 7 switch (height = raw_height) { case 763: height = 756; break; case 1531: height = 1514; break; } switch (width = raw_width) { case 1152: width = 1136; break; case 2304: width = 2271; break; d2768 1 a2768 2 raw_width = width = 1632; filters = 0x94949494; a2774 1 filters = 0x94949494; d2779 1 a2779 2 filters = 0x94949494; load_raw = high_12_load_raw; a2782 1 filters = 0x94949494; a2784 2 height = raw_height; width = raw_width; d2787 4 a2790 2 } else { fprintf (stderr, "%s: %s %s is not yet supported.\n",fname, make, model); d2800 2 d3006 1 a3006 1 "\nRaw Photo Decoder v5.20" @ 1.152 log @Added the Olympus C5060WZ. @ text @d2190 1 a2190 1 }, mul[3] = { 1.179, 1.0, 0.713 }; d2195 1 a2195 1 coeff[i][j] = foveon[i][j] * mul[i]; d2843 1 a2843 1 } else if (!strcmp(model,"SD9")) { d2856 6 d3106 1 a3106 1 "\nRaw Photo Decoder v5.19" @ 1.151 log @"-c" now works in Windows, so "-o" is superfluous. Fixed buffer overflow, segfaults, and memory leaks in main(). @ text @d1023 1 a1023 1 void olympus_c5050z_load_raw() d1030 1 a1030 1 fseek (ifp, 15360 + row*(width*height*3/4 + 184), SEEK_SET); d2721 1 a2721 1 load_raw = olympus_c5050z_load_raw; d2724 5 d3100 1 a3100 1 "\nRaw Photo Decoder v5.18" @ 1.150 log @Do not write image data to a terminal. In Windows, set stdout to binary mode. @ text @d29 1 d3087 2 a3088 2 char data[256], *cp; int arg, id, identify_only=0, write_to_stdout=0, minuso=0; d3095 1 a3095 1 "\nRaw Photo Decoder v5.17" a3103 1 "\n-o file Write output to this file" d3119 8 a3126 2 for (arg=1; argv[arg][0] == '-'; arg++) switch (argv[arg][1]) d3128 16 a3143 34 case 'i': identify_only = 1; break; case 'c': write_to_stdout = 1; break; case 'o': minuso = ++arg; break; case 'f': four_color_rgb = 1; break; case 'd': document_mode = 1; break; case 'q': quick_interpolate = 1; break; case 'g': gamma_val = atof(argv[++arg]); break; case 'b': bright = atof(argv[++arg]); break; case 'w': use_camera_wb = 1; break; case 'r': red_scale = atof(argv[++arg]); break; case 'l': blue_scale = atof(argv[++arg]); break; 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; d3145 1 a3145 1 fprintf (stderr, "Unknown option \"%s\"\n", argv[arg]); d3148 5 a3152 1 d3207 2 d3210 1 a3210 1 strcpy (data, "standard output"); d3213 4 a3216 6 strcpy (data, argv[arg]); if ((cp = strrchr (data, '.'))) *cp = 0; strcat (data, write_ext); if (minuso) strcpy (data, argv[minuso]); ofp = fopen (data, "wb"); d3218 2 a3219 2 perror(data); continue; d3222 1 a3222 1 fprintf (stderr, "Writing data to %s...\n", data); d3226 2 a3227 1 @ 1.149 log @Don't return without freeing fname. @ text @d29 1 d3087 1 a3087 1 int arg, id, identify_only=0, write_to_files=1, minuso=0; d3094 1 a3094 1 "\nRaw Photo Decoder v5.16" a3118 2 /* Parse out the options */ d3125 1 a3125 1 write_to_files = 0; break; d3161 12 a3172 1 /* Process the named files */ d3215 4 a3218 3 ofp = stdout; strcpy (data, "standard output"); if (write_to_files) { d3232 1 a3232 1 if (write_to_files) @ 1.148 log @Added the Olympus E-1. @ text @d1568 1 a1568 1 FILE *fp; a1578 1 if (*fname != '/') return; d1581 1 a1581 1 while (1) { @ 1.147 log @Don't assume that an "int" is 32 bits! @ text @d988 1 a988 1 void unpacked_load_raw(int rsh) d998 2 d1001 1 a1001 1 image[row*width+col][FC(row,col)] = ntohs(pixel[col]) << 8 >> (8+rsh); d1008 1 a1008 1 unpacked_load_raw(2); d1013 6 a1018 1 unpacked_load_raw(-2); d2692 8 d3094 1 a3094 1 "\nRaw Photo Decoder v5.15" @ 1.146 log @Created a new white balance for the PowerShot G3 and S45. Made identify() logic more readable. Removed redundant xxx_load_raw() code. Added the Phase One H10 and H20, and the Imacon Ixpress. @ text @d442 1 a442 1 unsigned long getbits(int nbits) d444 1 a444 1 static unsigned long bitbuf=0, ret=0; d452 1 a452 1 ret = bitbuf << (32 - vbits) >> (32 - nbits); @ 1.145 log @Made "juice" an argument to canon_rgb_coeff(). @ text @d931 46 d988 1 a988 1 void unpacked_12_load_raw() d994 1 a994 1 merror (pixel, "unpacked_12_load_raw()"); d999 1 a999 1 image[row*width+col][FC(row,col)] = ntohs(pixel[col]) << 2; d1004 1 a1004 1 void olympus_load_raw() d1006 2 a1007 2 ushort *pixel; int row, col; d1009 3 a1011 9 pixel = calloc (width, sizeof *pixel); merror (pixel, "olympus_load_raw()"); fseek (ifp, tiff_data_offset, SEEK_SET); for (row=0; row < height; row++) { fread (pixel, 2, width, ifp); for (col=0; col < width; col++) image[row*width+col][FC(row,col)] = ntohs(pixel[col]) >> 2; } free (pixel); d1014 1 a1014 1 void olympus2_load_raw() a1028 11 void kyocera_load_raw() { int row, col; fseek (ifp, tiff_data_offset, SEEK_SET); getbits(-1); for (row=0; row < height; row++) for (col=0; col < width; col++) image[row*width+col][FC(row,col)] = getbits(12) << 2; } d1980 1 d1999 6 d2038 4 d2120 1 d2282 2 a2283 2 char head[26], *c; unsigned hlen, fsize, magic, i; d2297 2 a2298 1 fread (head, 1, 26, ifp); d2301 13 a2313 4 fseek (ifp, 0, SEEK_SET); magic = fget4(ifp); if (order == 0x4949 || order == 0x4d4d) { if (!memcmp(head,"HEAPCCDR",8)) { d2318 1 a2318 1 } else if (magic == 0x4d524d) { /* "\0MRM" (Minolta) */ d2325 1 a2325 1 } else if (magic >> 16 == 0x424d) { /* "BM" */ d2333 1 a2333 1 } else if (magic >> 16 == 0x4252) { /* "BR" */ d2347 1 a2347 1 } else if (!memcmp(head+19,"ARECOYK",7)) { d2350 1 a2350 1 } else if (magic == 0x46554a49) { /* "FUJI" */ d2356 1 a2356 1 } else if (magic == 0x4453432d) /* "DSC-" */ d2358 1 a2358 1 else if (magic == 0x464f5662) /* "FOVb" */ d2472 8 a2479 2 pre_mul[0] = 1.965; pre_mul[2] = 1.208; d2650 1 a2650 1 load_raw = unpacked_12_load_raw; d2660 1 a2660 1 load_raw = unpacked_12_load_raw; d2663 22 d2690 1 a2690 1 load_raw = olympus_load_raw; d2698 1 a2698 1 load_raw = olympus_load_raw; d2705 1 a2705 1 load_raw = olympus2_load_raw; d2713 1 a2713 1 load_raw = kyocera_load_raw; d2853 1 a2853 1 load_raw = olympus_load_raw; d3079 1 a3079 1 "\nRaw Photo Decoder v5.10" @ 1.144 log @Added the Fuji S7000. @ text @d2154 1 a2154 1 void canon_rgb_coeff() a2160 1 float juice = 0.1; /* weaken the above matrix */ d2420 1 a2420 1 canon_rgb_coeff(); @ 1.143 log @Added the Nikon Coolpix 2100. @ text @d844 1 a844 1 void fuji_s5000_load_raw() d846 1 a846 1 ushort pixel[1472]; d849 3 a851 3 fseek (ifp, tiff_data_offset + (1472*4+24)*2, SEEK_SET); for (row=0; row < 2152; row++) { fread (pixel, 2, 1472, ifp); d853 3 a855 3 swab (pixel, pixel, 1472*2); for (col=0; col < 1424; col++) { r = 1423 - col + (row >> 1); d857 1 a857 1 image[r*width+c][FC(r,c)] = pixel[col]; d862 11 d2573 9 d3001 1 a3001 1 "\nRaw Photo Decoder v5.09" @ 1.142 log @Recognize newer Canon models by CCD size instead of by name. @ text @d763 47 d2302 1 a2302 1 strcpy (model,"E2500"); d2516 7 d2981 1 a2981 1 "\nRaw Photo Decoder v5.08" @ 1.141 log @Changed canon_has_lowbits() to get 16k instead of 8k. @ text @d2357 1 a2357 4 } else if (!strcmp(model,"PowerShot G2") || !strcmp(model,"PowerShot G3") || !strcmp(model,"PowerShot S40") || !strcmp(model,"PowerShot S45")) { d2366 1 a2366 2 } else if (!strcmp(model,"PowerShot G5") || !strcmp(model,"PowerShot S50")) { d2380 1 a2380 5 } else if (!strcmp(model,"EOS D60") || !strcmp(model,"EOS 10D") || !strcmp(model,"EOS 300D DIGITAL") || !strcmp(model,"EOS Kiss Digital") || !strcmp(model,"EOS DIGITAL REBEL")) { d2927 1 a2927 1 "\nRaw Photo Decoder v5.07" @ 1.140 log @Added "EOS Kiss Digital". @ text @d526 1 a526 1 uchar test[8192]; d530 2 a531 2 fread (test, 1, 8192, ifp); for (i=540; i < 8191; i++) d2935 1 a2935 1 "\nRaw Photo Decoder v5.06" @ 1.139 log @Fixed kodak_compressed_load_raw() to handle uncompressed blocks. @ text @d2387 1 d2935 1 a2935 1 "\nRaw Photo Decoder v5.05" @ 1.138 log @Added the PENTAX *ist D. @ text @d1023 2 a1024 1 unsigned row, col, len, i, bits=0, pred[2]; d1036 2 a1037 1 for (i=0; i < len; ) { d1039 3 a1041 2 blen[i++] = c & 15; blen[i++] = c >> 4; d1049 31 a1080 13 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]; d2934 1 a2934 1 "\nRaw Photo Decoder v5.04" @ 1.137 log @Added the Minolta DiMAGE A1. @ text @d2256 2 d2262 3 a2264 3 if (!strncmp(model,"Canon",5) || !strncmp(model,"NIKON",5) || !strncmp(model,"SIGMA",5)) memmove (model, model+6, 64-6); d2511 8 d2913 1 a2913 1 "\nRaw Photo Decoder v5.03" @ 1.136 log @Allow rgb_max to be 0xffff for the Fuji F700 without causing overflows in vng_interpolate() or convert_to_rgb(). Sometimes the Canon EOS D2000C doesn't split rows. @ text @d873 12 a884 1 void minolta_load_raw() d890 1 a890 1 merror (pixel, "minolta_load_raw()"); d2504 5 a2508 3 load_raw = minolta_load_raw; pre_mul[0] = 1; pre_mul[2] = 1; d2903 1 a2903 1 "\nRaw Photo Decoder v5.02" @ 1.135 log @Updated my email address and URL @ text @d2 1 a2 1 Raw Photo Decoder (formerly "Canon PowerShot Converter") d70 1 a70 1 int histogram[0x1000]; d608 1 a608 1 if (make[0] == 'C') trick=2; /* Canon */ d838 1 a838 1 image[r*width+c][FC(r,c)] = val >> 1; d1692 1 a1692 1 brow[2][col][c] = t > 0 ? t:0; d2488 1 a2488 1 rgb_max = 0x7fff; d2757 1 a2757 1 rgb[3] = sqrt(rgb[3]); d2761 1 a2761 1 histogram[img[3] >> 4]++; /* bin width is 16 */ d2778 1 a2778 1 for (val=0x1000, total=0; --val; ) d2793 1 a2793 1 scale = rgb[3] ? mul * pow (rgb[3]/max, gamma_val-1) : 0; d2890 1 a2890 1 "\nRaw Photo Decoder v5.00" @ 1.134 log @Added the Canon EOS DIGITAL REBEL @ text @d3 1 a3 1 Copyright 1997-2003 by Dave Coffin d20 1 a20 1 http://www.shore.net/~dcoffin/powershot/ljpeg_decode.tar.gz d2894 1 a2894 1 "\nby Dave Coffin (dcoffin@@shore.net)" @ 1.133 log @Allow the coeff[][] matrix to be used with RGB cameras. Added a matrix to improve the color on my PowerShot G2. @ text @d2352 2 a2353 1 !strcmp(model,"EOS 300D DIGITAL")) { @ 1.132 log @Added the Canon EOS 300D. @ text @d71 2 d2060 19 d2082 1 a2082 1 float my_coeff[3][4] = d2087 1 a2087 1 for (r=0; r < 3; r++) { a2089 1 } d2153 1 a2153 1 unsigned hlen, fsize, magic, g; d2331 2 d2694 4 a2697 4 if (use_coeff) for (g=0; g < colors; g++) { coeff[0][g] *= red_scale; coeff[2][g] *= blue_scale; d2699 2 a2700 2 else if (colors == 3) { pre_mul[0] *= red_scale; /* Apply user-selected color balance */ d2702 12 a2713 10 if (four_color_rgb) { /* Use two types of green */ magic = filters; for (g=0; g < 32; g+=4) { if ((filters >> g & 15) == 9) filters |= 2 << g; if ((filters >> g & 15) == 6) filters |= 8 << g; } if (filters != magic) colors++; } a2882 1 void (*write_fun)(FILE *) = write_ppm; d2889 1 a2889 1 "\nRaw Photo Decoder v4.94" @ 1.131 log @Rewrote rollei_load_raw() to decode the entire image. @ text @d2329 2 a2330 1 !strcmp(model,"EOS 10D")) { d2866 1 a2866 1 "\nRaw Photo Decoder v4.93" @ 1.130 log @Removed "xmag" variable. Added the Rollei d530flex and Nikon D2H cameras. @ text @d843 2 a844 2 ushort *pixel, val; int row, col; d846 5 a850 2 pixel = calloc (width, 2); merror (pixel, "rollei_load_raw()"); d852 15 a866 6 for (row=0; row < height; row++) { fread (pixel, 2, width, ifp); for (col=0; col < width; col++) { val = ntohs(pixel[col]); val = val << 6 | val >> 10; image[row*width+col][FC(row,col)] = val >> 2; a868 1 free (pixel); a2005 1 tiff_data_offset += raw_width * (raw_width == 1316 ? 2:4); d2865 1 a2865 1 "\nRaw Photo Decoder v4.92" @ 1.129 log @Added support for the Fuji S5000 and F700 models. @ text @d62 1 a62 1 int is_canon, is_cmy, is_foveon, use_coeff, trim, xmag, ymag; d133 1 a133 1 These are Bayer grids, used by most RGB cameras: d135 1 a135 1 0x94949494: 0x61616161: 0x16161616: d137 5 a141 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 R G R G R G 0 G R G R G R 0 B G B G B G 1 G B G B G B 1 B G B G B G 1 G R G R G R 2 R G R G R G 2 G R G R G R 2 B G B G B G 3 G B G B G B 3 B G B G B G 3 G R G R G R d640 1 a640 1 int waste=0; d650 5 a654 1 waste = 4; d672 1 a672 1 for (col=0; col < width+waste; col++) d680 2 a681 2 if (col < 2) { i = 2*(row & 1) + col; d683 1 a683 1 hpred[col] = vpred[i]; d686 1 a686 1 if (col >= width) continue; d718 1 a718 1 int waste=0, skip16=0; d728 1 a728 1 waste = 4; d730 1 a730 1 waste = 3; d734 4 d751 1 a751 1 for (col=0; col < width+waste; col++) { d753 1 a753 1 if (col < width) d841 19 d1972 28 d2130 1 a2130 1 xmag = ymag = 1; d2186 3 a2188 1 } else if (magic == 0x464f5662) /* "FOVb" */ d2381 7 d2592 7 d2747 1 a2747 1 xmag*(width-trim*2), ymag*(height-trim*2)); d2749 1 a2749 1 ppm = calloc (width-trim*2, 3*xmag); d2761 1 a2761 2 for (i=0; i < xmag; i++) ppm[xmag*(col-trim)+i][c] = val; d2765 1 a2765 1 fwrite (ppm, width-trim*2, 3*xmag, ofp); d2855 1 a2855 1 "\nRaw Photo Decoder v4.90" @ 1.128 log @Added "-q" option for simple bilinear interpolation. @ text @d36 1 d771 1 a771 1 void fuji_load_raw() d776 1 a776 2 fseek (ifp, 100, SEEK_SET); fseek (ifp, fget4(ifp) + (2944*24+32)*2, SEEK_SET); d787 46 d2125 7 a2131 3 } else if (magic == 0x46554a49) /* "FUJI" */ parse_tiff(120); else if (magic == 0x464f5662) /* "FOVb" */ d2373 1 a2373 1 load_raw = fuji_load_raw; d2376 15 d2785 1 a2785 1 "\nRaw Photo Decoder v4.88" @ 1.127 log @Nikon changed the format of uncompressed D100 images. @ text @d66 1 a66 1 int four_color_rgb=0, use_camera_wb=0, document_mode=0; d1535 2 d2720 1 a2720 1 "\nRaw Photo Decoder v4.87" d2732 1 d2760 2 d2826 2 a2827 1 fprintf (stderr, "VNG interpolation...\n"); @ 1.126 log @Use the correct method to find the Fuji S2's raw data. @ text @a649 2 if (!strcmp(model,"D100")) width = 3034; d691 3 a693 3 Try to figure out if the image is compressed, based on my limited collection of NEF files. For the D100, every 16th byte of an uncompressed image is zero. d700 2 d703 1 a703 1 return tiff_data_compression == 34713; d716 2 d724 1 a724 1 if (!strcmp(model,"D100")) { d727 1 d2718 1 a2718 1 "\nRaw Photo Decoder v4.86" @ 1.125 log @Added support for the Casio QV-2000UX. @ text @d770 1 a770 1 int gray=0, row, col, r, c; d772 2 a773 5 fseek (ifp, 0, SEEK_SET); while (gray < 2944) if (fget2(ifp) == 2048) gray++; else gray=0; fseek (ifp, (2944*23+32) << 1, SEEK_CUR); d2715 1 a2715 1 "\nRaw Photo Decoder v4.85" @ 1.124 log @Moved unistd.h, added "-o" option. @ text @d845 1 a845 1 void casio_qv3000ex_load_raw() d847 1 a847 1 uchar pixel[2080]; d850 3 a852 1 fseek (ifp, 0, SEEK_SET); d854 1 a854 1 fread (pixel, 1, 2080, ifp); d858 1 d2093 3 a2095 1 if (fsize == 3217760) d2476 6 d2485 1 d2487 1 a2487 1 load_raw = casio_qv3000ex_load_raw; a2491 1 tiff_data_offset = 0; d2718 1 a2718 1 "\nRaw Photo Decoder v4.84" @ 1.123 log @Added code to repair bad pixels. @ text @a28 1 #include d36 1 d2699 1 a2699 1 int arg, id, identify_only=0, write_to_files=1; d2707 1 a2707 1 "\nRaw Photo Decoder v4.83" d2716 1 d2740 2 d2821 2 @ 1.122 log @Added support for the Canon PowerShot G5. @ text @d28 2 d56 1 d1348 53 d1880 4 d2020 1 a2020 1 camera_red = camera_blue = black = 0; d2707 1 a2707 1 "\nRaw Photo Decoder v4.81" d2798 1 @ 1.121 log @Added support for the CONTAX N DIGITAL camera. @ text @d2129 2 a2130 1 } else if (!strcmp(model,"PowerShot S50")) { d2647 1 a2647 1 "\nRaw Photo Decoder v4.80" @ 1.120 log @Don't mistake Microsoft BMP for Nucore BMQ (both start with "BM") @ text @d831 11 d1956 1 a1956 1 char head[8], *c; d1971 1 a1971 1 fread (head, 1, 8, ifp); d2011 3 d2288 8 d2646 1 a2646 1 "\nRaw Photo Decoder v4.79" @ 1.119 log @Allow the "-i" option to work with multiple files. @ text @d1980 6 a1985 2 strcpy (model,"BMQ"); goto nucore; d2624 1 a2624 1 "\nRaw Photo Decoder v4.78" @ 1.118 log @Wrote a function to handle all memory errors. @ text @d2612 1 a2612 1 int arg, id_one_file=0, write_to_files=1; d2620 1 a2620 1 "\nRaw Photo Decoder v4.77" d2627 1 a2627 1 "\n-i Identify the first file and exit" d2649 1 a2649 1 id_one_file = 1; break; d2689 6 a2694 4 if (id_one_file) { if (!ifp || identify(argv[arg])) exit(1); fprintf (stderr, "%s is a %s %s image.\n", argv[arg], make, model); exit(0); @ 1.117 log @Added the five megapixel Nucore BMQ format. @ text @d141 7 d549 1 a549 4 if (!pixel) { perror("canon_compressed_load_raw() calloc failed"); exit(1); } d658 1 a658 4 if (!curve) { perror("curve calloc failed"); exit(1); } d790 1 a790 4 if (!pixel) { perror("minolta_load_raw() calloc failed"); exit(1); } d806 1 a806 4 if (!pixel) { perror("olympus_load_raw() calloc failed"); exit(1); } d870 1 a870 4 if (!data) { perror("nucore_load_raw() calloc failed"); exit(1); } d892 1 a892 4 if (!pixel) { perror("kodak_easy_load_raw() calloc failed"); exit(1); } d1160 1 a1160 4 if (!smrow[6]) { perror("foveon_interpolate() calloc failed"); exit(1); } d1268 1 a1268 4 if (!shrink) { perror("foveon_interpolate() calloc failed"); exit(1); } d1498 1 a1498 4 if (!brow[4]) { perror("vng_interpolate() calloc failed"); exit(1); } d1840 1 a1840 4 if (!buf) { perror("parse_foveon() malloc failed"); exit(1); } d2514 1 a2514 4 if (!ppm) { perror("write_ppm() calloc failed"); exit(1); } d2563 1 a2563 4 if (!buffer) { perror("write_psd() calloc failed"); exit(1); } d2593 1 a2593 4 if (!ppm) { perror("write_ppm16() calloc failed"); exit(1); } d2620 1 a2620 1 "\nRaw Photo Decoder v4.76" d2700 1 a2700 4 if (!image) { perror("image calloc failed"); exit(1); } @ 1.116 log @Don't try to decode TIFF files written by Adobe Photoshop. @ text @d872 1 a872 1 int row, col; d880 1 a880 1 for (row=0; row < height; row++) { d882 4 d2015 4 d2652 1 a2652 1 "\nRaw Photo Decoder v4.75" @ 1.115 log @Decode the Fuji S2 correctly by rotating 45 degrees. @ text @d1718 1 d1746 5 d2644 1 a2644 1 "\nRaw Photo Decoder v4.74" @ 1.114 log @Added support for the Canon EOS D2000C. @ text @a138 9 The Fuji S2 does not use a Bayer grid. It has flat, wide pixels in the following pattern, stored in the file with a ninety-degree rotation (not shown here). bbbb|rrrr|bbbb|rrrr|bbbb|rrrr gggg|gggg|gggg|gggg|gggg|gggg rrrr|bbbb|rrrr|bbbb|rrrr|bbbb gggg|gggg|gggg|gggg|gggg|gggg d761 1 a761 1 Rotate the image ninety degrees. d766 1 a766 1 int gray=0, row, col; d773 1 a773 1 for (col=width; col--; ) { d775 5 a779 2 for (row=0; row < height; row++) image[row*width+col][FC(row,col)] = ntohs(pixel[row]) << 2; d2243 3 a2245 4 height = 2880; width = 2144; filters = 0x58525852; xmag = 2; d2638 1 a2638 1 "\nRaw Photo Decoder v4.72" @ 1.113 log @Added Nucore BMQ and RAW file formats. @ text @d2166 7 d2645 1 a2645 1 "\nRaw Photo Decoder v4.71" @ 1.112 log @Fix for CodeWarrior compiler (Thorsten Lemke) @ text @d875 19 d1997 14 d2409 5 d2638 1 a2638 1 "\nRaw Photo Decoder v4.70" @ 1.111 log @Added support for four Casio cameras. Added support for the Sigma SD9 in MED and LOW resolutions. Added grayscale "Document Mode". @ text @d610 3 a612 3 for (col=0; col < width; ) { image[r*width+col++][FC(r,col)] = buf[0][0] << 2; image[r*width+col++][FC(r,col)] = buf[0][1] << 2; @ 1.110 log @Changed some words in the usage message. @ text @d63 1 a63 1 int four_color_rgb=0, use_camera_wb=0; d818 1 a818 1 fseek (ifp, 0x4000, SEEK_SET); d842 33 d1029 4 d1034 2 a1035 1 case 2304: top = 7; left = 17; break; /* Sigma SD9 */ d1333 4 a1336 1 void scale_colors() a1338 1 #ifdef STATS d1340 1 a1340 1 double sum[4]; d1346 25 a1370 1 #endif d1374 9 a1382 20 for (c=0; c < colors; c++) if ((val = image[row*width+col][c])) { val -= black; #ifdef STATS if ((unsigned) row-225 < 192 && (unsigned) col-288 < 256) { if (min[c] > val) min[c] = val; if (max[c] < val) max[c] = val; sum[c] += val; count[c]++; } #endif val *= pre_mul[c]; if (val < 0) val = 0; if (val > rgb_max) val = rgb_max; image[row*width+col][c] = val; } #ifdef STATS for (c=0; c < colors; c++) fprintf (stderr, "%6d%6d %f\n", min[c], max[c], sum[c]/count[c]); #endif d1992 9 d2227 1 d2235 1 d2346 9 a2354 2 height = 1514; width = 2271; d2360 16 d2423 1 a2423 1 int row, col, r, g; d2427 2 d2433 2 d2439 1 a2439 1 rgb[r] = img[0]; d2600 1 a2600 1 "\nRaw Photo Decoder v4.64" d2610 1 d2634 2 d2693 2 d2698 1 a2698 1 if (filters) { @ 1.109 log @Support the Kodak DCS Pro 14n in "low-res" 6MB mode. @ text @d2518 3 a2520 3 "\n-f Interpolate RGB as four colors" "\n-g Set gamma value (%5.3f by default, only for 24-bit output)" "\n-b Set brightness (%5.3f by default)" d2522 2 a2523 2 "\n-r Set red scaling (daylight = 1.0)" "\n-l Set blue scaling (daylight = 1.0)" d2527 1 a2527 2 "\n\n", argv[0], gamma_val, bright); @ 1.108 log @Color-balanced the PowerShot A5 @ text @d55 1 d58 1 a58 1 int is_canon, is_cmy, use_coeff, trim, xmag, ymag; d911 53 d1556 3 d1899 1 a1899 1 is_cmy = use_coeff = 0; d2247 6 d2254 5 a2258 8 pre_mul[0] = 1.06; pre_mul[2] = 1.50; } else if (!strncmp(model2,"PB645H",6)) { pre_mul[0] = 1.20; pre_mul[2] = 1.52; } else if (!strcmp(model,"DCS Pro 14n")) { pre_mul[0] = 0.9932; pre_mul[2] = 1.1288; d2269 7 a2275 1 load_raw = kodak_compressed_load_raw; break; d2286 1 d2509 1 a2509 1 "\nRaw Photo Decoder v4.61" d2595 1 a2595 1 if (colors == 3 && !filters) { @ 1.107 log @Don't convert each pixel twice to RGB. Convert once and save the result in image[] array. @ text @d1918 3 a1920 3 pre_mul[0] = 1.550; pre_mul[1] = 1.354; pre_mul[3] = 1.014; d2442 1 a2442 1 "\nRaw Photo Decoder v4.60" @ 1.106 log @Don't allow subzero RGB values for CMY cameras. @ text @d65 1 d2264 4 a2267 1 void get_rgb(float rgb[4], ushort image[4]) d2269 3 a2271 2 int r, g; float cmy[4]; d2273 30 a2302 12 memset (rgb, 0, 4 * sizeof (float)); if (colors == 1) { for (r=0; r < 3; r++) /* RGB from grayscale */ rgb[r] = image[0]; rgb[3] = 3 * rgb[0]*rgb[0]; } else if (!use_coeff) for (r=0; r < 3; r++) { /* RGB from RGB */ if (r == 1 && colors == 4) rgb[1] = (image[1] + image[3]) >> 1; else rgb[r] = image[r]; rgb[3] += rgb[r]*rgb[r]; /* Compute magnitude */ a2303 17 else for (r=0; r < 3; r++) { /* RGB from GMCY or Foveon */ for (g=0; g < colors; g++) rgb[r] += image[g] * coeff[r][g]; if (rgb[r] < 0) rgb[r] = 0; if (rgb[r] > rgb_max) rgb[r] = rgb_max; rgb[3] += rgb[r]*rgb[r]; } if (is_cmy) { memcpy (cmy, rgb, sizeof cmy); rgb[0] = cmy[0] + cmy[1] - cmy[2]; rgb[1] = cmy[1] + cmy[2] - cmy[0]; rgb[2] = cmy[2] + cmy[0] - cmy[1]; for (r=0; r < 3; r++) if (rgb[r] < 0) rgb[r] = 0; rgb[3] = rgb[0]*rgb[0] + rgb[1]*rgb[1] + rgb[2]*rgb[2]; } d2311 3 a2313 2 int y, x, i; unsigned c, val; a2314 2 float rgb[4], max, max2, expo, mul, scale; int total, histogram[0x1000]; d2317 1 a2317 12 Build a histogram of magnitudes using 4096 bins of 64 values each. */ memset (histogram, 0, sizeof histogram); for (y=trim; y < height-trim; y++) for (x=trim; x < width-trim; x++) { get_rgb (rgb, image[y*width+x]); val = (int) sqrt(rgb[3]) >> 6; if (val > 0xfff) val=0xfff; histogram[val]++; } /* Set the white point to the 99.66th percentile d2321 1 a2321 2 max = val << 6; max2 = max * max; a2330 1 expo = (gamma_val-1)/2; /* Pull these out of the loop */ d2333 3 a2335 5 for (y=trim; y < height-trim; y++) { for (x=trim; x < width-trim; x++) { get_rgb (rgb, image[y*width+x]); d2337 3 a2339 6 scale = 0; if (rgb[3]) scale = mul * pow(rgb[3]/max2,expo); for (c=0; c < 3; c++) { val=rgb[c]*scale; d2342 1 a2342 1 ppm[xmag*(x-trim)+i][c] = val; d2369 2 a2370 3 int hw[2], psize, y, x, c, val; float rgb[4]; ushort *buffer, *pred; d2385 3 a2387 3 for (y=trim; y < height-trim; y++) { for (x=trim; x < width-trim; x++) { get_rgb (rgb, image[y*width+x]); d2405 2 a2406 3 ushort (*ppm)[3]; int y, x, c, val; float rgb[4]; d2417 3 a2419 3 for (y=trim; y < height-trim; y++) { for (x=trim; x < width-trim; x++) { get_rgb (rgb, image[y*width+x]); d2423 1 a2423 1 ppm[x-trim][c] = htons(val); d2442 1 a2442 1 "\nRaw Photo Decoder v4.54" d2541 2 @ 1.105 log @Added definitions for WIN32 @ text @d1838 1 a1838 1 camera_red = camera_blue = 0; d2294 2 a2445 13 /* Creates a new filename with a different extension */ void exten(char *new_name, const char *old, const char *ext) { char *cp; strcpy(new_name,old); cp=strrchr(new_name,'.'); if (!cp) cp=new_name+strlen(new_name); strcpy(cp,ext); } d2448 1 a2448 1 char data[256]; d2457 1 a2457 1 "\nRaw Photo Decoder v4.53" a2521 1 black = 0; d2559 4 a2562 2 exten(data, argv[arg], write_ext); ofp = fopen(data,"wb"); @ 1.104 log @Changed "read_crw" to "load_raw" everywhere. @ text @d31 2 @ 1.103 log @Added the Canon EOS 10D @ text @d58 1 a58 1 void (*read_crw)(); d146 1 a146 1 void ps600_read_crw() d187 1 a187 1 void a5_read_crw() d222 1 a222 1 void a50_read_crw() d257 1 a257 1 void pro70_read_crw() d462 1 a462 1 blank pixels that (*read_crw) will strip off. d531 1 a531 1 void canon_compressed_read_crw() d548 1 a548 1 perror("canon_compressed_read_crw() calloc failed"); d613 1 a613 1 void lossless_jpeg_read_crw() d629 1 a629 1 void lossless_jpeg_read_crw() { } d635 1 a635 1 void nikon_compressed_read_crw() d712 1 a712 1 void nikon_read_crw() d718 1 a718 1 nikon_compressed_read_crw(); d750 1 a750 1 void nikon_e950_read_crw() d768 1 a768 1 void fuji_read_crw() d785 1 a785 1 void minolta_read_crw() d792 1 a792 1 perror("minolta_read_crw() calloc failed"); d804 1 a804 1 void olympus_read_crw() d811 1 a811 1 perror("olympus_read_crw() calloc failed"); d823 1 a823 1 void olympus2_read_crw() d838 1 a838 1 void kodak_easy_read_crw() d847 1 a847 1 perror("kodak_easy_read_crw() calloc failed"); d863 1 a863 1 void kodak_compressed_read_crw() d931 1 a931 1 void foveon_read_crw() d1906 1 a1906 1 read_crw = ps600_read_crw; d1914 1 a1914 1 read_crw = a5_read_crw; d1923 1 a1923 1 read_crw = a50_read_crw; d1932 1 a1932 1 read_crw = pro70_read_crw; d1941 1 a1941 1 read_crw = canon_compressed_read_crw; d1950 1 a1950 1 read_crw = canon_compressed_read_crw; d1958 1 a1958 1 read_crw = canon_compressed_read_crw; d1968 1 a1968 1 read_crw = canon_compressed_read_crw; d1975 1 a1975 1 read_crw = canon_compressed_read_crw; d1982 1 a1982 1 read_crw = canon_compressed_read_crw; d1990 1 a1990 1 read_crw = canon_compressed_read_crw; d1998 1 a1998 1 read_crw = lossless_jpeg_read_crw; d2006 1 a2006 1 read_crw = lossless_jpeg_read_crw; d2015 1 a2015 1 read_crw = nikon_read_crw; d2022 1 a2022 1 read_crw = nikon_read_crw; d2030 1 a2030 1 read_crw = nikon_read_crw; d2037 1 a2037 1 read_crw = nikon_read_crw; d2046 1 a2046 1 read_crw = nikon_e950_read_crw; d2056 1 a2056 1 read_crw = nikon_read_crw; d2070 1 a2070 1 read_crw = nikon_read_crw; d2082 1 a2082 1 read_crw = nikon_read_crw; d2091 1 a2091 1 read_crw = fuji_read_crw; d2098 1 a2098 1 read_crw = minolta_read_crw; d2105 1 a2105 1 read_crw = olympus_read_crw; d2112 1 a2112 1 read_crw = olympus_read_crw; d2119 1 a2119 1 read_crw = olympus2_read_crw; d2201 1 a2201 1 read_crw = kodak_easy_read_crw; break; d2203 1 a2203 1 read_crw = lossless_jpeg_read_crw; break; d2206 1 a2206 1 read_crw = kodak_compressed_read_crw; break; d2216 1 a2216 1 read_crw = foveon_read_crw; d2224 1 a2224 1 if (read_crw == lossless_jpeg_read_crw) { d2466 1 a2466 1 "\nRaw Photo Decoder v4.52" d2551 1 a2551 1 (*read_crw)(); @ 1.102 log @Added "-i" option for quickly identifying raw photos. @ text @d1985 2 a1986 1 } else if (!strcmp(model,"EOS D60")) { d2466 1 a2466 1 "\nRaw Photo Decoder v4.51" @ 1.101 log @Added support for the PowerShot S50. @ text @d2457 1 a2457 1 int arg, write_to_files=1; d2465 1 a2465 1 "\nRaw Photo Decoder v4.50" d2470 1 a2470 1 "\n\nUsage: %s [options] file1.crw file2.crw ...\n" d2472 1 d2493 2 d2532 5 a2536 3 if (!ifp) { perror(argv[arg]); continue; d2538 1 @ 1.100 log @Re-adjusted the Nikon E950 based on _sunlit_ photos. @ text @d543 1 d1971 7 d2465 1 a2465 1 "\nRaw Photo Decoder v4.49" @ 1.99 log @Use the new Nikon E950 matrix for the 990 also. @ text @d1760 4 a1763 2 float sum, my_coeff[3][4] = { { -1.4, 1.4, -1.2, 2.2 }, { 4, -2, -2, 3 }, { -1, 1.5, 3.3, -2 } }; a1765 2 for (sum=g=0; g < 4; g++) sum += my_coeff[r][g]; d1767 1 a1767 1 coeff[r][g] = my_coeff[r][g] / sum; d2039 3 a2041 3 pre_mul[0] = 1.09392; pre_mul[1] = 1.04542; pre_mul[2] = 1.2396; d2457 1 a2457 1 "\nRaw Photo Decoder v4.48" @ 1.98 log @Added support for the Nikon E950 and E990. Created a special coeff[] matrix for the E950. @ text @d2048 1 d2457 1 a2457 1 "\nRaw Photo Decoder v4.47" @ 1.97 log @Forgot bit-shift for the Olympus C5050Z (no big deal) @ text @d749 15 d1757 15 d1868 3 a1870 1 else if (fsize == 2940928) /* Nikon "DIAG RAW" formats */ d1873 1 a1873 1 strcpy (model,"E995"); d2032 2 a2033 2 } else if (!strcmp(model,"E2500")) { height = 1204; d2036 7 a2042 2 goto coolpix; } else if (!strcmp(model,"E995")) { d2046 9 d2227 1 a2227 1 if (colors == 4) d2456 1 a2456 1 "\nRaw Photo Decoder v4.45" @ 1.96 log @Added more transformation and smoothing steps to foveon_interpolate(). @ text @d818 1 a818 1 image[row*width+col][FC(row,col)] = getbits(12); @ 1.95 log @Added support for the Nikon E4300 (no white balance) @ text @d957 12 d971 2 d982 3 a984 5 { -631, -2025, 822 } } }; float mul[3] = { 1.0321, 1.0, 1.1124 }; static const int curve[72] = { 0,1,2,2,3,4,5,6,6,7,8,9,9,10,11,11,12,13,13,14,14, d988 23 a1010 2 curve2[20] = { 0,1,1,2,3,3,4,4,5,5,6,6,6,7,7,7,7,7,7,7 }; ushort *pix, prev[3]; d1012 1 a1012 1 int (*smrow[7])[4], smlast, smred, smred_p=0, hood[7], min, max; d1126 1 a1126 5 i = (total[c] * j >> 16) - pix[c]; if (i < -71) i = -27; else if (i < 0) i = -curve[-i]; else if (i < 72) i = curve[ i]; else i = 27; d1128 1 a1128 5 if (i > 19) i -= 8; else if (i >= 0) i -= curve2[ i]; else if (i > -20) i += curve2[-i]; else i += 8; ipix[c] = i; d1132 1 a1132 6 i = ipix[c] - sum; if (i < -19) i = -8; else if (i < 0) i = -curve2[-i]; else if (i < 20) i = curve2[ i]; else i = 8; i = ipix[c] - i; d1139 80 d1730 4 a1733 4 { 1.5, -0.5, 0 }, { -2.3, 5.3, -2 }, { 0.68, -3.18, 3.5 } }, mul[3] = { 1.0, 1.0, 0.7448 }; d2162 1 d2410 1 a2410 1 "\nRaw Photo Decoder v4.42" @ 1.94 log @Added support for the Kodak DCS Pro 14n. @ text @d1744 2 d1910 5 d2309 1 a2309 1 "\nRaw Photo Decoder v4.41" @ 1.93 log @Rebalanced my PS600 from an old photo -- filter colors have shifted. Explicitly declared "signed char" in vng_interpolate(). Added support for some Nikon "DIAG RAW" formats. Added a Foveon-specific interpolation routine. @ text @d868 5 d2030 3 d2302 1 a2302 1 "\nRaw Photo Decoder v4.40" @ 1.92 log @Removed PNG support, and replaced it with 48-bit PPM. @ text @d731 1 a731 1 if (model[0] == 'E') d733 6 d952 165 d1166 1 a1166 1 static const char *cp, terms[] = { d1625 4 a1628 4 { 1.25, 0, -0.25 }, { -2.5, 6, -2.5 }, { -0.5, 0, 1.5 } }; d1633 1 a1633 1 coeff[i][j] = foveon[i][j]; d1697 1 a1697 1 unsigned magic, hlen, g; d1706 3 a1708 1 make[0] = model[0] = model2[0] = 0; d1710 6 a1716 2 hlen = fget4(ifp); fread (head, 1, 8, ifp); d1718 1 a1718 2 fseek (ifp, 0, SEEK_END); parse_ciff(hlen, ftell(ifp) - hlen); d1722 18 a1739 15 } else { fseek (ifp, 0, SEEK_SET); magic = fget4(ifp); if (magic == 0x46554a49) /* "FUJI" */ parse_tiff(120); else if (magic == 0x4d524d) { /* "\0MRM" */ parse_tiff(48); fseek (ifp, 4, SEEK_SET); tiff_data_offset = fget4(ifp) + 8; fseek (ifp, 24, SEEK_SET); raw_height = fget2(ifp); raw_width = fget2(ifp); } else if (magic == 0x464f5662) /* "FOVb" */ parse_foveon(); } d1767 2 a1768 3 pre_mul[0] = 1.388; pre_mul[1] = 1.489; pre_mul[2] = 1.051; d1893 15 d1911 2 a1913 1 filters = 0xb4b4b4b4; a2046 2 pre_mul[0] = 1.159; pre_mul[1] = 1.006; d2193 1 a2193 1 unsigned char head[] = { d2294 1 a2294 1 "\nRaw Photo Decoder v4.35" d2375 7 a2381 2 fprintf (stderr, "Scaling raw data (black=%d)...\n", black); scale_colors(); @ 1.91 log @Created a transform matrix for Foveon data, similar to GMCY. @ text @d6 3 a8 3 any digital camera into PPM or PNG format. TIFF and CIFF parsing are based upon public specifications, but no such documentation is available for the raw sensor data, so writing this program has a36 4 #ifndef NO_PNG #include #endif d600 1 a600 2 register int r, col; int trick=1; d641 1 a641 1 int vpred[4], hpred[2], csize, row, col, i, len; a643 1 register int diff; d846 1 a846 1 register int diff; d907 1 a907 1 short table[1024], pred[3]; d917 1 a917 1 table[i] = fget2(ifp); d935 1 a935 2 i = dindex->leaf; pred[c] += table[i]; d1155 1 a1155 1 register uchar a, b; d1170 1 a1170 1 register uchar a, b, c, d; d1938 1 a1938 1 register unsigned c, val; d1977 1 a1977 1 get_rgb(rgb,image[y*width+x]); d2031 3 a2033 5 for (y=trim; y < height-trim; y++) { for (x=trim; x < width-trim; x++) { get_rgb(rgb, image[y * width + x]); a2045 1 #ifndef NO_PNG d2047 1 a2047 1 Write the image to a 48-bit PNG file. d2049 1 a2049 1 void write_png(FILE *ofp) d2051 1 a2051 3 png_structp png_ptr; png_infop info_ptr; ushort (*png)[3]; d2055 6 a2060 28 png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) return; info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return; } if (setjmp(png_ptr->jmpbuf)) { png_destroy_write_struct(&png_ptr, &info_ptr); return; } png_init_io (png_ptr, ofp); png_set_IHDR (png_ptr, info_ptr, width-trim*2, height-trim*2, 16, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Comment out this line if you want compression */ png_set_compression_level(png_ptr, 0); png_write_info(png_ptr, info_ptr); if (htons(0xaa55) != 0xaa55) png_set_swap(png_ptr); png = calloc(width-trim*2,6); if (!png) { perror("write_png() calloc failed"); d2066 1 a2066 1 get_rgb(rgb, image[y*width+x]); d2070 1 a2070 1 png[x-trim][c] = val; d2073 1 a2073 1 png_write_row(png_ptr, (png_bytep) png); d2075 1 a2075 3 free (png); png_write_end(png_ptr, NULL); png_destroy_write_struct(&png_ptr, &info_ptr); a2076 1 #endif d2102 1 a2102 1 "\nRaw Photo Decoder v4.34" d2118 1 a2118 3 #ifndef NO_PNG "\n-4 Write 48-bit PNG" #endif a2150 1 #ifndef NO_PNG d2152 2 a2153 2 write_fun = write_png; write_ext = ".png"; a2154 1 #endif @ 1.90 log @Color-balanced the Sigma SD9 based on the outdoor photo. Added support for the Olympus C5050Z. @ text @d59 1 a59 1 int is_canon, is_cmy, is_rgb, trim, xmag, ymag; d1458 67 a1524 1 void make_coeff(); d1539 1 a1539 1 is_cmy = 0; d1859 1 d1880 8 a1887 1 if ((is_rgb = colors == 3)) { a1899 6 } else if (colors == 4) { make_coeff(); for (g=0; g < 4; g++) { coeff[0][g] *= red_scale; coeff[2][g] *= blue_scale; } a1903 52 /* Given a matrix that converts RGB to GMCY, create a matrix to do the opposite. Only square matrices can be inverted, so I create four 3x3 matrices by omitting a different GMCY color in each one. The final coeff[][] matrix is the sum of these four. */ void make_coeff() { static const float gmcy[4][3] = { /* red green blue */ { 0.11, 0.86, 0.08 }, /* green */ { 0.50, 0.29, 0.51 }, /* magenta */ { 0.11, 0.92, 0.75 }, /* cyan */ { 0.81, 0.98, 0.08 } /* yellow */ }; double invert[3][6], num; int ignore, i, j, k, r, g; memset (coeff, 0, sizeof coeff); for (ignore=0; ignore < 4; ignore++) { for (j=0; j < 3; j++) { g = (j < ignore) ? j : j+1; for (r=0; r < 3; r++) { invert[j][r] = gmcy[g][r]; /* 3x3 matrix to invert */ invert[j][r+3] = (r == j); /* Identity matrix */ } } for (j=0; j < 3; j++) { num = invert[j][j]; /* Normalize this row */ for (i=0; i < 6; i++) invert[j][i] /= num; for (k=0; k < 3; k++) { /* Subtract it from the other rows */ if (k==j) continue; num = invert[k][j]; for (i=0; i < 6; i++) invert[k][i] -= invert[j][i] * num; } } for (j=0; j < 3; j++) { /* Add the result to coeff[][] */ g = (j < ignore) ? j : j+1; for (r=0; r < 3; r++) coeff[r][g] += invert[r][j+3]; } } for (r=0; r < 3; r++) { /* Normalize such that: */ for (num=g=0; g < 4; g++) /* (1,1,1,1) x coeff = (1,1,1) */ num += coeff[r][g]; for (g=0; g < 4; g++) coeff[r][g] /= num; } } d1914 1 a1914 1 } else if (is_rgb) d1923 2 a1924 2 for (r=0; r < 3; r++) { /* RGB from GMCY */ for (g=0; g < 4; g++) d2139 1 a2139 1 "\nRaw Photo Decoder v4.32" @ 1.89 log @Added preliminary support for the Sigma SD9. Rebalanced the color on the PowerShot 600. @ text @d3 1 a3 1 Copyright 1997-2002 by Dave Coffin d807 15 d1694 7 d1793 2 a1794 2 pre_mul[0] = 1.006; pre_mul[2] = 1.147; d2123 1 a2123 1 "\nRaw Photo Decoder v4.30" @ 1.88 log @Gave up trying to uncap red and blue when green is not saturated. @ text @d871 67 d952 4 a955 3 for (col=0; col < width; col++) { c = FC(row,col); val = image[row*width+col][c] - black; d957 6 a962 6 if ((unsigned) row-186 < 10 && (unsigned) col-465 < 104) { if (min[c] > val) min[c] = val; if (max[c] < val) max[c] = val; sum[c] += val; count[c]++; } d964 5 a968 5 val *= pre_mul[c]; if (val < 0) val = 0; if (val > rgb_max) val = rgb_max; image[row*width+col][c] = val; } d1407 36 d1484 2 a1485 1 } d1494 2 a1495 1 if (!strncmp(model,"Canon",5) || !strncmp(model,"NIKON",5)) d1514 3 a1516 3 pre_mul[0] = 1.377; pre_mul[1] = 1.428; pre_mul[2] = 1.010; d1766 7 d2101 1 a2101 1 "\nRaw Photo Decoder v4.26" @ 1.87 log @Provided option to interpolate RGB as _four_ colors, to correct the "screen door effect". @ text @d898 1 a898 3 if (val > rgb_max && (!is_rgb || (c & 1) || image[row*width+col+(col ? -1:1)][FC(row,col+1)]+256 > rgb_max)) val = rgb_max; d1988 1 a1988 1 "\nRaw Photo Decoder v4.25" @ 1.86 log @I deleted "rgb_max -= black;" by mistake. Oops! @ text @d54 1 a54 2 int height, width, trim, colors, is_cmy, is_canon, black, rgb_max; int xmag, ymag; d58 2 a59 1 int use_camera_wb=0; a60 1 char make[64], model[64], model2[64]; d64 3 a66 2 float rgb_mul[3], camera_red, camera_blue; float gmcy_mul[4], coeff[3][4]; d78 1 a78 1 Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2 = R/G/B a873 1 float *scale; a883 1 scale = (colors == 3) ? rgb_mul:gmcy_mul; d896 1 a896 1 val *= scale[c]; d898 2 a899 2 if (val > rgb_max && (colors != 3 || c == 1 || image[row*width+col+(col ? -1:1)][1]+256 > rgb_max)) d1350 1 a1350 1 unsigned magic, hlen; d1352 1 a1352 2 rgb_mul[0] = rgb_mul[1] = rgb_mul[2] = 1; gmcy_mul[0] = gmcy_mul[1] = gmcy_mul[2] = gmcy_mul[3] = 1; d1410 3 a1412 3 gmcy_mul[0] = 1.377; gmcy_mul[1] = 1.428; gmcy_mul[2] = 1.010; d1419 3 a1421 3 gmcy_mul[0] = 1.550; gmcy_mul[1] = 1.354; gmcy_mul[3] = 1.014; d1428 3 a1430 3 gmcy_mul[0] = 1.750; gmcy_mul[1] = 1.381; gmcy_mul[3] = 1.182; d1437 3 a1439 3 gmcy_mul[0] = 1.389; gmcy_mul[1] = 1.343; gmcy_mul[3] = 1.034; d1446 3 a1448 3 gmcy_mul[0] = 1.496; gmcy_mul[1] = 1.509; gmcy_mul[3] = 1.009; d1455 3 a1457 3 gmcy_mul[0] = 1.446; gmcy_mul[1] = 1.405; gmcy_mul[2] = 1.016; d1463 2 a1464 2 rgb_mul[0] = 1.785; rgb_mul[2] = 1.266; d1473 2 a1474 2 rgb_mul[0] = 1.965; rgb_mul[2] = 1.208; d1480 2 a1481 2 rgb_mul[0] = 1.592; rgb_mul[2] = 1.261; d1487 2 a1488 2 rgb_mul[0] = 2.242; rgb_mul[2] = 1.245; d1496 2 a1497 2 rgb_mul[0] = 1.976; rgb_mul[2] = 1.282; d1504 2 a1505 2 rgb_mul[0] = 1.66; rgb_mul[2] = 1.13; d1512 2 a1513 2 rgb_mul[0] = 0.838; rgb_mul[2] = 1.095; d1519 2 a1520 2 rgb_mul[0] = 1.347; rgb_mul[2] = 3.279; d1527 2 a1528 2 rgb_mul[0] = 1.910; rgb_mul[2] = 1.220; d1534 2 a1535 2 rgb_mul[0] = 2.374; rgb_mul[2] = 1.677; d1543 3 a1545 3 gmcy_mul[0] = 1.300; gmcy_mul[1] = 1.300; gmcy_mul[3] = 1.148; d1552 2 a1553 2 rgb_mul[0] = 1.424; rgb_mul[2] = 1.718; d1559 2 a1560 2 rgb_mul[0] = 1; rgb_mul[2] = 1; d1566 2 a1567 2 rgb_mul[0] = 1.43; rgb_mul[2] = 1.77; d1573 2 a1574 2 rgb_mul[0] = 1.43; rgb_mul[2] = 1.77; d1581 2 a1582 2 rgb_mul[0] = 0.973; rgb_mul[2] = 0.987; d1585 2 a1586 2 rgb_mul[0] = 0.996; rgb_mul[2] = 1.279; d1589 2 a1590 2 rgb_mul[0] = 1.21; rgb_mul[2] = 1.63; d1593 2 a1594 2 rgb_mul[0] = 1.46; rgb_mul[2] = 1.84; d1601 2 a1602 2 rgb_mul[0] = 1.43; rgb_mul[2] = 2.16; d1605 2 a1606 2 rgb_mul[0] = 1.28; rgb_mul[2] = 2.00; d1609 2 a1610 2 rgb_mul[0] = 1.00; rgb_mul[2] = 1.20; d1612 2 a1613 2 rgb_mul[0] = 0.985; rgb_mul[2] = 1.15; d1615 2 a1616 2 rgb_mul[0] = 1.00; rgb_mul[2] = 1.20; d1618 2 a1619 2 rgb_mul[0] = 1.12; rgb_mul[2] = 1.07; d1622 2 a1623 2 rgb_mul[0] = 1.05; rgb_mul[2] = 1.17; d1628 2 a1629 2 rgb_mul[0] = 1.35; rgb_mul[2] = 1.18; d1632 2 a1633 2 rgb_mul[0] = 1.06; rgb_mul[2] = 1.72; d1638 2 a1639 2 rgb_mul[0] = 1.06; rgb_mul[2] = 1.385; d1641 2 a1642 2 rgb_mul[0] = 1.06; rgb_mul[2] = 1.50; d1644 2 a1645 2 rgb_mul[0] = 1.20; rgb_mul[2] = 1.52; d1650 1 d1675 2 a1676 2 rgb_mul[0] = camera_red; rgb_mul[2] = camera_blue; d1680 20 a1699 3 rgb_mul[0] *= red_scale; /* Apply user-selected color balance */ rgb_mul[2] *= blue_scale; if (colors == 4) make_coeff(); d1748 1 a1748 1 for (num=g=0; g < 4; g++) /* (1,1,1,1) x coeff = rgb_mul[] */ d1751 1 a1751 1 coeff[r][g] *= rgb_mul[r]/num; d1765 1 a1765 1 } else if (colors == 3) d1767 4 a1770 1 rgb[r] = image[r]; d1990 1 a1990 1 "\nRaw Photo Decoder v4.21" d1998 1 d2021 2 @ 1.85 log @Do scaling in GMCY space before vng_interpolate() For this I had to rebalance all GMCY cameras. @ text @d884 1 d1972 1 a1972 1 "\nRaw Photo Decoder v4.20" @ 1.84 log @Do RGB scaling _before_ vng_interpolate() Use correct formula for diagonal gradients @ text @d66 1 a66 1 float coeff[3][4]; a870 15 void subtract_black() { ushort *img; int size; img = image[0]; size = width * height * 4; while (size--) if (*img > black) *img++ -= black; else *img++ = 0; rgb_max -= black; } d874 11 a884 2 if (colors != 3) return; d888 7 a894 6 if (c != 1) { val = image[row*width+col][c] * rgb_mul[c]; if (val > rgb_max && image[row*width+col+(col ? -1:1)][1]+256 > rgb_max) val = rgb_max; image[row*width+col][c] = val; d896 12 a907 1 } d1345 2 a1346 2 Open a CRW file, identify which camera created it, and set global variables accordingly. Returns nonzero if an error occurs. d1353 2 a1354 3 rgb_mul[0] = 1.592; rgb_mul[1] = 1.0; rgb_mul[2] = 1.261; d1357 1 a1357 1 colors = 4; d1409 1 d1412 3 a1414 2 rgb_mul[0] = 1.667; rgb_mul[2] = 1.667; d1418 1 d1421 3 a1423 2 rgb_mul[0] = 1.111; rgb_mul[2] = 0.978; d1427 1 d1430 3 a1432 2 rgb_mul[0] = 1.316; rgb_mul[2] = 0.776; d1436 1 d1439 3 d1445 1 d1448 3 d1454 1 d1457 3 a1459 2 rgb_mul[0] = 1.469; rgb_mul[2] = 1.327; a1462 1 colors = 3; a1472 1 colors = 3; d1475 1 a1475 1 rgb_mul[0] = 1.966; a1479 1 colors = 3; d1482 2 a1486 1 colors = 3; a1494 1 colors = 3; a1502 1 colors = 3; a1511 1 colors = 3; a1518 1 colors = 3; a1525 1 colors = 3; a1533 1 colors = 3; d1542 1 d1545 3 a1547 2 rgb_mul[0] = 2.126; rgb_mul[2] = 1.197; a1550 1 colors = 3; a1558 1 colors = 3; a1565 1 colors = 3; a1572 1 colors = 3; a1579 1 colors = 3; a1580 2 rgb_mul[0] = 1; rgb_mul[2] = 1; d1731 3 a1733 1 for (r=0; r < 3; r++) /* Multiply coeff[][] by rgb_mul[] */ d1735 2 a1736 1 coeff[r][g] *= rgb_mul[r]; d1759 1 d1971 1 a1971 1 "\nRaw Photo Decoder v4.10" d2053 1 a2053 4 if (black) { fprintf (stderr, "Subtracting thermal noise (%d)...\n", black); subtract_black(); } @ 1.83 log @Set camera white balance for EOS D30 if it's not "Auto". @ text @d886 18 d941 1 a941 1 int code[8][576], *ip, ihood[8], gval[8], gmin, gmax, sum[4]; d1003 11 a1013 1 *ip++ = INT_MAX; a1015 5 for (cp=chood, g=0; g < 8; g++) { ihood[g] = *cp++ * width; ihood[g] += *cp++; ihood[g] *= 4; } d1043 2 a1044 1 for (num=g=0; g < 8; g++) { /* Average the neighbors */ d1047 4 a1050 1 sum[c] += pix[ihood[g] + c]; d1054 1 a1054 2 color = FC(row,col); /* Save to buffer */ for (c=0; c < colors; c++) { d1525 1 d1740 1 a1740 3 rgb[r] = image[r] * rgb_mul[r]; if (rgb[r] > rgb_max && image[1]+256 > rgb_max) rgb[r] = rgb_max; d1959 1 a1959 1 "\nRaw Photo Decoder v4.03" d2045 1 @ 1.82 log @Moved the fopen() call into main() @ text @d1279 8 a1286 4 if (type == 0x1031) { /* Get the raw width and height */ fseek (ifp, aoff+2, SEEK_SET); raw_width = fget2(ifp); raw_height = fget2(ifp); d1295 5 d1934 1 a1934 1 "\nRaw Photo Decoder v4.02" @ 1.81 log @Don't apply rgb_max until the green channel is saturated @ text @d27 1 d1307 1 a1307 1 int open_and_id(char *fname) a1320 5 ifp = fopen(fname,"rb"); if (!ifp) { perror(fname); return 1; } d1925 1 a1925 1 "\nRaw Photo Decoder v4.01" d1989 7 a1995 2 if (open_and_id(argv[arg])) { if (ifp) fclose(ifp); @ 1.80 log @Use Variable Number Gradient interpolation for all cameras. @ text @d1709 1 a1709 1 if (rgb[r] > rgb_max) d1929 1 a1929 1 "\nRaw Photo Decoder v4.00" @ 1.79 log @Fixed ProBack645 kludge with "model2" string. New "-w" flag uses camera white balance settings. @ text @d54 1 a72 29 I assume that the influence of one pixel upon another is proportionate to the inverse square of the distance between them. So I've designed three neighborhoods for aspect ratios of 1:1, 1:2, and 2:1. Triplet format is y-offset,x-offset,weight. 0,0,0 marks the end. */ const char square_hood[] = { -1,-1,1, -1,0,2, -1,1,1, 0,-1,2, 0,1,2, 1,-1,1, 1,0,2, 1,1,1, 0,0,0 }; const char wide_hood[] = { -1,-1,1, -1,0,1, -1,1,1, 0,-2,1, 0,-1,4, 0,1,4, 0,2,1, 1,-1,1, 1,0,1, 1,1,1, 0,0,0 }; const char tall_hood[] = { -2,0,1, -1,-1,1, -1,0,4, -1,1,1, 0,-1,1, 0,1,1, 1,-1,1, 1,0,4, 1,1,1, 2,0,1, 0,0,0 }; const char *hood; /* d886 3 a888 56 RGB interpolation algorithm designed by Matt Dillon. GMCY cameras still use my algorithm. His explanation follows: * When this function is called, we only have one color for * each pixel. This code searches the 5x5 neighborhood and * synthesizes the other colors based on interpolation. The * algorithm works as follows. Take one portion of the * CCD filter pattern: * * 0 1 2 3 4 * 0 G R G R G * 1 B G B G B * 2 G RR G * 3 B G B G B * 4 G R G R G * * Lets say we are on pixel (x,y) = (2,2), the bracketed green above, and * we are trying to synthesize the Blue and Red guns for that pixel based * on the surrounding pixels. * * We could average the surrounding blue pixels to synthesize a blue for * (2,2) but that will blur the image somewhat if we are on the boundary * of an edge. Instead what we do is calculate a temporary green for each * blue pixel and then generate the blue for (2,2) by scaling it against * the differential between the temporary green and the green in (2,2). * * For example, the green for the blue pixel at (2,1) is calculated by * averaging the green at (2,0) and (2,2). A scaling factor is generated * using this green and the green at (2,2), we multiply in the Blue pixel * at (2,1), and that is the Blue we store for (2,2). It's actually somewhat * more complicated since there are other blue's around (2,2). What we do * is execute this calculate for each blue and do a weighted average of the * result, and that final number is the Blue we store at (2,2). * * The scaling factor tends to blow up in low-light situations due to * the calculation of the scaling factor becoming skewed (think about the * difference between two pixel brightnesses of 10 and 15, and 4000 and 4005). * To compensate we introduce a constant in the scaling process, llfactor. * The higher the constant the closer the scaling factor gets to 1:1 (a * straight average of the surrounding blue's regardless of the scale * generated using the green's). This results in somewhat more blurring * but hides low-light dropouts. */ #define lowlight_val 0 void dillon_interpolate() { int row, col, cc, c; int vb, vr, val; int dx, dy; int avg[4], sum[4]; int base = 4096 + 64; int llfactor = 8 + lowlight_val * 16; int weight; int size; ushort (*oimage)[4]; d890 1 a890 7 size = height * width * 8; oimage = malloc(size); if (!oimage) { perror("dillon_interpolate() calloc failed"); exit(1); } memcpy (oimage, image, size); d892 52 a943 21 for (row=2; row < height-2; row++) { for (col=2; col < width-2; col++) { cc = FC(row,col); vb = oimage[row*width+col][cc]; avg[0] = avg[1] = avg[2] = avg[3] = 0; sum[0] = sum[1] = sum[2] = sum[3] = 0; for (dy = -1; dy <= 1; ++dy) { for (dx = -1; dx <= 1; ++dx) { c = FC(row+dy, col+dx); vr = oimage[(row+dy*2)*width + (col+dx*2)][cc]; vr = (vb + vr) / 2; /* * RGB CCDs almost universally repeat the same * color filter 2 pixels in any direction. */ val = oimage[(row+dy)*width + (col+dx)][c]; weight = base - abs(vr - vb); val = (llfactor + vb) * val / (llfactor + vr); weight = 100; avg[c] += val * weight; sum[c] += weight; d945 12 d958 3 a960 3 for (c=0; c < colors; c++) { if (sum[c]) image[row*width+col][c] = (avg[c] + (sum[c]/2)) / sum[c]; d962 1 d965 18 a982 26 free (oimage); } /* When this function is called, we only have one color for each pixel. Search the 3x3 neighborhood for pixels of other colors, and average them. Diagonal neighbors get counted once, orthogonal neighbors twice. */ void bilinear_interpolate() { unsigned row, col, cc, y, x, w, c, avg[8]; const char *h; for (row=1; row < height-1; row++) for (col=1; col < width-1; col++) { cc = FC(row,col); memset (avg, 0, sizeof avg); for (h = hood; ; ) { y = row + *h++; x = col + *h++; if ((w = *h++) == 0) break; if (y >= height || x >= width) continue; if ((c = FC(y,x)) == cc) continue; avg[c] += w * image[y*width+x][c]; avg[c+4] += w; d984 1 a984 3 for (c=0; c < colors; c++) if (c != cc) image[row*width+col][c] = avg[c] / avg[c+4]; d986 9 a994 23 } /* We now have all color values for each pixel. Sharpen the spatial detail by assuming that neighboring pixels have similar color ratios. To avoid amplifying noise, wherever any color value falls below a certain threshold, that pixel and all neighboring pixels will be left unchanged. */ void smooth_hues() { ushort (*last)[4]; ushort (*curr)[4]; void *tmp; unsigned row, col, cc, y, x, w, c, val, avg[8]; const char *h; last = calloc (width, sizeof *curr); curr = calloc (width, sizeof *curr); if (!last || !curr) { perror("smooth_hues() calloc failed"); d997 4 a1000 1 for (row=2; row < height-2; row++) { d1002 14 a1015 7 memset (avg, 0, sizeof avg); for (h = hood; ; ) { /* Any noisy neighbors in the 'hood? */ y = row + *h++; x = col + *h++; if ((w = *h++) == 0) break; for (c=0; c < colors; c++) if (image[y*width+x][c] < 75) goto noise; d1017 13 a1029 10 cc = FC(row,col); /* Neighbors are OK to use */ for (h = hood; ; ) { y = row + *h++; x = col + *h++; if ((w = *h++) == 0) break; if ((c = FC(y,x)) == cc) continue; val = ((unsigned long) image[y*width+x][c] << 16) / image[y*width+x][cc] * image[row*width+col][cc] >> 16; avg[c] += w * val; avg[c+4] += w; d1031 1 a1031 3 noise: for (c=0; c < colors; c++) curr[col][c] = avg[c+4] ? avg[c]/avg[c+4] : image[row*width+col][c]; d1033 8 a1040 9 if (row > 2) memcpy (image[(row-1)*width+2], last+2, (width-4)*sizeof *last); tmp = last; last = curr; curr = tmp; } memcpy (image[(row-1)*width+2], last+2, (width-4)*sizeof *last); free (last); free (curr); d1180 1 a1180 1 if (tag == 0x927c) { /* MakerNote */ d1213 1 a1213 3 fread (make, 64, 1, ifp); if (len > 63) len=63; make[len]=0; d1216 1 a1216 3 fread (model, 64, 1, ifp); if (len > 63) len=63; model[len]=0; d1219 1 a1219 3 fread (model2, 64, 1, ifp); if (len > 63) len=63; model2[len]=0; d1318 1 a1318 1 hood = square_hood; d1356 1 a1356 1 model[16] = 0; d1482 1 a1482 1 hood = wide_hood; d1506 1 a1506 1 hood = tall_hood; d1734 1 a1734 1 int y, x, i, ymag=1, xmag=1; a1758 2 if (hood == tall_hood) xmag = 2; if (hood == wide_hood) ymag = 2; d1921 1 a1921 1 int i, arg, write_to_files=1, dillon=0, dillon_ok, smooth=1; d1929 1 a1929 1 "\nRaw Photo Decoder v3.65" a1936 2 "\n-d Use Dillon interpolation if possible" "\n-s Number of times to smooth hues (1 by default)" a1958 4 case 'd': dillon = 1; break; case 's': smooth = atoi(argv[++arg]); break; d2011 1 a2011 18 if (filters == 0) goto nointerp; dillon_ok = dillon; for (i=8; i < 32; i+=8) if ((filters >> i & 0xff) != (filters & 0xff)) dillon_ok = 0; if (dillon_ok) { fprintf (stderr, "Dillon interpolation...\n"); dillon_interpolate(); trim = 2; } else { if (dillon) fprintf (stderr, "Filter pattern is not Dillon-compatible.\n"); fprintf (stderr, "Bilinear interpolation...\n"); bilinear_interpolate(); for (i=0; i < smooth; i++) { fprintf (stderr, "Smoothing hues...\n"); smooth_hues(); } d2013 2 a2015 1 nointerp: @ 1.78 log @Added support for Kodak DCR compression @ text @d57 1 a57 1 int kodak_645m; d59 1 a59 1 char make[64], model[64]; d63 1 a63 1 float rgb_mul[3]; a1177 6 case 0x920e: kodak_645m = 0; break; case 0xa20e: kodak_645m = 1; break; d1184 1 a1184 1 int base=0, offset=0, entries, tag, type, len, val; d1209 9 d1279 5 d1312 1 d1330 11 d1346 7 d1377 1 d1388 1 a1388 1 model[0] = 0; d1665 6 a1670 8 } else if (!strcmp(model,"ProBack645")) { if (kodak_645m) { rgb_mul[0] = 1.06; /* 645M sample image */ rgb_mul[2] = 1.50; } else { rgb_mul[0] = 1.20; /* 645H sample image */ rgb_mul[2] = 1.52; } d1697 7 d1829 1 a1829 1 perror("ppm calloc failed"); d1888 1 a1888 1 perror("psd calloc failed"); d1949 1 a1949 1 perror("png calloc failed"); d1994 1 a1994 1 "\nRaw Photo Decoder v3.60" d2006 1 d2034 2 @ 1.77 log @Added support for the Canon EOS-1DS. @ text @d57 1 d859 39 d1017 1 a1017 1 void first_interpolate() d1050 1 a1050 1 void second_interpolate() d1061 1 a1061 1 perror("second_interpolate() calloc failed"); d1178 6 d1277 1 d1624 21 d1652 3 d1961 1 a1961 1 "\nRaw Photo Decoder v3.54" d1970 1 a1970 1 "\n-s Number of times to smooth colors (1 by default)" d2058 2 a2059 2 fprintf (stderr, "First interpolation...\n"); first_interpolate(); d2061 2 a2062 2 fprintf (stderr, "Second interpolation...\n"); second_interpolate(); @ 1.76 log @Fixed segfault caused by "crw -d -4" @ text @d165 3 a167 3 The Fuji S2 does not use a Bayer grid. Instead, it flattens out the pixels as shown below, and then stores these pixels in the file with a ninety-degree rotation. d647 1 a647 4 if (!strcmp(model,"EOS-1D")) fseek (ifp, 288912, SEEK_SET); else fseek (ifp, tiff_data_offset, SEEK_SET); d1436 1 d1439 10 d1890 1 a1890 1 "\nRaw Photo Decoder v3.53" d1975 1 a1975 1 if (colors == 1) goto nointerp; @ 1.75 log @Correct a 2:1 or 1:2 aspect ratio in write_ppm, not in the documentation. PSD and PNG output are unchanged. @ text @d1847 1 a1847 1 png[x-1][c] = val; d1882 1 a1882 1 "\nRaw Photo Decoder v3.52" @ 1.74 log @Added support for the Fuji FinePixS2Pro and Minolta DiMAGE 7. Improved interpolation to better handle non-square pixels. @ text @d1685 1 a1685 1 int y, x; d1710 4 a1713 1 fprintf (ofp, "P6\n%d %d\n255\n", width-trim*2, height-trim*2); d1715 1 a1715 1 ppm = calloc(width-trim*2,3); d1736 2 a1737 1 ppm[x-trim][c]=val; d1740 2 a1741 1 fwrite (ppm, width-trim*2, 3, ofp); d1882 1 a1882 1 "\nRaw Photo Decoder v3.50" @ 1.73 log @Major overhaul in version 3.40: Camera make and model are two separate strings. Added support for 15 new camera models (mostly Kodak). Thanks to Kodak, I now support greyscale and CMY cameras. All Canon-compressed formats get decoded in one subroutine. Get the correct value for nef_curve_offset, we hope. Changed name from "Canon PowerShot Converter" to "Raw Photo Decoder", as Canon cameras are a minority now. @ text @d53 1 a53 1 int height, width, trim, colors, is_cmy, black, canon, rgb_max; d71 29 d155 1 a155 9 Some RGB cameras use 0x94949494: 0 1 2 3 4 5 0 R G R G R G 1 G B G B G B 2 R G R G R G 3 G B G B G B Some use 0x61616161: d157 1 a157 5 0 1 2 3 4 5 0 G R G R G R 1 B G B G B G 2 G R G R G R 3 B G B G B G d159 14 a172 1 Some use 0x16161616: a173 5 0 1 2 3 4 5 0 B G B G B G 1 G R G R G R 2 B G B G B G 3 G R G R G R d480 2 a481 1 if (c == 0xff && canon) fgetc(ifp); /* Canon puts an extra 0 after 0xff */ d778 39 d982 2 a983 2 int row, col, cc, x, y, c, val; int avg[8]; d989 9 a997 11 for (y = row-1; y < row+2; y++) for (x = col-1; x < col+2; x++) if ((c = FC(y,x)) != cc) { val = image[y*width+x][c]; avg[c] += val; avg[c+4]++; if (y==row || x==col) { /* Orthogonal neighbor */ avg[c] += val; avg[c+4]++; } } d1018 2 a1019 2 int row, col, cc, x, y, c, val; int avg[8]; d1030 14 a1043 9 for (y = row-1; y < row+2; y++) /* Any noisy neighbors? */ for (x = col-1; x < col+2; x++) for (c=0; c < colors; c++) if (image[y*width+x][c] < 75) goto noise; cc = FC(row,col); for (y = row-1; y < row+2; y++) /* Neighbors are OK to use */ for (x = col-1; x < col+2; x++) if ((c = FC(y,x)) != cc) { val = ((unsigned long) image[y*width+x][c] << 16) / d1045 3 a1047 7 avg[c] += val; avg[c+4]++; if (y==row || x==col) { /* Count orthogonal neighbor twice */ avg[c] += val; avg[c+4]++; } } d1073 3 a1075 1 if (order == 0x4d4d) /* "MM" means big-endian */ a1076 2 else /* "II" means little-endian */ return a + (b << 8); d1090 3 a1092 1 if (order == 0x4d4d) a1093 2 else return a + (b << 8) + (c << 16) + (d << 24); d1096 1 a1096 1 void tiff_parse_subifd() d1126 1 a1126 1 fseek (ifp, val, SEEK_SET); d1202 1 a1202 1 void parse_tiff() d1209 2 a1210 1 fseek (ifp, 2, SEEK_SET); /* open_and_id() already got byte order */ d1213 1 a1213 1 fseek (ifp, doff, SEEK_SET); d1221 1 a1221 1 fseek (ifp, val, SEEK_SET); d1236 3 a1238 3 fseek (ifp, val, SEEK_SET); fseek (ifp, fget4(ifp), SEEK_SET); tiff_parse_subifd(); d1242 1 a1242 1 tiff_parse_subifd(); d1301 1 a1301 1 int hlen; d1309 1 a1309 1 canon = 1; d1326 14 a1339 1 parse_tiff(); d1344 1 a1344 1 if (!strncmp(make,"OLYMPUS",7)) d1360 1 a1444 1 canon = 0; a1452 1 canon = 0; a1460 1 canon = 0; d1462 1 a1469 1 canon = 0; a1476 1 canon = 0; d1481 17 d1877 1 a1877 1 "\nRaw Photo Decoder v3.40" @ 1.72 log @Trying not to amplify noise in second_interpolate(). @ text @d2 1 a2 1 Canon PowerShot Converter d5 5 a9 6 A portable ANSI C program to convert raw CRW files from Canon digital cameras into PPM or PNG format. This is an entirely original work; no other copyrights apply. Any similarity to Canon's code is only to the extent necessary to decode image formats of Canon's design. d12 1 a12 1 otherwise. Comments and questions are welcome. d17 2 a18 2 The Canon EOS-1D digital camera compresses its data with lossless JPEG. To read EOS-1D images, you must also download: d53 1 a53 1 int height, width, trim, colors, black, canon, rgb_max; d55 2 a56 1 int nef_curve_offset, nef_data_compression, nef_data_offset, nef_rows_per_strip; d58 1 a58 1 char name[64]; d134 1 a134 1 The EOS-1D uses 0x61616161: d142 1 a142 1 The Nikon cameras use 0x16161616: a513 6 void pro90_read_crw() { ushort pixel[1944*8]; int row, r, col; decompress(0,540); d515 2 a516 20 Read eight rows at a time. Each row has 1896 image pixels and 48 black pixels. */ for (row=0; row < height; row += 8) { decompress(pixel,243); for (r=0; r < 8; r++) { for (col=0; col < width; col++) image[(row+r)*width+col][FC(row+r,col)] = (pixel[(r*1944)+col] & 0x3ff) << 4; for (col=width; col < 1944; col++) black += pixel[(r*1944)+col] & 0x3ff; } } black = ((INT64) black << 4) / ((1944 - width) * height); } void g1_read_crw() { ushort pixel[2144*2]; int row, r, col; d518 1 a518 5 decompress(0,540); /* Read two rows at a time. The image has a black border, eight pixels wide on top, two on the bottom, four on the left, and 52 on the right. d520 1 a520 14 for (row = -8; row < height+2; row += 2) { decompress(pixel,67); for (r=0; r < 2; r++) for (col = -4; col < width+52; col++) if ((unsigned) (row+r) < height && (unsigned) col < width) image[(row+r)*width+col][FC(row+r,col)] = (pixel[(r*2144)+col+4] & 0x3ff) << 4; else black += pixel[(r*2144)+col+4] & 0x3ff; } black = ((INT64) black << 4) / (10 * 2144 + 56 * height); } void g2_read_crw() d522 11 a532 20 ushort pixel[2376*8]; int row, r, col; decompress(0,540); /* Read eight rows at a time. The image has a black border, six pixels wide on top, two on the bottom, 12 on the left, and 52 on the right. */ for (row = -6; row < height+2; row += 8) { decompress(pixel,297); for (r=0; r < 8; r++) for (col = -12; col < width+52; col++) if ((unsigned) (row+r) < height && (unsigned) col < width) image[(row+r)*width+col][FC(row+r,col)] = (pixel[(r*2376)+col+12] & 0x3ff) << 4; else black += pixel[(r*2376)+col+12] & 0x3ff; } black = ((INT64) black << 4) / (8 * 2376 + 64 * height); d535 1 a535 7 /* The "PowerShot" cameras provide 10 bits per pixel in one compressed chunk. The "EOS" cameras provide 12 bits per pixel: first the two low bits of every pixel, not compressed, followed by the top ten bits compressed as in the PowerShot cameras. */ void d30_read_crw() d538 1 a538 1 int i, row, r, col, save; d544 1 d546 1 d549 1 a549 1 pixel = calloc (raw_width*4, sizeof *pixel); d551 1 a551 1 perror("d30_read_crw() calloc failed"); d554 14 a567 9 decompress(0, 540 + raw_height*raw_width/4); for (row=0; row < raw_height; row+=4) { decompress(pixel, raw_width/16); /* Get four rows */ save = ftell(ifp); /* Don't lose our place */ fseek (ifp, 26 + row*raw_width/4, SEEK_SET);/* Add the low bits */ for (prow=pixel, i=0; i < raw_width; i++) { c = fgetc(ifp); for (r=0; r < 8; r+=2) *prow++ = (*prow << 2) + ((c >> r) & 3); d569 1 a569 2 fseek (ifp, save, SEEK_SET); for (r=0; r < 4; r++) d576 1 a576 1 (pixel[r*raw_width+col] & 0xfff) << 2; d578 1 a578 1 black += pixel[r*raw_width+col] & 0xfff; d582 1 a582 1 black = ((INT64) black << 2) / (left * height); d599 2 d605 1 d607 3 a609 2 row *= 2; for (r = row; r < row + 2; r++) d617 1 a617 1 void eos1d_read_crw() d621 4 a624 1 fseek (ifp, 288912, SEEK_SET); d635 2 d654 1 a654 1 if (!strcmp(name,"NIKON D1X")) d656 1 a656 1 if (!strcmp(name,"NIKON D100")) a661 2 if (nef_curve_offset == 0) nef_curve_offset = strcmp(name,"NIKON D100") ? 3488:5974; d674 1 a674 2 fseek (ifp, nef_data_offset, SEEK_SET); fseek (ifp, fget4(ifp), SEEK_SET); d711 3 a713 4 if (strcmp(name,"NIKON D100")) return nef_data_compression == 0x8799; fseek (ifp, nef_data_offset, SEEK_SET); fseek (ifp, fget4(ifp), SEEK_SET); d729 1 a729 1 if (!strcmp(name,"NIKON D1X")) d731 1 a731 1 if (!strcmp(name,"NIKON D100")) { d736 2 a737 1 if (nef_rows_per_strip == 0) return; d740 1 a740 1 if (name[0] == 'E') a741 5 if (irow % nef_rows_per_strip == 0) { fseek (ifp, nef_data_offset + irow/nef_rows_per_strip*4, SEEK_SET); fseek (ifp, fget4(ifp), SEEK_SET); getbits(-1); } d771 25 d1032 1 a1032 1 void nef_parse_subifd() d1034 1 a1034 1 int entries, tag, type, len, val; d1055 1 a1055 1 nef_data_compression = val; d1059 7 a1065 3 nef_data_offset = ftell(ifp)-4; else nef_data_offset = val; a1069 1 nef_rows_per_strip = val; d1083 1 a1083 1 int base=0, offset=0, entries, tag, type, len, val, save; d1108 2 a1109 1 save = ftell(ifp); d1136 1 a1136 1 Parse a TIFF file looking for camera name and decompress offsets. d1142 2 a1144 3 nef_data_compression = 0; nef_data_offset = 0; nef_rows_per_strip = 0; d1158 5 d1164 3 a1166 1 fread (name, 64, 1, ifp); d1169 9 a1177 5 if (len == 2) { /* Get the _second_ sub-image */ fget4(ifp); fseek (ifp, fget4(ifp), SEEK_SET); } nef_parse_subifd(); d1190 1 a1190 1 The camera name, and the decode table number. d1206 1 a1206 1 if (type == 0x080a) { /* Get the camera name */ d1208 3 a1210 2 while (fgetc(ifp)); fread (name, 64, 1, ifp); d1243 1 d1251 1 a1251 1 name[0] = 0; d1263 14 a1276 1 c = name + strlen(name); /* Remove trailing spaces */ d1278 2 a1279 2 if (name[0] == 0) { fprintf(stderr,"%s has an unknown format.\n",fname); d1282 1 a1282 1 if (!strcmp(name,"Canon PowerShot 600")) { d1289 1 a1289 1 } else if (!strcmp(name,"Canon PowerShot A5")) { d1296 1 a1296 1 } else if (!strcmp(name,"Canon PowerShot A50")) { d1303 1 a1303 1 } else if (!strcmp(name,"Canon PowerShot Pro70")) { d1308 1 a1308 1 } else if (!strcmp(name,"Canon PowerShot Pro90 IS")) { d1312 2 a1313 2 read_crw = pro90_read_crw; } else if (!strcmp(name,"Canon PowerShot G1")) { d1317 1 a1317 1 read_crw = g1_read_crw; d1320 1 a1320 1 } else if (!strcmp(name,"Canon PowerShot S30")) { d1325 1 a1325 1 read_crw = g1_read_crw; d1328 4 a1331 2 } else if (!strcmp(name,"Canon PowerShot G2") || !strcmp(name,"Canon PowerShot S40")) { d1336 1 a1336 1 read_crw = g2_read_crw; d1339 1 a1339 1 } else if (!strcmp(name,"Canon EOS D30")) { d1344 2 a1345 2 read_crw = d30_read_crw; } else if (!strcmp(name,"Canon EOS D60")) { d1350 1 a1350 1 read_crw = d30_read_crw; d1354 1 a1354 2 } else if (!strcmp(name,"Canon EOS-1D")) { #ifdef LJPEG_DECODE d1359 1 a1359 1 read_crw = eos1d_read_crw; d1362 1 a1362 5 #else fprintf(stderr,"crw.c was compiled without EOS-1D support.\n"); return 1; #endif } else if (!strcmp(name,"NIKON D1")) { d1371 1 a1371 1 } else if (!strcmp(name,"NIKON D1H")) { d1380 1 a1380 1 } else if (!strcmp(name,"NIKON D1X")) { d1389 1 a1389 1 } else if (!strcmp(name,"NIKON D100")) { d1398 1 a1398 1 } else if (!strcmp(name,"E5000") || !strcmp(name,"E5700")) { d1406 1 a1406 1 } else if (!strcmp(name,"E-10")) { d1414 1 a1414 1 } else if (!strncmp(name,"E-20",4)) { d1422 67 d1490 7 a1496 1 fprintf(stderr,"Sorry, the %s is not yet supported.\n",name); d1499 1 d1558 1 d1561 5 a1565 1 if (colors == 3) d1579 7 d1618 1 a1618 1 fprintf(ofp,"P6\n%d %d\n255\n",width-trim*2,height-trim*2); d1784 2 a1785 2 fprintf(stderr, "\nCanon PowerShot Converter v3.18" d1787 1 a1787 1 " with EOS-1D support" d1843 1 a1843 1 fprintf(stderr,"Unknown option \"%s\"\n",argv[arg]); d1851 1 d1861 2 a1862 2 black = 0; fprintf (stderr, "Loading %s image from %s...\n",name,argv[arg]); d1866 1 a1866 1 fprintf (stderr, "Subtracting thermal noise (%d)...\n",black); d1869 2 d1890 1 d1901 1 a1901 1 fprintf (stderr, "Writing data to %s...\n",data); @ 1.71 log @Bought a Kodak Grey Card and rebalanced my PowerShot G2. (using the white side, direct sunlight, no clouds) @ text @d966 7 a972 3 We now have all color values for each pixel. Smooth the color balance to avoid artifacts. This function may be called more than once. d990 5 d996 1 a996 2 memset (avg, 0, sizeof avg); for (y = row-1; y < row+2; y++) d998 1 a998 1 if ((c = FC(y,x)) != cc && image[y*width+x][cc]) { d1003 1 a1003 1 if (y==row || x==col) { /* Orthogonal neighbor */ d1008 1 a1008 1 curr[col][cc] = image[row*width+col][cc]; d1010 1 a1010 2 if (c != cc) curr[col][c] = avg[c+4] ? avg[c] / avg[c+4] : 0; d1697 1 a1697 1 "\nCanon PowerShot Converter v3.15" @ 1.70 log @Reorganized NEF decoding, improved compatibility with Windows and C++. @ text @d1323 2 a1324 2 rgb_mul[0] = 1.828; rgb_mul[2] = 1.326; d1690 1 a1690 1 "\nCanon PowerShot Converter v3.14" @ 1.69 log @Correctly decode the Nikon E5000 and E5700 @ text @d28 5 d34 2 d56 1 a56 1 int nikon_curve_offset, nikon_data_compression, nikon_data_offset; d189 1 a189 1 black = ((long long) black << 4) / ((896 - width) * height); d224 1 a224 1 black = ((long long) black << 4) / ((992 - width) * height); d259 1 a259 1 black = ((long long) black << 4) / ((1320 - width) * height); d534 1 a534 1 black = ((long long) black << 4) / ((1944 - width) * height); d558 1 a558 1 black = ((long long) black << 4) / (10 * 2144 + 56 * height); d582 1 a582 1 black = ((long long) black << 4) / (8 * 2376 + 64 * height); d632 1 a632 1 black = ((long long) black << 2) / (left * height); d683 1 a683 1 void nikon_d1x_read_crw() a690 1 uchar test[256], skip16=0; d697 1 a697 7 /* Try to figure out if the image is compressed, based on my limited collection of NEF files. For the D100, every 16th byte of an uncompressed image is zero. */ fseek (ifp, nikon_data_offset, SEEK_SET); if (!strcmp(name,"NIKON D100")) { a698 22 fread (test, 1, 256, ifp); for (i=0; i < 16; i++) if (test[i*16+15]) goto compressed; fseek (ifp, -256, SEEK_CUR); width = 3037; waste = 3; skip16 = 1; } else if (nikon_data_compression == 0x8799) goto compressed; /* Read an uncompressed image */ getbits(-1); for (row=0; row < height; row++) { for (col=0; col < width+waste; col++) { i = getbits(12); if (col < width) image[row*width+col][FC(row,col)] = i << 2; if (skip16 && (col % 10) == 9) getbits(8); } } return; a699 2 /* Read an compressed image */ compressed: d703 3 a705 3 if (nikon_curve_offset == 0) nikon_curve_offset = strcmp(name,"NIKON D100") ? 3488:5974; fseek (ifp, nikon_curve_offset, SEEK_SET); d711 1 a711 1 perror("nikon_d1x_read_crw() calloc failed"); d717 2 a718 1 fseek (ifp, nikon_data_offset, SEEK_SET); d722 2 a723 2 for (col=0; col < width+waste; col++) { d745 21 a765 1 void nikon_e5000_read_crw() d767 2 a768 3 uchar data[3864], *dp; ushort pixel[2576], *pix; int irow, row, col; d770 27 a796 8 fseek (ifp, 589225, SEEK_SET); for (irow=row=0; irow < height; irow++) { fread (data, 3864, 1, ifp); for (dp=data, pix=pixel; dp < data+3864; dp+=3, pix+=2) { pix[0] = (dp[0] << 4) + (dp[1] >> 4); pix[1] = (dp[1] << 8) + dp[2]; a797 5 for (col=0; col < width; col++) image[row*width+col][FC(row,col)] = (pixel[col] & 0xfff) << 2; if ((row+=2) >= height) /* Once we've read all the even rows, */ row = 1; /* read the odd rows. */ d973 1 a973 1 ushort (*this)[4]; d978 3 a980 3 last = calloc (width, sizeof *this); this = calloc (width, sizeof *this); if (!last || !this) { d1000 1 a1000 1 this[col][cc] = image[row*width+col][cc]; d1003 1 a1003 1 this[col][c] = avg[c+4] ? avg[c] / avg[c+4] : 0; d1008 2 a1009 2 last = this; this = tmp; d1013 1 a1013 1 free (this); d1049 1 a1049 1 void nikon_parse_subifd() d1051 1 a1051 1 int entries, tag, type, len, val, save; a1061 1 save = ftell(ifp); d1072 1 a1072 1 nikon_data_compression = val; d1076 3 a1078 5 nikon_data_offset = val; else { fseek (ifp, val, SEEK_SET); nikon_data_offset = fget4(ifp); } d1081 1 d1083 2 d1086 1 a1091 1 fseek (ifp, save, SEEK_SET); d1095 1 a1095 1 void nikon_parse_makernote() d1124 1 a1124 1 nikon_curve_offset = base+val + 2; d1129 1 a1129 1 void nikon_parse_exif() d1142 1 a1142 1 nikon_parse_makernote(); d1155 4 a1158 3 nikon_curve_offset = 0; nikon_data_compression = 0; nikon_data_offset = 0; d1176 5 a1180 1 nikon_parse_subifd(); d1183 1 a1183 1 nikon_parse_exif(); d1359 1 a1359 1 read_crw = nikon_d1x_read_crw; d1368 1 a1368 1 read_crw = nikon_d1x_read_crw; d1377 1 a1377 1 read_crw = nikon_d1x_read_crw; d1386 1 a1386 1 read_crw = nikon_d1x_read_crw; d1392 1 d1394 1 a1394 1 read_crw = nikon_e5000_read_crw; d1669 1 a1669 1 void exten(char *new, const char *old, const char *ext) d1673 3 a1675 3 strcpy(new,old); cp=strrchr(new,'.'); if (!cp) cp=new+strlen(new); d1690 1 a1690 1 "\nCanon PowerShot Converter v3.11" @ 1.68 log @Greatly improved NEF parsing, thanks to Chris Breeze. @ text @d768 1 a768 1 void nikon_e5700_read_crw() d774 1 a774 1 fseek (ifp, 589226, SEEK_SET); d780 2 a781 2 pix[0] = (dp[0] << 8) + (dp[1] & 0xf0) + (dp[1] >> 4); pix[1] = (dp[2] << 4) + (dp[1] & 0x0f); d1374 1 a1374 1 } else if (!strcmp(name,"E5700")) { d1377 2 a1378 2 filters = 0xe1e1e1e1; read_crw = nikon_e5700_read_crw; d1674 1 a1674 1 "\nCanon PowerShot Converter v3.10" @ 1.67 log @Don't assume that the compiler evaluates left-to-right! @ text @d49 1 a49 1 int nef_data_offset; d678 1 a678 1 int waste=0, comp; d696 1 a696 4 fseek (ifp, nef_data_offset+58, SEEK_SET); comp = fget2(ifp); fseek (ifp, nef_data_offset+142, SEEK_SET); fseek (ifp, fget4(ifp)+8, SEEK_SET); d706 1 a706 1 } else if (comp == 0x8799) d727 3 a729 4 if (!strcmp(name,"NIKON D100")) fseek (ifp, 5974, SEEK_SET); else fseek (ifp, 3488, SEEK_SET); d741 1 a741 2 fseek (ifp, nef_data_offset+82, SEEK_SET); fseek (ifp, fget4(ifp), SEEK_SET); d1039 99 d1145 3 d1159 1 a1161 1 fseek (ifp, val, SEEK_SET); d1165 5 a1169 1 nef_data_offset = val; d1180 1 a1180 1 void parse (int offset, int length) d1209 1 a1209 1 parse (aoff, len); d1244 1 a1244 1 parse (hlen, ftell(ifp) - hlen); d1674 1 a1674 1 "\nCanon PowerShot Converter v3.06" @ 1.66 log @Color-balanced the PowerShot G2 based on my new camera. @ text @d1013 1 d1017 4 d1022 3 a1024 3 return (fgetc(f) << 8) + fgetc(f); else return fgetc(f) + (fgetc(f) << 8); d1032 6 d1039 1 a1039 1 return (fgetc(f) << 24) + (fgetc(f) << 16) + (fgetc(f) << 8) + fgetc(f); d1041 1 a1041 1 return fgetc(f) + (fgetc(f) << 8) + (fgetc(f) << 16) + (fgetc(f) << 24); d1573 1 a1573 1 "\nCanon PowerShot Converter v3.05" @ 1.65 log @Allow Dillon interpolation for some GMCY cameras. @ text @d1196 2 a1197 2 rgb_mul[0] = 2.156; rgb_mul[2] = 1.043; d1562 1 a1562 1 "\nCanon PowerShot Converter v3.04" @ 1.64 log @Added support for the Nikon E5700 @ text @d1554 1 a1554 1 int i, arg, write_to_files=1, dillon=0, smooth=1; d1562 1 a1562 1 "\nCanon PowerShot Converter v3.03" d1570 1 a1570 1 "\n-d Use Dillon interpolation for RGB cameras" d1645 5 a1649 1 if (dillon && colors == 3) { d1654 2 @ 1.63 log @Added support for the Olympus E-20 @ text @d773 23 d1262 7 d1562 1 a1562 1 "\nCanon PowerShot Converter v3.02" @ 1.62 log @Don't do arithmetic with byte-swapped numbers! @ text @d775 1 a775 1 ushort pixel[2256]; d778 5 d785 1 a785 1 fread (pixel, 2, 2256, ifp); d789 1 d1247 8 d1532 1 a1532 1 "\nCanon PowerShot Converter v3.01" @ 1.61 log @Added support for uncompressed Nikon D100 images. Added support for the Olympus E-10 (uncompressed) Added Matt Dillon's RGB interpolation algorithm. Releasing all this as version 3.00. @ text @d1409 1 a1409 1 psize = hw[0] * hw[1]; d1518 1 a1518 1 "\nCanon PowerShot Converter v3.00" @ 1.60 log @Added support for the Nikon D100 @ text @d47 1 a47 1 int height, width, colors, black, canon, rgb_max; d678 1 a678 1 int waste=0; d684 1 a688 1 /* Read an uncompressed image */ d691 5 d697 14 a710 4 if (fget2(ifp) != 0x8799) { fseek (ifp, nef_data_offset+142, SEEK_SET); fseek (ifp, fget4(ifp)+8, SEEK_SET); getbits(-1); d712 9 a720 5 for (row=0; row < height; row++) { for (col=0; col < width; col++) image[row*width+col][FC(row,col)] = getbits(12) << 2; for (col=0; col < waste; col++) getbits(12); a721 1 return; d723 1 d726 1 d730 1 a730 1 if (!strcmp(name,"NIKON D100 ")) d773 13 d802 98 d1012 1 a1012 1 if (fget2(ifp) != 42) return; d1081 1 a1081 1 char head[8]; d1108 2 d1197 1 a1197 1 } else if (!strcmp(name,"NIKON D1 ")) { d1224 1 a1224 1 } else if (!strcmp(name,"NIKON D100 ")) { d1226 1 a1226 1 width = 3034; d1233 8 d1336 2 a1337 2 for (y=1; y < height-1; y++) for (x=1; x < width-1; x++) { d1351 1 a1351 1 fprintf(ofp,"P6\n%d %d\n255\n",width-2,height-2); d1353 1 a1353 1 ppm = calloc(width-2,3); d1361 1 a1361 1 for (y=1; y < height-1; y++) d1363 1 a1363 1 for (x=1; x < width-1; x++) d1374 1 a1374 1 ppm[x-1][c]=val; d1377 1 a1377 1 fwrite (ppm, width-2, 3, ofp); d1404 2 a1405 2 hw[0] = htonl(height-2); /* write the header */ hw[1] = htonl(width-2); d1409 1 a1409 1 psize = (height-2) * (width-2); d1417 1 a1417 1 for (y=1; y < height-1; y++) d1419 1 a1419 1 for (x=1; x < width-1; x++) d1459 1 a1459 1 png_set_IHDR (png_ptr, info_ptr, width-2, height-2, d1471 1 a1471 1 png = calloc(width-2,6); d1477 2 a1478 2 for (y=1; y < height-1; y++) { for (x=1; x < width-1; x++) { d1510 1 a1510 1 int i, arg, smooth=1, write_to_files=1; d1518 1 a1518 1 "\nCanon PowerShot Converter v2.96" d1526 1 d1549 2 d1601 12 a1612 5 fprintf (stderr, "First interpolation...\n"); first_interpolate(); for (i=0; i < smooth; i++) { fprintf (stderr, "Second interpolation...\n"); second_interpolate(); @ 1.59 log @Fixed compiler warnings generated by "gcc -O2 -Wall". @ text @d710 4 a713 1 fseek (ifp, 3488, SEEK_SET); d1091 9 d1377 1 a1377 1 "\nCanon PowerShot Converter v2.95" @ 1.58 log @Added command-line arguments for color balance. @ text @d588 1 a588 1 unsigned top, left, irow, icol; d674 1 d879 1 a879 1 while (doff = fget4(ifp)) { d1058 1 a1058 1 fprintf(stderr,"crw.c was compiled without EOS-1D support.\n",fname); d1173 1 a1173 1 int y, x, i; a1177 1 char p6head[32]; @ 1.57 log @Added support for the Nikon D1H @ text @d54 1 a54 1 float gamma_val=0.8, bright=1.0; d1091 2 d1365 1 a1365 1 "\nCanon PowerShot Converter v2.94" d1376 2 d1401 4 @ 1.56 log @Calculate the GMCY -> RGB matrix here, instead of using invert.c. @ text @d1069 9 d1363 1 a1363 1 "\nCanon PowerShot Converter v2.93" @ 1.55 log @Don't multiply rgb_max by bright -- that was a mistake. @ text @d938 2 d947 1 a947 6 static const float def_coeff[3][4] = { { -2.400719, 3.539540, -2.515721, 3.421035 }, /* red from GMCY */ { 4.013642, -1.710916, 0.690795, 0.417247 }, /* green from GMCY */ { -2.345669, 3.385090, 3.521597, -2.249256 } /* blue from GMCY */ }; int hlen, i, r, g; d1082 1 a1082 4 for (r=0; r < 3; r++) { for (g=0; g < 4; g++) coeff[r][g] = def_coeff[r][g] * rgb_mul[r]; } d1087 16 a1102 1 Convert a GMCY quadruplet to an RGB triplet. d1104 30 a1133 2 The following table shows how the four CCD pixel types respond to the three primary colors, on a scale of 0-100. a1134 9 RGB---> red green blue GMCY-v green 11 86 8 magenta 50 29 51 cyan 11 92 75 yellow 81 98 8 get_rgb() is based on an inversion of this table. */ d1140 2 a1141 2 for (r=0; r < 3; r++) { if (colors == 3) { d1145 4 a1148 1 } else { d1151 2 a1152 1 if (rgb[r] < 0) rgb[r]=0; a1153 2 rgb[3] += rgb[r]*rgb[r]; /* Compute magnitude */ } d1354 1 a1354 1 "\nCanon PowerShot Converter v2.91" @ 1.54 log @Fixed the "pink sky" problem for RGB cameras, and adjusted the brightness algorithm. @ text @d955 1 a955 1 rgb_max = 0x4000 * bright; d1049 1 a1049 1 rgb_max = 16000 * bright; d1324 1 a1324 1 "\nCanon PowerShot Converter v2.90" @ 1.53 log @Added option to call second_interpolate() multiple times, or not at all. Color-balanced the Canon EOS D60. @ text @d47 1 a47 1 int height, width, colors, black, canon; d761 1 d955 1 d1049 1 d1113 1 a1113 1 if (colors == 3) d1115 3 a1117 1 else { d1150 1 a1150 1 Set the maximum magnitude to the 98th percentile d1153 1 a1153 1 if ((total+=histogram[val]) > (int)(width*height*0.06)) break; d1165 1 a1165 1 mul = bright * 362 / max; d1173 2 a1174 1 scale = rgb[3] ? mul * pow(rgb[3]/max2,expo) : 0; d1206 1 a1206 1 int hw[2], psize, y, x, c, val, max=0xffff; a1222 5 if (colors == 3) max = 0x4000 * bright; if (max > 0xffff) max = 0xffff; d1230 1 a1230 1 if (val > max) val = max; d1249 1 a1249 1 int y, x, c, val, max=0xffff; a1282 5 if (colors == 3) max = 0x4000 * bright; if (max > 0xffff) max = 0xffff; d1288 1 a1288 1 if (val > max) val = max; d1324 1 a1324 1 "\nCanon PowerShot Converter v2.88" @ 1.52 log @The top 12 rows of the D60 image contain strange values. Don't use them to calculate the black point. @ text @d1045 2 d1320 1 a1320 1 int i, arg, write_to_files=1; d1328 1 a1328 1 "\nCanon PowerShot Converter v2.86" d1336 1 d1356 2 d1404 4 a1407 3 fprintf (stderr, "Second interpolation...\n"); second_interpolate(); @ 1.51 log @Added support for the Canon EOS D60 camera. @ text @d616 2 a617 1 if (irow < height && icol < width) d625 1 a625 8 /* "i" is the number of full rows to include in the average. On the EOS D60, the top seven rows are zero, not black, hence I do not include them in the denominator. */ i = raw_height - height; if (raw_width == 3152) i -= 7; black = ((long long) black << 2) / (i * raw_width + left * height); d1326 1 a1326 1 "\nCanon PowerShot Converter v2.85" @ 1.50 log @Never call pow(base,exp) with a base of zero @ text @d48 1 d461 1 a461 1 void decompress(ushort *outbuf, int width, int count) d467 1 a467 1 if (!width) { /* Initialize */ d499 1 a499 1 if (pixel++ % width == 0) d512 1 a512 1 decompress(0,0,540); d518 1 a518 1 decompress(pixel,1944,243); d535 1 a535 1 decompress(0,0,540); d542 1 a542 1 decompress(pixel,2144,67); d559 1 a559 1 decompress(0,0,540); d566 1 a566 1 decompress(pixel,2376,297); d579 4 a582 3 All other cameras give 10 bits per sample; the EOS D30 gives 12. The other two bits are in a different part of the file, so I save my place, and seek over there to pick them up. d586 1 a586 1 ushort pixel[2224*4], *prow; d588 1 d591 16 a606 11 decompress(0,0,810076); /* Read four rows at a time. The image has a black border, six pixels wide on top, two on the bottom, 48 on the left, and none on the right. */ for (row = -6; row < height+2; row += 4) { decompress(pixel,2224,139); save = ftell(ifp); fseek (ifp, (row+6)*(2224/4) + 26, SEEK_SET); /* Get low bits */ for (prow=pixel, i=0; i < 2224; i++) { d613 6 a618 4 for (col = -48; col < width; col++) if ((unsigned) (row+r) < height && col >= 0) image[(row+r)*width+col][FC(row+r,col)] = (pixel[(r*2224)+col+48] & 0xfff) << 2; d620 2 a621 1 black += pixel[(r*2224)+col+48] & 0xfff; d623 9 a631 1 black = ((long long) black << 2) / (8 * 2224 + 48 * height); d928 5 d1045 6 d1332 1 a1332 1 "\nCanon PowerShot Converter v2.81" @ 1.49 log @Added support for the Nikon D1 model @ text @d1141 2 a1142 1 scale = mul * pow(rgb[3]/max2,expo); d1302 1 a1302 1 "\nCanon PowerShot Converter v2.80" @ 1.48 log @Removed unnecessary return @ text @d25 5 a32 4 #include #include #include #include d134 1 a134 1 The Nikon D1X uses 0x16161616: d664 1 d675 3 a677 1 fseek (ifp, nef_data_offset+76, SEEK_SET); d679 1 a679 1 fseek (ifp, nef_data_offset+160, SEEK_SET); d683 6 a688 6 for (row=0; row < 1324; row++) for (col=0; col < 4028; col++) { diff = getbits(12); if (col < width) image[row*width+col][FC(row,col)] = diff << 2; } d708 1 a708 1 fseek (ifp, nef_data_offset+100, SEEK_SET); d712 2 a713 2 for (row=0; row < 1324; row++) for (col=0; col < 4028; col++) { d874 1 a874 1 case 0x110: d878 1 a878 1 case 0x8825: d1034 9 d1301 1 a1301 1 "\nCanon PowerShot Converter v2.75" @ 1.47 log @Added support for uncompressed Nikon D1X files. @ text @a1038 1 return 0; @ 1.46 log @Added Nikon NEF support that actually works! @ text @d672 17 d704 2 a705 1 fseek (ifp, nef_data_offset+244, SEEK_SET); d723 1 a723 1 if (col >= 4024) continue; a1025 1 return 0; d1289 1 a1289 1 "\nCanon PowerShot Converter v2.70" @ 1.45 log @Added support for the Nikon D1X compressed NEF format. @ text @d47 1 d132 8 d659 1 a659 1 short fget2 (FILE *f); d687 1 a687 1 fseek (ifp, 83662, SEEK_SET); d709 1 a709 1 image[row*width+col][FC(row,col)] = curve[diff]; d814 1 a814 1 short fget2 (FILE *f) d834 31 d922 1 d924 12 a935 35 hlen = fget4(ifp); fread (head, 1, 8, ifp); if (memcmp(head,"HEAPCCDR",8) || (order != 0x4949 && order != 0x4d4d)) { fseek(ifp, 250, SEEK_SET); fread(name, 64, 1, ifp); if (!strcmp(name,"Canon EOS-1D")) { #ifdef LJPEG_DECODE height = 1662; width = 2496; colors = 3; filters = 0x61616161; read_crw = eos1d_read_crw; rgb_mul[0] = 1.976; rgb_mul[2] = 1.282; return 0; #else fprintf(stderr,"crw.c was compiled without EOS-1D support.\n",fname); return 1; #endif } fseek(ifp, 382, SEEK_SET); fread(name, 64, 1, ifp); if (!strcmp(name,"NIKON D1X")) { height = 1324; width = 4024; colors = 3; canon = 0; filters = 0x94949494; read_crw = nikon_d1x_read_crw; rgb_mul[0] = 1.3; rgb_mul[2] = 1.24; return 0; } fprintf(stderr,"%s is not a Canon RAW file.\n",fname); a937 6 name[0] = 0; fseek (ifp, 0, SEEK_END); parse (hlen, ftell(ifp) - hlen); fseek (ifp, hlen, SEEK_SET); d999 24 d1272 1 a1272 1 "\nCanon PowerShot Converter v2.60" d1336 1 a1336 1 fprintf (stderr, "Loading data from %s...\n",argv[arg]); d1339 4 a1342 2 fprintf (stderr, "Subtracting thermal noise (%d)...\n",black); subtract_black(); @ 1.44 log @Merged in EOS-1D code after it passed beta test. @ text @d46 1 a46 1 int height, width, colors, black; d437 1 a437 1 if (c == 0xff) fgetc(ifp); /* always extra 00 after ff */ d650 55 d875 1 a902 3 } else { fprintf(stderr,"%s is not a Canon RAW file.\n",fname); return 1; d904 15 d1236 1 a1236 1 "\nCanon PowerShot Converter v2.55" @ 1.43 log @Adjusted the S30 color balance @ text @d17 6 a22 1 */ d33 6 d116 1 a116 1 All RGB cameras use 0x94949494: d123 8 d605 45 d831 20 a850 2 fprintf(stderr,"%s is not a Canon CRW file.\n",fname); return 1; d1168 4 a1171 1 "\nCanon PowerShot Converter v2.54" d1234 1 a1240 1 fclose(ifp); @ 1.42 log @Avoid bus errors on CPUs that enforce word alignment. @ text @d820 2 a821 2 rgb_mul[0] = 1.97; rgb_mul[2] = 1.123; d1086 1 a1086 1 "\nCanon PowerShot Converter v2.53" @ 1.41 log @Changes by Markus Mayer to prevent compiler warnings @ text @d958 1 a958 2 int *hw = (int *)(head+14); int psize, y, x, c, val, max=0xffff; d964 1 d1086 1 a1086 1 "\nCanon PowerShot Converter v2.52" @ 1.40 log @Color-balanced the PowerShot G1 @ text @d3 1 a3 1 Copyright 1997-2001 by Dave Coffin d302 1 a302 1 int make_decoder(struct decode *dest, const uchar *source, int level) d305 1 a305 1 static leaf; /* number of leaves already added */ d328 1 a328 1 init_tables(unsigned table) d431 1 a431 1 decompress(ushort *outbuf, int width, int count) d586 1 a586 1 subtract_black() d606 1 a606 1 first_interpolate() d637 1 a637 1 second_interpolate() d709 1 a709 1 parse (int offset, int length) d742 1 a742 1 open_and_id(char *fname) d863 1 a863 1 get_rgb(float rgb[4], ushort image[4]) d1065 1 a1065 1 exten(char *new, const char *old, const char *ext) d1075 1 a1075 1 main(int argc, char **argv) d1174 1 @ 1.39 log @Added NO_PNG compile flag, since most people don't need 48-bit output. @ text @d812 2 d1086 1 a1086 1 "\nCanon PowerShot Converter v2.51" @ 1.38 log @Fixed color balance for S40 and G2 cameras. @ text @d20 1 d22 1 d995 1 d1058 1 d1093 4 a1096 1 "\n-4 Write 48-bit PNG\n\n", d1120 1 d1125 1 @ 1.37 log @Removed old "ymul" hack. Use black pixels to subtract thermal noise from image. @ text @d3 1 a3 1 Copyright (c)1997-2001 by Dave Coffin d825 2 d1080 1 a1080 1 "\nCanon PowerShot Converter v2.50" @ 1.36 log @Added support for the PowerShot S30 camera @ text @d33 1 a33 1 int height, width, colors; a38 1 float ymul[4]; d51 2 a55 1 d57 1 a57 1 Filter pattern of the PowerShot 600: d60 3 a62 3 0 G M G M G M Return values 1 C Y C Y C Y 0 1 2 3 2 M G M G M G G M C Y d64 46 d111 1 d139 1 a139 1 are blank. Left-shift by 4 for extra precision in upcoming d144 2 d150 1 a152 9 /* Filter pattern of the PowerShot A5: 0 1 2 3 4 5 0 C Y C Y C Y Return values 1 G M G M G M 0 1 2 3 2 C Y C Y C Y G M C Y 3 M G M G M G */ d164 1 a164 1 for (dp=data, pix=pixel; dp < data+1200; dp+=10, pix+=8) d177 1 a177 1 are blank. Left-shift by 4 for extra precision in upcoming d182 2 d185 1 a187 13 /* Filter pattern of the PowerShot A50: 0 1 2 3 4 5 0 C Y C Y C Y Return values 1 M G M G M G 0 1 2 3 2 Y C Y C Y C G M C Y 3 G M G M G M 4 C Y C Y C Y 5 G M G M G M 6 Y C Y C Y C 7 M G M G M G */ d212 1 a212 1 are blank. Left-shift by 4 for extra precision in upcoming d217 2 d220 1 a222 13 /* Filter pattern of the PowerShot Pro70: 0 1 2 3 4 5 0 Y C Y C Y C Return values 1 M G M G M G 0 1 2 3 2 C Y C Y C Y G M C Y 3 G M G M G M 4 Y C Y C Y C 5 G M G M G M 6 C Y C Y C Y 7 M G M G M G */ d247 1 a247 1 extra precision in upcoming calculations. a474 7 /* Filter pattern of the PowerShot Pro90 and G1: 0 1 2 3 4 5 Return values 0 G M G M G M 0 1 2 3 1 Y C Y C Y C G M C Y */ d481 4 a484 1 d487 1 a487 1 for (r=0; r < 8; r++) d491 3 d495 1 d504 6 a509 4 /* Read two rows at a time, discarding the first eight */ for (row = -8; row < height; row += 2) { a510 1 if (row < 0) continue; d512 3 a514 2 for (col=0; col < width; col++) image[(row+r)*width+col][FC(row+r,col)] = d516 2 d519 1 a521 9 /* Filter pattern of the PowerShot G2 and EOS D30: 0 1 2 3 4 5 Return values 0 R G R G R G 0 1 2 1 G B G B G B R G B 2 R G R G R G 3 G B G B G B */ d524 2 a525 2 ushort pixel[2376*8], *prow, (*imrow)[4]; int row, r, orow, col; d528 6 a533 4 /* Read eight rows at a time, discarding the first six */ for (row = -6; row < height; row += 8) { d535 7 a541 9 for (r=0; r < 8; r++) { orow = row + r; if (orow < 0) continue; if (orow >= height) break; imrow = image + orow*width; prow = pixel + r*2376 + 12; for (col=0; col < width; col++) imrow[col][FC(orow,col)] = (prow[col] & 0x3ff) << 4; } d543 1 d553 2 a554 2 ushort pixel[2224*4], *prow, (*imrow)[4]; int i, row, r, orow, col, save; d558 6 a563 4 /* Read four rows at a time, discarding the first six rows */ for (row = -6; row < height; row += 4) { d573 23 a595 10 for (r=0; r < 4; r++) { orow = row + r; if (orow < 0) continue; if (orow >= height) break; imrow = image + orow*width; prow = pixel + r*2224 + 48; for (col=0; col < width; col++) imrow[col][FC(orow,col)] = (prow[col] & 0xfff) << 2; } } a749 1 for (i=0; i < 4; i++) ymul[i]=1.0; a780 2 ymul[0] = 0.9866; ymul[2] = 1.0125; a787 4 ymul[0] = 1.0005; ymul[1] = 1.0056; ymul[2] = 0.9980; ymul[3] = 0.9959; d882 1 a882 2 float rgb[4], max, max2, expo, scale; float gymul[4]; d913 1 a913 2 for (y=0; y < 4; y++) gymul[y] = bright * 362 / max * pow(ymul[y],gamma_val); d920 1 a920 1 scale = gymul[y&3] * pow(rgb[3]/max2,expo); d1078 1 a1078 1 "\nCanon PowerShot Converter v2.37" d1133 1 d1136 2 @ 1.35 log @Added support for 48-bit Adobe Photoshop format @ text @d784 8 d1054 1 a1054 1 "\nCanon PowerShot Converter v2.35" @ 1.34 log @Synchronized code between C programs, fail more intelligently on non-CRW files, have heap.c write JPEG thumbnails, and have decompress.c correctly parse the heap. @ text @d843 1 a843 1 write_ppm(FILE *ofp) d902 56 d962 1 a962 1 write_png(FILE *ofp) d967 2 a968 2 float rgb[4], val; int y, x, c, max=0xffff; d1038 3 a1040 1 int i, arg, write_to_files=1, format_png=0, row; d1046 1 a1046 1 "\nCanon PowerShot Converter v2.32" d1051 1 a1051 1 "\n-g Set gamma value (%5.3f by default)" d1054 2 a1055 1 "\n-4 Write 48-bit PNG (-g ignored)\n\n", d1072 7 a1078 1 format_png=0; break; d1080 3 a1082 1 format_png=1; break; d1110 1 d1112 1 a1112 1 exten(data, argv[arg], format_png ? ".png":".ppm"); d1119 2 a1120 7 if (format_png) { fprintf (stderr, "Writing PNG output...\n"); write_png(ofp); } else { fprintf (stderr, "Writing PPM output...\n"); write_ppm(ofp); } d1123 1 @ 1.33 log @Many changes for v2.30: Inlined the filter functions for better performance. Histogram the magnitudes instead of their squares. Set rgb_mul[1] = 1.0 and adjust red and blue accordingly. Allow manual brightness adjustment of PNG output. @ text @d122 1 a122 1 fread(data, 1240, 1, ifp); d167 1 a167 1 fread(data, 1650, 1, ifp); d212 1 a212 1 fread(data, 1940, 1, ifp); d653 3 a655 1 if (order == 0x4949) /* "II" means little-endian */ a656 6 else if (order == 0x4d4d) /* "MM" means big-endian */ return (fgetc(f) << 8) + fgetc(f); else { fprintf(stderr,"Unknown byte order!"); exit(1); } d664 3 a666 1 if (order == 0x4949) a667 6 else if (order == 0x4d4d) return (fgetc(f) << 24) + (fgetc(f) << 16) + (fgetc(f) << 8) + fgetc(f); else { fprintf(stderr,"Unknown byte order!"); exit(1); } d676 1 a676 1 int save, toff, nrecs, i, type, len, off; d679 2 a680 2 toff = fget4(ifp) + offset; fseek (ifp, toff, SEEK_SET); d685 2 a686 1 off = fget4(ifp); d689 1 a689 1 fseek (ifp, offset+off, SEEK_SET); d694 1 a694 1 fseek (ifp, offset+off, SEEK_SET); d698 1 a698 1 parse (offset+off, len); d728 2 a729 2 fread (&order, 2, 1, ifp); hlen = fget4(ifp); d732 1 a732 1 if (memcmp(head,"HEAPCCDR",8)) { d988 1 a988 1 "\nCanon PowerShot Converter v2.30" @ 1.32 log @Sometimes the CYGM-to-RGB matrix produces a negative value. Do not allow this! @ text @d6 1 a6 1 digital cameras into PPM format. d34 1 a36 1 int (*filter)(int,int); d49 8 a64 5 ps600_filter(int row, int col) { return (0xe1e4 >> ((((row) << 1 & 6) + ((col) & 1)) << 1) & 3); } d96 1 a96 1 image[orow*width+col][(*filter)(orow,col)] = pixel[col] << 4; a111 5 a5_filter(int row, int col) { return (0x1e4e >> ((((row) << 1 & 6) + ((col) & 1)) << 1) & 3); } d140 1 a140 1 image[row*width+col][(*filter)(row,col)] = (pixel[col] & 0x3ff) << 4; a156 5 a50_filter(int row, int col) { return (0x1b4e4b1e >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3); } d185 1 a185 1 image[row*width+col][(*filter)(row,col)] = (pixel[col] & 0x3ff) << 4; a201 5 pro70_filter(int row, int col) { return (0x1e4b4e1b >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3); } d229 1 a229 1 image[row*width+col][(*filter)(row,col)] = (pixel[col] & 0x3ff) << 4; a460 5 pro90_filter(int row, int col) { return (0xb4 >> ((((row) << 1 & 2) + ((col) & 1)) << 1) & 3); } d472 1 a472 1 image[(row+r)*width+col][(*filter)(row+r,col)] = d491 1 a491 1 image[(row+r)*width+col][(*filter)(row+r,col)] = a504 5 rgb_filter(row,col) { return (((row) & 1) + ((col) & 1)); } d523 1 a523 1 imrow[col][(*filter)(orow,col)] = (prow[col] & 0x3ff) << 4; d560 1 a560 1 imrow[col][(*filter)(orow,col)] = (prow[col] & 0xfff) << 2; d578 1 a578 1 cc = (*filter)(row,col); d582 1 a582 1 if ((c = (*filter)(y,x)) != cc) { d618 1 a618 1 cc = (*filter)(row,col); d622 1 a622 1 if ((c = (*filter)(y,x)) != cc && image[y*width+x][cc]) { d725 3 a727 1 for (i=0; i < 3; i++) rgb_mul[i]=1.0; d752 4 a755 2 rgb_mul[1] = 0.6; rgb_mul[2] = 1.0; a757 2 filter = ps600_filter; read_crw = ps600_read_crw; d761 4 a764 2 rgb_mul[1] = 0.90; rgb_mul[2] = 0.88; a768 2 filter = a5_filter; read_crw = a5_read_crw; d772 1 a772 3 rgb_mul[1] = 0.76; rgb_mul[2] = 0.59; filter = a50_filter; d774 2 d779 1 a779 3 rgb_mul[1] = 0.628; rgb_mul[2] = 0.792; filter = pro70_filter; d784 1 a784 3 rgb_mul[1] = 0.628; rgb_mul[2] = 0.792; filter = pro90_filter; d789 1 a789 3 rgb_mul[1] = 0.628; rgb_mul[2] = 0.792; filter = pro90_filter; d796 1 a796 3 rgb_mul[1] = 0.628; rgb_mul[2] = 0.792; filter = rgb_filter; d802 1 a802 3 rgb_mul[1] = 0.628; rgb_mul[2] = 0.792; filter = rgb_filter; d857 1 a857 1 int total, histogram[0x4000]; d861 1 a861 1 Build a histogram of magnitudes d867 2 a868 2 val = rgb[3]/0x100000; if (val > 0x3fff) val=0x3fff; d874 1 a874 1 for (val=0x4000, total=0; --val; ) d876 2 a877 2 max2 = val << 20; max = sqrt(max2); d952 4 a955 6 if (colors == 3) { /* Preserve the green bits */ rgb_mul[0] /= rgb_mul[1]; rgb_mul[2] /= rgb_mul[1]; rgb_mul[1] = 1.0; max = 0x4000; } d961 1 a961 1 val = rgb[c]; d995 1 a995 1 "\nCanon PowerShot Converter v2.21" d1003 1 a1003 1 "\n-4 Write 48-bit PNG (-g and -b ignored)\n\n", @ 1.31 log @When saving an RGB image to PNG, preserve the green bits. @ text @d868 1 a868 1 else d871 2 a929 1 if (val < 0) val=0; d1027 1 a1027 1 "\nCanon PowerShot Converter v2.20" @ 1.30 log @Added PNG support for all camera models. @ text @d876 1 a876 1 Convert the GMCY grid to RGB and write it to a PPM file. d940 1 a940 1 Write the rgb[] array to a PNG file d981 6 a986 2 if (colors == 3) max = rgb_mul[1] * 0x4000; @ 1.29 log @Properly parse through the CIFF data instead of searching for the camera name. @ text @d20 2 d938 62 d1016 1 a1016 1 int i, arg, write_to_files=1, row; d1022 1 a1022 1 "\nCanon PowerShot Converter v2.10" d1026 1 a1026 1 "\n-c Write PPM to standard output" d1028 3 a1030 1 "\n-b Set brightness (%5.3f by default)\n\n", d1046 4 d1076 1 a1076 1 fprintf (stderr, "Writing RGB output...\n"); d1078 1 a1078 1 exten(data, argv[arg],".ppm"); d1084 6 d1091 2 a1093 2 } else write_ppm(stdout); @ 1.28 log @Don't choke on corrupt data -- make best effort to decode Treat "PowerShot S40" as synonym for "PowerShot G2" @ text @d30 1 d32 1 d669 1 a669 2 Search for string str in block data of length len. Return pointer to matching string, or zero if not found. d671 1 a671 1 char *search(char *data, int len, char *str) d673 9 a681 2 char *d; int slen, i; d683 44 a726 4 slen=strlen(str); for (d=data; d < data+len-slen; d++) { for (i=0; d[i]==str[i] && i++ < slen; ); if (i >= slen) return d; a727 1 return 0; a729 1 #define tlen 0x8000 d736 1 a736 1 char head[26], tail[tlen], *name, *p; d742 1 a742 1 int i, r, g; d753 5 a757 2 fread (head,1,26,ifp); if (memcmp(head+6,"HEAPCCDR",8)) { d761 5 a765 6 /* Read the last tlen bytes of the file */ fseek (ifp, -tlen, SEEK_END); fread (tail, 1, tlen, ifp); fseek (ifp, 26, SEEK_SET); d767 1 a767 6 name = search(tail, tlen, "Canon PowerShot "); if (!name) name = search(tail, tlen, "Canon EOS "); if (!name) { fprintf(stderr,"%s: camera is not a Canon PowerShot.\n",fname); return 1; } else if (!strcmp(name,"Canon PowerShot 600")) { d801 1 a801 1 } else if (!strncmp(name,"Canon PowerShot Pro90",21)) { a807 1 init_tables (name[4762]); a814 1 init_tables (name[4762]); a823 1 init_tables (name[4774]); a831 1 init_tables (name[3594]); a841 1 #undef tlen d958 1 a958 1 "\nCanon PowerShot Converter v2.00" @ 1.27 log @Added support for PowerShot G2 and EOS D30 Eliminated pipelining -- all steps are now performed separately Totally rewrote interpolation to work with RGB or CYGM @ text @d313 1 a313 1 init_tables(int table) d640 1 a640 1 if ((c = (*filter)(y,x)) != cc) { d653 1 a653 1 this[col][c] = avg[c] / avg[c+4]; d774 2 a775 1 } else if (!strcmp(name,"Canon PowerShot G2")) { @ 1.26 log @Added G2 support, then discovered that the filters are RGB. It's time to rewrite this program! @ text @d6 1 a6 1 PowerShot digital cameras into PPM format. d30 2 a31 2 int height, width; ushort (*gmcy)[4]; d33 1 a33 2 void (*read_crw)(int); int histogram[1024]; d36 1 d58 1 a58 5 /* Load CCD pixel values into the gmcy[] array. Unknown colors (such as cyan under a magenta filter) must be set to zero. */ void ps600_read_crw(int row) a67 3 Since the rows are not stored in top-to-bottom order like the other cameras, we must load all rows before processing can begin. a68 2 if (row) return; a82 2 memset(gmcy + row*width, 0, width*sizeof *gmcy); d84 1 a84 1 Copy 854 pixels into the gmcy[] array. The other 42 pixels d89 1 a89 1 gmcy[orow*width+col][(*filter)(orow,col)] = pixel[col] << 4; d110 1 a110 5 /* Load CCD pixel values into the gmcy[] array. Unknown colors (such as cyan under a magenta filter) must be set to zero. */ void a5_read_crw(int row) d114 1 a114 1 int col; d119 13 a131 14 fread(data, 1240, 1, ifp); for (dp=data, pix=pixel; dp < data+1200; 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] ); } memset(gmcy + row*width, 0, width*sizeof *gmcy); d133 1 a133 1 Copy 960 pixels into the gmcy[] array. The other 32 pixels d137 3 a139 2 for (col=0; col < width; col++) gmcy[row*width+col][(*filter)(row,col)] = (pixel[col] & 0x3ff) << 4; d160 1 a160 5 /* Load CCD pixel values into the gmcy[] array. Unknown colors (such as cyan under a magenta filter) must be set to zero. */ void a50_read_crw(int row) d164 1 a164 1 int col; d169 13 a181 14 fread(data, 1650, 1, ifp); for (dp=data, pix=pixel; dp < data+1650; 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] ); } memset(gmcy + row*width, 0, width*sizeof *gmcy); d183 1 a183 1 Copy 1290 pixels into the gmcy[] array. The other 30 pixels d187 3 a189 2 for (col=0; col < width; col++) gmcy[row*width+col][(*filter)(row,col)] = (pixel[col] & 0x3ff) << 4; d210 1 a210 1 void pro70_read_crw(int row) d214 1 a214 1 int col; d219 13 a231 14 fread(data, 1940, 1, ifp); for (dp=data, pix=pixel; dp < data+1940; dp+=10, pix+=8) { pix[0] = (dp[1] << 2) + (dp[0] >> 6); /* Same as PS A5 */ 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] ); } memset(gmcy + row*width, 0, width*sizeof *gmcy); d233 1 a233 1 Copy all pixels into the gmcy[] array. Left-shift by 4 for d236 3 a238 2 for (col=0; col < width; col++) gmcy[row*width+col][(*filter)(row,col)] = (pixel[col] & 0x3ff) << 4; d376 1 d422 1 a422 1 if (!count) { /* Initialize */ d424 1 a424 1 fseek (ifp, 540, SEEK_SET); d474 1 a474 1 void pro90_read_crw(int row) d477 1 a477 1 int r, col; d479 1 a479 3 /* Read rows eight at a time */ if (row & 7) return; decompress(pixel,1944,243); d481 5 a485 4 memset(gmcy + row*width, 0, 8*width*sizeof *gmcy); for (r=0; r < 8; r++) for (col=0; col < width; col++) gmcy[(row+r)*width+col][(*filter)(row+r,col)] = d487 1 d490 1 a490 1 void g1_read_crw(int row) d493 1 a493 4 int r, col; /* Read rows two at a time */ if (row & 1) return; d495 1 a495 4 /* The first eight rows are blank. Discard them. */ if (row == 0) for (r=4; r--; ) decompress(pixel,2144,67); d497 1 a497 1 decompress(pixel,2144,67); d499 6 a504 4 memset(gmcy + row*width, 0, 2*width*sizeof *gmcy); for (r=0; r < 2; r++) for (col=0; col < width; col++) gmcy[(row+r)*width+col][(*filter)(row+r,col)] = d506 1 d510 1 a510 1 Filter pattern of the PowerShot G2: d513 4 a516 2 0 G M G M G M 0 1 2 3 1 Y C Y C Y C G M C Y d518 1 a518 1 g2_filter(int row, int col) d520 1 a520 1 return (0x4e >> ((((row) << 1 & 2) + ((col) & 1)) << 1) & 3); d523 1 a523 1 void g2_read_crw(int row) d525 4 a528 2 ushort pixel[2376*8], *prow, (*grow)[4]; int start=0, end, r, orow, col; d530 1 a530 1 /* Read rows eight at a time, discarding the first six rows */ d532 50 a581 4 if (row == 0) start = 6; else if ((row & 7) != 2) return; d583 31 a613 1 decompress(pixel,2376,297); d615 18 a632 9 end = height - row; if (end > 8) end = 8; memset(gmcy + row*width, 0, end*width*sizeof *gmcy); for (r=start; r < end; r++) { orow = row-start + r; grow = gmcy + orow*width; prow = pixel + r*2376 + 12; for (col=0; col < width; col++) grow[col][(*filter)(orow,col)] = (prow[col] & 0x3ff) << 4; d634 30 a695 1 float rgb_mul[3] = { 1.0, 1.0, 1.0 }; d699 2 d720 1 d729 2 a730 2 ymul[1] = 1.0125; ymul[3] = 0.9866; d738 4 a741 4 ymul[0] = 1.0056; ymul[1] = 0.9980; ymul[2] = 0.9959; ymul[3] = 1.0005; d765 1 a765 2 init_tables(name[4762]); decompress(0,0,0); d773 1 a773 2 init_tables(name[4762]); decompress(0,0,0); a775 1 height = 100; d777 1 d780 1 a780 1 filter = g2_filter; d782 10 a791 2 init_tables(name[4774]); decompress(0,0,0); a804 27 When this function is called, we only have one GMCY value for each pixel. Do linear interpolation to get the other three. read_crw(row+1) must happen before first_interpolate(row). first_interpolate() is non-destructive, so this row can be referenced while interpolating the next row. */ first_interpolate(int y) { int x, sy, sx, c; static const uchar shift[]={ 2,1,2, 1,16,1, 2,1,2 }, *sp; for (x=1; x < width-1; x++) { sp=shift; for (sy=y-1; sy < y+2; sy++) { for (sx=x-1; sx < x+2; sx++) { c=(*filter)(sy,sx); gmcy[y*width+x][c] += gmcy[sy*width+sx][c] >> *sp++; } } } } /* d819 1 a819 1 get_rgb(float rgb[4], ushort gmcy[4]) d823 7 a829 4 memset(rgb,0,4 * sizeof (float)); for (r=0; r < 3; r++) { /* RGB colors */ for (g=0; g < 4; g++) /* GMCY colors */ rgb[r] += coeff[r][g] * gmcy[g]; a834 54 Now that we have four GMCY values for each pixel (one known, three interpolated), adjust each interpolated value so that its ratio to the known value approximates that of neighboring pixels. second_interpolate(row) must be called after first_interpolate(row+1) A copy of the original row is needed to interpolating the next row. Therefore, second_interpolate() writes the modified row one pixel above and to the left of the original. Edge pixels are discarded. Pixels one in from the edge are memcpy'd to their new locations. Convert each GMCY value to RGB, and compile a histogram of their magnitudes. Discard the RGB values. */ second_interpolate(int y) { int x, c, sy, sx, sc; ushort this[4]; static const uchar shift[]={ 2,1,2, 1, 1, 2,1,2 }, *sp; float rgb[4]; unsigned val; if (y==1 || y==height-2) /* y is never outside this range */ { memcpy(gmcy+(y-1)*width,gmcy+y*width+1,(width-2)*sizeof this); return; } if (y==2) memset(histogram,0,sizeof histogram); memcpy(gmcy+(y-1)*width,gmcy+y*width+1,sizeof this); for (x=2; x < width-2; x++) { c=(*filter)(y,x); sp=shift; memset(this,0,sizeof this); this[c]=gmcy[y*width+x][c]; for (sy=y-1; sy < y+2; sy++) /* 28% of run-time is this loop */ for (sx=x-1; sx < x+2; sx = sx+1+(sy==y)) { sc=(*filter)(sy,sx); this[sc] += ( (unsigned long) gmcy[sy*width+sx][sc] << 16) / gmcy[sy*width+sx][c] * gmcy[y*width+x][c] >> (16 + *sp++); } memcpy(gmcy+(y-1)*width+x-1,this,sizeof this); get_rgb(rgb,this); val = rgb[3]/0x1000000; /* Collect statistics */ if (val > 1023) val=1023; histogram[val]++; } memcpy(gmcy+(y-1)*width+x-1,gmcy+y*width+x,sizeof this); } /* d844 1 a844 1 int total; d848 11 d861 1 a861 1 for (val=1024, total=0; --val; ) d863 1 a863 1 max2 = val << 24; d877 1 a877 1 for (y=0; y < height-2; y++) d879 1 a879 1 for (x=0; x < width-2; x++) d881 1 a881 1 get_rgb(rgb,gmcy[y*width+x]); d889 1 a889 1 ppm[x][c]=val; d919 1 a919 1 "\nCanon PowerShot Converter v1.92" d954 3 a956 3 gmcy = calloc(height*width,sizeof *gmcy); if (!gmcy) { perror("gmcy calloc failed"); d959 6 a964 12 for (row=0; row < 3; row++) (*read_crw)(row); first_interpolate(1); /* This loop is a good place to put a progress bar */ for (row=3; row < height; row++) { (*read_crw)(row); first_interpolate(row-1); second_interpolate(row-2); } second_interpolate(height-2); d967 1 d979 1 a979 1 free (gmcy); @ 1.25 log @Use a search algorithm to find the camera name at run-time. Size arrays dynamically depending on which camera was detected. Added support for compressed data format used by the Pro90 and G1. @ text @d2 1 a2 1 Canon PowerShot Converter v2.00 d6 1 a6 1 digital cameras into PPM format. d487 1 a487 1 pro90_g1_filter(int row, int col) d494 1 a494 1 ushort pixel[1944*8], *pix; d510 1 a510 1 ushort pixel[2144*2], *pix; d531 38 a620 1 if (!name) name = search(tail, tlen, "Canon EOS "); d622 1 a622 1 fprintf(stderr,"%s: cannot identify camera model.\n",fname); d663 1 a663 1 filter = pro90_g1_filter; d672 1 a672 1 filter = pro90_g1_filter; d676 10 d880 1 a880 1 "\nCanon PowerShot Converter v1.90" @ 1.24 log @Added typedef for "ushort". @ text @d2 2 a3 1 Canon PowerShot Converter v1.00 d5 2 a6 1 by Dave Coffin (dcoffin@@shore.net) d8 6 a13 3 No rights reserved. Do what you want with this code, but I accept no responsibility for any consequences of its (mis)use. a18 1 #include a23 62 #ifdef PS_600 #define H 613 #define W 854 #define RED_MUL 1.0 #define GRN_MUL 0.6 #define BLU_MUL 1.0 /* Use this to remove annoying horizontal patterns */ const float ymul[4] = { 1.0, 1.0125, 1.0, 0.9866 }; #elif defined(PS_A5) #define H 776 #define W 960 #define RED_MUL 1.0 #define GRN_MUL 0.90 #define BLU_MUL 0.88 const float ymul[4] = { 1.0056, 0.9980, 0.9959, 1.0005 }; #elif defined(PS_A50) #define H 968 #define W 1290 #define RED_MUL 1.0 #define GRN_MUL 0.76 #define BLU_MUL 0.59 const float ymul[4] = { 1.0, 1.0, 1.0, 1.0 }; #elif defined(PS_PRO70) #define H 1024 #define W 1552 #define RED_MUL 1.0 #define GRN_MUL 0.628 #define BLU_MUL 0.792 const float ymul[4] = { 1.0, 1.0, 1.0, 1.0 }; #else #error You must compile with exactly one of the following: #error -DPS_600 -DPS_A5 -DPS_A50 -DPS_PRO70 #endif /* Default values, which may be modified on the command line */ float gamma_val=0.8, bright=1.0; /* DOS likes to trash binary files!! */ #ifndef O_BINARY #define O_BINARY 0 #endif #define WFLAGS O_WRONLY | O_CREAT | O_TRUNC | O_BINARY d27 1 a27 1 /* This array holds the GMCY values for each pixel */ d29 5 a33 1 ushort gmcy[H][W][4]; d35 8 a43 1 #ifdef PS_600 d45 1 a45 2 Returns the filter color of a given pixel. The pattern is: d52 5 a56 3 */ #define filter(row,col) \ (0xe1e4 >> ((((row) << 1 & 6) + ((col) & 1)) << 1) & 3) d61 2 a62 2 */ void read_crw(int row, int fd) d75 1 a75 1 */ d78 1 a78 1 for (irow=orow=0; irow < H; irow++) d80 1 a80 1 read (fd, data, 1120); d93 1 a93 1 memset(gmcy[orow], 0, W*4*sizeof (ushort)); /* Set row to zero */ d98 3 a100 3 */ for (col=0; col < W; col++) gmcy[orow][col][filter(orow,col)] = pixel[col] << 4; d102 1 a102 1 if ((orow+=2) > H) /* Once we've read all the even rows, */ a106 2 #elif defined(PS_A5) d108 1 a108 2 Returns the filter color of a given pixel. The pattern is: d115 5 a119 3 */ #define filter(row,col) \ (0x1e4e >> ((((row) << 1 & 6) + ((col) & 1)) << 1) & 3) d124 2 a125 2 */ void read_crw(int row, int fd) d133 2 a134 2 */ read(fd,data,1240); d147 1 a147 1 memset(gmcy[row], 0, W*4*sizeof (ushort)); /* Set row to zero */ d152 3 a154 3 */ for (col=0; col < W; col++) gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3ff) << 4; a156 2 #elif defined(PS_A50) d158 1 a158 2 Returns the filter color of a given pixel. The pattern is: d169 5 a173 3 */ #define filter(row,col) \ (0x1b4e4b1e >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) d178 2 a179 2 */ void read_crw(int row, int fd) d187 2 a188 2 */ read(fd,data,1650); d201 1 a201 1 memset(gmcy[row], 0, W*4*sizeof (ushort)); /* Set row to zero */ d206 3 a208 3 */ for (col=0; col < W; col++) gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3ff) << 4; a210 2 #elif defined(PS_PRO70) d212 1 a212 2 Returns the filter color of a given pixel. The pattern is: d223 5 a227 3 */ #define filter(row,col) \ (0x1e4b4e1b >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) d229 1 a229 5 /* Load CCD pixel values into the gmcy[] array. Unknown colors (such as cyan under a magenta filter) must be set to zero. */ void read_crw(int row, int fd) d237 2 a238 2 */ read(fd,data,1940); d241 1 a241 1 pix[0] = (dp[1] << 2) + (dp[0] >> 6); /* Same as PS_A5 */ d251 1 a251 1 memset(gmcy[row], 0, W*4*sizeof (ushort)); /* Set row to zero */ d255 290 a544 3 */ for (col=0; col < W; col++) gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3ff) << 4; d547 103 a649 1 #endif /* End of model-specific code */ d658 1 a658 1 */ d664 1 a664 1 for (x=1; x < W-1; x++) d671 2 a672 2 c=filter(sy,sx); gmcy[y][x][c] += gmcy[sy][sx][c] >> *sp++; d691 2 a692 3 get_rgb() is based on this table. */ a695 9 static const float coeff[3][4] = { { -2.400719 * RED_MUL, 3.539540 * RED_MUL, /* red from GMCY */ -2.515721 * RED_MUL, 3.421035 * RED_MUL }, { 4.013642 * GRN_MUL, -1.710916 * GRN_MUL, /* green from GMCY */ 0.690795 * GRN_MUL, 0.417247 * GRN_MUL }, { -2.345669 * BLU_MUL, 3.385090 * BLU_MUL, /* blue from GMCY */ 3.521597 * BLU_MUL, -2.249256 * BLU_MUL } }; d698 1 a698 2 for (r=0; r < 3; r++) /* RGB colors */ { d720 1 a720 1 */ d729 1 a729 1 if (y==1 || y==H-2) /* y is never outside this range */ d731 1 a731 1 memcpy(&gmcy[y-1][0],&gmcy[y][1],(W-2)*sizeof this); d735 2 a736 2 memcpy(&gmcy[y-1][0],&gmcy[y][1],sizeof this); for (x=2; x < W-2; x++) d738 1 a738 1 c=filter(y,x); d741 1 a741 1 this[c]=gmcy[y][x][c]; d745 1 a745 1 sc=filter(sy,sx); d747 2 a748 2 ( (unsigned long) gmcy[sy][sx][sc] << 16) / gmcy[sy][sx][c] * gmcy[y][x][c] >> (16 + *sp++); d750 1 a750 1 memcpy(&gmcy[y-1][x-1],this,sizeof this); d756 1 a756 1 memcpy(&gmcy[y-1][x-1],&gmcy[y][x],sizeof this); d761 2 a762 2 */ write_ppm(int fd) d766 1 a766 1 uchar ppm[W-2][3]; d774 1 a774 1 */ d776 1 a776 1 if ((total+=histogram[val]) > (int)(W*H*0.06)) break; d780 1 a780 1 write(fd,p6head,sprintf(p6head,"P6\n%d %d\n255\n",W-2,H-2)); d782 5 d791 1 a791 1 for (y=0; y < H-2; y++) d793 1 a793 1 for (x=0; x < W-2; x++) d795 1 a795 1 get_rgb(rgb,gmcy[y][x]); d806 1 a806 1 write (fd, ppm, sizeof ppm); d808 1 d811 3 a813 1 /* Creates a new filename with a different extension */ d827 2 a828 1 int i, arg, fd, write_to_files=1, row; d833 1 a833 11 "\nCanon PowerShot " #ifdef PS_600 "600" #elif defined(PS_A5) "A5" #elif defined(PS_A50) "A50" #elif defined(PS_PRO70) "Pro70" #endif " Converter v1.00" d860 1 a860 1 /* Process the named files */ d864 2 a865 11 fd = open(argv[arg],O_RDONLY | O_BINARY); if (fd < 0) { perror(argv[arg]); continue; } /* Check the header to confirm this is a CRW file */ read (fd, data, 26); if (memcmp(data+6,"HEAPCCDR",8)) { fprintf(stderr,"%s is not a Canon PowerShot CRW file.\n",argv[arg]); d868 5 d874 1 a874 1 read_crw(row,fd); d876 5 a880 3 for (row=3; row < H; row++) { read_crw(row,fd); d884 4 a887 4 second_interpolate(H-2); close(fd); if (write_to_files) { d889 7 a895 6 fd = open(data,WFLAGS,0644); if (fd < 0) { perror(data); return; } write_ppm(fd); close(fd); d897 2 a898 1 write_ppm(1); @ 1.23 log @Removed the word "untested" @ text @d83 1 @ 1.22 log @Adjusted color balance from Snorre Selmer's pictures. @ text @d67 1 a67 1 #error -DPS_600 -DPS_A5 -DPS_A50 -DPS_PRO70 (untested) @ 1.21 log @Rotated ymul[] to match image, fixed declaration. @ text @d60 2 a61 2 #define GRN_MUL 0.76 #define BLU_MUL 0.59 @ 1.20 log @Added support for the PowerShot Pro70, based on Ed Hamrick's code. @ text @d30 1 a30 1 const float ymul[4] = { 0.9866, 1.0, 1.0125, 1.0 }; d41 1 a41 1 const float ymul[4] = { 1.0005, 1.0056, 0.9980, 0.9959 }; d175 1 a175 1 int row, col; @ 1.19 log @Attempted an optimization in second_interpolate() gmcy[row] really does need to be cleared before loading! @ text @d54 11 d67 1 a67 1 #error -DPS_600 -DPS_A5 -DPS_A50 -DPS_PRO70 d258 54 d389 1 a389 1 Edge pixels are discarded. Pixels one in from the edge get memcpy'd d505 2 @ 1.18 log @Candidate for 1.00 release. Fixed edges in second_interpolate() Discovered that "gcc -O" doubles execution speed. Wow! @ text @d127 1 d181 2 d236 2 d260 1 a260 1 uchar shift[]={ 2,1,2, 1,16,1, 2,1,2 }, *sp; d334 1 a334 1 static const uchar shift[]={ 2,1,2, 1,0,1, 2,1,2 }, *sp; a346 1 memset(this,0,sizeof this); d349 2 d352 1 a352 1 for (sx=x-1; sx < x+2; sx++) @ 1.17 log @Quick first draft of a pipelined CRW converter. Doesn't handle edges properly yet. Quite a disappointment; I was hoping to get a big speed increase from the L2 cache... @ text @d2 1 a2 1 Canon PowerShot Converter v0.96 a19 2 #define DEBUG d55 2 a56 1 #error You must compile with -DPS_600, -DPS_A5, or -DPS_A50 a88 1 a109 1 a131 1 memset(gmcy[orow], 0, W*8); /* Set row to zero */ a151 1 a184 1 memset(gmcy[row], 0, W*8); /* Set row to zero */ a237 1 memset(gmcy[row], 0, W*8); /* Set row to zero */ d248 3 a250 1 first_interpolate(row) must be called after read_crw(row+1)! d300 1 a300 1 memset(rgb,0,16); d310 11 a320 5 We now have all four GMCY values for each pixel. Smooth the color balance to avoid artifacts. As a side effect, this moves the whole image one pixel up and to the left. Convert each GMCY value to RGB, and compile a histogram of their magnitudes. RGB values are discarded and re-calculated in write_ppm(). d322 2 a323 1 second_interpolate(row) must be called after first_interpolate(row+1)! a324 1 d333 5 d339 1 d345 1 a345 1 for (sy=y-1; sy < y+2; sy++) d359 1 d369 1 a369 1 uchar ppm[W][3]; a382 4 #ifdef DEBUG fprintf(stderr,"Writing PPM file...\n"); #endif a384 4 /* Second pass: Scale RGB and write to PPM file */ d389 1 a389 1 for (y=1; y < H-1; y++) d391 1 a391 1 for (x=1; x < W-1; x++) d404 1 a404 1 write (fd, ppm+1, (W-2)*3); a405 4 #ifdef DEBUG fprintf(stderr,"Done!\n"); #endif a422 1 ushort dummy; d435 1 a435 1 " Converter v0.96" d479 4 a482 1 for (row=0; row < H; row++) a483 2 for (i=0; i < W; i+=4) dummy=gmcy[row][i][0]; d485 2 a486 2 if (row > 1) first_interpolate(row-1); if (row > 3) second_interpolate(row-2); d488 1 @ 1.16 log @If "ymul" is global, we can't modify it with each image Adjust the color balance for whiter whites @ text @a62 1 int write_to_files=1; d74 1 a74 1 /* This 4MB array holds the GMCY values for each pixel */ d77 1 a77 11 /* Creates a new filename with a different extension */ exten(char *new, const char *old, const char *ext) { char *cp; strcpy(new,old); cp=strrchr(new,'.'); if (!cp) cp=new+strlen(new); strcpy(cp,ext); } d98 1 a98 1 read_crw(const char *fname) d102 1 a102 19 int fd, irow, orow, col; fd = open(fname,O_RDONLY | O_BINARY); if (fd < 0) { perror(fname); return 0; } /* Check the header to confirm this is a CRW file */ read (fd, data, 26); if (memcmp(data,"MM",2) || memcmp(data+6,"HEAPCCDR",8)) { fprintf(stderr,"%s is not a Canon PowerShot 600 file.\n",fname); return 0; } #ifdef DEBUG fprintf(stderr,"Unpacking %s...\n",fname); #endif d108 3 d113 2 a141 2 close(fd); return 1; /* Success */ d164 1 a164 1 read_crw(const char *fname) d168 1 a168 19 int fd, row, col; fd = open(fname,O_RDONLY | O_BINARY); if (fd < 0) { perror(fname); return 0; } /* Check the header to confirm this is a CRW file */ read (fd, data, 26); if (memcmp(data,"II",2) || memcmp(data+6,"HEAPCCDR",8)) { fprintf(stderr,"%s is not a Canon PowerShot A5 file.\n",fname); return 0; } #ifdef DEBUG fprintf(stderr,"Unpacking %s...\n",fname); #endif d171 1 a171 2 Immediately after the 26-byte header come the data rows. Each row is 992 pixels, ten bits each, packed into 1240 bytes. d173 2 a174 1 for (row=0; row < H; row++) d176 9 a184 12 read(fd,data,1240); for (dp=data, pix=pixel; dp < data+1200; 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] ); } d190 3 a192 6 memset(gmcy[row], 0, W*8); /* Set row to zero */ for (col=0; col < W; col++) gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3ff) << 4; } close(fd); return 1; /* Success */ d218 1 a218 1 read_crw(const char *fname) d222 1 a222 19 int fd, row, col; fd = open(fname,O_RDONLY | O_BINARY); if (fd < 0) { perror(fname); return 0; } /* Check the header to confirm this is a CRW file */ read (fd, data, 26); if (memcmp(data,"II",2) || memcmp(data+6,"HEAPCCDR",8)) { fprintf(stderr,"%s is not a Canon PowerShot A50 file.\n",fname); return 0; } #ifdef DEBUG fprintf(stderr,"Unpacking %s...\n",fname); #endif d225 1 a225 2 Immediately after the 26-byte header come the data rows. Each row is 1320 pixels, ten bits each, packed into 1650 bytes. d227 2 a228 1 for (row=0; row < H; row++) d230 9 a238 12 read(fd,data,1650); for (dp=data, pix=pixel; dp < data+1650; 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] ); } d244 3 a246 6 memset(gmcy[row], 0, W*8); /* Set row to zero */ for (col=0; col < W; col++) gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3ff) << 4; } close(fd); return 1; /* Success */ d252 4 a255 3 When this function is called, we only have one GMCY value for each pixel. Do linear interpolation to get the other three. d257 1 a257 2 first_interpolate() d259 1 a259 1 int y, x, sy, sx, c; d262 1 a262 5 #ifdef DEBUG fprintf(stderr,"First interpolation...\n"); #endif for (y=1; y < H-1; y++) d264 2 a265 1 for (x=1; x < W-1; x++) d267 5 a271 7 sp=shift; for (sy=y-1; sy < y+2; sy++) for (sx=x-1; sx < x+2; sx++) { c=filter(sy,sx); gmcy[y][x][c] += gmcy[sy][sx][c] >> *sp++; } a276 43 We now have all four GMCY values for each pixel. Smooth the color balance to avoid artifacts. This function may be called more than once. */ second_interpolate() { ushort data[2][W][4]; ushort (*last_row)[4]=data[0]; ushort (*this_row)[4]=data[1]; void *tmp; int y, x, c, sy, sx, sc; uchar shift[]={ 2,1,2, 1,0,1, 2,1,2 }, *sp; #ifdef DEBUG fprintf(stderr,"Second interpolation...\n"); #endif for (y=2; y < H-2; y++) { memset(this_row, 0, W*8); for (x=2; x < W-2; x++) { sp=shift; c=filter(y,x); for (sy=y-1; sy < y+2; sy++) for (sx=x-1; sx < x+2; sx++) { sc=filter(sy,sx); this_row[x][sc] += ( (unsigned long) gmcy[sy][sx][sc] << 16) / gmcy[sy][sx][c] * gmcy[y][x][c] >> (16 + *sp++); } } if (y > 2) memcpy(gmcy[y-1]+2,last_row+2,(W-4)*8); tmp = last_row; last_row = this_row; this_row = tmp; } } /* d315 40 d357 1 a357 2 write_ppm(char *fname) d359 1 a359 1 int fd=1, y, x, i; d364 1 a364 1 int histo[1024], total; a366 18 #ifdef DEBUG fprintf(stderr,"First pass RGB...\n"); #endif /* First pass: Gather stats on the RGB image */ memset(histo,0,sizeof histo); for (y=2; y < H-2; y++) { for (x=2; x < W-2; x++) { get_rgb(rgb,gmcy[y][x]); val = rgb[3]/0x1000000; if (val > 1023) val=1023; histo[val]++; } } d371 1 a371 1 if ((total+=histo[val]) > (int)(W*H*0.06)) break; d376 1 a376 1 fprintf(stderr,"Second pass RGB...\n"); a378 7 if (write_to_files) { fd = open(fname,WFLAGS,0644); if (fd < 0) { perror(fname); return; } } a405 1 if (write_to_files) close(fd); d412 11 d425 3 a427 2 char fname[256]; int arg; d471 9 a479 1 if (read_crw(argv[arg])) d481 2 a482 4 first_interpolate(); second_interpolate(); exten(fname, argv[arg],".ppm"); write_ppm(fname); d484 20 @ 1.15 log @Version 0.95 Added support for the PowerShot A50 @ text @d2 1 a2 1 Canon PowerShot Converter v0.95 a13 1 #include d51 2 a52 2 #define GRN_MUL 0.90 #define BLU_MUL 0.88 d414 1 a414 1 get_rgb(float rgb[4], ushort gmcy[4]) /* 3.70 seconds */ d446 1 d495 1 a495 1 ymul[y] = bright * 362 / max * pow(ymul[y],gamma_val); d502 1 a502 1 scale = ymul[y&3] * pow(rgb[3]/max2,expo); d537 1 a537 1 " Converter v0.95" @ 1.14 log @Saw major problems with the "tea can" image and made corrections: - Magnitudes, not color values, are used to find the maximum. - Color balance and row multipliers (ymul[]) have been adjusted. @ text @d2 1 a2 1 Canon PowerShot Converter v0.94 d32 3 d44 13 d58 1 a58 1 #error You must compile with -DPS_600 or -DPS_A5 d245 46 d294 33 a449 7 /* Use this to remove annoying horizontal patterns */ #ifdef PS_600 float ymul[4] = { 0.9866, 1.0, 1.0125, 1.0 }; #elif defined(PS_A5) float ymul[4] = { 1.0005, 1.0056, 0.9980, 0.9959 }; #endif d534 2 d537 1 a537 1 " Converter v0.94" @ 1.13 log @Merged PowerShot A5 code back into the trunk. @ text @d2 1 a2 1 Canon PowerShot Converter v0.90 d38 2 a39 2 #define GRN_MUL 1.0 #define BLU_MUL 1.0 d349 1 a349 1 register c, val; d351 2 a352 2 float rgb[4], max, max2, expo, mult, scale; int histo[512], total; d359 1 a359 1 float ymul[4] = { 1.0, 1.0, 1.0, 1.0 }; d375 3 a377 4 for (c=0; c < 3; c++) { histo [(int)rgb[c] >> 10]++; } d381 1 a381 1 Set the maximum to the 96th percentile d383 4 a386 4 for (val=512, total=0; --val; ) if ((total+=histo[val]) > (int)(W*H*0.11)) break; max = val << 10; max2 = max*max; a405 1 mult = bright * 362 / max; d407 1 a407 1 ymul[y] = pow(ymul[y],gamma_val); d414 1 a414 1 scale = mult * ymul[y&3] * pow(rgb[3]/max2,expo); d447 1 a447 1 " Converter v0.90" @ 1.12 log @Replaced "60000" with a macro. @ text @d2 1 a2 1 Canon PowerShot 600 Converter v0.86 d4 1 a4 1 by Dave Coffin (dcoffin at shore dot net) d23 4 a26 1 /* Use these to adjust the final color balance */ d32 13 a61 2 #define H 613 #define W 854 d75 1 d155 76 d355 6 a360 2 /* Use this to remove an annoying horizontal pattern */ float ymul[4]={ 0.9866, 1.0, 1.0125, 1.0 }; d443 7 a449 1 "\nCanon PowerShot 600 Converter v0.86" @ 1.11 log @Cosmetic changes to match the new PowerShot A5 version @ text @d290 1 a290 1 if ((total+=histo[val]) > 60000) break; @ 1.11.1.1 log @Converter for the Canon PowerShot A5 @ text @d2 1 a2 1 Canon PowerShot A5 Converter v0.86 d26 1 a26 1 #define GRN_MUL 1.0 d46 2 a47 2 #define H 776 #define W 960 d66 4 a69 4 0 C Y C Y C Y Return values 1 G M G M G M 0 1 2 3 2 C Y C Y C Y G M C Y 3 M G M G M G d73 1 a73 1 (0x1e4e >> ((((row) << 1 & 6) + ((col) & 1)) << 1) & 3) d81 3 a83 3 uchar data[1240], *dp; ushort pixel[992], *pix; int fd, row, col; d93 1 a93 1 if (memcmp(data,"II",2) || memcmp(data+6,"HEAPCCDR",8)) d95 1 a95 1 fprintf(stderr,"%s is not a Canon PowerShot A5 file.\n",fname); d104 3 a106 2 Immediately after the 26-byte header come the data rows. Each row is 992 pixels, ten bits each, packed into 1240 bytes. d108 2 a109 1 for (row=0; row < H; row++) d111 2 a112 2 read(fd,data,1240); for (dp=data, pix=pixel; dp < data+1200; dp+=10, pix+=8) d114 8 a121 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] ); d123 1 d125 1 a125 1 Copy 960 pixels into the gmcy[] array. The other 32 pixels d129 1 a129 1 memset(gmcy[row], 0, W*8); /* Set row to zero */ d131 4 a134 1 gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3f0) << 4; d264 2 a265 2 /* Use this to remove annoying horizontal patterns */ float ymul[4]={ 1.0, 1.0, 1.0, 1.0 }; d348 1 a348 1 "\nCanon PowerShot A5 Converter v0.86" @ 1.11.1.2 log @Fixed two bugs that Vlad pointed out. What a difference!! @ text @d2 1 a2 1 Canon PowerShot A5 Converter v0.87 d128 1 a128 1 gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3ff) << 4; d284 1 a284 1 if ((total+=histo[val]) > 90000) break; d342 1 a342 1 "\nCanon PowerShot A5 Converter v0.87" @ 1.11.1.3 log @Replaced "90000" with a macro. @ text @d284 1 a284 1 if ((total+=histo[val]) > (int)(W*H*0.11)) break; @ 1.10 log @Changed the width and height to macros for more flexibility. @ text @d2 1 a2 1 CRW to PPM converter Version 0.85 d4 1 a4 1 by Dave Coffin (dcoffin at shore dot net) 8/30/97 d32 1 d42 1 a42 3 int write_to_files=1; typedef unsigned char uchar; d51 1 a51 1 exten(char *new, char *old, char *ext) d77 1 a77 1 (such as cyan under a magenta filter) must be set to zero. d79 1 a79 2 read_crw(char *fname) d95 1 a95 1 fprintf(stderr,"%s is not a CRW file.\n",fname); d104 3 a106 3 Immediately after the 26-byte header come the data rows. First the even rows 0..612, then the odd rows 1..611. Each row is 896 pixels, ten bits per pixel, packed into 1120 bytes (8960 bits). a110 1 /* Read one packed row */ a111 2 /* Unpack the pixels */ d126 2 a127 2 are blank. Left-shift by 4 for extra precision in upcoming calculations. d129 1 a129 1 memset(gmcy[orow], 0, W * 8); /* Set row to zero */ d133 2 a134 2 if ((orow+=2) > H) /* Once we've read all the even rows, */ orow = 1; /* read the odd rows. */ d137 1 a137 1 return 1; /* Success */ d142 2 a143 2 value for each pixel. Do linear interpolation to get the other three. d161 1 a161 1 for (sx=x-1; sx < x+2; sx++) d163 2 a164 2 c=filter(sy,sx); gmcy[y][x][c] += gmcy[sy][sx][c] >> *sp++; d172 2 a173 2 the color balance to avoid artifacts. This function may be called more than once. d198 1 a198 1 for (sx=x-1; sx < x+2; sx++) d200 4 a203 4 sc=filter(sy,sx); this_row[x][sc] += ( (unsigned long) gmcy[sy][sx][sc] << 16) / gmcy[sy][sx][c] * gmcy[y][x][c] >> (16 + *sp++); d217 1 a217 1 to the three primary colors, on a scale of 0-100. d248 1 a248 1 } d282 1 a282 1 histo [(int)rgb[c] >> 10]++; d311 1 a311 1 expo = (gamma_val-1)/2; /* Pull these out of the loop */ d331 1 a331 1 write (fd, ppm+1, (W-2) * 3); d348 3 a350 3 "\nCRW to PPM converter by Dave Coffin (dcoffin@@shore.net)" "\nVersion 0.85, last modified 8/30/97\n" "\nUsage: %s [options] file1.crw file2.crw ...\n" d352 1 a352 1 "\n-c Write to standard output" @ 1.9 log @Changed "gamma" to "gamma_val" to avoid name conflict. @ text @d9 3 d47 3 a49 1 ushort gmcy[613][854][4]; d111 1 a111 1 for (irow=orow=0; irow < 613; irow++) d134 2 a135 2 memset(gmcy[orow], 0, 854 * 8); /* Set row to zero */ for (col=0; col < 854; col++) d138 1 a138 1 if ((orow+=2) > 612) /* Once we've read all the even rows, */ d160 1 a160 1 for (y=1; y < 612; y++) d162 1 a162 1 for (x=1; x < 853; x++) d183 1 a183 1 ushort data[2][854][4]; d195 1 a195 1 for (y=2; y < 611; y++) d197 2 a198 2 memset(this_row, 0, 854*8); for (x=2; x < 852; x++) d211 1 a211 1 if (y > 2) memcpy(gmcy[y-1]+2,last_row+2,850*8); d264 1 a264 1 uchar ppm[854][3]; d267 1 d280 1 a280 1 for (y=2; y < 611; y++) d282 1 a282 1 for (x=2; x < 852; x++) d310 1 a310 1 write(fd,"P6\n852 611\n255\n",15); d321 1 a321 1 for (y=1; y < 612; y++) d323 1 a323 1 for (x=1; x < 853; x++) d336 1 a336 1 write (fd, ppm+1, 852 * 3); @ 1.8 log @Version 0.85 Added user-adjustable brightness and gamma correction. @ text @d28 1 a28 1 float gamma=0.8, bright=1.0; d310 1 a310 1 expo = (gamma-1)/2; /* Pull these out of the loop */ d313 1 a313 1 ymul[y] = pow(ymul[y],gamma); d354 1 a354 1 argv[0], gamma, bright); d366 1 a366 1 gamma=atof(argv[++arg]); break; @ 1.7 log @Version 0.8 Devised a totally new interpolation algorithm, using a 3x3 block. Run time is much longer, but image quality has vastly improved. @ text @d2 1 a2 1 CRW to PPM converter Version 0.8 d4 1 a4 1 by Dave Coffin (dcoffin at shore dot net) 8/23/97 d15 1 d23 2 a24 2 #define GRN_MUL 0.535 #define BLU_MUL 0.709 d26 3 a28 1 #define GAMMA 0.75 d38 2 d229 1 a229 1 get_rgb(float rgb[3], ushort gmcy[4]) /* 3.70 seconds */ d242 4 a245 3 memset(rgb,0,12); for (r=0; r < 3; r++) /* RGB colors */ for (g=0; g < 4; g++) /* GMCY colors */ d247 2 d257 1 a257 1 int fd, y, x, i; d260 5 a264 2 float rgb[3], max, gamma, gamtab[257]; int histo[256], total, bot, mid, top; d271 1 a271 2 First pass: Needed to find the maximum color value. Construct a histogram with binning of 1024. d281 1 a281 1 histo [(int)rgb[c] >> 10] ++; d286 1 a286 1 Set the maximum to the 95th percentile d288 2 a289 2 for (val=256, total=0; --val; ) if ((total+=histo[val]) > 80000) break; d291 1 a291 4 gamma = GAMMA; for (i=0; i < 257; i++) gamtab[i] = pow(i/256.0,1/gamma) * max; d297 7 a303 4 fd = open(fname,WFLAGS,0644); if (fd < 0) { perror(fname); return; } d309 7 a315 1 for (y=1; y < 612; y++) /* 4.93 seconds */ d320 2 d324 4 a327 9 for (bot=0,top=256; top-bot > 1; ) /* 3.00 seconds */ { mid = bot+top >> 1; /* Do a binary search */ if (rgb[c] > gamtab[mid]) bot=mid; else top=mid; } ppm[x][c]=bot; d332 1 a332 1 close(fd); d344 1 a344 1 if (argc < 2) d346 9 a354 3 puts("\nCRW to PPM converter by Dave Coffin (dcoffin@@shore.net)"); puts("Version 0.8, last modified 8/23/97\n"); printf("Usage: %s file1.crw file2.crw ...\n\n",argv[0]); d358 19 a376 1 for (arg=1; arg < argc; arg++) @ 1.6 log @Version 0.4, just for testing A breakthrough! I finally figured out what the "mystery pixels" are. @ text @d2 1 a2 1 CRW to PPM converter Version 0.4 d4 1 a4 1 by Dave Coffin (dcoffin at shore dot net) 8/24/97 a16 2 /* Create extra files with debugging info */ d22 4 a25 2 #define GRN_MUL 0.5 #define BLU_MUL 1.0 d52 10 a61 5 #ifdef DEBUG debug (char *arg, char *ext) { char fname[64]; int fd; d63 2 a64 9 exten(fname,arg,ext); fd = open(fname,WFLAGS,0644); if (fd < 0) { perror(fname); fd = open("/dev/null",O_WRONLY); } return fd; } #endif d67 2 a68 6 Returns the color of a given pixel. The pattern goes: (0,0)-> G M G M G M row 0 C Y C Y C Y row 1 M G M G M G row 2 C Y C Y C Y row 3 a69 9 color (unsigned x, unsigned y) { int color; color = ((y & 1) << 1) + (x & 1); if ((y & 3) == 2) /* 0=green, 1=magenta, 2=cyan, 3=yellow */ color ^= 1; /* Swap green and magenta on row 2 */ return color; } d71 1 a71 2 /* Read a CRW file into the pgm[] array */ read_crw(char *arg) d73 3 a75 9 uchar data[1120], *dp, *gp; int fd, irow, icol, orow, ocol; #ifdef DEBUG int gfd, gcol, mfd, mcol; uchar grid[896], myst[224]; gfd = debug(arg,".grid"); mfd = debug(arg,".myst"); d77 1 a77 5 write(gfd,"P5\n896 613\n255\n",15); write(mfd,"P4\n1792 613\n",12); #endif fd = open(arg,O_RDONLY | O_BINARY); d79 1 a79 1 { perror(arg); d82 3 a84 1 read (fd, data, 26); /* Check the header */ d87 1 a87 1 fprintf(stderr,"%s is not a CRW file.\n",arg); d91 10 d103 2 a104 1 read (fd, data, 1120); /* Read one row */ d106 2 a107 2 #ifdef DEBUG for (dp=data, gp=grid; dp < data+1120; dp+=10, gp+=8) d109 8 a116 21 /* wrong */ gp[0]=(dp[0] << 2) + (dp[1] >> 4 & 3); gp[1]=(dp[2] << 2) + (dp[1] >> 2 & 3); gp[2]=(dp[3] << 2) + (dp[1] >> 0 & 3); gp[3]=(dp[4] << 2) + (dp[1] >> 6 & 3); gp[4]=(dp[5] << 2) + (dp[9] >> 0 & 3); gp[5]=(dp[6] << 2) + (dp[9] >> 2 & 3); gp[6]=(dp[7] << 2) + (dp[9] >> 4 & 3); gp[7]=(dp[8] << 2) + (dp[9] >> 6 & 3); #if 0 /* right */ gp[0]=(dp[0] << 2) + (dp[1] >> 6 & 3); gp[1]=(dp[2] << 2) + (dp[1] >> 4 & 3); gp[2]=(dp[3] << 2) + (dp[1] >> 2 & 3); gp[3]=(dp[4] << 2) + (dp[1] >> 0 & 3); gp[4]=(dp[5] << 2) + (dp[9] >> 0 & 3); gp[5]=(dp[6] << 2) + (dp[9] >> 2 & 3); gp[6]=(dp[7] << 2) + (dp[9] >> 4 & 3); gp[7]=(dp[8] << 2) + (dp[9] >> 6 & 3); #endif a117 5 lseek (gfd, orow*896+15, 0); write (gfd, grid, 896); lseek (mfd, orow*224+12, 0); write (mfd, myst, 224); #endif d119 29 a147 12 #if 0 for (icol=gcol=mcol=0; icol < 1120; icol++) { if ( icol % 10 != 1 && icol % 10 != 9 ) grid[gcol++] = data[icol]; /* Data pixels go here */ else myst[mcol++] = data[icol]; /* Mystery pixels go here */ } lseek (gfd, orow*896+15, 0); write (gfd, grid, 896); lseek (mfd, orow*224+12, 0); write (mfd, myst, 224); d150 3 a152 1 for (icol=ocol=0; icol < 1067; icol++) d154 7 a160 5 if ( icol % 10 != 1 && icol % 10 != 9 ) { gmcy[orow][ocol][color(orow,ocol)] = (ushort) data[icol] << 6; ocol++; } a161 2 if ((orow+=2) > 612) /* Once we've read all the even rows, */ orow = 1; /* read the odd rows. */ d163 17 a179 1 close(fd); d182 1 a182 2 close(gfd); close(mfd); d185 21 a205 1 return 1; /* Success */ d209 1 a209 1 Converts a GMCY quadruplet into an RGB triplet. d223 2 a224 1 get_rgb(float rgb[3], uchar gmcy[4]) d243 11 d255 3 a257 1 #if 0 d260 2 a261 4 For all values of (x,y), the pixels (x,y), (x+1,y), (x,y+1), and (x+1,y+1) form a GMCY vector (i.e. no two have the same color). Convert these vectors to RGB, then try to remove the artifacts that appear when there's an edge between x and x+1. d263 26 a288 5 write_ppm(char *fname) { int out, y, x, sy, sx, c, val, prev; uchar gmcy[4], ppm[853][3]; float rgb[3]; d290 2 a291 2 out = open(fname,WFLAGS,0644); if (out < 0) d294 1 a294 1 write(out,"P6\n853 612\n255\n",15); d296 4 a299 1 for (y=0; y < 612; y++) d301 1 a301 1 for (x=0; x < 853; x++) d303 1 a303 4 for (sy=y; sy < y+2; sy++) for (sx=x; sx < x+2; sx++) gmcy[color(sx,sy)] = pgm[sy][sx]; get_rgb(rgb,gmcy); d306 9 a314 4 val = floor(rgb[c]); if (val < 0) val=0; if (val > 255) val=255; ppm[x][c] = val; d317 1 a317 1 write (out, ppm, sizeof ppm); d319 5 a323 1 close(out); a324 1 #endif d329 1 a329 2 int arg, fd, x, y; short magic; d334 1 a334 1 puts("Version 0.4, last modified 8/24/97\n"); d343 3 a345 2 exten(fname, argv[arg],".ppm"); /* Open a PPM file for RGB output */ #if 0 a346 1 #endif @ 1.5 log @Version 0.3 More comments, better error checking. Switched back to 2x2 blocks, and tried Moire smoothing. @ text @d2 1 a2 1 CRW to PPM converter Version 0.3 d4 1 a4 1 by Dave Coffin (dcoffin at shore dot net) 3/24/97 d17 1 a17 1 typedef unsigned char uchar; d19 1 a19 2 /* This array holds the raw pixel values */ uchar pgm[613][854]; d21 5 a25 5 /* Write the raw pixel values to a PGM file before RGB conversion. Useful for debugging. */ #define WANT_PGM_FILE d28 1 d35 51 d87 1 a87 1 read_crw(int in) d89 13 a101 2 uchar data[1120]; int bin, irow, icol, orow, ocol; d103 11 a113 3 read (in, data, 24); /* Chop the header */ if (memcmp(data+4,"HEAPCCDR",8)) /* Make sure it's CRW */ return 1; d117 47 a163 1 read (in, data, 1120); /* Read one row */ d166 5 a170 2 if ( icol % 10 != 1 && icol % 10 != 9 ) /* Delete the "mystery pixels" */ pgm[orow][ocol++] = data[icol]; d175 1 a175 3 close(in); return 0; /* Success */ } d177 4 a180 28 /* Used for parsing PGM headers */ int get_num(FILE *fp) { int num=0; char c; for (;;) { if (isspace(c=getc(fp))) /* Ignore whitespace */ continue; if ( c=='#' ) /* Ignore comments */ while (getc(fp) != '\n'); else if (isdigit(c)) /* Grab digits */ { do { num = num*10 + (c - '0'); /* Make a number */ c=getc(fp); } while (isdigit(c)); return num; /* Return it */ } else fprintf(stderr,"Illegal byte in header\n"); } } /* Read a PGM file, skipping the CRW -> PGM conversion */ read_pgm(int in) { int width, height, maxval; FILE *fp; d182 1 a182 17 #if O_BINARY != 0 fp=fdopen(in,"rb"); #else fp=fdopen(in,"r"); #endif width=get_num(fp); height=get_num(fp); maxval=get_num(fp); if (width != 854 || height != 613 || maxval != 255) { fprintf(stderr, "PGM file must be 854x613, 256 colors!\n"); fclose(fp); return 1; } fread(pgm,854,613,fp); fclose(fp); return 0; d205 6 a210 6 { -2.400719, 3.539540, -2.515721, 3.421035 }, /* red */ #if 0 { 4.013642, -1.710916, 0.690795, 0.417247 }, /* green */ #endif { 2.006821, -0.855458, 0.345397, 0.208623 }, /* green/2 (why??) */ { -2.345669, 3.385090, 3.521597, -2.249256 } /* blue */ a218 11 /* Returns the color of a given pixel. The pattern goes: (0,0)-> G M G M G M C Y C Y C Y M G M G M G C Y C Y C Y */ color (unsigned x, unsigned y) { int color; d220 1 a220 5 color = ((y & 1) << 1) + (x & 1); if ((y & 3) == 2) /* 0=green, 1=magenta, 2=cyan, 3=yellow */ color ^= 1; /* Swap green and magenta */ return color; } a255 16 /* This moire smoothing doesn't work very well. */ #ifdef MOIRE_SMOOTH for (c=0; c < 3; c++) { prev = ppm[0][c]; for (x=1; x < 852; x++) { val = prev + ppm[x][c]*2 + ppm[x+1][c] + 1 >> 2; prev = ppm[x][c]; ppm[x][c] = val; } } #endif d260 1 a260 11 /* Creates a new filename with a different extension */ exten(char *new, char *old, char *ext) { char *cp; strcpy(new,old); cp=strrchr(new,'.'); if (!cp) cp=new+strlen(new); strcpy(cp,ext); } d271 1 a271 1 puts("Version 0.3, last modified 3/24/97\n"); d278 1 a278 6 fd = open(argv[arg],O_RDONLY | O_BINARY); if (fd < 0) { perror(argv[arg]); continue; } read(fd,&magic,2); if (magic == 0x4d4d) /* "MM" */ d280 3 a282 14 if (read_crw(fd)) { fprintf(stderr,"%s is not a CRW file.\n",argv[arg]); continue; } #ifdef WANT_PGM_FILE exten(fname, argv[arg],".pgm"); /* Write the pixel data to */ fd = open(fname,WFLAGS,0644); /* a PGM file */ if (fd < 0) { perror(fname); continue; } write(fd,"P5\n854 613\n255\n",15); write(fd, pgm, 613*854); close(fd); a284 7 else if (ntohs(magic)==0x5035) /* "P5" */ { if (read_pgm(fd)) continue; } exten(fname, argv[arg],".ppm"); /* Open a PPM file for RGB output */ write_ppm(fname); @ 1.4 log @Changes for version 0.2: Removed BLACK correction; it didn't help. Pre-solved color equations for a big speed increase. @ text @d2 1 a2 1 CRW to PPM converter Version 0.2 d4 1 a4 1 by Dave Coffin (dcoffin at shore dot net) 2/24/97 d42 2 d50 1 a50 1 if ( icol % 10 != 1 && icol % 10 != 9 ) /* Cut out noise columns */ d110 12 a121 1 Ask Canon how this works; I have no clue. d123 1 a123 1 get_rgb(float rgb[3], int gmcy[4]) d128 6 a133 3 { -5.175675, 3.853136, -1.681311, 5.270232 }, { 1.281218, -1.147541, 1.935073, 0.487001 }, { -3.167515, 2.900609, 4.132598, -1.720971 } d161 4 a164 2 Interpolate GMCY values for each non-edge pixel (using all eight neighbors), then convert the result to RGB. d168 2 a169 2 int out, y, x, sy, sx, c, val, gmcy[4]; uchar ppm[852][3]; a170 1 uchar shift[]={ 0,1,0, 1,2,1, 0,1,0 }, *sp; d176 1 a176 1 write(out,"P6\n852 611\n255\n",15); d178 1 a178 1 for (y=0; y < 611; y++) d180 1 a180 1 for (x=0; x < 852; x++) d182 4 a185 7 memset(gmcy,0,sizeof gmcy); sp=shift; for (sy=y; sy < y+3; sy++) /* Average a 3x3 block */ for (sx=x; sx < x+3; sx++) gmcy[color(sx,sy)] += pgm[sy][sx] << *sp++; get_rgb(rgb,gmcy); /* Convert GMCY averages to RGB */ d188 3 a190 3 val = floor(rgb[c]/4); /* Save the RGB values */ if (val < 0) val=0; if (val > 255) val=255; d194 16 d235 1 a235 1 puts("Version 0.2, last modified 2/24/97\n"); d249 4 a252 1 read_crw(fd); d265 1 a265 1 else if (magic==0x3550 || magic==0x5035) /* "P5" or "5P" */ @ 1.3 log @Final 0.1 version. Changed 2x2 blocks to weighted 3x3 neighborhood. @ text @d2 1 a2 1 CRW to PPM converter Version 0.1 d4 1 a4 1 by Dave Coffin (dcoffin@@shore.net) 2/22/97 a34 23 /* Subtract this number from all input pixels */ #define BLACK 6 /* This table describes the color response of the four pixel types, according to experiment. It is used by get_rgb() to convert GMCY colorspace to RGB. Notice that blue light generates a negative response in green and yellow pixels. Strange. */ const float coeff[4][3] = { /* red * + green * + blue * = pixel color */ { 0.052296, 0.255409,-0.047466 }, /* green */ { 0.156993, 0.046792, 0.046537 }, /* magenta */ {-0.004344, 0.280239, 0.045865 }, /* cyan */ { 0.145482, 0.309211,-0.089371 }, /* yellow */ }; /* Matrix used for solving equations */ double mat[3][4]; a106 39 These three functions solve a 4x3 matrix (three equations, three unknowns), leaving the answers in the last column. To improve performance, they should be combined, inlined, and written in assembly. */ norm(row) { float div; int i; div=mat[row][row]; for (i=row+1; i < 4; i++) mat[row][i] /= div; } sub(arow,brow) { float mul; int i; mul=mat[arow][brow]; for (i=brow+1; i < 4; i++) mat[arow][i] -= mat[brow][i] * mul; } solve() { norm(0); sub(1,0); sub(2,0); norm(1); sub(0,1); sub(2,1); norm(2); sub(0,2); sub(1,2); } /* d108 1 a108 5 We have four equations with three unknowns. My answer is to solve the system four times, omitting one equation each time, then average the results. Canon must know a better way--this method is SLOW!!! d112 7 a118 1 int omit, color, equ, i; d121 3 a123 13 for (omit=0; omit < 4; omit++) { for (color=equ=0; color < 4; color++) if (color != omit) { for (i=0; i < 3; i++) mat[equ][i] = coeff[color][i]; mat[equ++][3] = gmcy[color]; } solve(); for (i=0; i < 3; i++) /* Save this solution */ rgb[i] += mat[i][3]; } d169 1 a169 1 gmcy[color(sx,sy)] += pgm[sy][sx] - BLACK << *sp++; d174 1 a174 1 val = floor(rgb[c]/24); /* Scale and save the RGB values */ d205 1 a205 1 puts("Version 0.1, last modified 2/22/97\n"); @ 1.2 log @Use 2x2 squares instead of orthogonal neighbors. @ text @d23 2 a24 2 Write the raw pixel values to a PGM file before RGB conversion. Useful for debugging. a27 6 /* Subtract this number from all pixels after writing PGM file. */ #define BLACK 6 /* Matrix used for solving equations */ double mat[3][4]; d35 3 d40 5 a44 11 pixel types, according to experiment. I have no idea why some terms are negative. Perhaps Canon would like to fill in the correct values? An intuitive, but incorrect, table would be: red green blue 0 1 0 green 1 0 1 magenta 0 1 1 cyan 1 1 0 yellow d48 5 a52 4 { 0.052296, 0.255409,-0.047466 }, { 0.156993, 0.046792, 0.046537 }, {-0.004344, 0.280239, 0.045865 }, { 0.145482, 0.309211,-0.089371 }, d55 2 a56 9 #if 0 { /* red * + green * + blue * = pixel color */ { 0.051146, 0.319806, -0.067939 }, /* green */ { 0.219660, 0.045533, 0.048611 }, /* magenta */ {-0.045775, 0.337888, 0.057842 }, /* cyan */ { 0.184652, 0.391803, -0.127791 }, /* yellow */ }; #endif d132 2 a133 2 improve performance, this should be inlined or written in assembly. d170 5 a174 4 The tough part is, we have four equations with three unknowns. The best answer is to solve the system four times, omitting one equation each time, then average the results. d176 1 a176 1 get_rgb(float rgb[3], uchar gmcy[4]) d197 1 a197 1 Returns the color of the given pixel. The pattern goes: d214 4 d220 2 a221 2 int out, y, x, sy, sx, c, val; uchar gmcy[4], ppm[853][3]; d223 1 d229 1 a229 1 write(out,"P6\n853 612\n255\n",15); d231 1 a231 1 for (y=0; y < 612; y++) d233 1 a233 1 for (x=0; x < 853; x++) d235 8 a242 5 for (sy=y; sy < y+2; sy++) for (sx=x; sx < x+2; sx++) gmcy[color(sx,sy)] = pgm[sy][sx] - BLACK; get_rgb(rgb,gmcy); for (c=0; c < 3; c++) /* Scale and save the RGB values */ d244 1 a244 1 val = floor(rgb[c]/4); @ 1.1 log @Initial revision @ text @d32 1 a32 1 float mat[3][4]; d55 8 a62 1 float coeff[4][3] = a72 7 { { 0.052296, 0.255409,-0.047466 }, { 0.156993, 0.046792, 0.046537 }, {-0.004344, 0.280239, 0.045865 }, { 0.145482, 0.309211,-0.089371 }, }; d183 36 a218 2 /* Add one pixel to the equation */ add_pixel (int row, unsigned x, unsigned y) d220 1 a220 1 int color, value, i; a221 1 if (x >= 854 || y >= 613) return; /* Don't count this pixel */ d225 1 a225 7 value = pgm[y][x] - BLACK; #if BLACK if (value < 0) value=0; #endif for (i=0; i < 3; i++) mat[row][i] += coeff[color][i]; mat[row][3] += value; d230 3 a232 3 int out, y, x, c, val; uchar ppm[854*3], *pptr, max[4]; float scale=1; d238 1 a238 14 write(out,"P6\n854 613\n255\n",15); #if 0 memset(max,0,4); for (y=0; y < 613; y++) for (x=0; x < 854; x++) { c = ((y & 1) << 1) + (x & 1); if ((y & 3) == 2) /* 0=green, 1=magenta, 2=cyan, 3=yellow */ c ^= 1; /* Swap green and magenta */ if (max[c] < pgm[y][x]) max[c] = pgm[y][x]; } #endif d240 1 a240 1 for (y=0; y < 613; y++) d242 1 a242 2 pptr=ppm; for (x=0; x < 854; x++) d244 5 a248 8 memset(mat,0,sizeof mat); /* Zero out the matrix */ add_pixel(0,x,y); /* Equation 0 uses this pixel */ add_pixel(1,x-1,y); /* Equation 1 uses pixels left and right */ add_pixel(1,x+1,y); add_pixel(2,x,y-1); /* Equation 2 uses pixels above and below */ add_pixel(2,x,y+1); solve(); /* Solve for red, green, and blue */ for (c=0; c < 3; c++) /* Scale and save these values */ d250 1 a250 1 val = floor(mat[c][3] * scale); d253 1 a253 1 *pptr++ = val; d256 1 a256 1 write (out, ppm, 854*3); @