/// <summary> /// fill to left side and right side of the line /// </summary> /// <param name="destBuffer"></param> /// <param name="x"></param> /// <param name="y"></param> unsafe void LinearFill(int *destBuffer, int x, int y) { int leftFillX = x; int bufferOffset = _destImgRW.GetBufferOffsetXY32(x, y); int pixelOffset = (imageWidth * y) + x; while (true) { fillRule.SetPixel(destBuffer + bufferOffset); pixelsChecked[pixelOffset] = true; leftFillX--; pixelOffset--; bufferOffset--; if (leftFillX <= 0 || (pixelsChecked[pixelOffset]) || !fillRule.CheckPixel(*(destBuffer + bufferOffset))) { break; } } leftFillX++; // int rightFillX = x; bufferOffset = _destImgRW.GetBufferOffsetXY32(x, y); pixelOffset = (imageWidth * y) + x; while (true) { fillRule.SetPixel(destBuffer + bufferOffset); pixelsChecked[pixelOffset] = true; rightFillX++; pixelOffset++; bufferOffset++; if (rightFillX >= imageWidth || pixelsChecked[pixelOffset] || !fillRule.CheckPixel(*(destBuffer + bufferOffset))) { break; } } rightFillX--; ranges.Enqueue(new Range(leftFillX, rightFillX, y)); }
void Attach(IBitmapSrc sourceImage, PixelBlender32 outputPxBlender, int distanceBetweenPixelsInclusive, int arrayElemOffset, int bitsPerPixel) { _sourceImage = sourceImage; SetDimmensionAndFormat(sourceImage.Width, sourceImage.Height, sourceImage.Stride, bitsPerPixel, distanceBetweenPixelsInclusive); int srcOffset32 = sourceImage.GetBufferOffsetXY32(0, 0); SetBuffer(sourceImage.GetBufferPtr(), srcOffset32 + arrayElemOffset); this.OutputPixelBlender = outputPxBlender; }
public void Fill(IBitmapSrc bufferToFillOn, int x, int y) { y -= imageHeight; unchecked // this way we can overflow the uint on negative and get a big number { if ((uint)x >= bufferToFillOn.Width || (uint)y >= bufferToFillOn.Height) { return; } } _destImgRW = bufferToFillOn; TempMemPtr destBufferPtr = bufferToFillOn.GetBufferPtr(); unsafe { imageWidth = bufferToFillOn.Width; imageHeight = bufferToFillOn.Height; //reset new buffer, clear mem? pixelsChecked = new bool[imageWidth * imageHeight]; int *destBuffer = (int *)destBufferPtr.Ptr; int startColorBufferOffset = bufferToFillOn.GetBufferOffsetXY32(x, y); int start_color = *(destBuffer + startColorBufferOffset); fillRule.SetStartColor(Drawing.Color.FromArgb( (start_color >> 16) & 0xff, (start_color >> 8) & 0xff, (start_color) & 0xff)); LinearFill(destBuffer, x, y); while (ranges.Count > 0) { Range range = ranges.Dequeue(); int downY = range.y - 1; int upY = range.y + 1; int downPixelOffset = (imageWidth * (range.y - 1)) + range.startX; int upPixelOffset = (imageWidth * (range.y + 1)) + range.startX; for (int rangeX = range.startX; rangeX <= range.endX; rangeX++) { if (range.y > 0) { if (!pixelsChecked[downPixelOffset]) { int bufferOffset = bufferToFillOn.GetBufferOffsetXY32(rangeX, downY); if (fillRule.CheckPixel(*(destBuffer + bufferOffset))) { LinearFill(destBuffer, rangeX, downY); } } } if (range.y < (imageHeight - 1)) { if (!pixelsChecked[upPixelOffset]) { int bufferOffset = bufferToFillOn.GetBufferOffsetXY32(rangeX, upY); if (fillRule.CheckPixel(*(destBuffer + bufferOffset))) { LinearFill(destBuffer, rangeX, upY); } } } upPixelOffset++; downPixelOffset++; } } } destBufferPtr.Release(); }
public sealed override void GenerateColors(Drawing.Color[] outputColors, int startIndex, int x, int y, int len) { ISpanInterpolator spanInterpolator = Interpolator; spanInterpolator.Begin(x + dx, y + dy, len); int x_hr; int y_hr; spanInterpolator.GetCoord(out x_hr, out y_hr); int x_lr = x_hr >> img_subpix_const.SHIFT; int y_lr = y_hr >> img_subpix_const.SHIFT; int bufferIndex = _bmpSrc.GetBufferOffsetXY32(x_lr, y_lr); unsafe { using (CpuBlit.Imaging.TempMemPtr srcBufferPtr = _bmpSrc.GetBufferPtr()) { int *pSource = (int *)srcBufferPtr.Ptr + bufferIndex; do { int src_value = *pSource; //separate each component //TODO: review here, color from source buffer //should be in 'pre-multiplied' format. //so it should be converted to 'straight' color by call something like ..'FromPreMult()' outputColors[startIndex++] = Drawing.Color.FromArgb( (byte)((src_value >> 24) & 0xff), //a (byte)((src_value >> 16) & 0xff), //r (byte)((src_value >> 8) & 0xff), //g (byte)((src_value) & 0xff)); //b pSource++; //move next } while (--len != 0); } } //version 1 , incorrect //ISpanInterpolator spanInterpolator = Interpolator; //spanInterpolator.Begin(x + dx, y + dy, len); //int x_hr; //int y_hr; //spanInterpolator.GetCoord(out x_hr, out y_hr); //int x_lr = x_hr >> img_subpix_const.SHIFT; //int y_lr = y_hr >> img_subpix_const.SHIFT; //int bufferIndex = srcRW.GetBufferOffsetXY(x_lr, y_lr); //byte[] srcBuffer = srcRW.GetBuffer(); //unsafe //{ // fixed (byte* pSource = srcBuffer) // { // do // { // outputColors[startIndex++] = *(Drawing.Color*)&(pSource[bufferIndex]); // bufferIndex += 4; // } while (--len != 0); // } //} }
public sealed override void GenerateColors(Drawing.Color[] outputColors, int startIndex, int x, int y, int len) { #if DEBUG int tmp_len = len; #endif unsafe { //TODO: review here if (_mode0) { using (CpuBlit.Imaging.TempMemPtr.FromBmp(_imgsrc, out int *srcBuffer)) { int bufferIndex = _imgsrc.GetBufferOffsetXY32(x, y); //unsafe { #if true do { //TODO: review here, match component? //ORDER IS IMPORTANT! //TODO : use CO (color order instead) int color = srcBuffer[bufferIndex++]; //byte b = (byte)srcBuffer[bufferIndex++]; //byte g = (byte)srcBuffer[bufferIndex++]; //byte r = (byte)srcBuffer[bufferIndex++]; //byte a = (byte)srcBuffer[bufferIndex++]; //outputColors[startIndex] = Drawing.Color.FromArgb(a, r, g, b); outputColors[startIndex] = Drawing.Color.FromArgb( (color >> 24) & 0xff, //a (color >> 16) & 0xff, //r (color >> 8) & 0xff, //b (color) & 0xff //b ); ++startIndex; } while (--len != 0); #else fixed(byte *pSource = &fg_ptr[bufferIndex]) { int *pSourceInt = (int *)pSource; fixed(RGBA_Bytes *pDest = &span[spanIndex]) { int *pDestInt = (int *)pDest; do { *pDestInt++ = *pSourceInt++; } while (--len != 0); } } #endif } } } else { ISpanInterpolator spanInterpolator = base.Interpolator; using (CpuBlit.Imaging.TempMemPtr srcBufferPtr = _imgsrc.GetBufferPtr()) { int *srcBuffer = (int *)srcBufferPtr.Ptr; spanInterpolator.Begin(x + base.dx, y + base.dy, len); int accColor0, accColor1, accColor2, accColor3; int back_r = m_bgcolor.red; int back_g = m_bgcolor.green; int back_b = m_bgcolor.blue; int back_a = m_bgcolor.alpha; int maxx = _imgsrc.Width - 1; int maxy = _imgsrc.Height - 1; int color = 0; unchecked { do { int x_hr; int y_hr; spanInterpolator.GetCoord(out x_hr, out y_hr); x_hr -= base.dxInt; y_hr -= base.dyInt; int x_lr = x_hr >> img_subpix_const.SHIFT; int y_lr = y_hr >> img_subpix_const.SHIFT; int weight; if (x_lr >= 0 && y_lr >= 0 && x_lr < maxx && y_lr < maxy) { int bufferIndex = _imgsrc.GetBufferOffsetXY32(x_lr, y_lr); accColor0 = accColor1 = accColor2 = accColor3 = (int)img_subpix_const.SCALE * (int)img_subpix_const.SCALE / 2; x_hr &= img_subpix_const.MASK; y_hr &= img_subpix_const.MASK; //bufferIndex = _imgsrc.GetBufferOffsetXY32(x_lr, y_lr); weight = ((img_subpix_const.SCALE - x_hr) * (img_subpix_const.SCALE - y_hr)); if (weight > BASE_MASK) { color = srcBuffer[bufferIndex]; accColor3 += weight * ((color >> 24) & 0xff); //a accColor0 += weight * ((color >> 16) & 0xff); //r accColor1 += weight * ((color >> 8) & 0xff); //g accColor2 += weight * ((color) & 0xff); //b } weight = (x_hr * ((int)img_subpix_const.SCALE - y_hr)); if (weight > BASE_MASK) { bufferIndex++; color = srcBuffer[bufferIndex]; // accColor3 += weight * ((color >> 24) & 0xff); //a accColor0 += weight * ((color >> 16) & 0xff); //r accColor1 += weight * ((color >> 8) & 0xff); //g accColor2 += weight * ((color) & 0xff); //b } weight = (((int)img_subpix_const.SCALE - x_hr) * y_hr); if (weight > BASE_MASK) { ++y_lr; // bufferIndex = _imgsrc.GetBufferOffsetXY32(x_lr, y_lr); color = srcBuffer[bufferIndex]; // accColor3 += weight * ((color >> 24) & 0xff); //a accColor0 += weight * ((color >> 16) & 0xff); //r accColor1 += weight * ((color >> 8) & 0xff); //g accColor2 += weight * ((color) & 0xff); //b } weight = (x_hr * y_hr); if (weight > BASE_MASK) { bufferIndex++; color = srcBuffer[bufferIndex]; // accColor3 += weight * ((color >> 24) & 0xff); //a accColor0 += weight * ((color >> 16) & 0xff); //r accColor1 += weight * ((color >> 8) & 0xff); //g accColor2 += weight * ((color) & 0xff); //b } accColor0 >>= img_subpix_const.SHIFT * 2; accColor1 >>= img_subpix_const.SHIFT * 2; accColor2 >>= img_subpix_const.SHIFT * 2; accColor3 >>= img_subpix_const.SHIFT * 2; } else { if (x_lr < -1 || y_lr < -1 || x_lr > maxx || y_lr > maxy) { accColor0 = back_r; accColor1 = back_g; accColor2 = back_b; accColor3 = back_a; } else { accColor0 = accColor1 = accColor2 = accColor3 = (int)img_subpix_const.SCALE * (int)img_subpix_const.SCALE / 2; x_hr &= (int)img_subpix_const.MASK; y_hr &= (int)img_subpix_const.MASK; weight = (((int)img_subpix_const.SCALE - x_hr) * ((int)img_subpix_const.SCALE - y_hr)); if (weight > BASE_MASK) { if ((uint)x_lr <= (uint)maxx && (uint)y_lr <= (uint)maxy) { BlendInFilterPixel( ref accColor0, ref accColor1, ref accColor2, ref accColor3, srcBuffer, _imgsrc.GetBufferOffsetXY32(x_lr, y_lr), weight); } else { accColor0 += back_r * weight; accColor1 += back_g * weight; accColor2 += back_b * weight; accColor3 += back_a * weight; } } x_lr++; weight = (x_hr * ((int)img_subpix_const.SCALE - y_hr)); if (weight > BASE_MASK) { if ((uint)x_lr <= (uint)maxx && (uint)y_lr <= (uint)maxy) { BlendInFilterPixel(ref accColor0, ref accColor1, ref accColor2, ref accColor3, srcBuffer, _imgsrc.GetBufferOffsetXY32(x_lr, y_lr), weight); } else { accColor0 += back_r * weight; accColor1 += back_g * weight; accColor2 += back_b * weight; accColor3 += back_a * weight; } } x_lr--; y_lr++; weight = (((int)img_subpix_const.SCALE - x_hr) * y_hr); if (weight > BASE_MASK) { if ((uint)x_lr <= (uint)maxx && (uint)y_lr <= (uint)maxy) { BlendInFilterPixel(ref accColor0, ref accColor1, ref accColor2, ref accColor3, srcBuffer, _imgsrc.GetBufferOffsetXY32(x_lr, y_lr), weight); } else { accColor0 += back_r * weight; accColor1 += back_g * weight; accColor2 += back_b * weight; accColor3 += back_a * weight; } } x_lr++; weight = (x_hr * y_hr); if (weight > BASE_MASK) { if ((uint)x_lr <= (uint)maxx && (uint)y_lr <= (uint)maxy) { BlendInFilterPixel(ref accColor0, ref accColor1, ref accColor2, ref accColor3, srcBuffer, _imgsrc.GetBufferOffsetXY32(x_lr, y_lr), weight); } else { accColor0 += back_r * weight; accColor1 += back_g * weight; accColor2 += back_b * weight; accColor3 += back_a * weight; } } accColor0 >>= img_subpix_const.SHIFT * 2; accColor1 >>= img_subpix_const.SHIFT * 2; accColor2 >>= img_subpix_const.SHIFT * 2; accColor3 >>= img_subpix_const.SHIFT * 2; } } #if DEBUG if (startIndex >= outputColors.Length) { } #endif outputColors[startIndex] = PixelFarm.Drawing.Color.FromArgb( (byte)accColor3, (byte)accColor0, (byte)accColor1, (byte)accColor2 ); //outputColors[startIndex].red = (byte)accColor0; //outputColors[startIndex].green = (byte)accColor1; //outputColors[startIndex].blue = (byte)accColor2; //outputColors[startIndex].alpha = (byte)accColor3; ++startIndex; spanInterpolator.Next(); } while (--len != 0); } } } } }
/// <summary> /// create thumbnail img with super-sampling technique,(Expensive, High quality thumb) /// </summary> /// <param name="source"></param> /// <param name="dst"></param> public static MemBitmap CreateThumbnailWithSuperSamplingTechnique(this MemBitmap source, float scaleRatio) { // Paint.NET (MIT,from version 3.36.7, see=> https://github.com/rivy/OpenPDN //in this version new image MUST smaller than the original one *** if (scaleRatio >= 1 || scaleRatio < 0) { return(null); } //create new bitmap int newBmpW = (int)Math.Round(source.Width * scaleRatio); int newBmpH = (int)Math.Round(source.Height * scaleRatio); MemBitmap thumbBitmap = new MemBitmap(newBmpW, newBmpH); //*** IBitmapSrc source_1 = (IBitmapSrc)source; unsafe { Rectangle dstRoi2 = new Rectangle(0, 0, newBmpW, newBmpH); int dstWidth = dstRoi2.Width; int dstHeight = dstRoi2.Height; int srcH = source.Height; int srcW = source.Width; Imaging.TempMemPtr dstMemPtr = MemBitmap.GetBufferPtr(thumbBitmap); int dstStrideInt32 = newBmpW; for (int dstY = dstRoi2.Top; dstY < dstRoi2.Bottom; ++dstY) { //from dst => find proper source (y) //double srcTop = (double)(dstY * srcH) / (double)dstHeight; double srcTop = (double)(dstY * srcH) / (double)dstHeight; double srcTopFloor = Math.Floor(srcTop); double srcTopWeight = 1 - (srcTop - srcTopFloor); int srcTopInt = (int)srcTopFloor; //double srcBottom = (double)((dstY + 1) * srcH) / (double)dstHeight; double srcBottom = (double)((dstY + 1) * srcH) / (double)dstHeight; double srcBottomFloor = Math.Floor(srcBottom - 0.00001); double srcBottomWeight = srcBottom - srcBottomFloor; int srcBottomInt = (int)srcBottomFloor; int *srcBuffer = (int *)(MemBitmap.GetBufferPtr(source)).Ptr; int srcStrideInt32 = source.Width; //*** int *dstAddr = (int *)dstMemPtr.Ptr + (dstStrideInt32 * dstY); //begin at for (int dstX = dstRoi2.Left; dstX < dstRoi2.Right; ++dstX) { //from dst=> find proper source (x) double srcLeft = (double)(dstX * srcW) / (double)dstWidth; double srcLeftFloor = Math.Floor(srcLeft); double srcLeftWeight = 1 - (srcLeft - srcLeftFloor); int srcLeftInt = (int)srcLeftFloor; double srcRight = (double)((dstX + 1) * srcW) / (double)dstWidth; double srcRightFloor = Math.Floor(srcRight - 0.00001); double srcRightWeight = srcRight - srcRightFloor; int srcRightInt = (int)srcRightFloor; double blueSum = 0; double greenSum = 0; double redSum = 0; double alphaSum = 0; //now we know (left,top) of source that we want //then ask the pixel value from source at that pos //(1) left fractional edge { //PaintFx.ColorBgra* srcLeftPtr = source.GetPointAddressUnchecked(srcLeftInt, srcTopInt + 1); int *srcLeftColorAddr = srcBuffer + source_1.GetBufferOffsetXY32(srcLeftInt, srcTopInt + 1); for (int srcY = srcTopInt + 1; srcY < srcBottomInt; ++srcY) { int srcColor = *srcLeftColorAddr; double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * srcLeftWeight; blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; //move to next row srcLeftColorAddr += srcStrideInt32; //srcLeftPtr = (ColorBgra*)((byte*)srcLeftPtr + source._stride); } } // { //(2) right fractional edge //ColorBgra* srcRightPtr = source.GetPointAddressUnchecked(srcRightInt, srcTopInt + 1); int *srcRightColorAddr = srcBuffer + source_1.GetBufferOffsetXY32(srcRightInt, srcTopInt + 1); for (int srcY = srcTopInt + 1; srcY < srcBottomInt; ++srcY) { int srcColor = *srcRightColorAddr; double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * srcRightWeight; blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; //srcRightPtr = (ColorBgra*)((byte*)srcRightPtr + source._stride); srcRightColorAddr += srcStrideInt32; //move to next row } } // { //(3) top fractional edge //ColorBgra* srcTopPtr = source.GetPointAddressUnchecked(srcLeftInt + 1, srcTopInt); int *srcTopColorAddr = srcBuffer + source_1.GetBufferOffsetXY32(srcLeftInt + 1, srcTopInt); for (int srcX = srcLeftInt + 1; srcX < srcRightInt; ++srcX) { int srcColor = *srcTopColorAddr; double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * srcTopWeight; blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; //move to next column //++srcTopPtr; ++srcTopColorAddr; } } // { //(4) bottom fractional edge //ColorBgra* srcBottomPtr = source.GetPointAddressUnchecked(srcLeftInt + 1, srcBottomInt); int *srcBottomColorAddr = srcBuffer + source_1.GetBufferOffsetXY32(srcLeftInt + 1, srcBottomInt); for (int srcX = srcLeftInt + 1; srcX < srcRightInt; ++srcX) { int srcColor = *srcBottomColorAddr; double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * srcBottomWeight; blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; //++srcBottomPtr; //move to next column //++srcTopPtr; ++srcBottomColorAddr; } } { //(5) center area for (int srcY = srcTopInt + 1; srcY < srcBottomInt; ++srcY) { //ColorBgra* srcPtr = source.GetPointAddressUnchecked(srcLeftInt + 1, srcY); int *srcColorAddr = srcBuffer + source_1.GetBufferOffsetXY32(srcLeftInt + 1, srcY); for (int srcX = srcLeftInt + 1; srcX < srcRightInt; ++srcX) { int srcColor = *srcColorAddr; int a = ((srcColor >> CO.A_SHIFT) & 0xff); blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a; alphaSum += a; ++srcColorAddr; } } } //(6) four corner pixels { //6.1 //ColorBgra srcTL = source.GetPoint(srcLeftInt, srcTopInt); int srcColor = *(srcBuffer + source_1.GetBufferOffsetXY32(srcLeftInt, srcTopInt)); double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * (srcTopWeight * srcLeftWeight); blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; } { //6.2 //ColorBgra srcTR = source.GetPoint(srcRightInt, srcTopInt); //double srcTRA = srcTR.A; //blueSum += srcTR.B * (srcTopWeight * srcRightWeight) * srcTRA; //greenSum += srcTR.G * (srcTopWeight * srcRightWeight) * srcTRA; //redSum += srcTR.R * (srcTopWeight * srcRightWeight) * srcTRA; //alphaSum += srcTR.A * (srcTopWeight * srcRightWeight); int srcColor = *(srcBuffer + source_1.GetBufferOffsetXY32(srcRightInt, srcTopInt)); double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * (srcTopWeight * srcRightWeight); blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; } { //(6.3) int srcColor = *(srcBuffer + source_1.GetBufferOffsetXY32(srcLeftInt, srcBottomInt)); double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * (srcBottomWeight * srcLeftWeight); blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; //without a //ColorBgra srcBL = source.GetPoint(srcLeftInt, srcBottomInt); //double srcBLA = srcBL.A; //blueSum += srcBL.B * (srcBottomWeight * srcLeftWeight) * srcBLA; //greenSum += srcBL.G * (srcBottomWeight * srcLeftWeight) * srcBLA; //redSum += srcBL.R * (srcBottomWeight * srcLeftWeight) * srcBLA; //alphaSum += srcBL.A * (srcBottomWeight * srcLeftWeight); } { //(6.4) //ColorBgra srcBR = source.GetPoint(srcRightInt, srcBottomInt); //double srcBRA = srcBR.A; //blueSum += srcBR.B * (srcBottomWeight * srcRightWeight) * srcBRA; //greenSum += srcBR.G * (srcBottomWeight * srcRightWeight) * srcBRA; //redSum += srcBR.R * (srcBottomWeight * srcRightWeight) * srcBRA; //alphaSum += srcBR.A * (srcBottomWeight * srcRightWeight); int srcColor = *(srcBuffer + source_1.GetBufferOffsetXY32(srcRightInt, srcBottomInt)); double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * (srcBottomWeight * srcRightWeight); blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; } double area = (srcRight - srcLeft) * (srcBottom - srcTop); double alpha = alphaSum / area; double blue; double green; double red; if (alpha == 0) { blue = 0; green = 0; red = 0; } else { blue = blueSum / alphaSum; green = greenSum / alphaSum; red = redSum / alphaSum; } // add 0.5 so that rounding goes in the direction we want it to blue += 0.5; green += 0.5; red += 0.5; alpha += 0.5; //*** //dstPtr->Bgra = (uint)blue + ((uint)green << 8) + ((uint)red << 16) + ((uint)alpha << 24); //++dstPtr; *dstAddr = ((byte)alpha) << CO.A_SHIFT | ((byte)blue) << CO.B_SHIFT | ((byte)green) << CO.G_SHIFT | ((byte)red) << CO.R_SHIFT; //(uint)blue + ((uint)green << 8) + ((uint)red << 16) + ((uint)alpha << 24); ++dstAddr; } } } return(thumbBitmap); }
// Create //-------------------------------------------------------------------- public void Create(IBitmapSrc src) { // we are going to create a dialated image for filtering // we add m_dilation pixels to every side of the image and then copy the image in the x // dirrection into each end so that we can sample into this image to get filtering on x repeating // if the original image look like this // // 123456 // // the new image would look like this // // 0000000000 // 0000000000 // 5612345612 // 0000000000 // 0000000000 _height = (int)AggMath.uceil(src.Height); _width = (int)AggMath.uceil(src.Width); _width_hr = (int)AggMath.uround(src.Width * LineAA.SUBPIXEL_SCALE); _half_height_hr = (int)AggMath.uround(src.Height * LineAA.SUBPIXEL_SCALE / 2); _offset_y_hr = _dilation_hr + _half_height_hr - LineAA.SUBPIXEL_SCALE / 2; _half_height_hr += LineAA.SUBPIXEL_SCALE / 2; int bufferWidth = _width + _dilation * 2; int bufferHeight = _height + _dilation * 2; int bytesPerPixel = src.BitDepth / 8; int newSizeInBytes = bufferWidth * bufferHeight * bytesPerPixel; if (_DataSizeInBytes < newSizeInBytes) { _DataSizeInBytes = newSizeInBytes; _data.Dispose(); IntPtr nativeBuff = System.Runtime.InteropServices.Marshal.AllocHGlobal(_DataSizeInBytes); _data = new TempMemPtr(nativeBuff, _DataSizeInBytes); } _buf = new PixelProcessing.SubBitmapBlender(_data, 0, bufferWidth, bufferHeight, bufferWidth * bytesPerPixel, src.BitDepth, bytesPerPixel); unsafe { using (TempMemPtr destMemPtr = _buf.GetBufferPtr()) using (TempMemPtr srcMemPtr = src.GetBufferPtr()) { int *destBuffer = (int *)destMemPtr.Ptr; int *srcBuffer = (int *)srcMemPtr.Ptr; // copy the image into the middle of the dest for (int y = 0; y < _height; y++) { for (int x = 0; x < _width; x++) { int sourceOffset = src.GetBufferOffsetXY32(x, y); int destOffset = _buf.GetBufferOffsetXY32(_dilation, y + _dilation); destBuffer[destOffset] = srcBuffer[sourceOffset]; } } // copy the first two pixels form the end into the begining and from the begining into the end for (int y = 0; y < _height; y++) { int s1Offset = src.GetBufferOffsetXY32(0, y); int d1Offset = _buf.GetBufferOffsetXY32(_dilation + _width, y); int s2Offset = src.GetBufferOffsetXY32(_width - _dilation, y); int d2Offset = _buf.GetBufferOffsetXY32(0, y); for (int x = 0; x < _dilation; x++) { destBuffer[d1Offset++] = srcBuffer[s1Offset++]; destBuffer[d2Offset++] = srcBuffer[s2Offset++]; } } } } }
// Create //-------------------------------------------------------------------- public void Create(IBitmapSrc src) { // we are going to create a dialated image for filtering // we add m_dilation pixels to every side of the image and then copy the image in the x // dirrection into each end so that we can sample into this image to get filtering on x repeating // if the original image look like this // // 123456 // // the new image would look like this // // 0000000000 // 0000000000 // 5612345612 // 0000000000 // 0000000000 m_height = (int)AggMath.uceil(src.Height); m_width = (int)AggMath.uceil(src.Width); m_width_hr = (int)AggMath.uround(src.Width * LineAA.SUBPIXEL_SCALE); m_half_height_hr = (int)AggMath.uround(src.Height * LineAA.SUBPIXEL_SCALE / 2); m_offset_y_hr = m_dilation_hr + m_half_height_hr - LineAA.SUBPIXEL_SCALE / 2; m_half_height_hr += LineAA.SUBPIXEL_SCALE / 2; int bufferWidth = m_width + m_dilation * 2; int bufferHeight = m_height + m_dilation * 2; int bytesPerPixel = src.BitDepth / 8; int newSizeInBytes = bufferWidth * bufferHeight * bytesPerPixel; if (m_DataSizeInBytes < newSizeInBytes) { m_DataSizeInBytes = newSizeInBytes; m_data = new int[m_DataSizeInBytes / 4]; } m_buf = new PixelProcessing.SubBitmapBlender(m_data, 0, bufferWidth, bufferHeight, bufferWidth * bytesPerPixel, src.BitDepth, bytesPerPixel); unsafe { CpuBlit.Imaging.TempMemPtr destMemPtr = m_buf.GetBufferPtr(); CpuBlit.Imaging.TempMemPtr srcMemPtr = src.GetBufferPtr(); int *destBuffer = (int *)destMemPtr.Ptr; int *srcBuffer = (int *)srcMemPtr.Ptr; // copy the image into the middle of the dest for (int y = 0; y < m_height; y++) { for (int x = 0; x < m_width; x++) { int sourceOffset = src.GetBufferOffsetXY32(x, y); int destOffset = m_buf.GetBufferOffsetXY32(m_dilation, y + m_dilation); destBuffer[destOffset] = srcBuffer[sourceOffset]; } } // copy the first two pixels form the end into the begining and from the begining into the end for (int y = 0; y < m_height; y++) { int s1Offset = src.GetBufferOffsetXY32(0, y); int d1Offset = m_buf.GetBufferOffsetXY32(m_dilation + m_width, y); int s2Offset = src.GetBufferOffsetXY32(m_width - m_dilation, y); int d2Offset = m_buf.GetBufferOffsetXY32(0, y); for (int x = 0; x < m_dilation; x++) { destBuffer[d1Offset++] = srcBuffer[s1Offset++]; destBuffer[d2Offset++] = srcBuffer[s2Offset++]; } } srcMemPtr.Release(); destMemPtr.Release(); } }
void CopyFromNoClipping(IBitmapSrc sourceImage, Q1Rect clippedSourceImageRect, int destXOffset, int destYOffset) { if (BytesBetweenPixelsInclusive != BitDepth / 8 || sourceImage.BytesBetweenPixelsInclusive != sourceImage.BitDepth / 8) { throw new Exception("WIP we only support packed pixel formats at this time."); } if (BitDepth == sourceImage.BitDepth) { int lengthInBytes = clippedSourceImageRect.Width * BytesBetweenPixelsInclusive; int sourceOffset = sourceImage.GetBufferOffsetXY32(clippedSourceImageRect.Left, clippedSourceImageRect.Bottom); unsafe { using (TempMemPtr memPtr = sourceImage.GetBufferPtr()) using (TempMemPtr destPtr = this.GetBufferPtr()) { byte *sourceBuffer = (byte *)memPtr.Ptr; byte *destBuffer = (byte *)destPtr.Ptr; int destOffset = GetBufferOffsetXY32(clippedSourceImageRect.Left + destXOffset, clippedSourceImageRect.Bottom + destYOffset); for (int i = 0; i < clippedSourceImageRect.Height; i++) { PixelFarm.Drawing.Internal.MemMx.memmove(destBuffer, destOffset * 4, sourceBuffer, sourceOffset, lengthInBytes); sourceOffset += sourceImage.Stride; destOffset += Stride; } } } } else { bool haveConversion = true; switch (sourceImage.BitDepth) { case 24: switch (BitDepth) { case 32: { //TODO: review here, this may not correct int numPixelsToCopy = clippedSourceImageRect.Width; for (int i = clippedSourceImageRect.Bottom; i < clippedSourceImageRect.Top; i++) { int sourceOffset = sourceImage.GetBufferOffsetXY32(clippedSourceImageRect.Left, clippedSourceImageRect.Bottom + i); //byte[] sourceBuffer = sourceImage.GetBuffer(); //byte[] destBuffer = GetBuffer(); using (TempMemPtr srcMemPtr = sourceImage.GetBufferPtr()) using (TempMemPtr destBufferPtr = this.GetBufferPtr()) { int destOffset = GetBufferOffsetXY32( clippedSourceImageRect.Left + destXOffset, clippedSourceImageRect.Bottom + i + destYOffset); unsafe { int *destBuffer = (int *)destBufferPtr.Ptr; int *sourceBuffer = (int *)srcMemPtr.Ptr; for (int x = 0; x < numPixelsToCopy; x++) { int color = sourceBuffer[sourceOffset++]; destBuffer[destOffset++] = (255 << 24) | //a (color & 0xff0000) | //b (color & 0x00ff00) | //g (color & 0xff); //destBuffer[destOffset++] = sourceBuffer[sourceOffset++]; //destBuffer[destOffset++] = sourceBuffer[sourceOffset++]; //destBuffer[destOffset++] = 255; } } } } } break; default: haveConversion = false; break; } break; default: haveConversion = false; break; } if (!haveConversion) { throw new NotImplementedException("You need to write the " + sourceImage.BitDepth.ToString() + " to " + BitDepth.ToString() + " conversion"); } } }