예제 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public PixelMap GetPixelMap()
        {
            if (_YMap == null)
            {
                return(null);
            }

            int area = _YMap.Width * _YMap.Height;

            int width  = _YMap.Width;
            int height = _YMap.Height;
            int pixsep = 3;
            int rowsep = width * pixsep;

            sbyte[] bytes = new sbyte[height * rowsep];

            _YMap.Image(0, bytes, rowsep, pixsep, false);

            if ((_CrMap != null) && (_CbMap != null) && (_CrCbDelay >= 0))
            {
                _CbMap.Image(1, bytes, rowsep, pixsep, _CrCbHalf);
                _CrMap.Image(2, bytes, rowsep, pixsep, _CrCbHalf);
            }

            // Convert image to RGB
            PixelMap pixelMap = new PixelMap().Init(bytes, height, width);

            if ((_CrMap != null) && (_CbMap != null) && (_CrCbDelay >= 0))
            {
                unsafe
                {
                    fixed(sbyte *pBuffer = bytes)
                    {
                        Pixel *pPix = (Pixel *)pBuffer;

                        InterWaveTransform.YCbCr2Rgb(pPix, width, height);
                    }
                }
            }
            else
            {
                IPixelReference pixel = pixelMap.CreateGPixelReference(0);
                for (int x = width * height; x-- > 0; pixel.IncOffset())
                {
                    pixel.SetGray((sbyte)(127 - pixel.Blue));
                }
            }

            return(pixelMap);
        }
예제 #2
0
        public IPixelMap GetPixelMap(int subsample, Rectangle rect, IPixelMap retval)
        {
            if (_YMap == null)
            {
                return(null);
            }

            if (retval == null)
            {
                retval = new PixelMap();
            }

            int width  = rect.Width;
            int height = rect.Height;
            int pixsep = 3;
            int rowsep = width * pixsep;

            sbyte[] bytes = retval.Init(height, width, null).Data;

            _YMap.Image(subsample, rect, 0, bytes, rowsep, pixsep, false);

            if ((_CrMap != null) && (_CbMap != null) && (_CrCbDelay >= 0))
            {
                _CbMap.Image(subsample, rect, 1, bytes, rowsep, pixsep, _CrCbHalf);
                _CrMap.Image(subsample, rect, 2, bytes, rowsep, pixsep, _CrCbHalf);
            }

            if ((_CrMap != null) && (_CbMap != null) && (_CrCbDelay >= 0))
            {
                unsafe
                {
                    fixed(sbyte *pBuffer = bytes)
                    {
                        Pixel *pPix = (Pixel *)pBuffer;

                        InterWaveTransform.YCbCr2Rgb(pPix, width, height);
                    }
                }
            }
            else
            {
                IPixelReference pixel = retval.CreateGPixelReference(0);
                for (int x = width * height; x-- > 0; pixel.IncOffset())
                {
                    pixel.SetGray((sbyte)(127 - pixel.Blue));
                }
            }

            return(retval);
        }
예제 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="img8"></param>
        /// <param name="imgrowsize"></param>
        /// <param name="msk8"></param>
        /// <param name="mskrowsize"></param>
        public unsafe void Create(sbyte *img8, int imgrowsize, sbyte *msk8, int mskrowsize = 0)
        {
            int i, j;

            // Allocate decomposition buffer
            short[]  bData16 = new short[BlockWidth * BlockHeight];
            GCHandle pData16 = GCHandle.Alloc(bData16, GCHandleType.Pinned);
            short *  data16  = (short *)pData16.AddrOfPinnedObject();

            // Copy pixels
            short *p   = data16;
            sbyte *row = img8;

            for (i = 0; i < Height; i++)
            {
                for (j = 0; j < Width; j++)
                {
                    *p++ = (short)(row[j] << InterWaveEncoder.iw_shift);
                }

                row += imgrowsize;

                for (j = Width; j < BlockWidth; j++)
                {
                    *p++ = 0;
                }
            }

            for (i = Height; i < BlockHeight; i++)
            {
                for (j = 0; j < BlockWidth; j++)
                {
                    *p++ = 0;
                }
            }

            // Handle bitmask
            if (msk8 != (sbyte *)0)
            {
                InterpolateMask(data16, Width, Height, BlockWidth, msk8, mskrowsize);
                ForwardMask(data16, Width, Height, BlockWidth, 1, 32, msk8, mskrowsize);
            }
            else
            {
                // Perform traditional decomposition
                InterWaveTransform.Forward(data16, Width, Height, BlockWidth, 1, 32);
            }

            // Copy coefficient into blocks
            p = data16;
            InterWaveBlock[] blocks = Blocks;
            int bidx = 0;

            for (i = 0; i < BlockHeight; i += 32)
            {
                for (j = 0; j < BlockWidth; j += 32)
                {
                    short[]  liftblock  = new short[1024];
                    GCHandle pLiftblock = GCHandle.Alloc(liftblock, GCHandleType.Pinned);

                    // transfer coefficients at (p+j) into aligned block
                    short *pp = p + j;
                    short *pl = (short *)pLiftblock.AddrOfPinnedObject();

                    for (int ii = 0; ii < 32; ii++, pp += BlockWidth)
                    {
                        for (int jj = 0; jj < 32; jj++)
                        {
                            *pl++ = pp[jj];
                        }
                    }
                    // transfer into IW44Image::Block (apply zigzag and scaling)
                    blocks[bidx].ReadLiftBlock(liftblock);
                    bidx++;
                }
                // next row of blocks
                p += 32 * BlockWidth;
            }
        }
