/// <summary> Fill this image from another source at reduced resolution. Pixel /// averaging will be used. /// /// </summary> /// <param name="src">image map to reduce /// </param> /// <param name="subsample">rate to subsample /// </param> /// <param name="pdr">target bounds /// </param> public virtual void Downsample(Map src, int subsample, Rectangle pdr) { Rectangle rect = new Rectangle(0, 0, ((src.ImageWidth + subsample) - 1) / subsample, ((src.ImageHeight + subsample) - 1) / subsample); if (pdr != null) { if ((pdr.Right < rect.Right) || (pdr.Bottom < rect.Bottom) || (pdr.Left > rect.Left) || (pdr.Top > rect.Top)) { throw new ArgumentException("Specified rectangle overflows destination PixelMap"); } rect = pdr; } Init(rect.Height, rect.Width, null); int sy = rect.Bottom * subsample; int sxz = rect.Right * subsample; int sidx = src.RowOffset(sy); int didx = 0; PixelReference sptr = src.CreateGPixelReference(0); PixelReference dptr = CreateGPixelReference(0); for (int y = 0; y < ImageHeight; y++) { int sx = sxz; for (int x = ImageWidth; x-- > 0; dptr.IncOffset()) { int r = 0; int g = 0; int b = 0; int s = 0; int kidx = sidx; int lsy = sy + subsample; if (lsy > src.ImageHeight) { lsy = src.ImageHeight; } int lsx = sx + subsample; if (lsx > src.ImageWidth) { lsx = src.ImageWidth; } for (int rsy = sy; rsy < lsy; rsy++) { sptr.SetOffset(kidx + sx); if (!IsRampNeeded) { for (int rsx = lsx - sx; rsx-- > 0; sptr.IncOffset()) { r += sptr.Red; g += sptr.Green; b += sptr.Blue; s++; } } else { for (int rsx = lsx - sx; rsx-- > 0; sptr.IncOffset()) { Pixel pix = src.PixelRamp(sptr); r += pix.Red; g += pix.Green; b += pix.Blue; s++; } } kidx += src.GetRowSize(); } if (s >= _invmap.Length) { dptr.SetBGR(b / s, g / s, r / s); } else { dptr.SetBGR(((b * _invmap[s]) + 32768) >> 16, ((g * _invmap[s]) + 32768) >> 16, ((r * _invmap[s]) + 32768) >> 16); } sx += subsample; } sy += subsample; sidx += src.RowOffset(subsample); dptr.SetOffset(didx += GetRowSize()); } }
/// <summary> Fill this image from another source at reduced resolution of 4 vertical /// pixels to 3. An extrapulating pixel averaging algorithm is used. /// /// </summary> /// <param name="src">image map to reduce /// </param> /// <param name="pdr">target bounds /// /// </param> /// <throws> IllegalArgumentException if the target rectangle is out of bounds </throws> public virtual void Downsample43(Map src, Rectangle pdr) { int srcwidth = src.ImageWidth; int srcheight = src.ImageHeight; //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" int destwidth = (int)Math.Ceiling(srcwidth * 0.75D); //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" int destheight = (int)Math.Ceiling(srcheight * 0.75D); Rectangle rect = new Rectangle(0, 0, destwidth, destheight); if (pdr != null) { if ((pdr.Right < rect.Right) || (pdr.Bottom < rect.Bottom) || (pdr.Left > rect.Left) || (pdr.Top > rect.Top)) { throw new ArgumentException("rectangle out of bounds" + "pdr=(" + pdr.Right + "," + pdr.Bottom + "," + pdr.Left + "," + pdr.Top + "),rect=(" + rect.Right + "," + rect.Bottom + "," + rect.Left + "," + rect.Top + ")"); } rect = pdr; destwidth = rect.Width; destheight = rect.Height; } Init(destheight, destwidth, null); int sy = rect.Bottom / 3; int dy = rect.Bottom - (3 * sy); // if(dy < 0) // { // sy--; // dy += 3; // } int sxz = rect.Right / 3; int dxz = rect.Right - (3 * sxz); if (dxz < 0) { sxz--; dxz += 3; } sxz *= 4; sy *= 4; PixelReference spix0 = src.CreateGPixelReference(0); PixelReference spix1 = src.CreateGPixelReference(0); PixelReference spix2 = src.CreateGPixelReference(0); PixelReference spix3 = src.CreateGPixelReference(0); PixelReference dpix0 = CreateGPixelReference(0); PixelReference dpix1 = CreateGPixelReference(0); PixelReference dpix2 = CreateGPixelReference(0); while (dy < destheight) { spix0.SetOffset(sy++, sxz); if (sy >= srcheight) { sy--; } spix1.SetOffset(sy++, sxz); if (sy >= srcheight) { sy--; } spix2.SetOffset(sy++, sxz); if (sy >= srcheight) { sy--; } spix3.SetOffset(sy++, sxz); dpix0.SetOffset((dy < 0) ? 0 : dy, dxz); if (++dy >= destheight) { dy--; } dpix1.SetOffset((dy < 0) ? 0 : dy, dxz); if (++dy >= destheight) { dy--; } dpix2.SetOffset(dy++, dxz); int dx = dxz; int sx = sxz; Pixel pix0 = src.PixelRamp(spix0); Pixel pix1 = src.PixelRamp(spix1); Pixel pix2 = src.PixelRamp(spix2); Pixel pix3 = src.PixelRamp(spix3); while (dx < destwidth) { int s00b = pix0.Blue; int s00g = pix0.Green; int s00r = pix0.Red; int s01b = pix1.Blue; int s01g = pix1.Green; int s01r = pix1.Red; int s02b = pix2.Blue; int s02g = pix2.Green; int s02r = pix2.Red; int s03b = pix3.Blue; int s03g = pix3.Green; int s03r = pix3.Red; if (++sx < srcwidth) { spix0.IncOffset(); spix1.IncOffset(); spix2.IncOffset(); spix3.IncOffset(); pix0 = src.PixelRamp(spix0); pix1 = src.PixelRamp(spix1); pix2 = src.PixelRamp(spix2); pix3 = src.PixelRamp(spix3); } int s10b = pix0.Blue; int s10g = pix0.Green; int s10r = pix0.Red; int s11b = pix1.Blue; int s11g = pix1.Green; int s11r = pix1.Red; int s12b = pix2.Blue; int s12g = pix2.Green; int s12r = pix2.Red; int s13b = pix3.Blue; int s13g = pix3.Green; int s13r = pix3.Red; if (++sx < srcwidth) { spix0.IncOffset(); spix1.IncOffset(); spix2.IncOffset(); spix3.IncOffset(); pix0 = src.PixelRamp(spix0); pix1 = src.PixelRamp(spix1); pix2 = src.PixelRamp(spix2); pix3 = src.PixelRamp(spix3); } int s20b = pix0.Blue; int s20g = pix0.Green; int s20r = pix0.Red; int s21b = pix1.Blue; int s21g = pix1.Green; int s21r = pix1.Red; int s22b = pix2.Blue; int s22g = pix2.Green; int s22r = pix2.Red; int s23b = pix3.Blue; int s23g = pix3.Green; int s23r = pix3.Red; if (++sx < srcwidth) { spix0.IncOffset(); spix1.IncOffset(); spix2.IncOffset(); spix3.IncOffset(); pix0 = src.PixelRamp(spix0); pix1 = src.PixelRamp(spix1); pix2 = src.PixelRamp(spix2); pix3 = src.PixelRamp(spix3); } int s30b = pix0.Blue; int s30g = pix0.Green; int s30r = pix0.Red; int s31b = pix1.Blue; int s31g = pix1.Green; int s31r = pix1.Red; int s32b = pix2.Blue; int s32g = pix2.Green; int s32r = pix2.Red; int s33b = pix3.Blue; int s33g = pix3.Green; int s33r = pix3.Red; if (++sx < srcwidth) { spix0.IncOffset(); spix1.IncOffset(); spix2.IncOffset(); spix3.IncOffset(); pix0 = src.PixelRamp(spix0); pix1 = src.PixelRamp(spix1); pix2 = src.PixelRamp(spix2); pix3 = src.PixelRamp(spix3); } dpix0.Blue = (sbyte)(((11 * s00b) + (2 * (s01b + s10b)) + s11b + 8) >> 4); dpix0.Green = (sbyte)(((11 * s00g) + (2 * (s01g + s10g)) + s11g + 8) >> 4); dpix0.Red = (sbyte)(((11 * s00r) + (2 * (s01r + s10r)) + s11r + 8) >> 4); dpix1.Blue = (sbyte)(((7 * (s01b + s02b)) + s11b + s12b + 8) >> 4); dpix1.Green = (sbyte)(((7 * (s01g + s02g)) + s11g + s12g + 8) >> 4); dpix1.Red = (sbyte)(((7 * (s01r + s02r)) + s11r + s12r + 8) >> 4); dpix2.Blue = (sbyte)(((11 * s03b) + (2 * (s02b + s13b)) + s12b + 8) >> 4); dpix2.Green = (sbyte)(((11 * s03g) + (2 * (s02g + s13g)) + s12g + 8) >> 4); dpix2.Red = (sbyte)(((11 * s03r) + (2 * (s02r + s13r)) + s12r + 8) >> 4); if (++dx < destwidth) { dpix0.IncOffset(); dpix1.IncOffset(); dpix2.IncOffset(); } dpix0.Blue = (sbyte)(((7 * (s10b + s20b)) + s11b + s21b + 8) >> 4); dpix0.Green = (sbyte)(((7 * (s10g + s20g)) + s11g + s21g + 8) >> 4); dpix0.Red = (sbyte)(((7 * (s10r + s20r)) + s11r + s21r + 8) >> 4); dpix1.Blue = (sbyte)((s12b + s22b + s11b + s21b + 2) >> 2); dpix1.Green = (sbyte)((s12g + s22g + s11g + s21g + 2) >> 2); dpix1.Red = (sbyte)((s12r + s22r + s11r + s21r + 2) >> 2); dpix2.Blue = (sbyte)(((7 * (s13b + s23b)) + s12b + s22b + 8) >> 4); dpix2.Green = (sbyte)(((7 * (s13g + s23g)) + s12g + s22g + 8) >> 4); dpix2.Red = (sbyte)(((7 * (s13r + s23r)) + s12r + s22r + 8) >> 4); if (++dx < destwidth) { dpix0.IncOffset(); dpix1.IncOffset(); dpix2.IncOffset(); } dpix0.Blue = (sbyte)(((11 * s30b) + (2 * (s31b + s20b)) + s21b + 8) >> 4); dpix0.Green = (sbyte)(((11 * s30g) + (2 * (s31g + s20g)) + s21g + 8) >> 4); dpix0.Red = (sbyte)(((11 * s30r) + (2 * (s31r + s20r)) + s21r + 8) >> 4); dpix1.Blue = (sbyte)(((7 * (s31b + s32b)) + s21b + s22b + 8) >> 4); dpix1.Green = (sbyte)(((7 * (s31g + s32g)) + s21g + s22g + 8) >> 4); dpix1.Red = (sbyte)(((7 * (s31r + s32r)) + s21r + s22r + 8) >> 4); dpix2.Blue = (sbyte)(((11 * s33b) + (2 * (s32b + s23b)) + s22b + 8) >> 4); dpix2.Green = (sbyte)(((11 * s33g) + (2 * (s32g + s23g)) + s22g + 8) >> 4); dpix2.Red = (sbyte)(((11 * s33r) + (2 * (s32r + s23r)) + s22r + 8) >> 4); if (++dx < destwidth) { dpix0.IncOffset(); dpix1.IncOffset(); dpix2.IncOffset(); } } } }
/// <summary> Insert the specified bitmap with the specified color. /// /// </summary> /// <param name="bm">bitmap to insert /// </param> /// <param name="xpos">horizontal position /// </param> /// <param name="ypos">vertical position /// </param> /// <param name="color">color to insert bitmap with /// </param> public virtual void Blit(Bitmap bm, int xpos, int ypos, Pixel color) { // Check if (color == null) { return; } // Compute number of rows and columns int xrows = ypos + bm.ImageHeight; if (xrows > ImageHeight) { xrows = ImageHeight; } if (ypos > 0) { xrows -= ypos; } int xcolumns = xpos + bm.ImageWidth; if (xcolumns > ImageWidth) { xcolumns = ImageWidth; } if (xpos > 0) { xcolumns -= xpos; } if ((xrows <= 0) || (xcolumns <= 0)) { return; } // Precompute multiplier map int maxgray = bm.Grays - 1; int[] multiplier = new int[maxgray]; for (int i = 0; i < maxgray; i++) { multiplier[i] = 0x10000 - ((i << 16) / maxgray); } // Cache target color int gr = color.Red; int gg = color.Green; int gb = color.Blue; // Compute starting point int src = bm.RowOffset((ypos < 0) ? (-ypos) : 0) - ((xpos < 0) ? xpos : 0); int dst = ((ypos > 0) ? RowOffset(ypos) : 0) + ((xpos > 0) ? xpos : 0); PixelReference dstPixel = CreateGPixelReference(dst); // Loop over rows for (int y = 0; y < xrows; y++) { // Loop over columns dstPixel.SetOffset(dst); for (int x = 0; x < xcolumns; dstPixel.IncOffset()) { int srcpix = bm.GetByteAt(src + (x++)); // Perform pixel operation if (srcpix != 0) { if (srcpix >= maxgray) { dstPixel.SetBGR(gb, gg, gr); } else { int level0 = multiplier[srcpix]; int level1 = 0x10000 - level0; dstPixel.SetBGR(_clip[((dstPixel.Blue * level0) + (gb * level1)) >> 16], _clip[((dstPixel.Green * level0) + (gg * level1)) >> 16], _clip[((dstPixel.Red * level0) + (gr * level1)) >> 16]); } } } // Next line dst += GetRowSize(); src += bm.GetRowSize(); } }
internal static Graphics.Pixel InvertColor(Graphics.Pixel color) { return(new Graphics.Pixel((sbyte)(color.Blue ^ unchecked ((sbyte)0xff)), (sbyte)(color.Green ^ unchecked ((sbyte)0xff)), (sbyte)(color.Red ^ unchecked ((sbyte)0xff)))); }
public static unsafe Bitmap BuildImage(this DjvuImage image, int subsample = 1) { Verify.SubsampleRange(subsample); lock (image.LoadingLock) { Bitmap background = image.GetBackgroundImage(subsample, true); // TODO ETW logging goes here using (Bitmap foreground = image.GetForegroundImage(subsample, true)) { using (Bitmap mask = image.GetMaskImage(subsample, true)) { image.HasLoaded = true; BitmapData backgroundData = background.LockBits(new Rectangle(0, 0, background.Width, background.Height), ImageLockMode.ReadWrite, background.PixelFormat); int backgroundPixelSize = GetPixelSize(backgroundData.PixelFormat); BitmapData foregroundData = foreground.LockBits(new Rectangle(0, 0, foreground.Width, foreground.Height), ImageLockMode.ReadOnly, foreground.PixelFormat); int foregroundPixelSize = GetPixelSize(foregroundData.PixelFormat); BitmapData maskData = mask.LockBits(new 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 (image.IsInverted) { backgroundRow[xb] = InvertColor(xF); } else { backgroundRow[xb] = xF; } } else if (image.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> Overwrites #p# with the color located at position #index# in the /// palette. /// /// </summary> /// <param name="index">DOCUMENT ME! /// </param> /// <param name="p">DOCUMENT ME! /// </param> public void index_to_color(int index, DjvuNet.Graphics.Pixel p) { p.CopyFrom(PaletteColors[index]); }
public void Scale(Rectangle srcRect, IPixelMap srcMap, Rectangle targetRect, IPixelMap targetMap) { // Parameter validation if ((srcRect.Width != srcMap.Width) || (srcRect.Height != srcMap.Height)) { throw new DjvuArgumentException("Invalid rectangle", nameof(srcRect)); } // Compute rectangles Rectangle required_red = new Rectangle(); Rectangle sourceRect = CreateRectangles(targetRect, required_red); if ((srcRect.XMin > sourceRect.XMin) || (srcRect.YMin > sourceRect.YMin) || (srcRect.XMax < sourceRect.XMax) || (srcRect.YMax < sourceRect.YMax)) { throw new DjvuArgumentException("Invalid rectangle", nameof(srcRect)); } // Adjust output pixmap if ((targetRect.Width != (int)targetMap.Width) || (targetRect.Height != (int)targetMap.Height)) { targetMap.Init(targetRect.Height, targetRect.Width, null); } // Prepare temp stuff int bufw = required_red.Width; Pixel[] lbuffer = new Pixel[bufw + 2]; try { if ((_XShift > 0) || (_YShift > 0)) { _PixelMap1 = new PixelMap().Init(1, bufw, null); _PixelMap2 = new PixelMap().Init(2, bufw, null); _L1 = _L2 = -1; } IPixelReference upper = srcMap.CreateGPixelReference(0, 0); IPixelReference lower = srcMap.CreateGPixelReference(0, 0); IPixelReference dest = targetMap.CreateGPixelReference(0, 0); // Loop on output lines for (int y = targetRect.YMin; y < targetRect.YMax; y++) { // Perform vertical interpolation { int fy = _VCoord[y]; int fy1 = fy >> FRACBITS; int fy2 = fy1 + 1; // Obtain upper and lower line in reduced image if ((_XShift > 0) || (_YShift > 0)) { lower = GetLine(fy1, required_red, srcRect, srcMap); upper = GetLine(fy2, required_red, srcRect, srcMap); } else { int dx = required_red.XMin - srcRect.XMin; if (required_red.YMin > fy1) { fy1 = required_red.YMin; } if (required_red.YMax <= fy2) { fy2 = required_red.YMax - 1; } lower.SetOffset(fy1 - srcRect.YMin, dx); // srcMap.CreateGPixelReference(fy1 - srcRect.YMin, dx); upper.SetOffset(fy2 - srcRect.YMin, dx); // srcMap.CreateGPixelReference(fy2 - srcRect.YMin, dx); } // Compute line int idest = 1; short[] deltas = interp[fy & FRACMASK]; unsafe { for (int edest = idest + bufw; idest < edest; upper.IncOffset(), lower.IncOffset()) { Pixel destPix = lbuffer[idest++]; int color = 0; sbyte *colorPtr = (sbyte *)&color; // Skip alpha and set pointer to Blue colorPtr++; *colorPtr = lower.Blue; *colorPtr += (sbyte)deltas[(256 + upper.Blue) - *colorPtr]; // Set pointer to Green colorPtr++; *colorPtr = lower.Green; *colorPtr += (sbyte)deltas[(256 + upper.Green) - *colorPtr]; // Set pointer to Red colorPtr++; *colorPtr = lower.Red; *colorPtr += (sbyte)deltas[(256 + upper.Red) - *colorPtr]; //Pixel d = (Pixel) lower.ToPixel(); //destPix.SetBGR(d); destPix.SetBGR(*colorPtr); } } } // Perform horizontal interpolation { // Prepare for side effects lbuffer[0] = lbuffer[1]; // lbuffer[bufw] = lbuffer[bufw]; int line = 1 - required_red.XMin; dest.SetOffset(y - targetRect.YMin, 0); //= targetMap.CreateGPixelReference(y - targetRect.YMin, 0); // Loop horizontally unsafe { for (int x = targetRect.XMin; x < targetRect.XMax; x++) { int n = _HCoord[x]; int lowerl = line + (n >> FRACBITS); Pixel lower0 = lbuffer[lowerl]; Pixel lower1 = lbuffer[lowerl + 1]; short[] deltas = interp[n & FRACMASK]; int color = 0; sbyte *colorPtr = (sbyte *)&color; // Skip alpha and set pointer to Blue colorPtr++; *colorPtr = lower0.Blue; *colorPtr += (sbyte)deltas[(256 + lower1.Blue) - *colorPtr]; // Set pointer to Green colorPtr++; *colorPtr = lower0.Green; *colorPtr += (sbyte)deltas[(256 + lower1.Green) - *colorPtr]; // Set pointer to Red colorPtr++; *colorPtr = lower0.Red; *colorPtr += (sbyte)deltas[(256 + lower1.Red) - *colorPtr]; dest.SetBGR(*colorPtr); dest.IncOffset(); } } } } } finally { _PixelMap1 = null; _PixelMap2 = null; } }