private unsafe void UpdateBitmap() { if (m_Image == null) { return; } // Fill pixel per pixel int W = m_Image.Width; int H = m_Image.Height; if (m_Bitmap != null && (m_Bitmap.Width != W || m_Bitmap.Height != H)) { m_Bitmap.Dispose(); m_Bitmap = null; } if (m_Bitmap == null) { m_Bitmap = new Bitmap(W, H, PixelFormat.Format32bppArgb); } ImageUtility.float4[,] OriginalContentRGB = new ImageUtility.float4[W, H]; if (m_ViewLinear) { m_ProfileLinear.XYZ2RGB(m_Image.ContentXYZ, OriginalContentRGB); } else { m_ProfilesRGB.XYZ2RGB(m_Image.ContentXYZ, OriginalContentRGB); } // ImageUtility.float4[,] ContentRGB = ApplyBrightnessContrastGamma( OriginalContentRGB, m_Brightness, m_Contrast, m_Gamma ); ImageUtility.float4[,] ContentRGB = OriginalContentRGB; BitmapData LockedBitmap = m_Bitmap.LockBits(new Rectangle(0, 0, W, H), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); for (int Y = 0; Y < H; Y++) { byte *pScanline = (byte *)LockedBitmap.Scan0.ToPointer() + LockedBitmap.Stride * Y; for (int X = 0; X < W; X++) { byte R = (byte)Math.Max(0, Math.Min(255, 255 * ContentRGB[X, Y].x)); byte G = (byte)Math.Max(0, Math.Min(255, 255 * ContentRGB[X, Y].y)); byte B = (byte)Math.Max(0, Math.Min(255, 255 * ContentRGB[X, Y].z)); byte A = (byte)Math.Max(0, Math.Min(255, 255 * (m_ViewLinear ? ContentRGB[X, Y].w : ImageUtility.ColorProfile.Linear2sRGB(ContentRGB[X, Y].w)))); *pScanline++ = B; *pScanline++ = G; *pScanline++ = R; *pScanline++ = 0xFF; } } m_Bitmap.UnlockBits(LockedBitmap); Refresh(); }
private unsafe void UpdateBitmap() { if (m_Image == null) { return; } // Fill pixel per pixel int W = m_Image.Width; int H = m_Image.Height; if (m_Bitmap != null && (m_Bitmap.Width != W || m_Bitmap.Height != H)) { m_Bitmap.Dispose(); m_Bitmap = null; } if (m_Bitmap == null) { m_Bitmap = new Bitmap(W, H, PixelFormat.Format32bppArgb); } ImageUtility.float4[,] ContentRGB = new ImageUtility.float4[W, H]; if (m_ViewLinear) { m_ProfileLinear.XYZ2RGB(m_Image.ContentXYZ, ContentRGB); } else { m_ProfilesRGB.XYZ2RGB(m_Image.ContentXYZ, ContentRGB); } BitmapData LockedBitmap = m_Bitmap.LockBits(new Rectangle(0, 0, W, H), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); for (int Y = 0; Y < H; Y++) { byte *pScanline = (byte *)LockedBitmap.Scan0.ToPointer() + LockedBitmap.Stride * Y; for (int X = 0; X < W; X++) { byte R = (byte)Math.Max(0, Math.Min(255, 255 * ContentRGB[X, Y].x)); byte G = (byte)Math.Max(0, Math.Min(255, 255 * ContentRGB[X, Y].y)); byte B = (byte)Math.Max(0, Math.Min(255, 255 * ContentRGB[X, Y].z)); byte A = (byte)Math.Max(0, Math.Min(255, 255 * (m_ViewLinear ? ContentRGB[X, Y].w : ImageUtility.ColorProfile.Linear2sRGB(ContentRGB[X, Y].w)))); switch (m_ViewMode) { case VIEW_MODE.RGB: *pScanline++ = B; *pScanline++ = G; *pScanline++ = R; *pScanline++ = 0xFF; break; case VIEW_MODE.R: *pScanline++ = R; *pScanline++ = R; *pScanline++ = R; *pScanline++ = 0xFF; break; case VIEW_MODE.G: *pScanline++ = G; *pScanline++ = G; *pScanline++ = G; *pScanline++ = 0xFF; break; case VIEW_MODE.B: *pScanline++ = B; *pScanline++ = B; *pScanline++ = B; *pScanline++ = 0xFF; break; case VIEW_MODE.AO: *pScanline++ = A; *pScanline++ = A; *pScanline++ = A; *pScanline++ = 0xFF; break; case VIEW_MODE.AO_FROM_RGB: { float LinR = ImageUtility.ColorProfile.sRGB2Linear(ContentRGB[X, Y].x); float LinG = ImageUtility.ColorProfile.sRGB2Linear(ContentRGB[X, Y].y); float LinB = ImageUtility.ColorProfile.sRGB2Linear(ContentRGB[X, Y].z); float LinAO = (float)Math.Sqrt(LinR * LinR + LinG * LinG + LinB * LinB) * 0.57735026918962576450914878050196f; // divided by sqrt(3) A = (byte)Math.Max(0, Math.Min(255, 255 * ImageUtility.ColorProfile.Linear2sRGB(LinAO))); *pScanline++ = A; *pScanline++ = A; *pScanline++ = A; *pScanline++ = 0xFF; } break; case VIEW_MODE.RGB_AO: { float LinR = ImageUtility.ColorProfile.sRGB2Linear(ContentRGB[X, Y].x); float LinG = ImageUtility.ColorProfile.sRGB2Linear(ContentRGB[X, Y].y); float LinB = ImageUtility.ColorProfile.sRGB2Linear(ContentRGB[X, Y].z); float LinAO = ContentRGB[X, Y].w; LinR *= LinAO; LinG *= LinAO; LinB *= LinAO; R = (byte)Math.Max(0, Math.Min(255, 255 * ImageUtility.ColorProfile.Linear2sRGB(LinR))); G = (byte)Math.Max(0, Math.Min(255, 255 * ImageUtility.ColorProfile.Linear2sRGB(LinG))); B = (byte)Math.Max(0, Math.Min(255, 255 * ImageUtility.ColorProfile.Linear2sRGB(LinB))); *pScanline++ = B; *pScanline++ = G; *pScanline++ = R; *pScanline++ = 0xFF; } break; } } } m_Bitmap.UnlockBits(LockedBitmap); Refresh(); }
/// <summary> /// Rebuilds and assigns the bitmap for the output panel from the loaded image /// </summary> private void RebuildImage() { if ( m_BitmapXYZ == null ) return; bool sRGB = checkBoxsRGB.Checked; bool SpatialCorrection = checkBoxSpatialLuminanceCorrection.Checked; ImageUtility.float4[,] Image = new ImageUtility.float4[m_BitmapXYZ.Width,m_BitmapXYZ.Height]; int W = m_BitmapXYZ.Width; int H = m_BitmapXYZ.Height; if ( checkBoxLuminance.Checked ) { // Convert into luminances only for ( int Y = 0; Y < H; Y++ ) for ( int X = 0; X < W; X++ ) { float L = m_BitmapXYZ.ContentXYZ[X, Y].y; if ( SpatialCorrection ) L*= m_CalibrationDatabase.GetSpatialLuminanceCorrectionFactor( (float) X / W, (float) Y / H ); if ( sRGB ) L = ImageUtility.ColorProfile.Linear2sRGB( L ); Image[X, Y].x = L; Image[X, Y].y = L; Image[X, Y].z = L; } } else { // RGB ImageUtility.float4[,] Content = m_BitmapXYZ.ContentXYZ; if ( checkBoxSpatialLuminanceCorrection.Checked ) { Content = new ImageUtility.float4[m_BitmapXYZ.Width,m_BitmapXYZ.Height]; Array.Copy( m_BitmapXYZ.ContentXYZ, Content, Content.LongLength ); for ( int Y=0; Y < H; Y++ ) for ( int X=0; X < W; X++ ) { ImageUtility.float4 XYZ = Content[X,Y]; ImageUtility.float3 xyY = ImageUtility.ColorProfile.XYZ2xyY( (ImageUtility.float3) XYZ ); xyY.z *= m_CalibrationDatabase.GetSpatialLuminanceCorrectionFactor( (float) X / W, (float) Y / H ); XYZ = new ImageUtility.float4( ImageUtility.ColorProfile.xyY2XYZ( xyY ), XYZ.w ); Content[X,Y] = XYZ; } } // Build conversion profile ImageUtility.ColorProfile Profile = new ImageUtility.ColorProfile( ImageUtility.ColorProfile.Chromaticities.sRGB, // Always use standard sRGB illuminant sRGB ? ImageUtility.ColorProfile.GAMMA_CURVE.sRGB : ImageUtility.ColorProfile.GAMMA_CURVE.STANDARD, // Either use sRGB linear toe or a standard gamma sRGB ? ImageUtility.ColorProfile.GAMMA_EXPONENT_sRGB : 1.0f ); // Either use sRGB gamma or linear gamma // Convert Profile.XYZ2RGB( Content, Image ); } outputPanel.Image = Image; }