Example #1
0
        /// <summary>
        /// Creates a padded Fax page.  Source must be 1bpp.  Returned bitmap is 1bpp.
        /// </summary>
        /// <param name="bmp"></param>
        /// <param name="quality"></param>
        /// <param name="paperSize"></param>
        /// <returns></returns>
        public static Bitmap CreateCopyFaxGeometryPadding(Bitmap bmp, FaxQuality quality, PaperSize paperSize)
        {
            PageInfo inf = new PageInfo(bmp);

            if (!(inf.GetStandardFaxQuality == quality))
            {
                throw new Exception("Fax quality must match source.");
            }
            if (!(inf.PixelFormat != PixelFormat.Format1bppIndexed))
            {
                throw new Exception("Source bitmap must have 1bppIndexed format.");
            }

            if (!(inf.GetStandardPaperSize == paperSize))
            {
                return(BitmapHelper.CreateCopyExact(bmp));
            }

            if (inf.GetStandardPaperSize == PaperSize.Legal && paperSize == PaperSize.Letter)
            {
                throw new Exception("Method cannnot reduce Paper size.");
            }

            Bitmap ret = BitmapHelper.CreateBitMap(paperSize, quality, PixelFormat.Format1bppIndexed);

            // Lock source bitmap in memory
            BitmapData sourceData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            // Copy image data to binary array
            int imageSize = sourceData.Stride * sourceData.Height;

            byte[] sourceBuffer = new byte[imageSize];
            Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);

            // Unlock source bitmap
            bmp.UnlockBits(sourceData);

            // Lock destination bitmap in memory
            BitmapData destinationData = ret.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);

            // Copy binary image data to destination bitmap
            Marshal.Copy(sourceBuffer, 0, destinationData.Scan0, imageSize);

            // Unlock destination bitmap
            ret.UnlockBits(destinationData);
            return(ret);
        }