예제 #4
0
        /// <summary>
        /// Calculates multi scale iterative masked decomposition.
        /// </summary>
        /// <param name="data16"></param>
        /// <param name="w"></param>
        /// <param name="h"></param>
        /// <param name="rowsize"></param>
        /// <param name="begin"></param>
        /// <param name="end"></param>
        /// <param name="mask8"></param>
        /// <param name="mskrowsize"></param>
        public static unsafe void ForwardMask(short *data16, int w, int h, int rowsize,
                                              int begin, int end, sbyte *mask8, int mskrowsize)
        {
            int    i, j;
            sbyte *m;
            short *p;
            short *d;

            // Allocate buffers
            short[]  ssdata  = new short[w * h];
            GCHandle sHandle = GCHandle.Alloc(ssdata, GCHandleType.Pinned);
            short *  sdata   = (short *)sHandle.AddrOfPinnedObject();

            sbyte[]  ssmask = new sbyte[w * h];
            GCHandle sMask  = GCHandle.Alloc(ssdata, GCHandleType.Pinned);
            sbyte *  smask  = (sbyte *)sMask.AddrOfPinnedObject();

            // Copy mask
            m = smask;

            for (i = 0; i < h; i += 1, m += w, mask8 += mskrowsize)
            {
                MemoryUtilities.MoveMemory((void *)m, (void *)mask8, w);
            }

            // Loop over scale
            for (int scale = begin; scale < end; scale <<= 1)
            {
                // Copy data into sdata buffer
                p = data16;
                d = sdata;
                for (i = 0; i < h; i += scale)
                {
                    for (j = 0; j < w; j += scale)
                    {
                        d[j] = p[j];
                    }

                    p += rowsize * scale;
                    d += w * scale;
                }

                // Decompose
                InterWaveTransform.Forward(sdata, w, h, w, scale, scale + scale);

                // Cancel masked coefficients
                d = sdata;
                m = smask;
                for (i = 0; i < h; i += scale + scale)
                {
                    for (j = scale; j < w; j += scale + scale)
                    {
                        if (m[j] != 0)
                        {
                            d[j] = 0;
                        }
                    }
                    d += w * scale;
                    m += w * scale;
                    if (i + scale < h)
                    {
                        for (j = 0; j < w; j += scale)
                        {
                            if (m[j] != 0)
                            {
                                d[j] = 0;
                            }
                        }
                        d += w * scale;
                        m += w * scale;
                    }
                }

                // Reconstruct
                InterWaveTransform.Backward(sdata, w, h, w, scale + scale, scale);

                // Correct visible pixels
                p = data16;
                d = sdata;
                m = smask;
                for (i = 0; i < h; i += scale)
                {
                    for (j = 0; j < w; j += scale)
                    {
                        if (m[j] == 0)
                        {
                            d[j] = p[j];
                        }
                    }
                    p += rowsize * scale;
                    m += w * scale;
                    d += w * scale;
                }

                // Decompose again (no need to iterate actually!)
                InterWaveTransform.Forward(sdata, w, h, w, scale, scale + scale);

                // Copy coefficients from sdata buffer
                p = data16;
                d = sdata;
                for (i = 0; i < h; i += scale)
                {
                    for (j = 0; j < w; j += scale)
                    {
                        p[j] = d[j];
                    }
                    p += rowsize * scale;
                    d += w * scale;
                }

                // Compute new mask for next scale
                m = smask;
                sbyte *m0 = m;
                sbyte *m1 = m;
                for (i = 0; i < h; i += scale + scale)
                {
                    m0 = m1;
                    if (i + scale < h)
                    {
                        m1 = m + w * scale;
                    }
                    for (j = 0; j < w; j += scale + scale)
                    {
                        if (m[j] != 0 && m0[j] != 0 && m1[j] != 0 && (j <= 0 || m[j - scale] != 0) && (j + scale >= w || m[j + scale] != 0))
                        {
                            m[j] = 1;
                        }
                        else
                        {
                            m[j] = 0;
                        }
                    }
                    m = m1 + w * scale;
                }
            }
            // Free buffers
            sMask.Free();
            sHandle.Free();
        }
        /// <summary>
        /// Initializes an InterWavePixelMap with color image #bm#.  This constructor
        /// performs the wavelet decomposition of image #bm# and records the
        /// corresponding wavelet coefficients. Argument #mask# is an optional
        /// bilevel image specifying the masked pixels(see \Ref{ IW44Image.h}).
        /// Argument #crcbmode# specifies how the chrominance information should be
        /// encoded(see \Ref{ CRCBMode}).
        /// </summary>
        /// <param name="bm"></param>
        /// <param name="mask"></param>
        /// <param name="mode"></param>
        public unsafe void InitializeEncoder(IPixelMap pm, Bitmap gmask = null, YCrCbMode crcbmode = YCrCbMode.Normal)
        {
            /* Free */
            CloseEncoder();

            // Handle CRCB mode
            switch (crcbmode)
            {
            case YCrCbMode.None:
                _CrCbHalf  = true;
                _CrCbDelay = -1;
                break;

            case YCrCbMode.Half:
                _CrCbHalf  = true;
                _CrCbDelay = 10;
                break;

            case YCrCbMode.Normal:
                _CrCbHalf  = false;
                _CrCbDelay = 10;
                break;

            case YCrCbMode.Full:
                _CrCbHalf  = false;
                _CrCbDelay = 0;
                break;
            }

            // Prepare mask information
            sbyte *msk8       = (sbyte *)IntPtr.Zero;
            int    mskrowsize = 0;

            Bitmap   mask  = gmask;
            GCHandle hMask = default(GCHandle);

            if (mask != null)
            {
                hMask      = GCHandle.Alloc(mask.Data, GCHandleType.Pinned);
                msk8       = (sbyte *)hMask.AddrOfPinnedObject();
                mskrowsize = mask.GetRowSize();
            }

            /* Create */
            int width  = pm.Width;
            int height = pm.Height;

            sbyte[]  sYBuffer = new sbyte[width * height];
            GCHandle hYBuffer = GCHandle.Alloc(sYBuffer, GCHandleType.Pinned);
            sbyte *  yBuffer  = (sbyte *)hYBuffer.AddrOfPinnedObject();

            // Create maps
            InterWaveMapEncoder eymap = new InterWaveMapEncoder(width, height);

            _YMap = eymap;

            GCHandle hData = GCHandle.Alloc(pm.Data, GCHandleType.Pinned);
            Pixel *  pData = (Pixel *)hData.AddrOfPinnedObject();

            // Create chrominance maps
            if (_CrCbDelay >= 0)
            {
                sbyte[]  sCbBuffer = new sbyte[width * height];
                GCHandle hCbBuffer = GCHandle.Alloc(sCbBuffer, GCHandleType.Pinned);
                sbyte *  cbBuffer  = (sbyte *)hCbBuffer.AddrOfPinnedObject();

                sbyte[]  sCrBuffer = new sbyte[width * height];
                GCHandle hCrBuffer = GCHandle.Alloc(sCrBuffer, GCHandleType.Pinned);
                sbyte *  crBuffer  = (sbyte *)hCrBuffer.AddrOfPinnedObject();

                InterWaveMapEncoder ecbmap = new InterWaveMapEncoder(width, height);
                _CbMap = ecbmap;

                InterWaveMapEncoder ecrmap = new InterWaveMapEncoder(width, height);
                _CrMap = ecrmap;

                // Color space conversion from RGB to YCbCr and channel separation
                InterWaveTransform.Rgb2YCbCr(pData, width, height, width * 3, yBuffer, cbBuffer, crBuffer, width);

                // Create YMap
                eymap.Create(yBuffer, width, msk8, mskrowsize);
                // Create CbMap
                ecbmap.Create(cbBuffer, width, msk8, mskrowsize);
                // Create CrMap
                ecrmap.Create(crBuffer, width, msk8, mskrowsize);

                // Perform chrominance reduction (CrCbHalf)
                if (_CrCbHalf)
                {
                    ecbmap.Slashres(2);
                    ecrmap.Slashres(2);
                }

                if (hCbBuffer.IsAllocated)
                {
                    hCbBuffer.Free();
                }

                if (hCrBuffer.IsAllocated)
                {
                    hCrBuffer.Free();
                }
            }
            else
            {
                // Fill buffer with luminance information
                InterWaveTransform.Rgb2Y(pData, width, height, pm.GetRowSize(), yBuffer, width);
                // Create YMAP
                eymap.Create(yBuffer, width, msk8, mskrowsize);

                // Inversion for gray images
                sbyte *e = yBuffer + width * height;
                for (sbyte *b = yBuffer; b < e; b++)
                {
                    *b = (sbyte)(255 - *b);
                }
            }

            if (hMask.IsAllocated)
            {
                hMask.Free();
            }

            hData.Free();
            hYBuffer.Free();
        }