public void Scale(Rectangle provided_input, PixelMap sourceMap, Rectangle targetRect, PixelMap output) { // Compute rectangles Rectangle required_red = new Rectangle(); Rectangle sourceRect = CreateRectangles(targetRect, required_red); // Parameter validation if ( (provided_input.Width != sourceMap.ImageWidth) || (provided_input.Height != sourceMap.ImageHeight)) { throw new Exception("invalid rectangle"); } if ( (provided_input.XMin > sourceRect.XMin) || (provided_input.YMin > sourceRect.YMin) || (provided_input.XMax < sourceRect.XMax) || (provided_input.YMax < sourceRect.YMax)) { throw new Exception("invalid rectangle"); } // Adjust output pixmap if ( (targetRect.Width != (int)output.ImageWidth) || (targetRect.Height != (int)output.ImageHeight)) { output.Init( targetRect.Height, targetRect.Width, null); } // Prepare temp stuff int bufw = required_red.Width; Pixel[] lbuffer = new Pixel[bufw + 2]; for (int i = 0; i < lbuffer.Length;) { lbuffer[i++] = new Pixel(); } try { if ((xshift > 0) || (yshift > 0)) { p1 = new PixelMap().Init(1, bufw, null); p2 = new PixelMap().Init(2, bufw, null); l1 = l2 = -1; } // 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; PixelReference upper; PixelReference lower; // Obtain upper and lower line in reduced image if ((xshift > 0) || (yshift > 0)) { lower = GetLine(fy1, required_red, provided_input, sourceMap); upper = GetLine(fy2, required_red, provided_input, sourceMap); } else { int dx = required_red.XMin - provided_input.XMin; if (required_red.YMin > fy1) { fy1 = required_red.YMin; } if (required_red.YMax <= fy2) { fy2 = required_red.YMax - 1; } lower = sourceMap.CreateGPixelReference(fy1 - provided_input.YMin, dx); upper = sourceMap.CreateGPixelReference(fy2 - provided_input.YMin, dx); } // Compute line int idest = 1; short[] deltas = interp[fy & FRACMASK]; for ( int edest = idest + bufw; idest < edest; upper.IncOffset(), lower.IncOffset()) { Pixel dest = lbuffer[idest++]; int lower_r = lower.Red; int delta_r = deltas[(256 + upper.Red) - lower_r]; int lower_g = lower.Green; int delta_g = deltas[(256 + upper.Green) - lower_g]; int lower_b = lower.Blue; int delta_b = deltas[(256 + upper.Blue) - lower_b]; dest.SetBGR(lower_b + delta_b, lower_g + delta_g, lower_r + delta_r); } } // Perform horizontal interpolation { // Prepare for side effects lbuffer[0] = lbuffer[1]; // lbuffer[bufw] = lbuffer[bufw]; int line = 1 - required_red.XMin; PixelReference dest = output.CreateGPixelReference(y - targetRect.YMin, 0); // Loop horizontally for (int x = targetRect.XMin; x < targetRect.XMax; x++) { int n = hcoord[x]; int lower = line + (n >> FRACBITS); Pixel lower0 = lbuffer[lower]; Pixel lower1 = lbuffer[lower + 1]; short[] deltas = interp[n & FRACMASK]; int lower_r = lower0.Red; int delta_r = deltas[(256 + lower1.Red) - lower_r]; int lower_g = lower0.Green; int delta_g = deltas[(256 + lower1.Green) - lower_g]; int lower_b = lower0.Blue; int delta_b = deltas[(256 + lower1.Blue) - lower_b]; dest.SetBGR(lower_b + delta_b, lower_g + delta_g, lower_r + delta_r); dest.IncOffset(); } } } } finally { p1 = null; p2 = null; } }
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; } }