Example #2
0
        internal static Bitmap Convert8BppTo32Bpp(Bitmap bmp)
        {
            if (bmp.PixelFormat != PixelFormat.Format8bppIndexed)
            {
                throw new Exception("PixelFormat must be Format8bppIndexed.");
            }

            //Grayscale value (0-255) = R = G = B
            //So copy grayscale value to R/G/B bytes, setting A to 255
            BitmapData bmpData   = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
            int        imageSize = bmpData.Stride * bmpData.Height;

            byte[] bmpBuffer = new byte[imageSize];
            Marshal.Copy(bmpData.Scan0, bmpBuffer, 0, imageSize);
            bmp.UnlockBits(bmpData);

            Bitmap     destBmp  = BitmapHelper.CreateBitMap(bmp, PixelFormat.Format32bppArgb);
            BitmapData destData = destBmp.LockBits(new Rectangle(0, 0, destBmp.Width, destBmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

            imageSize = destData.Stride * destData.Height;
            byte[] destBuffer = new byte[imageSize];

            Color[] colorArray = new Color[bmp.Palette.Entries.Length];
            for (int i = 0; i < bmp.Palette.Entries.Length; i++)
            {
                colorArray[i] = bmp.Palette.Entries[i];
            }                                                                                                            //Create array of palette for quick lookup below

            for (int y = 0; y < bmp.Height; y++)
            {
                for (int x = 0; x < bmp.Width; x++)
                {
                    destBuffer[y * destData.Stride + (x * 4)]     = colorArray[bmpBuffer[y * bmpData.Stride + x]].B;                     //B //bmpBuffer[y * bmpData.Stride + x];
                    destBuffer[y * destData.Stride + (x * 4) + 1] = colorArray[bmpBuffer[y * bmpData.Stride + x]].G;                     //G //bmpBuffer[y * bmpData.Stride + x];
                    destBuffer[y * destData.Stride + (x * 4) + 2] = colorArray[bmpBuffer[y * bmpData.Stride + x]].R;                     //R //bmpBuffer[y * bmpData.Stride + x];
                    destBuffer[y * destData.Stride + (x * 4) + 3] = colorArray[bmpBuffer[y * bmpData.Stride + x]].A;                     //A //255;
                }
            }

            Marshal.Copy(destBuffer, 0, destData.Scan0, imageSize);
            destBmp.UnlockBits(destData);
            return(destBmp);
        }
Example #3
0
        /// <summary>
        /// Draws the given Bitmap into a new Bitmap that has the indicated fax geometry. Always returns
        /// 32bpp pixel format.
        /// </summary>
        /// <param name="bmp">The source bitmap.</param>
        /// <param name="quality">The Fax Quality.  Default is Low.</param>
        /// <param name="paperSize">The Paper size.  Default is Auto.</param>
        /// <param name="interpolationMode">The Interpolation mode.  Default is High, but will use the current value in Image Utility, unless defined here. size.</param>
        /// <returns>The new PageImageList (always with 32bpp pixel format)</returns>
        internal static Bitmap CreateCopyFaxGeometry(Bitmap bmp, FaxQuality quality, PaperSize paperSize, InterpolationMode interpolationMode)
        {
            bool   destroytemp = false;
            Bitmap tmp         = null;
            Bitmap ret         = null;

            if (bmp.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                tmp = Convert8BppTo32Bpp(bmp); destroytemp = true;
            }
            else if (bmp.PixelFormat == PixelFormat.Format32bppArgb)
            {
                tmp = bmp;
            }
            else
            {
                tmp = BitmapHelper.CreateCopy32Bit(bmp); destroytemp = true;
            }
            //else if (bmp.PixelFormat != PixelFormat.Format32bppArgb) { tmp = bmp; }
            //else { tmp = BitmapHelper.CreateCopy32Bit(bmp); destroytemp = true; }

            ret = BitmapHelper.CreateBitMap(paperSize, quality, PixelFormat.Format32bppArgb);

            Graphics g = Graphics.FromImage(ret);

            g.InterpolationMode = interpolationMode;
            GraphicsUnit gu = GraphicsUnit.Pixel;

            g.DrawImage(tmp, ret.GetBounds(ref gu), tmp.GetBounds(ref gu), GraphicsUnit.Pixel);
            g.Dispose();
            if (destroytemp)
            {
                tmp.Dispose();
            }
            return(ret);
        }
Example #4
0
        /// <summary>
        /// Creates a new Bitmap with the resolution reduced by half in the vertical direction using
        /// the indicated method.  Source must be 1bppIndexed.  Source must be a standard Fax size.
        /// </summary>
        /// <param name="bmp">Source Bitmap.</param>
        /// <param name="scaleMethod">The scaling method.</param>
        /// <returns>The new bitmap in 1bppIndexed format.</returns>
        internal static Bitmap ConvertTiffHiToTiffLow(Bitmap bmp, HighToLowScaleMethod scaleMethod)
        {
            PaperSize paperSize = BitmapHelper.GetStandardPaperSize(bmp);

            //If the paper size is not standard then throw error
            if (paperSize == PaperSize.Undefined)
            {
                throw new Exception("Source bitmap returned an incorrect paper size.");
            }

            //If its not in 32bppArgb format then throw error
            if (bmp.PixelFormat != PixelFormat.Format1bppIndexed)
            {
                throw new Exception("Source format must be Format1bppIndexed.");
            }

            //If its already a low resolution, then copy and return.
            if (bmp.VerticalResolution == ImageUtility.FAX_TIF_VER_RES_LOW)
            {
                return(BitmapHelper.CreateCopyExact(bmp));
            }

            //No Scale requested.
            if (scaleMethod == HighToLowScaleMethod.NoScale)
            {
                return(BitmapHelper.CreateCopyExact(bmp));
            }

            //If its in tiff high resolution, then throw error
            if (bmp.VerticalResolution != ImageUtility.FAX_TIF_VER_RES_HI)
            {
                throw new Exception("Source resolution is not FAX_TIF_VER_RES_HI.");
            }

            Bitmap ret = BitmapHelper.CreateBitMap(paperSize, FaxQuality.Normal, PixelFormat.Format1bppIndexed);

            // Lock source bitmap in memory
            BitmapData sourceData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed);

            // Copy image data to binary array
            int imageSize = sourceData.Stride * sourceData.Height;

            byte[] sourceBuffer = new byte[imageSize];
            Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);

            // Unlock source bitmap
            bmp.UnlockBits(sourceData);

            // Lock destination bitmap in memory
            BitmapData destinationData = ret.LockBits(new Rectangle(0, 0, ret.Width, ret.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);

            // Create destination buffer
            imageSize = destinationData.Stride * destinationData.Height;
            byte[] destinationBuffer = new byte[imageSize];

            int nnx_ratio = (int)((sourceData.Stride << 16) / destinationData.Stride) + 1;
            int nny_ratio = (int)((sourceData.Height << 16) / destinationData.Height) + 1;

            int   A, B, C, D, x, y, index, gray;
            float x_ratio = ((float)(sourceData.Stride - 1)) / destinationData.Stride;
            float y_ratio = ((float)(sourceData.Height - 1)) / destinationData.Height;
            float x_diff, y_diff;
            int   offset = 0;

            for (int j = 0; j < destinationData.Height; j++)              //For every row
            {
                for (int i = 0; i < destinationData.Stride; i++)          //For each byte in row
                {
                    byte s1 = sourceBuffer[(j * 2) * destinationData.Stride + i];
                    byte s2 = sourceBuffer[((j * 2) + 1) * destinationData.Stride + i];
                    byte d1 = 0;

                    switch (scaleMethod)
                    {
                    case HighToLowScaleMethod.ORing:
                    {
                        d1 = (byte)(s1 | s2);
                        destinationBuffer[j * destinationData.Stride + i] = d1;
                        break;
                    }

                    case HighToLowScaleMethod.ANDing:
                    {
                        d1 = (byte)(s1 & s2);
                        destinationBuffer[j * destinationData.Stride + i] = d1;
                        break;
                    }

                    case HighToLowScaleMethod.Elimination:
                    {
                        d1 = s1;
                        destinationBuffer[j * destinationData.Stride + i] = d1;
                        break;
                    }

                    case HighToLowScaleMethod.Averaging:
                    {
                        //d1 = (byte)(s1 | s2);
                        //d1 = (byte)(s1 ^ s2);
                        d1 = (byte)((s1 + s2) / 2);
                        //int a1s1 = s1 >> 6 & 3;
                        //int a1s2 = s2 >> 6 & 3;
                        //int a2s1 = s1 >> 4 & 3;
                        //int a2s2 = s2 >> 4 & 3;
                        //int a3s1 = s1 >> 2 & 3;
                        //int a3s2 = s2 >> 2 & 3;
                        //int a4s1 = s1 & 3;
                        //int a4s2 = s2 & 3;
                        //d1 = (byte)(((a1s1 + a1s2) / 2 << 6) + ((a2s1 + a2s2) / 2 << 4) + ((a3s1 + a3s2) / 2 << 2) + ((a4s1 + a4s2) / 2));
                        destinationBuffer[j * destinationData.Stride + i] = d1;
                        break;
                    }

                    case HighToLowScaleMethod.NearestNeighbor:
                    {
                        int x2 = ((i * nnx_ratio) >> 16);
                        int y2 = ((j * nny_ratio) >> 16);

                        destinationBuffer[j * destinationData.Stride + i] = sourceBuffer[(y2 * sourceData.Stride) + x2];
                        break;
                    }

                    case HighToLowScaleMethod.Bilinear:
                    {
                        x      = (int)(x_ratio * i);
                        y      = (int)(y_ratio * j);
                        x_diff = (x_ratio * i) - x;
                        y_diff = (y_ratio * j) - y;
                        index  = y * sourceData.Stride + x;

                        A    = sourceBuffer[index] & 0xff;
                        B    = sourceBuffer[index + 1] & 0xff;
                        C    = sourceBuffer[index + sourceData.Stride] & 0xff;
                        D    = sourceBuffer[index + sourceData.Stride + 1] & 0xff;
                        gray = (int)(
                            A * (1 - x_diff) * (1 - y_diff) + B * (x_diff) * (1 - y_diff) +
                            C * (y_diff) * (1 - x_diff) + D * (x_diff * y_diff)
                            );

                        destinationBuffer[offset++] = (byte)gray;
                        break;
                    }
                    }
                }
            }

            // Copy binary image data to destination bitmap
            Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);

            // Unlock destination bitmap
            ret.UnlockBits(destinationData);
            return(ret);
        }
