private void BrCalc_Advanced() { #region Variables BitmapEx bmp1, bmp2, bmp3; const int min = 5; const int max = 250; bmp1 = GetThumb(0, true); int isdark, xS, yS; const uint ThumbWidth = 300; const uint ThumbHeight = 200; uint x, y, rowstride, n = bmp1.ChannelCount; long index, count; double br1, br2, br3, newBr, maxiBrDiff; double[,] BrightChangeMask = new double[ThumbWidth, ThumbHeight]; bool[,] NonUseMask = new bool[ThumbWidth, ThumbHeight]; double[][] PixelBrightness = new double[ThumbWidth * ThumbHeight][]; ColorRGB c; #endregion //TODO: make calculation parallel for (int f = 0; f < Frames.Count; f += 2) { if (MainWorker.CancellationPending) { return; } #region Variables if (f == 0) { f++; } if (f + 2 >= Frames.Count) { f = Frames.Count - 2; } bmp1 = GetThumb(f - 1, false).Scale(ThumbWidth, ThumbHeight); bmp2 = GetThumb(f, false).Scale(ThumbWidth, ThumbHeight); bmp3 = GetThumb(f + 1, false).Scale(ThumbWidth, ThumbHeight); rowstride = bmp1.Stride; n = bmp1.ChannelCount; index = count = isdark = 0; br1 = br2 = br3 = newBr = maxiBrDiff = 0; RGBSpace space = new RGBColorspacesRGB(); #endregion unsafe { bmp1.LockBits(); bmp2.LockBits(); bmp3.LockBits(); byte *pix1 = (byte *)bmp1.Scan0; byte *pix2 = (byte *)bmp2.Scan0; byte *pix3 = (byte *)bmp3.Scan0; #region Mask for (y = 0; y < ThumbHeight; y++) { for (x = 0; x < rowstride; x += n) { index = y * rowstride + x; c = new ColorRGB(pix1[index], pix1[index + 1], pix1[index + 2], space); fixed(double *pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br1 = (c.R + c.G + c.B) * 255d / 3d; c = new ColorRGB(pix2[index], pix2[index + 1], pix2[index + 2], space); fixed(double *pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br2 = (c.R + c.G + c.B) * 255d / 3d; c = new ColorRGB(pix3[index], pix3[index + 1], pix3[index + 2], space); fixed(double *pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br3 = (c.R + c.G + c.B) * 255d / 3d; if (br1 > min && br2 > min && br3 > min && br1 < max && br2 < max && br3 < max) { NonUseMask[x / n, y] = false; } else { NonUseMask[x / n, y] = true; } } } List <double> brightnessDiff1; List <double> brightnessDiff2; for (y = 0; y < ThumbHeight; y++) { for (x = 0; x < bmp1.Stride; x += n) { if (NonUseMask[x / n, y] == false) { count = 0; brightnessDiff1 = new List <double>(); brightnessDiff2 = new List <double>(); for (yS = -1; yS <= 1; yS++) { if (y + yS < ThumbHeight && y + yS >= 0) { for (xS = -1; xS <= 1; xS++) { if (x + xS < rowstride && x + xS >= 0) { if (NonUseMask[(x + xS) / n, y + yS] == false) { index = (y + yS) * rowstride + x + xS; c = new ColorRGB(pix1[index], pix1[index + 1], pix1[index + 2], space); fixed(double *pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br1 = (c.R + c.G + c.B) * 255d / 3d; c = new ColorRGB(pix2[index], pix2[index + 1], pix2[index + 2], space); fixed(double *pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br2 = (c.R + c.G + c.B) * 255d / 3d; c = new ColorRGB(pix3[index], pix3[index + 1], pix3[index + 2], space); fixed(double *pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br3 = (c.R + c.G + c.B) * 255d / 3d; brightnessDiff1.Add(Math.Abs(br1 - br2)); brightnessDiff2.Add(Math.Abs(br2 - br3)); count++; } } } } } if (count > 0) { BrightChangeMask[x / n, y] = Math.Max(brightnessDiff1.Average(), brightnessDiff2.Average()); } else { BrightChangeMask[x / n, y] = 0; } if (maxiBrDiff < BrightChangeMask[x / n, y]) { maxiBrDiff = BrightChangeMask[x / n, y]; } } else { BrightChangeMask[x / n, y] = 0; } } } bmp1.UnlockBits(); bmp2.UnlockBits(); bmp3.UnlockBits(); for (y = 0; y < ThumbHeight; y++) { for (x = 0; x < ThumbWidth; x++) { if (NonUseMask[x, y] == false) { if (maxiBrDiff > 0) { newBr = (BrightChangeMask[x, y] * 100) / maxiBrDiff; if (newBr > 100) { newBr = 100; } BrightChangeMask[x, y] = Math.Abs(newBr - 100); } else { BrightChangeMask[x, y] = 100; } } else { BrightChangeMask[x, y] = 0; } if (BrightChangeMask[x, y] < 0.5) { isdark++; } } } if ((isdark * 100) / (ThumbHeight * ThumbWidth) > 97) { throw new ImageTooDarkException(); } if (this.GetType() == typeof(ProjectLS)) { ((FrameLS)Frames[f]).UsageMask = BrightChangeMask; } #endregion MainWorker.ReportProgress(0, new ProgressChangeEventArgs((f + 1) * 100 / (Frames.Count - 1), ProgressType.CalculateBrightness)); #region Brightness count = 0; for (y = 0; y < ThumbHeight; y++) { for (x = 0; x < rowstride; x += n) { index = y * rowstride + x; c = new ColorRGB(pix1[index], pix1[index + 1], pix1[index + 2], space); fixed(double *pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br1 = (c.R + c.G + c.B) * 255d / 3d; c = new ColorRGB(pix2[index], pix2[index + 1], pix2[index + 2], space); fixed(double *pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br2 = (c.R + c.G + c.B) * 255d / 3d; c = new ColorRGB(pix3[index], pix3[index + 1], pix3[index + 2], space); fixed(double *pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br3 = (c.R + c.G + c.B) * 255d / 3d; double factor = BrightChangeMask[x / n, y] / 100; PixelBrightness[count] = new double[3] { br1 *factor, br2 *factor, br3 *factor }; count++; } } double val0 = (PixelBrightness.Average(p => p[0])); double val1 = (PixelBrightness.Average(p => p[1])); double val2 = (PixelBrightness.Average(p => p[2])); if (f == 1) { Frames[0].OriginalBrightness = val0; } double val1P = (val1 * 100) / val0; Frames[f].OriginalBrightness = (Frames[f - 1].OriginalBrightness * val1P) / 100; double val2P = (val2 * 100) / val0; Frames[f + 1].OriginalBrightness = (Frames[f - 1].OriginalBrightness * val2P) / 100; Frames[f - 1].AlternativeBrightness = Frames[f - 1].OriginalBrightness; Frames[f].AlternativeBrightness = Frames[f].OriginalBrightness; Frames[f + 1].AlternativeBrightness = Frames[f + 1].OriginalBrightness; Frames[f - 1].NewBrightness = Frames[f - 1].OriginalBrightness; Frames[f].NewBrightness = Frames[f].OriginalBrightness; Frames[f + 1].NewBrightness = Frames[f + 1].OriginalBrightness; #endregion } } //LTODO: write statistic/BV-value check #region Statistics/BV-Values Check /*Status = CalcState.Statistics; * * for (int f = 1; f < filecount; f++) * { * if (AllFiles[f].HasExif) * { * double EvP = (Math.Min(AllFiles[f].Brightness, AllFiles[f - 1].Brightness) * 100) / Math.Max(AllFiles[f].Brightness, AllFiles[f - 1].Brightness); * double bv1 = Math.Abs(AllFiles[f - 1].Bv); * double bv2 = Math.Abs(AllFiles[f].Bv); * double BvP = (Math.Min(bv1, bv2) * 100) / Math.Max(bv1, bv2); * if (bv1 < bv2) { BvP *= -1; } * double res = BvP - EvP; * if (AllFiles[f].Brightness < AllFiles[f - 1].Brightness) { res *= -1; } * AllFiles[f].StatisticalError = res; * } * else * { * //do statistical check * } * * CalcWorker[0].ReportProgress((int)((((double)f / (double)filecount)) * 100f), Status); * }*/ #endregion Statistics/BV-Values Check }
private void BrCalc_Advanced() { #region Variables BitmapEx bmp1, bmp2, bmp3; const int min = 5; const int max = 250; bmp1 = GetThumb(0, true); int isdark, xS, yS; const uint ThumbWidth = 300; const uint ThumbHeight = 200; uint x, y, rowstride, n = bmp1.ChannelCount; long index, count; double br1, br2, br3, newBr, maxiBrDiff; double[,] BrightChangeMask = new double[ThumbWidth, ThumbHeight]; bool[,] NonUseMask = new bool[ThumbWidth, ThumbHeight]; double[][] PixelBrightness = new double[ThumbWidth * ThumbHeight][]; ColorRGB c; #endregion //TODO: make calculation parallel for (int f = 0; f < Frames.Count; f += 2) { if (MainWorker.CancellationPending) { return; } #region Variables if (f == 0) { f++; } if (f + 2 >= Frames.Count) { f = Frames.Count - 2; } bmp1 = GetThumb(f - 1, false).Scale(ThumbWidth, ThumbHeight); bmp2 = GetThumb(f, false).Scale(ThumbWidth, ThumbHeight); bmp3 = GetThumb(f + 1, false).Scale(ThumbWidth, ThumbHeight); rowstride = bmp1.Stride; n = bmp1.ChannelCount; index = count = isdark = 0; br1 = br2 = br3 = newBr = maxiBrDiff = 0; RGBSpace space = new RGBColorspacesRGB(); #endregion unsafe { bmp1.LockBits(); bmp2.LockBits(); bmp3.LockBits(); byte* pix1 = (byte*)bmp1.Scan0; byte* pix2 = (byte*)bmp2.Scan0; byte* pix3 = (byte*)bmp3.Scan0; #region Mask for (y = 0; y < ThumbHeight; y++) { for (x = 0; x < rowstride; x += n) { index = y * rowstride + x; c = new ColorRGB(pix1[index], pix1[index + 1], pix1[index + 2], space); fixed (double* pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br1 = (c.R + c.G + c.B) * 255d / 3d; c = new ColorRGB(pix2[index], pix2[index + 1], pix2[index + 2], space); fixed (double* pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br2 = (c.R + c.G + c.B) * 255d / 3d; c = new ColorRGB(pix3[index], pix3[index + 1], pix3[index + 2], space); fixed (double* pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br3 = (c.R + c.G + c.B) * 255d / 3d; if (br1 > min && br2 > min && br3 > min && br1 < max && br2 < max && br3 < max) { NonUseMask[x / n, y] = false; } else { NonUseMask[x / n, y] = true; } } } List<double> brightnessDiff1; List<double> brightnessDiff2; for (y = 0; y < ThumbHeight; y++) { for (x = 0; x < bmp1.Stride; x += n) { if (NonUseMask[x / n, y] == false) { count = 0; brightnessDiff1 = new List<double>(); brightnessDiff2 = new List<double>(); for (yS = -1; yS <= 1; yS++) { if (y + yS < ThumbHeight && y + yS >= 0) { for (xS = -1; xS <= 1; xS++) { if (x + xS < rowstride && x + xS >= 0) { if (NonUseMask[(x + xS) / n, y + yS] == false) { index = (y + yS) * rowstride + x + xS; c = new ColorRGB(pix1[index], pix1[index + 1], pix1[index + 2], space); fixed (double* pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br1 = (c.R + c.G + c.B) * 255d / 3d; c = new ColorRGB(pix2[index], pix2[index + 1], pix2[index + 2], space); fixed (double* pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br2 = (c.R + c.G + c.B) * 255d / 3d; c = new ColorRGB(pix3[index], pix3[index + 1], pix3[index + 2], space); fixed (double* pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br3 = (c.R + c.G + c.B) * 255d / 3d; brightnessDiff1.Add(Math.Abs(br1 - br2)); brightnessDiff2.Add(Math.Abs(br2 - br3)); count++; } } } } } if (count > 0) { BrightChangeMask[x / n, y] = Math.Max(brightnessDiff1.Average(), brightnessDiff2.Average()); } else { BrightChangeMask[x / n, y] = 0; } if (maxiBrDiff < BrightChangeMask[x / n, y]) { maxiBrDiff = BrightChangeMask[x / n, y]; } } else { BrightChangeMask[x / n, y] = 0; } } } bmp1.UnlockBits(); bmp2.UnlockBits(); bmp3.UnlockBits(); for (y = 0; y < ThumbHeight; y++) { for (x = 0; x < ThumbWidth; x++) { if (NonUseMask[x, y] == false) { if (maxiBrDiff > 0) { newBr = (BrightChangeMask[x, y] * 100) / maxiBrDiff; if (newBr > 100) { newBr = 100; } BrightChangeMask[x, y] = Math.Abs(newBr - 100); } else { BrightChangeMask[x, y] = 100; } } else { BrightChangeMask[x, y] = 0; } if (BrightChangeMask[x, y] < 0.5) { isdark++; } } } if ((isdark * 100) / (ThumbHeight * ThumbWidth) > 97) { throw new ImageTooDarkException(); } if (this.GetType() == typeof(ProjectLS)) { ((FrameLS)Frames[f]).UsageMask = BrightChangeMask; } #endregion MainWorker.ReportProgress(0, new ProgressChangeEventArgs((f + 1) * 100 / (Frames.Count - 1), ProgressType.CalculateBrightness)); #region Brightness count = 0; for (y = 0; y < ThumbHeight; y++) { for (x = 0; x < rowstride; x += n) { index = y * rowstride + x; c = new ColorRGB(pix1[index], pix1[index + 1], pix1[index + 2], space); fixed (double* pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br1 = (c.R + c.G + c.B) * 255d / 3d; c = new ColorRGB(pix2[index], pix2[index + 1], pix2[index + 2], space); fixed (double* pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br2 = (c.R + c.G + c.B) * 255d / 3d; c = new ColorRGB(pix3[index], pix3[index + 1], pix3[index + 2], space); fixed (double* pt = c.ValueArray) { ((RGBSpace)c.Space).ToLinear(pt, pt); } br3 = (c.R + c.G + c.B) * 255d / 3d; double factor = BrightChangeMask[x / n, y] / 100; PixelBrightness[count] = new double[3] { br1 * factor, br2 * factor, br3 * factor }; count++; } } double val0 = (PixelBrightness.Average(p => p[0])); double val1 = (PixelBrightness.Average(p => p[1])); double val2 = (PixelBrightness.Average(p => p[2])); if (f == 1) { Frames[0].OriginalBrightness = val0; } double val1P = (val1 * 100) / val0; Frames[f].OriginalBrightness = (Frames[f - 1].OriginalBrightness * val1P) / 100; double val2P = (val2 * 100) / val0; Frames[f + 1].OriginalBrightness = (Frames[f - 1].OriginalBrightness * val2P) / 100; Frames[f - 1].AlternativeBrightness = Frames[f - 1].OriginalBrightness; Frames[f].AlternativeBrightness = Frames[f].OriginalBrightness; Frames[f + 1].AlternativeBrightness = Frames[f + 1].OriginalBrightness; Frames[f - 1].NewBrightness = Frames[f - 1].OriginalBrightness; Frames[f].NewBrightness = Frames[f].OriginalBrightness; Frames[f + 1].NewBrightness = Frames[f + 1].OriginalBrightness; #endregion } } //LTODO: write statistic/BV-value check #region Statistics/BV-Values Check /*Status = CalcState.Statistics; for (int f = 1; f < filecount; f++) { if (AllFiles[f].HasExif) { double EvP = (Math.Min(AllFiles[f].Brightness, AllFiles[f - 1].Brightness) * 100) / Math.Max(AllFiles[f].Brightness, AllFiles[f - 1].Brightness); double bv1 = Math.Abs(AllFiles[f - 1].Bv); double bv2 = Math.Abs(AllFiles[f].Bv); double BvP = (Math.Min(bv1, bv2) * 100) / Math.Max(bv1, bv2); if (bv1 < bv2) { BvP *= -1; } double res = BvP - EvP; if (AllFiles[f].Brightness < AllFiles[f - 1].Brightness) { res *= -1; } AllFiles[f].StatisticalError = res; } else { //do statistical check } CalcWorker[0].ReportProgress((int)((((double)f / (double)filecount)) * 100f), Status); }*/ #endregion Statistics/BV-Values Check }