/// <summary> /// Gets the foreground image for the page /// </summary> /// <param name="resizeToPage"></param> /// <returns></returns> internal System.Drawing.Bitmap GetForegroundImage(int subsample, bool resizeImage = false) { Verify.SubsampleRange(subsample); lock (_LoadingLock) { Bitmap result = null; JB2Image jb2image = null; var iwPixelMap = _Page.ForegroundIWPixelMap; if (iwPixelMap != null) { result = _Page.ForegroundIWPixelMap.GetPixelMap().ToImage(); } else if ((jb2image = _Page.ForegroundJB2Image) != null) { result = jb2image.GetBitmap().ToImage(); } else if (iwPixelMap == null && jb2image == null) { result = DjvuImage.CreateBlankImage(Brushes.Black, _Page.Width / subsample, _Page.Height / subsample); } return(resizeImage == true?DjvuImage.ResizeImage(result, _Page.Width / subsample, _Page.Height / subsample) : result); } }
/// <summary> /// Extracts a thumbnail image for the page /// </summary> /// <returns></returns> public Bitmap ExtractThumbnailImage() { if (_Page.Thumbnail != null) { return(_Page.Thumbnail.Image.ToImage()); } Bitmap result = BuildImage(); var scaleAmount = (double)128 / result.Width; return(DjvuImage.ResizeImage(result, (int)(result.Width * scaleAmount), (int)(result.Height * scaleAmount))); }
/// <summary> /// Gets the background image for the page /// </summary> /// <returns></returns> internal System.Drawing.Bitmap GetBackgroundImage(int subsample, bool resizeImage = false) { Verify.SubsampleRange(subsample); int width = _Page.Width; int height = _Page.Height; BG44Chunk[] backgrounds = _Page.PageForm?.GetChildrenItems <BG44Chunk>(); if ((backgrounds == null || backgrounds.Length == 0) && width > 0 && height > 0) { return(DjvuImage.CreateBlankImage(Brushes.White, width, height)); } // Get the composite background image Wavelet.IInterWavePixelMap backgroundMap = null; lock (LoadingLock) { foreach (BG44Chunk background in backgrounds) { if (backgroundMap == null) { // Get the initial image backgroundMap = background.BackgroundImage; } else { if (!IsBackgroundDecoded) { background.ProgressiveDecodeBackground(backgroundMap); } } } IsBackgroundDecoded = true; } Bitmap result = backgroundMap.GetPixelMap().ToImage(); if (resizeImage) { int newWidth = width / subsample; int newHeight = height / subsample; return(DjvuImage.ResizeImage(result, newWidth, newHeight)); } else { return(result); } }
internal System.Drawing.Bitmap GetMaskImage(int subsample, bool resizeImage = false) { Verify.SubsampleRange(subsample); if (_Page.ForegroundJB2Image == null) { return(new System.Drawing.Bitmap(_Page.Width / subsample, _Page.Height / subsample, PixelFormat.Format8bppIndexed)); } lock (LoadingLock) { Bitmap result = _Page.ForegroundJB2Image.GetBitmap(subsample, GBitmap.BorderSize).ToImage(); return(resizeImage ? DjvuImage.ResizeImage(result, _Page.Width / subsample, _Page.Height / subsample) : result); } }
internal System.Drawing.Bitmap GetTextImage(int subsample, bool resizeImage = false) { Verify.SubsampleRange(subsample); if (_Page.ForegroundJB2Image == null) { return(new System.Drawing.Bitmap(_Page.Width / subsample, _Page.Height / subsample)); } lock (_LoadingLock) { var result = _Page.ForegroundJB2Image.GetBitmap(subsample, 4).ToImage(); return(resizeImage ? DjvuImage.ResizeImage(result, _Page.Width / subsample, _Page.Height / subsample) : result); } }
public DjvuPage(int pageNumber, IDjvuDocument document, DirmComponent header, ITH44Chunk thumbnail, IReadOnlyList<IDjviChunk> includedItems, DjvuFormElement form) { PageNumber = pageNumber; Document = document; Header = header; Thumbnail = thumbnail; IncludeFiles = includedItems; PageForm = form; _DjvuImage = new DjvuImage(this); PropertyChanged += DjvuPage_PropertyChanged; if (form.ChunkType != ChunkType.BM44Form && form.ChunkType != ChunkType.PM44Form && Info == null) { throw new DjvuFormatException( $"Page {PageNumber} does not have associated Info chunk." + "Page is invalid and can not be displayed"); } else if (form.ChunkType == ChunkType.BM44Form || form.ChunkType == ChunkType.PM44Form) { // TODO: Debug log or assert } }
internal DjvuPage() { _DjvuImage = new DjvuImage(this); }
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); } } } }
public System.Drawing.Bitmap BuildPageImage(bool rebuild = false) { const int subsample = 1; int width = _Page.Width / subsample; int height = _Page.Height / subsample; GMap map = null; Rectangle rect = new Rectangle(0, 0, width, height); Bitmap retVal = null; if (rebuild || _Image == null) { map = _Page.GetMap(new GRect(0, 0, width, height), subsample, null); if (map == null) { return(new Bitmap(width, height)); } if (map.BytesPerPixel == 3) { const PixelFormat format = PixelFormat.Format24bppRgb; retVal = DjvuImage.ImageFromMap(map, rect, format); } else if (map.BytesPerPixel == 1) { const PixelFormat format = PixelFormat.Format8bppIndexed; retVal = DjvuImage.ImageFromMap(map, rect, format); } } else { retVal = _Image; } if (map.BytesPerPixel == 3 && IsInverted) { retVal = DjvuImage.InvertColor(retVal); } else if (map.BytesPerPixel == 1) { System.Drawing.Imaging.ColorPalette palette = retVal.Palette; if (!IsInverted) { for (int i = 0; i < 256; i++) { palette.Entries[i] = Color.FromArgb(i, i, i); } retVal.Palette = palette; } else { int j = 0; for (int i = 0; i < 256; i++) { j = 255 - i; palette.Entries[i] = Color.FromArgb(j, j, j); } retVal.Palette = palette; } } return(retVal); //int[] pixels = new int[width * height]; //map.FillRgbPixels(0, 0, width, height, pixels, 0, width); //var image = ConvertDataToImage(pixels); //if (IsInverted == true) // image = InvertImage(image); //return image; }
/// <summary> /// Resizes the pages image to the new dimensions /// </summary> /// <param name="srcImage"></param> /// <param name="newWidth"></param> /// <param name="newHeight"></param> /// <returns></returns> public System.Drawing.Bitmap ResizeImage(int newWidth, int newHeight) { return(DjvuImage.ResizeImage(Image, newWidth, newHeight)); }
/// <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); } } } }