Example #5
0
        /// <summary>
        /// Creates a copy of the given bitmap after cropping white pixels from top and bottom of image.
        /// Requires a 1bitPerPixel image format, and must be a regular sized fax bitmap (1728 pixels wide).
        /// after rotation using the supplied intermediate resolution
        /// and Angle.  Positive Angle is Clockwise.  The resulting image has the same horizonatal
        /// and vertical resolution as the given page, but geometry may have changed (height and width).
        /// </summary>
        /// <param name="bmp">The Bitmap to rotate</param>
        /// <param name="intermediateResolution">The intermediate resolution to use.</param>
        /// <param name="rotationAngle">The angle to rotate the image</param>
        /// <returns></returns>
        public static Bitmap CreateCopyCrop(Bitmap bmp)
        {
            PageInfo bmpinfo = new PageInfo(bmp);

            if (bmpinfo.WidthPixels != ImageUtility.FAX_TIF_HOR_PX && bmpinfo.HorizontalResolution != ImageUtility.FAX_TIF_HOR_RES)
            {
                throw new Exception("Bitmap is not the correct size for cropping.");
            }

            if (bmp.PixelFormat != PixelFormat.Format1bppIndexed)
            {
                throw new Exception("Bitmap is not the correct pixel format for cropping.");
            }

            // Lock source bitmap in memory
            BitmapData sourceData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed);

            // Copy image data to binary array
            int imageSize = sourceData.Stride * sourceData.Height;

            byte[] sourceBuffer = new byte[imageSize];
            Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);

            // Unlock source bitmap
            bmp.UnlockBits(sourceData);


            int firstDataRow = BitmapHelper.ScanForFirstNonWhiteRow(sourceBuffer, sourceData.Stride, true, false);
            int lastDataRow  = BitmapHelper.ScanForFirstNonWhiteRow(sourceBuffer, sourceData.Stride, false, true);

            int totalRows = lastDataRow - firstDataRow + 1;
            int newHeight = 0;

            var quality = FaxQuality.Undefined;
            var paper   = PaperSize.Undefined;

            if (bmp.VerticalResolution == ImageUtility.FAX_TIF_VER_RES_HI)
            {
                if (totalRows <= ImageUtility.FAX_TIF_VER_PX_LTR_HI)
                {
                    newHeight = ImageUtility.FAX_TIF_VER_PX_LTR_HI; paper = PaperSize.Letter;
                }
                else if (totalRows <= ImageUtility.FAX_TIF_VER_PX_LGL_HI)
                {
                    newHeight = ImageUtility.FAX_TIF_VER_PX_LGL_HI; paper = PaperSize.Legal;
                }
                else
                {
                    newHeight = ImageUtility.FAX_TIF_VER_PX_LGL_HI; paper = PaperSize.Legal;
                }
                quality = FaxQuality.Fine;
            }
            if (bmp.VerticalResolution == ImageUtility.FAX_TIF_VER_RES_LOW)
            {
                if (totalRows <= ImageUtility.FAX_TIF_VER_PX_LTR_LOW)
                {
                    newHeight = ImageUtility.FAX_TIF_VER_PX_LTR_LOW; paper = PaperSize.Letter;
                }
                else if (totalRows <= ImageUtility.FAX_TIF_VER_PX_LGL_LOW)
                {
                    newHeight = ImageUtility.FAX_TIF_VER_PX_LGL_LOW; paper = PaperSize.Legal;
                }
                else
                {
                    newHeight = ImageUtility.FAX_TIF_VER_PX_LGL_LOW; paper = PaperSize.Legal;
                }
                quality = FaxQuality.Normal;
            }

            //Make sure the first data row does not go negative.
            firstDataRow = Math.Max(0, firstDataRow - ((newHeight - totalRows) / 2));
            //Make sure last does not extend out of the original document range.
            lastDataRow = Math.Min(Math.Max(0, bmp.Height - 1), Math.Max(0, firstDataRow + newHeight - 1));
            totalRows   = lastDataRow - firstDataRow + 1;

            var startindex    = firstDataRow * sourceData.Stride;
            var length        = totalRows * sourceData.Stride;
            var croppedBitmap = BitmapHelper.CreateBitMap(paper, quality, PixelFormat.Format1bppIndexed);

            // Lock destination bitmap in memory
            BitmapData destinationData = croppedBitmap.LockBits(new Rectangle(0, 0, croppedBitmap.Width, croppedBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);

            // Copy binary image data to destination bitmap
            Marshal.Copy(sourceBuffer, startindex, destinationData.Scan0, length);

            // Unlock destination bitmap
            croppedBitmap.UnlockBits(destinationData);

            return(croppedBitmap);
        }
