public unsafe System.Drawing.Bitmap BuildImage(int subsample = 1) { Verify.SubsampleRange(subsample); lock (LoadingLock) { System.Drawing.Bitmap background = GetBackgroundImage(subsample, true); // TODO ETW logging goes here using (System.Drawing.Bitmap foreground = GetForegroundImage(subsample, true)) { using (System.Drawing.Bitmap mask = GetMaskImage(subsample, true)) { HasLoaded = true; BitmapData backgroundData = background.LockBits(new System.Drawing.Rectangle(0, 0, background.Width, background.Height), ImageLockMode.ReadWrite, background.PixelFormat); int backgroundPixelSize = DjvuImage.GetPixelSize(backgroundData.PixelFormat); BitmapData foregroundData = foreground.LockBits(new System.Drawing.Rectangle(0, 0, foreground.Width, foreground.Height), ImageLockMode.ReadOnly, foreground.PixelFormat); int foregroundPixelSize = DjvuImage.GetPixelSize(foregroundData.PixelFormat); BitmapData maskData = mask.LockBits(new System.Drawing.Rectangle(0, 0, mask.Width, mask.Height), ImageLockMode.ReadOnly, mask.PixelFormat); //int maskPixelSize = GetPixelSize(maskData); int bgndHeight = background.Height; int bgndWidth = background.Width; int fgndHeight = foreground.Height; int fgndWidth = foreground.Width; int maskHeight = mask.Height; int maskWidth = mask.Width; int maskbgnH = maskHeight / bgndHeight; int maskfgnH = maskHeight / fgndHeight; int maskbgnW = maskWidth / bgndWidth; int maskfgnW = maskWidth / fgndWidth; //Parallel.For( // 0, // height, // y => // { for (int y = 0, yf = 0, yb = 0; y < maskHeight && yb < bgndHeight && yf < fgndHeight; ++y, yf = yb = y) { byte *maskRow = (byte *)maskData.Scan0 + (y * maskData.Stride); DjvuNet.Graphics.Pixel *backgroundRow = (DjvuNet.Graphics.Pixel *)(backgroundData.Scan0 + (yb * backgroundData.Stride)); DjvuNet.Graphics.Pixel *foregroundRow = (DjvuNet.Graphics.Pixel *)(foregroundData.Scan0 + (yf * foregroundData.Stride)); for (int x = 0, xf = 0, xb = 0; x < bgndWidth && xb < maskWidth && xf < fgndWidth; x++) { // Check if the mask byte is set if (maskRow[x] > 0) { DjvuNet.Graphics.Pixel xF = foregroundRow[xf]; if (_IsInverted) { backgroundRow[xb] = InvertColor(xF); } else { backgroundRow[xb] = xF; } } else if (_IsInverted) { backgroundRow[xb] = InvertColor(backgroundRow[xb]); } if (x >= 0) { if (x % maskbgnW == 0) { xb++; } if (x % maskfgnW == 0) { xf++; } } } if (y >= 0) { if (y % maskbgnH == 0) { yb++; } if (y % maskfgnH == 0) { yf++; } } } //}); mask.UnlockBits(maskData); foreground.UnlockBits(foregroundData); background.UnlockBits(backgroundData); return(background); } } } }
/// <summary> /// Gets the image for the page /// </summary> /// <returns> /// <see cref="System.Drawing.Bitmap"/>Bitmap image. /// </returns> public unsafe System.Drawing.Bitmap BuildImage(int subsample = 1) { // // TODO Fix image skew // Verify.SubsampleRange(subsample); lock (_LoadingLock) { Stopwatch stopWatch = Stopwatch.StartNew(); System.Drawing.Bitmap background = GetBackgroundImage(subsample, false); stopWatch.Stop(); // TODO ETW logging goes here stopWatch.Restart(); using (System.Drawing.Bitmap foreground = GetForegroundImage(subsample, false)) { stopWatch.Stop(); // TODO ETW logging goes here stopWatch.Restart(); using (System.Drawing.Bitmap mask = GetTextImage(subsample, false)) { stopWatch.Stop(); // TODO ETW logging goes here stopWatch.Restart(); _HasLoaded = true; BitmapData backgroundData = background.LockBits(new System.Drawing.Rectangle(0, 0, background.Width, background.Height), ImageLockMode.ReadWrite, background.PixelFormat); int backgroundPixelSize = DjvuImage.GetPixelSize(backgroundData.PixelFormat); BitmapData foregroundData = foreground.LockBits(new System.Drawing.Rectangle(0, 0, foreground.Width, foreground.Height), ImageLockMode.ReadOnly, foreground.PixelFormat); int foregroundPixelSize = DjvuImage.GetPixelSize(foregroundData.PixelFormat); BitmapData maskData = mask.LockBits(new System.Drawing.Rectangle(0, 0, mask.Width, mask.Height), ImageLockMode.ReadOnly, mask.PixelFormat); //int maskPixelSize = GetPixelSize(maskData); int bgndHeight = background.Height; int bgndWidth = background.Width; int fgndHeight = foreground.Height; int fgndWidth = foreground.Width; int maskHeight = mask.Height; int maskWidth = mask.Width; int maskbgnH = maskHeight / bgndHeight; int maskfgnH = maskHeight / fgndHeight; int maskbgnW = maskWidth / bgndWidth; int maskfgnW = maskWidth / fgndWidth; //Parallel.For( // 0, // height, // y => // { ; for (int y = 0, yf = 0, yb = 0; y < maskHeight && yb < bgndHeight && yf < fgndHeight; y++) { byte *maskRow = (byte *)maskData.Scan0 + (y * maskData.Stride); uint *backgroundRow = (uint *)(backgroundData.Scan0 + (yb * backgroundData.Stride)); uint *foregroundRow = (uint *)(foregroundData.Scan0 + (yf * foregroundData.Stride)); for (int x = 0, xf = 0, xb = 0; x < bgndWidth && xb < maskWidth && xf < fgndWidth; x++) { // Check if the mask byte is set if (maskRow[x] > 0) { uint xF = foregroundRow[xf]; if (_IsInverted) { backgroundRow[xb] = InvertColor(xF); } else { backgroundRow[xb] = xF; } } else if (_IsInverted == true) { uint xB = backgroundRow[xb]; backgroundRow[xb] = InvertColor(xB); } if (x > 0) { if (x % maskbgnW == 0) { xb++; } if (x % maskfgnW == 0) { xf++; } } } if (y > 0) { if (y % maskbgnH == 0) { yb++; } if (y % maskfgnH == 0) { yf++; } } } //}); mask.UnlockBits(maskData); foreground.UnlockBits(foregroundData); background.UnlockBits(backgroundData); stopWatch.Stop(); // TODO ETW logging goes here return(background); } } } }