/// <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); }
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); }
/// <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; } }
/// <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(); }