Example #6
0
        /// <summary>
        /// Reduces the PixelFormat to 1bppIndexed and will use threshold
        /// for color reduction.
        /// </summary>
        /// <param name="bmp">The source bitmap</param>
        /// <param name="threshold">The threshold to use</param>
        /// <returns>A new bitmap.</returns>
        public static Bitmap CreateCopy1BppIndexed(Bitmap bmp, int threshold)
        {
            //If its already in the format we need, make a copy and return.
            if (bmp.PixelFormat == PixelFormat.Format1bppIndexed)
            {
                return(BitmapHelper.CreateCopyExact(bmp));
            }

            //If its not in 32bppArgb format then throw error
            if (bmp.PixelFormat != PixelFormat.Format32bppArgb)
            {
                throw new Exception("Source format must be 32BppArgb.");
            }

            //Destination bitmap
            Bitmap ret = BitmapHelper.CreateBitMap(bmp, PixelFormat.Format1bppIndexed);

            // Lock source bitmap in memory
            BitmapData sourceData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            // Copy image data to binary array
            int imageSize = sourceData.Stride * sourceData.Height;

            byte[] sourceBuffer = new byte[imageSize];
            Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);

            // Unlock source bitmap
            bmp.UnlockBits(sourceData);

            // Lock destination bitmap in memory
            BitmapData destinationData = ret.LockBits(new Rectangle(0, 0, ret.Width, ret.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);

            // Create destination buffer
            imageSize = destinationData.Stride * destinationData.Height;
            byte[] destinationBuffer = new byte[imageSize];

            int  sourceIndex      = 0;
            int  destinationIndex = 0;
            int  pixelTotal       = 0;
            byte destinationValue = 0;
            int  pixelValue       = 128;
            int  height           = bmp.Height;
            int  width            = bmp.Width;

            // Iterate lines
            for (int y = 0; y < height; y++)
            {
                sourceIndex      = y * sourceData.Stride;
                destinationIndex = y * destinationData.Stride;
                destinationValue = 0;
                pixelValue       = 128;

                // Iterate pixels
                for (int x = 0; x < width; x++)
                {
                    // Compute pixel brightness (i.e. total of Red, Green, and Blue values)
                    pixelTotal = sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2] + sourceBuffer[sourceIndex + 3];
                    if (pixelTotal > threshold)
                    {
                        destinationValue += (byte)pixelValue;
                    }
                    if (pixelValue == 1)
                    {
                        destinationBuffer[destinationIndex] = destinationValue;
                        destinationIndex++;
                        destinationValue = 0;
                        pixelValue       = 128;
                    }
                    else
                    {
                        pixelValue >>= 1;
                    }
                    sourceIndex += 4;
                }
                if (pixelValue != 128)
                {
                    destinationBuffer[destinationIndex] = destinationValue;
                }
            }

            // Copy binary image data to destination bitmap
            Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);

            // Unlock destination bitmap
            ret.UnlockBits(destinationData);
            return(ret);
        }
