2 using System.Collections.Generic;
5 using Microsoft.Xna.Framework;
6 using Microsoft.Xna.Framework.Graphics;
10 using Microsoft.Xna.Framework.Graphics.PackedVector;
11 using Microsoft.Xna.Framework.Content;
12 using Microsoft.Xna.Framework.GamerServices;
20 private GraphicsDevice device;
21 SpriteBatch spriteBatch;
23 private Matrix rotationFromLMS;
24 private Matrix rotationToLMS;
26 private string colorVisionDeficency;
30 private RenderTarget2D target_lms;
32 private RenderTarget2D target_rgbToLab;
33 private RenderTarget2D target_contrastLoss;
34 private RenderTarget2D target_predominantComponent;
35 private RenderTarget2D target_eigenVector;
36 private RenderTarget2D target_projection;
37 private RenderTarget2D target_maxProjectionEffect;
38 private RenderTarget2D target_enhanceContrast;
39 private RenderTarget2D target_labToRGB;
52 private Texture2D toSimulate;
53 private Texture2D referenceImageRGB;
55 private Texture2D noiseTexture;
57 private Texture2D tex_lab;
58 private Texture2D tex_contrastLost;
59 private Texture2D tex_predominantComponent;
60 private Texture2D tex_eigenVectors;
61 private Texture2D tex_projected;
62 private Texture2D tex_maxProjectedEffect;
63 private Texture2D tex_enhancedContrast;
65 private Texture2D recoloredImage;
68 bool saveDebugTextures =
false;
69 bool debugOutput =
false;
76 public Matrix RotationFromLMS
78 set { rotationFromLMS = value; }
79 get {
return rotationFromLMS; }
82 public Matrix RotationToLMS
84 set { rotationToLMS = value; }
85 get {
return rotationToLMS; }
89 public Texture2D ImageToSimulate
93 width = toSimulate.Width;
94 height = toSimulate.Height;
96 get {
return toSimulate; }
102 public Texture2D RecoloredImage
104 set { recoloredImage = value; }
105 get {
return recoloredImage; }
108 public string ColorVisionDeficency
110 set { colorVisionDeficency = value; SetAngle(); SetMatrix(); }
111 get {
return colorVisionDeficency; }
114 public Texture2D ReferenceImageRGB
117 referenceImageRGB = value;
119 width = referenceImageRGB.Width;
120 height = referenceImageRGB.Height;
123 get {
return referenceImageRGB; }
126 public Texture2D LabImage
128 set { tex_lab = value; }
129 get {
return tex_lab; }
132 public Texture2D NoiseTexture
134 set { noiseTexture = value; Console.WriteLine(
"noise texture initialized"); }
135 get {
return noiseTexture; }
140 set { shader_lms = value; }
141 get {
return shader_lms; }
146 set { shader_rgbToLab = value; }
147 get {
return shader_rgbToLab; }
152 set { shader_contrastLoss = value; }
153 get {
return shader_contrastLoss; }
158 set { shader_predominantComponent = value; }
159 get {
return shader_predominantComponent; }
164 set { shader_eigenVector = value; }
165 get {
return shader_eigenVector; }
170 set { shader_projection = value; }
171 get {
return shader_projection; }
176 set { shader_maxProjectionEffect = value; }
177 get {
return shader_predominantComponent; }
182 set { shader_enhanceContrast = value; }
183 get {
return shader_enhanceContrast; }
188 set { shader_labToRGB = value; }
189 get {
return shader_labToRGB; }
196 public Image(GraphicsDevice _device,
string _colorVisionDeficency)
198 if (!saveDebugTextures)
200 saveDebugTextures = GameProperties.Instance.shaderDebugMode;
205 this.colorVisionDeficency = _colorVisionDeficency;
209 #region create render targets
210 PresentationParameters pp = device.PresentationParameters;
212 SurfaceFormat format = SurfaceFormat.Rgba64;
213 int bbwidth = pp.BackBufferWidth;
214 int bbheight = pp.BackBufferHeight;
215 DepthFormat depthStecilFormat = pp.DepthStencilFormat;
216 int multiSample = pp.MultiSampleCount;
218 target_lms =
new RenderTarget2D(device, bbwidth, bbheight,
false, format,
219 depthStecilFormat, multiSample, RenderTargetUsage.DiscardContents);
222 target_rgbToLab =
new RenderTarget2D(device, bbwidth, bbheight,
false, format,
223 depthStecilFormat, multiSample, RenderTargetUsage.DiscardContents);
225 target_contrastLoss =
new RenderTarget2D(device, bbwidth, bbheight,
false, format,
226 depthStecilFormat, multiSample, RenderTargetUsage.DiscardContents);
228 target_predominantComponent =
new RenderTarget2D(device, bbwidth, bbheight,
false, format,
229 depthStecilFormat, multiSample, RenderTargetUsage.DiscardContents);
231 target_maxProjectionEffect =
new RenderTarget2D(device, bbwidth, bbheight,
false, format,
232 depthStecilFormat, multiSample, RenderTargetUsage.DiscardContents);
234 target_eigenVector =
new RenderTarget2D(device, bbwidth, bbheight,
false, format,
235 depthStecilFormat, multiSample, RenderTargetUsage.DiscardContents);
237 target_projection =
new RenderTarget2D(device, bbwidth, bbheight,
false, format,
238 depthStecilFormat, multiSample, RenderTargetUsage.DiscardContents);
240 target_enhanceContrast =
new RenderTarget2D(device, bbwidth, bbheight,
false, format,
241 depthStecilFormat, multiSample, RenderTargetUsage.DiscardContents);
243 target_labToRGB =
new RenderTarget2D(device, bbwidth, bbheight,
false, format,
244 depthStecilFormat, multiSample, RenderTargetUsage.DiscardContents);
247 #region create textures
264 Console.WriteLine(
"Image class instanciated");
272 #region initialization stuff
275 private void SetAngle()
277 switch (colorVisionDeficency)
298 Console.WriteLine(
"angle set to " + angle);
304 private void SetMatrix()
306 rotationFromLMS = Matrix.CreateRotationX(MathHelper.ToRadians(angle));
307 rotationToLMS = Matrix.CreateRotationX(MathHelper.ToRadians(-1.0f * angle));
311 Console.WriteLine(
"rotation matrix set to: " +rotationFromLMS);
316 #region noise texture
317 private void SetNoiseTexture()
324 Console.WriteLine(
"setting noise texture");
327 Color[] noise =
new Color[width * height];
329 double variance = Math.Sqrt(2.0f*Math.Min(width,height));
330 float scale = (float)(variance*(2.0f/Math.PI));
333 Color old =
new Color(0.0f, 0.0f, 0.0f, 1.0f);
336 for (
int x=0; x<width; x++) {
337 for (
int y = 0; y < height; y++)
339 #region create random gauss
341 Random randx =
new Random();
342 double u1x = randx.NextDouble();
343 double u2x = randx.NextDouble();
344 double randStdNormalx = Math.Sqrt(-2.0 * Math.Log(u1x)) * Math.Sin(2.0 * Math.PI * u2x);
347 Random randy =
new Random();
348 double u1y = randy.NextDouble();
349 double u2y = randy.NextDouble();
350 double randStdNormaly = Math.Sqrt(-2.0 * Math.Log(u1y)) * Math.Sin(2.0 * Math.PI * u2y);
353 int index = y*width+x;
354 int rx = (int)Math.Floor(Math.Max(Math.Min(x + scale*randStdNormalx,width-1.0f),0.0f));
359 int ry = (int)Math.Floor(Math.Max(Math.Min(y + scale * randStdNormaly, height - 1.0f), 0.0f));
363 Vector4 currentColor =
new Vector4((rx + 0.5f)/width, (ry + 0.5f)/height, 0.0f, 1.0f);
365 noise[index] =
new Color(currentColor);
367 if (saveDebugTextures)
369 Color newC = noise[index];
370 if (newC.R > old.R) { old.R = newC.R; }
371 if (newC.G > old.G) { old.G = newC.G; }
372 if (newC.B > old.B) { old.B = newC.B; }
374 if (newC.R >= 255 && newC.G >= 255 && newC.B >= 255)
382 Console.WriteLine(
"index="+index+
" EXCEPTION!!!!!!!!!!!!!!!!!!!!!! " + e);
391 Console.WriteLine(
"max =" + old);
392 Console.WriteLine(
"count =" + count);
393 Console.WriteLine(
"set values to texture");
395 noiseTexture.SetData<Color>(noise);
400 Console.WriteLine(
" EXCEPTION!!!!!!!!!!!!!!!!!!!!!! " + e);
405 Console.WriteLine(
"noise texture set");
412 #region Simulate Perception
413 public void SimulatePerception(GraphicsDevice _device)
417 Console.WriteLine(
"start simulatin perception");
420 device.DepthStencilState = DepthStencilState.None;
422 colorVisionDeficency = GameProperties.Instance.CVD;
426 spriteBatch =
new SpriteBatch(device);
428 ConvertRGBtoLab(toSimulate);
430 ProjectToReducedLMS();
437 public void Recolor(GraphicsDevice _device)
441 Console.WriteLine(
"start recoloring");
444 device.DepthStencilState = DepthStencilState.None;
446 colorVisionDeficency = GameProperties.Instance.CVD;
450 spriteBatch =
new SpriteBatch(device);
452 ConvertRGBtoLab(referenceImageRGB);
456 PredominantComponent();
458 ComputeEigenVectors();
460 ProjectOntoLMSplane();
462 MaxProjectionEffect();
470 device.DepthStencilState = DepthStencilState.Default;
474 #region methods for each recoloring/simulation step
476 #region Simulate Perception
477 private void ProjectToReducedLMS()
485 tex_lab = target_rgbToLab;
489 device.SetRenderTarget(target_lms);
490 DrawSprite(tex_lab, shader_lms);
491 device.SetRenderTarget(null);
493 tex_enhancedContrast = target_lms;
495 if (saveDebugTextures)
497 saveScreenshot(tex_enhancedContrast,
"0_simulated",
"png");
502 Console.WriteLine(
"ProjectToReducedLMS done");
508 private void ConvertRGBtoLab(Texture2D _imageToConvert)
520 InitRGBToLab_Shader(_imageToConvert);
522 device.SetRenderTarget(target_rgbToLab);
523 DrawSprite3(_imageToConvert, shader_rgbToLab);
524 device.SetRenderTarget(null);
526 tex_lab = target_rgbToLab;
528 if (saveDebugTextures)
530 saveScreenshot(_imageToConvert,
"1_reference",
"png");
531 saveScreenshot(tex_lab,
"2_rgbToLab",
"png");
536 Console.WriteLine(
"ConvertRGBtoLab done");
542 #region contrast loss
543 private void ContrastLoss()
564 noiseTexture =
new Texture2D(device, width, height,
true, SurfaceFormat.Color);
567 InitContrastLoss_Shader();
569 device.SetRenderTarget(target_contrastLoss);
570 DrawSprite3(tex_lab, shader_contrastLoss);
571 device.SetRenderTarget(null);
573 tex_contrastLost = target_contrastLoss;
583 if (saveDebugTextures)
585 saveScreenshot(tex_contrastLost,
"3_ContrastLoss",
"png");
586 saveScreenshot(noiseTexture,
"noiseTexture",
"png");
591 Console.WriteLine(
"ContrastLoss done");
596 #region PCA: predominant component
597 private void PredominantComponent()
606 initPredominantComponenet_Shader();
608 device.SetRenderTarget(target_predominantComponent);
609 DrawSprite3(tex_contrastLost, shader_predominantComponent);
610 device.SetRenderTarget(null);
612 tex_predominantComponent = target_predominantComponent;
614 if (saveDebugTextures)
616 saveScreenshot(tex_predominantComponent,
"4_PredominantComponent",
"png");
621 Console.WriteLine(
"PCAPredominantComponent done");
626 #region eigen vectors
627 private void ComputeEigenVectors()
636 InitEigenVector_Shader();
638 device.SetRenderTarget(target_eigenVector);
639 DrawSprite(tex_predominantComponent, shader_eigenVector);
640 device.SetRenderTarget(null);
642 tex_eigenVectors = target_eigenVector;
644 if (saveDebugTextures)
646 saveScreenshot(tex_eigenVectors,
"5_EigenVectors",
"png");
651 Console.WriteLine(
"ComputeEigenVectors done");
656 #region project onto LMS plane
657 private void ProjectOntoLMSplane()
669 InitProjection_Shader();
671 device.SetRenderTarget(target_projection);
672 DrawSprite(tex_eigenVectors, Projection_Shader);
673 device.SetRenderTarget(null);
675 tex_projected = target_projection;
677 if (saveDebugTextures)
679 saveScreenshot(tex_projected,
"6_Projections",
"png");
683 Console.WriteLine(
"ProjectOntoLMSplane done");
688 #region max projection effect
689 private void MaxProjectionEffect()
696 initMaxProjectionEffect_Shader();
698 device.SetRenderTarget(target_maxProjectionEffect);
699 DrawSprite3(tex_projected, shader_maxProjectionEffect);
700 device.SetRenderTarget(null);
702 tex_maxProjectedEffect = target_maxProjectionEffect;
704 if (saveDebugTextures)
706 saveScreenshot(tex_maxProjectedEffect,
"7_MaxProjectionEffect",
"png");
711 Console.WriteLine(
"MaxProjectionEffect done");
716 #region enhance contrast
717 private void EnhanceContrast()
725 InitEnhanceContrast_Shader();
727 device.SetRenderTarget(target_enhanceContrast);
728 DrawSprite3(tex_maxProjectedEffect, shader_enhanceContrast);
729 device.SetRenderTarget(null);
731 tex_enhancedContrast = target_enhanceContrast;
733 if (saveDebugTextures)
735 saveScreenshot(tex_enhancedContrast,
"8_EnhanceContrast",
"png");
740 Console.WriteLine(
"EnhanceContrast done");
746 private void ConvertLabToRGB()
757 InitLabtoRGB_Shader();
759 device.SetRenderTarget(target_labToRGB);
760 DrawSprite3(tex_enhancedContrast, shader_labToRGB);
761 device.SetRenderTarget(null);
763 recoloredImage = target_labToRGB;
765 if (saveDebugTextures)
767 if (GameProperties.Instance.simulate)
769 saveScreenshot(recoloredImage,
"9_SimulatedImage",
"png");
773 saveScreenshot(recoloredImage,
"9_RecoloredImage",
"png");
779 Console.WriteLine(
"ConvertLabToRGB done");
786 #region set effect parameters for shader
791 private void InitLabtoRGB_Shader()
795 Console.WriteLine(
"initializing L*a*b* to RGB shader");
798 shader_labToRGB.EnhancedContrast_tex = tex_enhancedContrast;
799 shader_labToRGB.RotationMatrix = rotationFromLMS;
801 shader_labToRGB.SetEffectParameter_labToRGB();
807 private void InitEnhanceContrast_Shader()
811 Console.WriteLine(
"initializing Result Color shader");
814 shader_enhanceContrast.SetEffectParameter_EnhanceContrast(tex_maxProjectedEffect, tex_projected, tex_lab);
820 private void initMaxProjectionEffect_Shader()
824 Console.WriteLine(
"initializing PCA4 Reduction shader");
827 shader_maxProjectionEffect.SetEffectParameter_MaxProjectionEffect(tex_projected);
833 private void InitProjection_Shader()
837 Console.WriteLine(
"initializing Projection shader");
840 shader_projection.SetEffectParameter_Projection(tex_lab, tex_eigenVectors);
846 private void InitEigenVector_Shader()
850 Console.WriteLine(
"initializing EigenVector shader");
853 shader_eigenVector.SetEffectParameter_EigenVectors(tex_predominantComponent);
861 private void initPredominantComponenet_Shader()
865 Console.WriteLine(
"initializing Predominant Component shader");
868 shader_predominantComponent.SetEffectParameter_PredominantComponenet(tex_contrastLost);
874 private void InitContrastLoss_Shader()
878 Console.WriteLine(
"initializing Contrast Loss shader");
882 shader_contrastLoss.SetEffectParameter_ContrastLoss(tex_lab, noiseTexture);
888 private void InitRGBToLab_Shader(Texture2D _imageToConvert)
892 Console.WriteLine(
"initializing RGB to lab shader");
895 shader_rgbToLab.RGBTexture = _imageToConvert;
896 shader_rgbToLab.RotationMatrix = rotationToLMS;
898 shader_rgbToLab.SetEffectParameter_RGBtoLab();
904 private void InitLMSShader()
908 Console.WriteLine(
"initializing LMS shader");
910 shader_lms.SetEffectParameter_LMS(tex_lab);
926 device.Clear(Color.Black);
927 device.BlendState = BlendState.NonPremultiplied;
929 spriteBatch.Begin(0, BlendState.NonPremultiplied, null, null, null, shader);
931 spriteBatch.Draw(tex,
new Rectangle(0, 0, width, height), Color.Black);
941 private void DrawSprite3(Texture2D tex,
RecolorShader shader)
943 Console.WriteLine(
"drawing sprite: " + tex.Name);
945 device.Clear(Color.Black);
946 device.BlendState = BlendState.AlphaBlend;
950 spriteBatch.Begin(0, BlendState.AlphaBlend, null, null, null, shader);
954 Console.WriteLine(
"EXCEPTION!!!!!!!!!!!!!!!!" + e);
958 spriteBatch.Draw(tex,
new Rectangle(0, 0, width, height), Color.White);
967 #region save screenshot
968 private void saveScreenshot(Texture2D texture, String name, String ext)
975 Console.WriteLine(
"saving " + name);
978 if (!name.ElementAt(name.Length - 4).Equals(
".")) name = name +
"." + ext;
979 FileStream stream = File.OpenWrite(name);
983 texture.SaveAsPng(stream, texture.Width, texture.Height);
986 texture.SaveAsJpeg(stream, texture.Width, texture.Height);
989 if (name.ElementAt(name.Length - 4).Equals(
".")) name = name.Substring(0, name.Length - 4);
990 name = name +
".png";
991 texture.SaveAsPng(stream, texture.Width, texture.Height);
997 Console.WriteLine(
"Save Screenshot: ");
998 Console.WriteLine(e);