Example #7
0
 /// <summary>
 /// Creates an empty Bitmap that will have the same size and resolution
 /// of the source bitmap with the indicated pixel format.
 /// </summary>
 /// <param name="bmp">The bitmap to copy.</param>
 /// <param name="pixelFormat">The pixel format</param>
 /// <returns>The new bitmap.</returns>
 internal static Bitmap CreateBitMap(Bitmap bmp, PixelFormat pixelFormat)
 {
     return(ImageHelper.IsIndexedFormat(bmp) ? BitmapHelper.CreateBitMap(bmp.Width, bmp.Height, bmp.HorizontalResolution, bmp.VerticalResolution, bmp.Palette, pixelFormat)
                         : BitmapHelper.CreateBitMap(bmp.Width, bmp.Height, bmp.HorizontalResolution, bmp.VerticalResolution, pixelFormat));
 }
Example #8
0
        private static PageImage CreateFaxTiffFastTrack(PageImage page, PaperSize paperSize, FaxQuality faxQuality, ImageOperationResult result)
        {
            PageInfo  inf     = null;
            PageImage ret     = new PageImage();
            Bitmap    src     = null;
            Bitmap    destroy = null;

            src = BitmapHelper.CreateCopy1BppIndexed(page._sourceBmp);
            inf = new PageInfo(src);

            //If the size is not right copy to other size (padding or reducing)
            if (inf.GetStandardPaperSize != paperSize)
            {
                if (inf.GetStandardPaperSize == PaperSize.Legal && paperSize == PaperSize.Letter)
                {
                    destroy = src;
                    src     = BitmapHelper.CreateCopyFaxGeometry(src, faxQuality, paperSize, ImageUtility.InterpolationMode);
                    if (destroy != null)
                    {
                        destroy.Dispose(); destroy = null;
                    }
                    inf = new PageInfo(src);
                }
                if (inf.GetStandardPaperSize == PaperSize.Letter && paperSize == PaperSize.Legal)
                {
                    destroy = src;
                    src     = BitmapHelper.CreateCopyFaxGeometryPadding(src, faxQuality, paperSize);
                    if (destroy != null)
                    {
                        destroy.Dispose(); destroy = null;
                    }
                    inf = new PageInfo(src);
                }
            }

            //Make sure its 1bpp
            if (inf.PixelFormat != PixelFormat.Format1bppIndexed)
            {
                destroy = src;
                src     = BitmapHelper.CreateCopy1BppIndexed(src);
                if (destroy != null)
                {
                    destroy.Dispose(); destroy = null;
                }
                inf = new PageInfo(src);
            }

            //Reduce or increase quality as needed
            if (inf.GetStandardFaxQuality != faxQuality)
            {
                if (inf.GetStandardFaxQuality == FaxQuality.Fine && faxQuality == FaxQuality.Normal)
                {
                    destroy = src;
                    src     = BitmapHelper.ConvertTiffHiToTiffLow(src, ImageUtility.HighToLowScaleMethod);
                    if (destroy != null)
                    {
                        destroy.Dispose(); destroy = null;
                    }
                    inf = new PageInfo(src);
                }
                if (inf.GetStandardFaxQuality == FaxQuality.Normal && faxQuality == FaxQuality.Fine)
                {
                    destroy = src;
                    src     = BitmapHelper.ConvertTiffLowToTiffHi(src);
                    if (destroy != null)
                    {
                        destroy.Dispose(); destroy = null;
                    }
                    inf = new PageInfo(src);
                }
            }

            ret._pageInfo  = null;
            ret._sourceBmp = src;

            return(ret);
        }