Example #1
0
 /// <summary> Copy constructor. Creates a DataBlkInt which is the copy of the
 /// DataBlkInt given as paramter.
 ///
 /// </summary>
 /// <param name="DataBlkInt">the object to be copied.
 ///
 /// </param>
 public DataBlkInt(DataBlkInt src)
 {
     this.ulx        = src.ulx;
     this.uly        = src.uly;
     this.w          = src.w;
     this.h          = src.h;
     this.offset     = 0;
     this.scanw      = this.w;
     this.data_array = new int[this.w * this.h];
     for (int i = 0; i < this.h; i++)
     {
         Array.Copy(src.data_array, i * src.scanw, this.data_array, i * this.scanw, this.w);
     }
 }
Example #2
0
		/// <summary> Returns, in the blk argument, the block of image data containing the
		/// specifed rectangular area, in the specified component. The data is
		/// returned, as a reference to the internal data, if any, instead of as a
		/// copy, therefore the returned data should not be modified.
		/// 
		/// <p>After being read the coefficients are level shifted by subtracting
		/// 2^(nominal bit range - 1)<p>
		/// 
		/// <p>The rectangular area to return is specified by the 'ulx', 'uly', 'w'
		/// and 'h' members of the 'blk' argument, relative to the current
		/// tile. These members are not modified by this method. The 'offset' and
		/// 'scanw' of the returned data can be arbitrary. See the 'DataBlk'
		/// class.</p>
		/// 
		/// <p>If the data array in <tt>blk</tt> is <tt>null</tt>, then a new one
		/// is created if necessary. The implementation of this interface may
		/// choose to return the same array or a new one, depending on what is more
		/// efficient. Therefore, the data array in <tt>blk</tt> prior to the
		/// method call should not be considered to contain the returned data, a
		/// new array may have been created. Instead, get the array from
		/// <tt>blk</tt> after the method has returned.</p>
		/// 
		/// <p>The returned data always has its 'progressive' attribute unset
		/// (i.e. false).</p>
		/// 
		/// <p>When an I/O exception is encountered the JJ2KExceptionHandler is
		/// used. The exception is passed to its handleException method. The action
		/// that is taken depends on the action that has been registered in
		/// JJ2KExceptionHandler. See JJ2KExceptionHandler for details.</p>
		/// 
		/// </summary>
		/// <param name="blk">Its coordinates and dimensions specify the area to
		/// return. Some fields in this object are modified to return the data.
		/// 
		/// </param>
		/// <param name="c">The index of the component from which to get the data. Only 0
		/// is valid.
		/// 
		/// </param>
		/// <returns> The requested DataBlk
		/// 
		/// </returns>
		/// <seealso cref="getCompData">
		/// </seealso>
		/// <seealso cref="JJ2KExceptionHandler">
		/// 
		/// </seealso>
		public override DataBlk getInternCompData(DataBlk blk, int c)
		{
			int k, j, i, mi; // counters
			int levShift = 1 << (bitDepth - 1);
			
			// Check component index
			if (c != 0)
				throw new System.ArgumentException();
			
			// Check type of block provided as an argument
			if (blk.DataType != DataBlk.TYPE_INT)
			{
				if (intBlk == null)
					intBlk = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);
				else
				{
					intBlk.ulx = blk.ulx;
					intBlk.uly = blk.uly;
					intBlk.w = blk.w;
					intBlk.h = blk.h;
				}
				blk = intBlk;
			}
			
			// Get data array
			int[] barr = (int[]) blk.Data;
			if (barr == null || barr.Length < blk.w * blk.h * packBytes)
			{
				barr = new int[blk.w * blk.h];
				blk.Data = barr;
			}
			
			int paddingLength = (32 - bitDepth);
			if (buf == null || buf.Length < packBytes * blk.w)
			{
				buf = new byte[packBytes * blk.w];
			}
			try
			{
				switch (packBytes)
				{
					
					// Switch between one of the 3 byte packet type
					case 1:  // Samples packed into 1 byte
						// Read line by line
						mi = blk.uly + blk.h;
						if (isSigned)
						{
							for (i = blk.uly; i < mi; i++)
							{
								// Reposition in input
								in_Renamed.Seek(offset + i * w + blk.ulx, System.IO.SeekOrigin.Begin);
								in_Renamed.Read(buf, 0, blk.w);
								for (k = (i - blk.uly) * blk.w + blk.w - 1, j = blk.w - 1; j >= 0; k--)
									barr[k] = (((buf[j--] & 0xFF) << paddingLength) >> paddingLength);
							}
						}
						else
						{
							// Not signed
							for (i = blk.uly; i < mi; i++)
							{
								// Reposition in input
								in_Renamed.Seek(offset + i * w + blk.ulx, System.IO.SeekOrigin.Begin);
								in_Renamed.Read(buf, 0, blk.w);
								for (k = (i - blk.uly) * blk.w + blk.w - 1, j = blk.w - 1; j >= 0; k--)
									barr[k] = (SupportClass.URShift(((buf[j--] & 0xFF) << paddingLength), paddingLength)) - levShift;
							}
						}
						break;
					
					
					case 2:  // Samples packed into 2 bytes
						// Read line by line
						mi = blk.uly + blk.h;
						if (isSigned)
						{
							for (i = blk.uly; i < mi; i++)
							{
								// Reposition in input
								in_Renamed.Seek(offset + 2 * (i * w + blk.ulx), System.IO.SeekOrigin.Begin);
								in_Renamed.Read(buf, 0, blk.w << 1);
								switch (byteOrder)
								{
									
									case CSJ2K.j2k.io.EndianType_Fields.LITTLE_ENDIAN: 
										for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 1) - 1; j >= 0; k--)
										{
											barr[k] = ((((buf[j--] & 0xFF) << 8) | (buf[j--] & 0xFF)) << paddingLength) >> paddingLength;
										}
										break;
									
									case CSJ2K.j2k.io.EndianType_Fields.BIG_ENDIAN: 
										for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 1) - 1; j >= 0; k--)
										{
											barr[k] = (((buf[j--] & 0xFF) | ((buf[j--] & 0xFF) << 8)) << paddingLength) >> paddingLength;
										}
										break;
									
									default: 
										throw new System.ApplicationException("Internal JJ2000 bug");
									
								}
							}
						}
						else
						{
							// If not signed
							for (i = blk.uly; i < mi; i++)
							{
								// Reposition in input
								in_Renamed.Seek(offset + 2 * (i * w + blk.ulx), System.IO.SeekOrigin.Begin);
								in_Renamed.Read(buf, 0, blk.w << 1);
								switch (byteOrder)
								{
									
									case CSJ2K.j2k.io.EndianType_Fields.LITTLE_ENDIAN: 
										for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 1) - 1; j >= 0; k--)
										{
											barr[k] = (SupportClass.URShift(((((buf[j--] & 0xFF) << 8) | (buf[j--] & 0xFF)) << paddingLength), paddingLength)) - levShift;
										}
										break;
									
									case CSJ2K.j2k.io.EndianType_Fields.BIG_ENDIAN: 
										for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 1) - 1; j >= 0; k--)
										{
											barr[k] = (SupportClass.URShift((((buf[j--] & 0xFF) | ((buf[j--] & 0xFF) << 8)) << paddingLength), paddingLength)) - levShift;
										}
										break;
									
									default: 
										throw new System.ApplicationException("Internal JJ2000 bug");
									
								}
							}
						}
						break;
					
					
					case 4:  // Samples packed into 4 bytes
						// Read line by line
						mi = blk.uly + blk.h;
						if (isSigned)
						{
							for (i = blk.uly; i < mi; i++)
							{
								// Reposition in input
								in_Renamed.Seek(offset + 4 * (i * w + blk.ulx), System.IO.SeekOrigin.Begin);
								in_Renamed.Read(buf, 0, blk.w << 2);
								switch (byteOrder)
								{
									
									case CSJ2K.j2k.io.EndianType_Fields.LITTLE_ENDIAN: 
										for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 2) - 1; j >= 0; k--)
										{
											barr[k] = ((((buf[j--] & 0xFF) << 24) | ((buf[j--] & 0xFF) << 16) | ((buf[j--] & 0xFF) << 8) | (buf[j--] & 0xFF)) << paddingLength) >> paddingLength;
										}
										break;
									
									case CSJ2K.j2k.io.EndianType_Fields.BIG_ENDIAN: 
										for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 2) - 1; j >= 0; k--)
										{
											barr[k] = (((buf[j--] & 0xFF) | ((buf[j--] & 0xFF) << 8) | ((buf[j--] & 0xFF) << 16) | ((buf[j--] & 0xFF) << 24)) << paddingLength) >> paddingLength;
										}
										break;
									
									default: 
										throw new System.ApplicationException("Internal JJ2000 bug");
									
								}
							}
						}
						else
						{
							for (i = blk.uly; i < mi; i++)
							{
								// Reposition in input
								in_Renamed.Seek(offset + 4 * (i * w + blk.ulx), System.IO.SeekOrigin.Begin);
								in_Renamed.Read(buf, 0, blk.w << 2);
								switch (byteOrder)
								{
									
									case CSJ2K.j2k.io.EndianType_Fields.LITTLE_ENDIAN: 
										for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 2) - 1; j >= 0; k--)
										{
											barr[k] = (SupportClass.URShift(((((buf[j--] & 0xFF) << 24) | ((buf[j--] & 0xFF) << 16) | ((buf[j--] & 0xFF) << 8) | (buf[j--] & 0xFF)) << paddingLength), paddingLength)) - levShift;
										}
										break;
									
									case CSJ2K.j2k.io.EndianType_Fields.BIG_ENDIAN: 
										for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 2) - 1; j >= 0; k--)
										{
											barr[k] = (SupportClass.URShift((((buf[j--] & 0xFF) | ((buf[j--] & 0xFF) << 8) | ((buf[j--] & 0xFF) << 16) | ((buf[j--] & 0xFF) << 24)) << paddingLength), paddingLength)) - levShift;
										}
										break;
									
									default: 
										throw new System.ApplicationException("Internal JJ2000 bug");
									
								}
							}
						}
						break;
					
					
					default: 
						throw new System.IO.IOException("PGX supports only bit-depth between" + " 1 and 31");
					
				}
			}
			catch (System.IO.IOException e)
			{
				JJ2KExceptionHandler.handleException(e);
			}
			
			// Turn off the progressive attribute
			blk.progressive = false;
			// Set buffer attributes
			blk.offset = 0;
			blk.scanw = blk.w;
			return blk;
		}
Example #3
0
		/// <summary> Returns the specified code-block in the current tile for the specified
		/// component (as a reference or copy).
		/// 
		/// <p>The returned code-block may be progressive, which is indicated by
		/// the 'progressive' variable of the returned 'DataBlk'
		/// object. If a code-block is progressive it means that in a later request
		/// to this method for the same code-block it is possible to retrieve data
		/// which is a better approximation, since meanwhile more data to decode
		/// for the code-block could have been received. If the code-block is not
		/// progressive then later calls to this method for the same code-block
		/// will return the exact same data values.</p>
		/// 
		/// <p>The data returned by this method can be the data in the internal
		/// buffer of this object, if any, and thus can not be modified by the
		/// caller. The 'offset' and 'scanw' of the returned data can be
		/// arbitrary. See the 'DataBlk' class.</p>
		/// 
		/// </summary>
		/// <param name="c">The component for which to return the next code-block.
		/// 
		/// </param>
		/// <param name="m">The vertical index of the code-block to return, in the
		/// specified subband.
		/// 
		/// </param>
		/// <param name="n">The horizontal index of the code-block to return, in the
		/// specified subband.
		/// 
		/// </param>
		/// <param name="sb">The subband in which the code-block to return is.
		/// 
		/// </param>
		/// <param name="cblk">If non-null this object will be used to return the new
		/// code-block. If null a new one will be allocated and returned. If the
		/// "data" array of the object is non-null it will be reused, if possible,
		/// to return the data.
		/// 
		/// </param>
		/// <returns> The next code-block in the current tile for component 'n', or
		/// null if all code-blocks for the current tile have been returned.
		/// 
		/// </returns>
		/// <seealso cref="DataBlk">
		/// 
		/// </seealso>
		public override DataBlk getInternCodeBlock(int c, int m, int n, SubbandSyn sb, DataBlk cblk)
		{
			// This method is declared final since getNextCodeBlock() relies on
			// the actual implementation of this method.
			int j, jmin, k;
			int temp;
			float step;
			int shiftBits;
			int magBits;
			int[] outiarr, inarr;
			float[] outfarr;
			int w, h;
			bool reversible = qts.isReversible(tIdx, c);
			bool derived = qts.isDerived(tIdx, c);
			StdDequantizerParams params_Renamed = (StdDequantizerParams) qsss.getTileCompVal(tIdx, c);
			int G = ((System.Int32) gbs.getTileCompVal(tIdx, c));
			
			outdtype = cblk.DataType;
			
			if (reversible && outdtype != DataBlk.TYPE_INT)
			{
				throw new System.ArgumentException("Reversible quantizations " + "must use int data");
			}
			
			// To get compiler happy
			outiarr = null;
			outfarr = null;
			inarr = null;
			
			// Get source data and initialize output DataBlk object.
			switch (outdtype)
			{
				
				case DataBlk.TYPE_INT: 
					// With int data we can use the same DataBlk object to get the
					// data from the source and return the dequantized data, and we
					// can also work "in place" (i.e. same buffer).
					cblk = src.getCodeBlock(c, m, n, sb, cblk);
					// Input and output arrays are the same
					outiarr = (int[]) cblk.Data;
					break;
				
				case DataBlk.TYPE_FLOAT: 
					// With float data we must use a different DataBlk objects to get
					// the data from the source and to return the dequantized data.
					inblk = (DataBlkInt) src.getInternCodeBlock(c, m, n, sb, inblk);
					inarr = inblk.DataInt;
					if (cblk == null)
					{
						cblk = new DataBlkFloat();
					}
					// Copy the attributes of the CodeBlock object
					cblk.ulx = inblk.ulx;
					cblk.uly = inblk.uly;
					cblk.w = inblk.w;
					cblk.h = inblk.h;
					cblk.offset = 0;
					cblk.scanw = cblk.w;
					cblk.progressive = inblk.progressive;
					// Get output data array and check its size
					outfarr = (float[]) cblk.Data;
					if (outfarr == null || outfarr.Length < cblk.w * cblk.h)
					{
						outfarr = new float[cblk.w * cblk.h];
						cblk.Data = outfarr;
					}
					break;
				}
			
			magBits = sb.magbits;
			
			// Calculate quantization step and number of magnitude bits
			// depending on reversibility and derivedness and perform
			// inverse quantization
			if (reversible)
			{
				shiftBits = 31 - magBits;
				// For int data Inverse quantization happens "in-place". The input
				// array has an offset of 0 and scan width equal to the code-block
				// width.
				for (j = outiarr.Length - 1; j >= 0; j--)
				{
					temp = outiarr[j]; // input array is same as output one
					outiarr[j] = (temp >= 0)?(temp >> shiftBits):- ((temp & 0x7FFFFFFF) >> shiftBits);
				}
			}
			else
			{
				// Not reversible 
				if (derived)
				{
					// Max resolution level
					int mrl = src.getSynSubbandTree(TileIdx, c).resLvl;
					step = params_Renamed.nStep[0][0] * (1L << (rb[c] + sb.anGainExp + mrl - sb.level));
				}
				else
				{
					step = params_Renamed.nStep[sb.resLvl][sb.sbandIdx] * (1L << (rb[c] + sb.anGainExp));
				}
				shiftBits = 31 - magBits;
				
				// Adjust step to the number of shiftBits
				step /= (1 << shiftBits);
				
				switch (outdtype)
				{
					
					case DataBlk.TYPE_INT: 
						// For int data Inverse quantization happens "in-place". The
						// input array has an offset of 0 and scan width equal to the
						// code-block width.
						for (j = outiarr.Length - 1; j >= 0; j--)
						{
							temp = outiarr[j]; // input array is same as output one
							//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
							outiarr[j] = (int) (((float) ((temp >= 0)?temp:- (temp & 0x7FFFFFFF))) * step);
						}
						break;
					
					case DataBlk.TYPE_FLOAT: 
						// For float data the inverse quantization can not happen
						// "in-place".
						w = cblk.w;
						h = cblk.h;
						for (j = w * h - 1, k = inblk.offset + (h - 1) * inblk.scanw + w - 1, jmin = w * (h - 1); j >= 0; jmin -= w)
						{
							for (; j >= jmin; k--, j--)
							{
								temp = inarr[k];
								//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
								outfarr[j] = ((float) ((temp >= 0)?temp:- (temp & 0x7FFFFFFF))) * step;
							}
							// Jump to beggining of previous line in input
							k -= (inblk.scanw - w);
						}
						break;
					}
			}
			// Return the output code-block
			return cblk;
		}
Example #4
0
        public static Image FromStream(Stream stream)
        {
            RandomAccessIO in_stream = new ISRandomAccessIO(stream);

            // Initialize default parameters
            ParameterList defpl = GetDefaultParameterList(decoder_pinfo);

            // Create parameter list using defaults
            ParameterList pl = new ParameterList(defpl);

            // **** File Format ****
            // If the codestream is wrapped in the jp2 fileformat, Read the
            // file format wrapper
            FileFormatReader ff = new FileFormatReader(in_stream);
            ff.readFileFormat();
            if (ff.JP2FFUsed)
            {
                in_stream.seek(ff.FirstCodeStreamPos);
            }

            // +----------------------------+
            // | Instantiate decoding chain |
            // +----------------------------+

            // **** Header decoder ****
            // Instantiate header decoder and read main header 
            HeaderInfo hi = new HeaderInfo();
            HeaderDecoder hd;
            try
            {
                hd = new HeaderDecoder(in_stream, pl, hi);
            }
            catch (EndOfStreamException e)
            {
                throw new ApplicationException("Codestream too short or bad header, unable to decode.", e);
            }

            int nCompCod = hd.NumComps;
            int nTiles = hi.sizValue.NumTiles;
            DecoderSpecs decSpec = hd.DecoderSpecs;

            // Get demixed bitdepths
            int[] depth = new int[nCompCod];
            for (int i = 0; i < nCompCod; i++)
            {
                depth[i] = hd.getOriginalBitDepth(i);
            }

            // **** Bit stream reader ****
            BitstreamReaderAgent breader;
            try
            {
                breader = BitstreamReaderAgent.
                    createInstance(in_stream, hd, pl, decSpec,
                                   false, hi);
            }
            catch (IOException e)
            {
                throw new ApplicationException("Error while reading bit stream header or parsing packets.", e);
            }
            catch (ArgumentException e)
            {
                throw new ApplicationException("Cannot instantiate bit stream reader.", e);
            }

            // **** Entropy decoder ****
            EntropyDecoder entdec;
            try
            {
                entdec = hd.createEntropyDecoder(breader, pl);
            }
            catch (ArgumentException e)
            {
                throw new ApplicationException("Cannot instantiate entropy decoder.", e);
            }

            // **** ROI de-scaler ****
            ROIDeScaler roids;
            try
            {
                roids = hd.createROIDeScaler(entdec, pl, decSpec);
            }
            catch (ArgumentException e)
            {
                throw new ApplicationException("Cannot instantiate roi de-scaler.", e);
            }

            // **** Dequantizer ****
            Dequantizer deq;
            try
            {
                deq = hd.createDequantizer(roids, depth, decSpec);
            }
            catch (ArgumentException e)
            {
                throw new ApplicationException("Cannot instantiate dequantizer.", e);
            }

            // **** Inverse wavelet transform ***
            InverseWT invWT;
            try
            {
                // full page inverse wavelet transform
                invWT = InverseWT.createInstance(deq, decSpec);
            }
            catch (ArgumentException e)
            {
                throw new ApplicationException("Cannot instantiate inverse wavelet transform.", e);
            }

            int res = breader.ImgRes;
            invWT.ImgResLevel = res;

            // **** Data converter **** (after inverse transform module)
            ImgDataConverter converter = new ImgDataConverter(invWT, 0);

            // **** Inverse component transformation **** 
            InvCompTransf ictransf = new InvCompTransf(converter, decSpec, depth, pl);

            // **** Color space mapping ****
            BlkImgDataSrc color;
            if (ff.JP2FFUsed && pl.getParameter("nocolorspace").Equals("off"))
            {
                try
                {
                    ColorSpace csMap = new ColorSpace(in_stream, hd, pl);
                    BlkImgDataSrc channels = hd.createChannelDefinitionMapper(ictransf, csMap);
                    BlkImgDataSrc resampled = hd.createResampler(channels, csMap);
                    BlkImgDataSrc palettized = hd.createPalettizedColorSpaceMapper(resampled, csMap);
                    color = hd.createColorSpaceMapper(palettized, csMap);
                }
                catch (ArgumentException e)
                {
                    throw new ApplicationException("Could not instantiate ICC profiler.", e);
                }
                catch (ColorSpaceException e)
                {
                    throw new ApplicationException("Error processing ColorSpace information.", e);
                }
            }
            else
            { // Skip colorspace mapping
                color = ictransf;
            }

            // This is the last image in the decoding chain and should be
            // assigned by the last transformation:
            BlkImgDataSrc decodedImage = color;
            if (color == null)
            {
                decodedImage = ictransf;
            }
            int numComps = decodedImage.NumComps;

            int bytesPerPixel = (numComps == 4 ? 4 : 3);

            // **** Copy to Bitmap ****
            PixelFormat pixelFormat;
            switch (numComps)
            {
                case 1:
                    pixelFormat = PixelFormat.Format24bppRgb; break;
                case 3:
                    pixelFormat = PixelFormat.Format24bppRgb; break;
                case 4:
                    pixelFormat = PixelFormat.Format32bppArgb; break;
                default:
                    throw new ApplicationException("Unsupported PixelFormat.  " + numComps + " components.");
            }

            Bitmap dst = new Bitmap(decodedImage.ImgWidth, decodedImage.ImgHeight, pixelFormat);

            Coord numTiles = decodedImage.getNumTiles(null);

            int tIdx = 0;

            for (int y = 0; y < numTiles.y; y++)
            {
                // Loop on horizontal tiles
                for (int x = 0; x < numTiles.x; x++, tIdx++)
                {
                    decodedImage.setTile(x, y);

                    int height = decodedImage.getTileCompHeight(tIdx, 0);
                    int width = decodedImage.getTileCompWidth(tIdx, 0);

                    int tOffx = decodedImage.getCompULX(0) -
                        (int)Math.Ceiling(decodedImage.ImgULX /
                           (double)decodedImage.getCompSubsX(0));

                    int tOffy = decodedImage.getCompULY(0) -
                        (int)Math.Ceiling(decodedImage.ImgULY /
                            (double)decodedImage.getCompSubsY(0));

                    DataBlkInt[] db = new DataBlkInt[numComps];
                    int[] ls = new int[numComps];
                    int[] mv = new int[numComps];
                    int[] fb = new int[numComps];
                    for (int i = 0; i < numComps; i++)
                    {
                        db[i] = new DataBlkInt();
                        ls[i] = 1 << (decodedImage.getNomRangeBits(0) - 1);
                        mv[i] = (1 << decodedImage.getNomRangeBits(0)) - 1;
                        fb[i] = decodedImage.getFixedPoint(0);
                    }
                    for (int l = 0; l < height; l++)
                    {
                        for (int i = numComps - 1; i >= 0; i--)
                        {
                            db[i].ulx = 0;
                            db[i].uly = l;
                            db[i].w = width;
                            db[i].h = 1;
                            decodedImage.getInternCompData(db[i], i);
                        }
                        int[] k = new int[numComps];
                        for (int i = numComps - 1; i >= 0; i--) k[i] = db[i].offset + width - 1;

                        byte[] rowvalues = new byte[width * bytesPerPixel];

                        for (int i = width - 1; i >= 0; i--)
                        {
                            int[] tmp = new int[numComps];
                            for (int j = numComps - 1; j >= 0; j--)
                            {
                                tmp[j] = (db[j].data_array[k[j]--] >> fb[j]) + ls[j];
                                tmp[j] = (tmp[j] < 0) ? 0 : ((tmp[j] > mv[j]) ? mv[j] : tmp[j]);

                                if (decodedImage.getNomRangeBits(j) != 8)
                                    tmp[j] = (int)Math.Round(((double)tmp[j] / Math.Pow(2D, (double)decodedImage.getNomRangeBits(j))) * 255D);

                            }
                            int offset = i * bytesPerPixel;
                            switch (numComps)
                            {
                                case 1:
                                    rowvalues[offset + 0] = (byte)tmp[0];
                                    rowvalues[offset + 1] = (byte)tmp[0];
                                    rowvalues[offset + 2] = (byte)tmp[0];
                                    break;
                                case 3:
                                    rowvalues[offset + 0] = (byte)tmp[2];
                                    rowvalues[offset + 1] = (byte)tmp[1];
                                    rowvalues[offset + 2] = (byte)tmp[0];
                                    break;
                                case 4:
                                    rowvalues[offset + 0] = (byte)tmp[3];
                                    rowvalues[offset + 1] = (byte)tmp[2];
                                    rowvalues[offset + 2] = (byte)tmp[1];
                                    rowvalues[offset + 3] = (byte)tmp[0];
                                    break;
                            }
                        }

                        BitmapData dstdata = dst.LockBits(
                            new System.Drawing.Rectangle(tOffx, tOffy + l, width, 1),
                            ImageLockMode.ReadWrite, pixelFormat);

                        IntPtr ptr = dstdata.Scan0;
                        System.Runtime.InteropServices.Marshal.Copy(rowvalues, 0, ptr, rowvalues.Length);
                        dst.UnlockBits(dstdata);
                    }
                }
            }
            return dst;
        }
Example #5
0
        /// <summary> Returns, in the blk argument, the block of image data containing the
        /// specifed rectangular area, in the specified component. The data is
        /// returned, as a reference to the internal data, if any, instead of as a
        /// copy, therefore the returned data should not be modified.
        /// 
        /// <P> After being read the coefficients are level shifted by subtracting
        /// 2^(nominal bit range - 1)
        /// 
        /// <P>The rectangular area to return is specified by the 'ulx', 'uly', 'w'
        /// and 'h' members of the 'blk' argument, relative to the current
        /// tile. These members are not modified by this method. The 'offset' and
        /// 'scanw' of the returned data can be arbitrary. See the 'DataBlk' class.
        /// 
        /// <P>If the data array in <tt>blk</tt> is <tt>null</tt>, then a new one
        /// is created if necessary. The implementation of this interface may
        /// choose to return the same array or a new one, depending on what is more
        /// efficient. Therefore, the data array in <tt>blk</tt> prior to the
        /// method call should not be considered to contain the returned data, a
        /// new array may have been created. Instead, get the array from
        /// <tt>blk</tt> after the method has returned.
        /// 
        /// <P>The returned data always has its 'progressive' attribute unset
        /// (i.e. false).
        /// 
        /// <P>When an I/O exception is encountered the JJ2KExceptionHandler is
        /// used. The exception is passed to its handleException method. The action
        /// that is taken depends on the action that has been registered in
        /// JJ2KExceptionHandler. See JJ2KExceptionHandler for details.
        /// 
        /// <P>This method implements buffering for the 3 components: When the
        /// first one is asked, all the 3 components are read and stored until they
        /// are needed.
        /// 
        /// </summary>
        /// <param name="blk">Its coordinates and dimensions specify the area to
        /// return. Some fields in this object are modified to return the data.
        /// 
        /// </param>
        /// <param name="c">The index of the component from which to get the data. Only 0,
        /// 1 and 3 are valid.
        /// 
        /// </param>
        /// <returns> The requested DataBlk
        /// 
        /// </returns>
        /// <seealso cref="getCompData">
        /// 
        /// </seealso>
        /// <seealso cref="JJ2KExceptionHandler">
        /// 
        /// </seealso>
        public override DataBlk getInternCompData(DataBlk blk, int c)
        {
            // Check component index
            if (c < 0 || c > 2)
                throw new System.ArgumentException();

            // Check type of block provided as an argument
            if (blk.DataType != DataBlk.TYPE_INT)
            {
                if (intBlk == null)
                    intBlk = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);
                else
                {
                    intBlk.ulx = blk.ulx;
                    intBlk.uly = blk.uly;
                    intBlk.w = blk.w;
                    intBlk.h = blk.h;
                }
                blk = intBlk;
            }

            // If asking a component for the first time for this block, read all of the components
            if ((barr == null) || (dbi.ulx > blk.ulx) || (dbi.uly > blk.uly) || (dbi.ulx + dbi.w < blk.ulx + blk.w) || (dbi.uly + dbi.h < blk.uly + blk.h))
            {
                int i;
                int[] red, green, blue, alpha;
                int componentCount = (image.PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3;

                barr = new int[componentCount][];

                // Reset data arrays if needed
                if (barr[c] == null || barr[c].Length < blk.w * blk.h)
                {
                    barr[c] = new int[blk.w * blk.h];
                }
                blk.Data = barr[c];

                i = (c + 1) % 3;
                if (barr[i] == null || barr[i].Length < blk.w * blk.h)
                {
                    barr[i] = new int[blk.w * blk.h];
                }
                i = (c + 2) % 3;
                if (barr[i] == null || barr[i].Length < blk.w * blk.h)
                {
                    barr[i] = new int[blk.w * blk.h];
                }

                if (componentCount == 4)
                {
                    if (barr[3] == null || barr[3].Length < blk.w * blk.h)
                        barr[3] = new int[blk.w * blk.h];
                }

                // set attributes of the DataBlk used for buffering
                dbi.ulx = blk.ulx;
                dbi.uly = blk.uly;
                dbi.w = blk.w;
                dbi.h = blk.h;

                red = barr[0];
                green = barr[1];
                blue = barr[2];
                alpha = (componentCount == 4) ? barr[3] : null;

                Bitmap bitmap = (Bitmap)image;
                BitmapData data = bitmap.LockBits(new Rectangle(blk.ulx, blk.uly, blk.w, blk.h), ImageLockMode.ReadOnly,
                    (componentCount == 3) ? PixelFormat.Format24bppRgb : PixelFormat.Format32bppArgb);
                unsafe
                {
                    byte* ptr = (byte*)data.Scan0.ToPointer();
                    
                    int k = 0;
                    for (int j = 0; j < blk.w * blk.h; j++)
                    {
                        blue[k] = ((byte)*(ptr + 0) & 0xFF) - 128;
                        green[k] = ((byte)*(ptr + 1) & 0xFF) - 128;
                        red[k] = ((byte)*(ptr + 2) & 0xFF) - 128;
                        if (componentCount == 4)
                            alpha[k] = ((byte)*(ptr + 3) & 0xFF) - 128;

                        ++k;
                        ptr += 3;
                    }
                }
                bitmap.UnlockBits(data);

                barr[0] = red;
                barr[1] = green;
                barr[2] = blue;
                if (componentCount == 4)
                    barr[3] = alpha;

                // Set buffer attributes
                blk.Data = barr[c];
                blk.offset = 0;
                blk.scanw = blk.w;
            }
            else
            {
                //Asking for the 2nd or 3rd (or 4th) block component
                blk.Data = barr[c];
                blk.offset = (blk.ulx - dbi.ulx) * dbi.w + blk.ulx - dbi.ulx;
                blk.scanw = dbi.scanw;
            }

            // Turn off the progressive attribute
            blk.progressive = false;
            return blk;
        }
Example #6
0
 /// <summary> Closes the underlying file or netwrok connection to where the data is
 /// written. Any call to other methods of the class become illegal after a
 /// call to this one.
 /// 
 /// </summary>
 /// <exception cref="IOException">If an I/O error occurs.
 /// 
 /// </exception>
 public override void close()
 {
     int i;
     // Finish writing the file, writing 0s at the end if the data at end
     // has not been written.
     if (out_Renamed.Length != 3 * w * h + offset)
     {
         // Goto end of file
         out_Renamed.Seek(out_Renamed.Length, System.IO.SeekOrigin.Begin);
         // Fill with 0s n all the components
         for (i = 3 * w * h + offset - (int) out_Renamed.Length; i > 0; i--)
         {
             out_Renamed.WriteByte((System.Byte) 0);
         }
     }
     out_Renamed.Dispose();
     src = null;
     out_Renamed = null;
     db = null;
 }
Example #7
0
        /// <summary> Returns a block of image data containing the specifed rectangular area,
        /// in the specified component, as a reference to the internal buffer (see
        /// below). The rectangular area is specified by the coordinates and
        /// dimensions of the 'blk' object.
        /// 
        /// <p>The area to return is specified by the 'ulx', 'uly', 'w' and 'h'
        /// members of the 'blk' argument. These members are not modified by this
        /// method.</p>
        /// 
        /// <p>The data returned by this method can be the data in the internal
        /// buffer of this object, if any, and thus can not be modified by the
        /// caller. The 'offset' and 'scanw' of the returned data can be
        /// arbitrary. See the 'DataBlk' class.</p>
        /// 
        /// <p>The returned data has its 'progressive' attribute unset
        /// (i.e. false).</p>
        /// 
        /// </summary>
        /// <param name="blk">Its coordinates and dimensions specify the area to return.
        /// 
        /// </param>
        /// <param name="c">The index of the component from which to get the data.
        /// 
        /// </param>
        /// <returns> The requested DataBlk
        /// 
        /// </returns>
        /// <seealso cref="getInternCompData">
        /// 
        /// </seealso>
        public override DataBlk getInternCompData(DataBlk blk, int c)
        {
            int tIdx = TileIdx;
            if (src.getSynSubbandTree(tIdx, c).HorWFilter == null)
            {
                dtype = DataBlk.TYPE_INT;
            }
            else
            {
                dtype = src.getSynSubbandTree(tIdx, c).HorWFilter.DataType;
            }

            //If the source image has not been decomposed
            if (reconstructedComps[c] == null)
            {
                //Allocate component data buffer
                switch (dtype)
                {

                    case DataBlk.TYPE_FLOAT:
                        reconstructedComps[c] = new DataBlkFloat(0, 0, getTileCompWidth(tIdx, c), getTileCompHeight(tIdx, c));
                        break;

                    case DataBlk.TYPE_INT:
                        reconstructedComps[c] = new DataBlkInt(0, 0, getTileCompWidth(tIdx, c), getTileCompHeight(tIdx, c));
                        break;
                    }
                //Reconstruct source image
                waveletTreeReconstruction(reconstructedComps[c], src.getSynSubbandTree(tIdx, c), c);
            }

            if (blk.DataType != dtype)
            {
                if (dtype == DataBlk.TYPE_INT)
                {
                    blk = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);
                }
                else
                {
                    blk = new DataBlkFloat(blk.ulx, blk.uly, blk.w, blk.h);
                }
            }
            // Set the reference to the internal buffer
            blk.Data = reconstructedComps[c].Data;
            blk.offset = reconstructedComps[c].w * blk.uly + blk.ulx;
            blk.scanw = reconstructedComps[c].w;
            blk.progressive = false;
            return blk;
        }
Example #8
0
		/// <summary> Return a DataBlk containing the requested component
		/// upsampled by the scale factor applied to the particular
		/// scaling direction
		/// 
		/// Returns, in the blk argument, a block of image data containing the
		/// specifed rectangular area, in the specified component. The data is
		/// returned, as a copy of the internal data, therefore the returned data
		/// can be modified "in place".
		/// 
		/// <P>The rectangular area to return is specified by the 'ulx', 'uly', 'w'
		/// and 'h' members of the 'blk' argument, relative to the current
		/// tile. These members are not modified by this method. The 'offset' of
		/// the returned data is 0, and the 'scanw' is the same as the block's
		/// width. See the 'DataBlk' class.
		/// 
		/// <P>If the data array in 'blk' is 'null', then a new one is created. If
		/// the data array is not 'null' then it is reused, and it must be large
		/// enough to contain the block's data. Otherwise an 'ArrayStoreException'
		/// or an 'IndexOutOfBoundsException' is thrown by the Java system.
		/// 
		/// <P>The returned data has its 'progressive' attribute set to that of the
		/// input data.
		/// 
		/// </summary>
		/// <param name="blk">Its coordinates and dimensions specify the area to
		/// return. If it contains a non-null data array, then it must have the
		/// correct dimensions. If it contains a null data array a new one is
		/// created. The fields in this object are modified to return the data.
		/// 
		/// </param>
		/// <param name="c">The index of the component from which to get the data. Only 0
		/// and 3 are valid.
		/// 
		/// </param>
		/// <returns> The requested DataBlk
		/// 
		/// </returns>
		/// <seealso cref="getCompData">
		/// </seealso>
		public override DataBlk getInternCompData(DataBlk outblk, int c)
		{
			
			// If the scaling factor of this channel is 1 in both
			// directions, simply return the source DataBlk.
			
			if (src.getCompSubsX(c) == 1 && src.getCompSubsY(c) == 1)
				return src.getInternCompData(outblk, c);
			
			int wfactor = src.getCompSubsX(c);
			int hfactor = src.getCompSubsY(c);
			if ((wfactor != 2 && wfactor != 1) || (hfactor != 2 && hfactor != 1))
				throw new System.ArgumentException("Upsampling by other than 2:1" + " not supported");
			
			int leftedgeOut = - 1; // offset to the start of the output scanline
			int rightedgeOut = - 1; // offset to the end of the output
			// scanline + 1
			int leftedgeIn = - 1; // offset to the start of the input scanline  
			int rightedgeIn = - 1; // offset to the end of the input scanline + 1
			
			
			int y0In, y1In, y0Out, y1Out;
			int x0In, x1In, x0Out, x1Out;
			
			y0Out = outblk.uly;
			y1Out = y0Out + outblk.h - 1;
			
			x0Out = outblk.ulx;
			x1Out = x0Out + outblk.w - 1;
			
			y0In = y0Out / hfactor;
			y1In = y1Out / hfactor;
			
			x0In = x0Out / wfactor;
			x1In = x1Out / wfactor;
			
			
			// Calculate the requested height and width, requesting an extra
			// row and or for upsampled channels.
			int reqW = x1In - x0In + 1;
			int reqH = y1In - y0In + 1;
			
			// Initialize general input and output indexes
			int kOut = - 1;
			int kIn = - 1;
			int yIn;
			
			switch (outblk.DataType)
			{
				
				
				case DataBlk.TYPE_INT: 
					
					DataBlkInt inblkInt = new DataBlkInt(x0In, y0In, reqW, reqH);
					inblkInt = (DataBlkInt) src.getInternCompData(inblkInt, c);
					dataInt[c] = inblkInt.DataInt;
					
					// Reference the working array   
					int[] outdataInt = (int[]) outblk.Data;
					
					// Create data array if necessary
					if (outdataInt == null || outdataInt.Length != outblk.w * outblk.h)
					{
						outdataInt = new int[outblk.h * outblk.w];
						outblk.Data = outdataInt;
					}
					
					// The nitty-gritty.
					
					for (int yOut = y0Out; yOut <= y1Out; ++yOut)
					{
						
						yIn = yOut / hfactor;
						
						
						leftedgeIn = inblkInt.offset + (yIn - y0In) * inblkInt.scanw;
						rightedgeIn = leftedgeIn + inblkInt.w;
						leftedgeOut = outblk.offset + (yOut - y0Out) * outblk.scanw;
						rightedgeOut = leftedgeOut + outblk.w;
						
						kIn = leftedgeIn;
						kOut = leftedgeOut;
						
						if ((x0Out & 0x1) == 1)
						{
							// first is odd do the pixel once.
							outdataInt[kOut++] = dataInt[c][kIn++];
						}
						
						if ((x1Out & 0x1) == 0)
						{
							// last is even adjust loop bounds
							rightedgeOut--;
						}
						
						while (kOut < rightedgeOut)
						{
							outdataInt[kOut++] = dataInt[c][kIn];
							outdataInt[kOut++] = dataInt[c][kIn++];
						}
						
						if ((x1Out & 0x1) == 0)
						{
							// last is even do the pixel once.
							outdataInt[kOut++] = dataInt[c][kIn];
						}
					}
					
					outblk.progressive = inblkInt.progressive;
					break;
				
				
				case DataBlk.TYPE_FLOAT: 
					
					DataBlkFloat inblkFloat = new DataBlkFloat(x0In, y0In, reqW, reqH);
					inblkFloat = (DataBlkFloat) src.getInternCompData(inblkFloat, c);
					dataFloat[c] = inblkFloat.DataFloat;
					
					// Reference the working array   
					float[] outdataFloat = (float[]) outblk.Data;
					
					// Create data array if necessary
					if (outdataFloat == null || outdataFloat.Length != outblk.w * outblk.h)
					{
						outdataFloat = new float[outblk.h * outblk.w];
						outblk.Data = outdataFloat;
					}
					
					// The nitty-gritty.
					
					for (int yOut = y0Out; yOut <= y1Out; ++yOut)
					{
						
						yIn = yOut / hfactor;
						
						
						leftedgeIn = inblkFloat.offset + (yIn - y0In) * inblkFloat.scanw;
						rightedgeIn = leftedgeIn + inblkFloat.w;
						leftedgeOut = outblk.offset + (yOut - y0Out) * outblk.scanw;
						rightedgeOut = leftedgeOut + outblk.w;
						
						kIn = leftedgeIn;
						kOut = leftedgeOut;
						
						if ((x0Out & 0x1) == 1)
						{
							// first is odd do the pixel once.
							outdataFloat[kOut++] = dataFloat[c][kIn++];
						}
						
						if ((x1Out & 0x1) == 0)
						{
							// last is even adjust loop bounds
							rightedgeOut--;
						}
						
						while (kOut < rightedgeOut)
						{
							outdataFloat[kOut++] = dataFloat[c][kIn];
							outdataFloat[kOut++] = dataFloat[c][kIn++];
						}
						
						if ((x1Out & 0x1) == 0)
						{
							// last is even do the pixel once.
							outdataFloat[kOut++] = dataFloat[c][kIn];
						}
					}
					
					outblk.progressive = inblkFloat.progressive;
					break;
				
				
				case DataBlk.TYPE_SHORT: 
				case DataBlk.TYPE_BYTE: 
				default: 
					// Unsupported output type. 
					throw new System.ArgumentException("invalid source datablock " + "type");
				}
			
			return outblk;
		}
Example #9
0
		/// <summary> Returns the specified code-block in the current tile for the specified
		/// component, as a copy (see below).
		/// 
		/// <P>The returned code-block may be progressive, which is indicated by
		/// the 'progressive' variable of the returned 'DataBlk' object. If a
		/// code-block is progressive it means that in a later request to this
		/// method for the same code-block it is possible to retrieve data which is
		/// a better approximation, since meanwhile more data to decode for the
		/// code-block could have been received. If the code-block is not
		/// progressive then later calls to this method for the same code-block
		/// will return the exact same data values.
		/// 
		/// <P>The data returned by this method is always a copy of the internal
		/// data of this object, if any, and it can be modified "in place" without
		/// any problems after being returned. The 'offset' of the returned data is
		/// 0, and the 'scanw' is the same as the code-block width. See the
		/// 'DataBlk' class.
		/// 
		/// <P>The 'ulx' and 'uly' members of the returned 'DataBlk' object
		/// contain the coordinates of the top-left corner of the block, with
		/// respect to the tile, not the subband.
		/// 
		/// </summary>
		/// <param name="c">The component for which to return the next code-block.
		/// 
		/// </param>
		/// <param name="m">The vertical index of the code-block to return, in the
		/// specified subband.
		/// 
		/// </param>
		/// <param name="n">The horizontal index of the code-block to return, in the
		/// specified subband.
		/// 
		/// </param>
		/// <param name="sb">The subband in which the code-block to return is.
		/// 
		/// </param>
		/// <param name="cblk">If non-null this object will be used to return the new
		/// code-block. If null a new one will be allocated and returned. If the
		/// "data" array of the object is non-null it will be reused, if possible,
		/// to return the data.
		/// 
		/// </param>
		/// <returns> The next code-block in the current tile for component 'n', or
		/// null if all code-blocks for the current tile have been returned.
		/// 
		/// </returns>
		/// <seealso cref="DataBlk">
		/// 
		/// </seealso>
		public override DataBlk getCodeBlock(int c, int m, int n, SubbandSyn sb, DataBlk cblk)
		{
			//long stime = 0L; // Start time for timed sections
			int[] zc_lut; // The ZC lookup table to use
			int[] out_data; // The outupt data buffer
			int npasses; // The number of coding passes to perform
			int curbp; // The current magnitude bit-plane (starts at 30)
			bool error; // Error indicator
			int tslen; // Length of first terminated segment
			int tsidx; // Index of current terminated segment
			ByteInputBuffer in_Renamed = null;
			
			bool isterm;
			
			// Get the code-block to decode
			srcblk = src.getCodeBlock(c, m, n, sb, 1, - 1, srcblk);
			
#if DO_TIMING
			stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
#endif

			// Retrieve options from decSpec
			options = ((System.Int32) decSpec.ecopts.getTileCompVal(tIdx, c));
			
			// Reset state
			ArrayUtil.intArraySet(state, 0);
			
			// Initialize output code-block
			if (cblk == null)
				cblk = new DataBlkInt();
			cblk.progressive = srcblk.prog;
			cblk.ulx = srcblk.ulx;
			cblk.uly = srcblk.uly;
			cblk.w = srcblk.w;
			cblk.h = srcblk.h;
			cblk.offset = 0;
			cblk.scanw = cblk.w;
			out_data = (int[]) cblk.Data;
			
			if (out_data == null || out_data.Length < srcblk.w * srcblk.h)
			{
				out_data = new int[srcblk.w * srcblk.h];
				cblk.Data = out_data;
			}
			else
			{
				// Set data values to 0
				ArrayUtil.intArraySet(out_data, 0);
			}
			
			if (srcblk.nl <= 0 || srcblk.nTrunc <= 0)
			{
				// 0 layers => no data to decode => return all 0s
				return cblk;
			}
			
			// Get the length of the first terminated segment
			tslen = (srcblk.tsLengths == null)?srcblk.dl:srcblk.tsLengths[0];
			tsidx = 0;
			// Initialize for decoding
			npasses = srcblk.nTrunc;
			if (mq == null)
			{
				in_Renamed = new ByteInputBuffer(srcblk.data, 0, tslen);
				mq = new MQDecoder(in_Renamed, NUM_CTXTS, MQ_INIT);
			}
			else
			{
				// We always start by an MQ segment
				mq.nextSegment(srcblk.data, 0, tslen);
				mq.resetCtxts();
			}
			error = false;
			
			if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0)
			{
				if (bin == null)
				{
					if (in_Renamed == null)
						in_Renamed = mq.ByteInputBuffer;
					bin = new ByteToBitInput(in_Renamed);
				}
			}
			
			// Choose correct ZC lookup table for global orientation
			switch (sb.orientation)
			{
				
				case Subband.WT_ORIENT_HL: 
					zc_lut = ZC_LUT_HL;
					break;
				
				case Subband.WT_ORIENT_LH: 
				case Subband.WT_ORIENT_LL: 
					zc_lut = ZC_LUT_LH;
					break;
				
				case Subband.WT_ORIENT_HH: 
					zc_lut = ZC_LUT_HH;
					break;
				
				default: 
					throw new System.ApplicationException("JJ2000 internal error");
				
			}
			
			// NOTE: we don't currently detect which is the last magnitude
			// bit-plane so that 'isterm' is true for the last pass of it. Doing
			// so would aid marginally in error detection with the predictable
			// error resilient MQ termination. However, determining which is the
			// last magnitude bit-plane is quite hard (due to ROI, quantization,
			// etc.)  and in any case the predictable error resilient termination
			// used without the arithmetic coding bypass and/or regular
			// termination modes is almost useless.
			
			// Loop on bit-planes and passes
			
			curbp = 30 - srcblk.skipMSBP;
			
			// Check for maximum number of bitplanes quit condition
			if (mQuit != - 1 && (mQuit * 3 - 2) < npasses)
			{
				npasses = mQuit * 3 - 2;
			}
			
			// First bit-plane has only the cleanup pass
			if (curbp >= 0 && npasses > 0)
			{
				isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP) >= curbp);
				error = cleanuppass(cblk, mq, curbp, state, zc_lut, isterm);
				npasses--;
				if (!error || !doer)
					curbp--;
			}
			
			// Other bit-planes have the three coding passes
			if (!error || !doer)
			{
				while (curbp >= 0 && npasses > 0)
				{
					
					if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (curbp < 31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP))
					{
						// Use bypass decoding mode (only all bit-planes
						// after the first 4 bit-planes).
						
						// Here starts a new raw segment
						bin.setByteArray(null, - 1, srcblk.tsLengths[++tsidx]);
						isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0;
						error = rawSigProgPass(cblk, bin, curbp, state, isterm);
						npasses--;
						if (npasses <= 0 || (error && doer))
							break;
						
						if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
						{
							// Start a new raw segment
							bin.setByteArray(null, - 1, srcblk.tsLengths[++tsidx]);
						}
						isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP > curbp));
						error = rawMagRefPass(cblk, bin, curbp, state, isterm);
					}
					else
					{
						// Do not use bypass decoding mode
						if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
						{
							// Here starts a new MQ segment
							mq.nextSegment(null, - 1, srcblk.tsLengths[++tsidx]);
						}
						isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0;
						error = sigProgPass(cblk, mq, curbp, state, zc_lut, isterm);
						npasses--;
						if (npasses <= 0 || (error && doer))
							break;
						
						if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
						{
							// Here starts a new MQ segment
							mq.nextSegment(null, - 1, srcblk.tsLengths[++tsidx]);
						}
						isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP > curbp));
						error = magRefPass(cblk, mq, curbp, state, isterm);
					}
					
					npasses--;
					if (npasses <= 0 || (error && doer))
						break;
					
					if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (curbp < 31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP)))
					{
						// Here starts a new MQ segment
						mq.nextSegment(null, - 1, srcblk.tsLengths[++tsidx]);
					}
					isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP) >= curbp);
					error = cleanuppass(cblk, mq, curbp, state, zc_lut, isterm);
					npasses--;
					if (error && doer)
						break;
					// Goto next bit-plane
					curbp--;
				}
			}
			
			// If an error ocurred conceal it
			if (error && doer)
			{
				if (verber)
				{
					FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.WARNING, "Error detected at bit-plane " + curbp + " in code-block (" + m + "," + n + "), sb_idx " + sb.sbandIdx + ", res. level " + sb.resLvl + ". Concealing...");
				}
				conceal(cblk, curbp);
			}
			
#if DO_TIMING
			time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
#endif
			
			// Return decoded block
			return cblk;
		}
Example #10
0
        /// <summary>General utility used by ctors </summary>
        private void initialize()
        {
            this.pl = csMap.pl;
            this.ncomps = src.NumComps;

            shiftValueArray = new int[ncomps];
            maxValueArray = new int[ncomps];
            fixedPtBitsArray = new int[ncomps];

            srcBlk = new DataBlk[ncomps];
            inInt = new DataBlkInt[ncomps];
            inFloat = new DataBlkFloat[ncomps];
            workInt = new DataBlkInt[ncomps];
            workFloat = new DataBlkFloat[ncomps];
            dataInt = new int[ncomps][];
            dataFloat = new float[ncomps][];
            workDataInt = new int[ncomps][];
            workDataFloat = new float[ncomps][];
            dataInt = new int[ncomps][];
            dataFloat = new float[ncomps][];

            /* For each component, get a reference to the pixel data and
            * set up working DataBlks for both integer and float output.
            */
            for (int i = 0; i < ncomps; ++i)
            {

                shiftValueArray[i] = 1 << (src.getNomRangeBits(i) - 1);
                maxValueArray[i] = (1 << src.getNomRangeBits(i)) - 1;
                fixedPtBitsArray[i] = src.getFixedPoint(i);

                inInt[i] = new DataBlkInt();
                inFloat[i] = new DataBlkFloat();
                workInt[i] = new DataBlkInt();
                workInt[i].progressive = inInt[i].progressive;
                workFloat[i] = new DataBlkFloat();
                workFloat[i].progressive = inFloat[i].progressive;
            }
        }
Example #11
0
		/// <summary> This functions gets a DataBlk with the size of the current code-block
		/// and fills it with the ROI mask. The lowest scaling value in the mask
		/// for this code-block is returned by the function to be used for
		/// modifying the rate distortion estimations.
		/// 
		/// </summary>
		/// <param name="db">The data block that is to be filled with the mask
		/// 
		/// </param>
		/// <param name="sb">The root of the current subband tree
		/// 
		/// </param>
		/// <param name="magbits">The number of magnitude bits in this code-block
		/// 
		/// </param>
		/// <param name="c">Component number
		/// 
		/// </param>
		/// <returns> Whether or not a mask was needed for this tile 
		/// </returns>
		public abstract bool getROIMask(DataBlkInt db, Subband sb, int magbits, int c);
Example #12
0
        /// <summary> Writes the data of the specified area to the file, coordinates are
        /// relative to the current tile of the source. Before writing, the
        /// coefficients are limited to the nominal range.
        /// 
        /// <p>This method may not be called concurrently from different
        /// threads.</p>
        /// 
        /// <p>If the data returned from the BlkImgDataSrc source is progressive,
        /// then it is requested over and over until it is not progressive
        /// anymore.</p>
        /// 
        /// </summary>
        /// <param name="ulx">The horizontal coordinate of the upper-left corner of the
        /// area to write, relative to the current tile.
        /// 
        /// </param>
        /// <param name="uly">The vertical coordinate of the upper-left corner of the area
        /// to write, relative to the current tile.
        /// 
        /// </param>
        /// <param name="width">The width of the area to write.
        /// 
        /// </param>
        /// <param name="height">The height of the area to write.
        /// 
        /// </param>
        /// <exception cref="IOException">If an I/O error occurs.
        /// 
        /// </exception>
        public override void write(int ulx, int uly, int w, int h)
        {
            int k, i, j;
            int fracbits = fb; // In local variable for faster access
            int tOffx, tOffy; // Active tile offset in the X and Y direction

            // Initialize db
            db.ulx = ulx;
            db.uly = uly;
            db.w = w;
            db.h = h;
            // Get the current active tile offset
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            tOffx = src.getCompULX(c) - (int) System.Math.Ceiling(src.ImgULX / (double) src.getCompSubsX(c));
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            tOffy = src.getCompULY(c) - (int) System.Math.Ceiling(src.ImgULY / (double) src.getCompSubsY(c));
            // Check the array size
            if (db.data_array != null && db.data_array.Length < w * h)
            {
                // A new one will be allocated by getInternCompData()
                db.data_array = null;
            }
            // Request the data and make sure it is not
            // progressive
            do
            {
                db = (DataBlkInt) src.getInternCompData(db, c);
            }
            while (db.progressive);

            // variables used during coeff saturation
            int tmp, maxVal = (1 << src.getNomRangeBits(c)) - 1;

            // If nominal bitdepth greater than 8, calculate down shift
            int downShift = src.getNomRangeBits(c) - 8;
            if (downShift < 0)
            {
                downShift = 0;
            }

            // Check line buffer
            if (buf == null || buf.Length < w)
            {
                buf = new byte[w]; // Expand buffer
            }

            // Write line by line
            for (i = 0; i < h; i++)
            {
                // Skip to beggining of line in file
                out_Renamed.Seek(this.offset + this.w * (uly + tOffy + i) + ulx + tOffx, System.IO.SeekOrigin.Begin);
                // Write all bytes in the line
                if (fracbits == 0)
                {
                    for (k = db.offset + i * db.scanw + w - 1, j = w - 1; j >= 0; j--, k--)
                    {
                        tmp = db.data_array[k] + levShift;
                        buf[j] = (byte) (((tmp < 0)?0:((tmp > maxVal)?maxVal:tmp)) >> downShift);
                    }
                }
                else
                {
                    for (k = db.offset + i * db.scanw + w - 1, j = w - 1; j >= 0; j--, k--)
                    {
                        tmp = (db.data_array[k] >> fracbits) + levShift;
                        buf[j] = (byte) (((tmp < 0)?0:((tmp > maxVal)?maxVal:tmp)) >> downShift);
                    }
                }
                out_Renamed.Write(buf, 0, w);
            }
        }
Example #13
0
        /// <summary> Returns, in the blk argument, the block of image data containing the
        /// specifed rectangular area, in the specified component. The data is
        /// returned, as a reference to the internal data, if any, instead of as a
        /// copy, therefore the returned data should not be modified.
        /// 
        /// <P> After being read the coefficients are level shifted by subtracting
        /// 2^(nominal bit range - 1)
        /// 
        /// <P>The rectangular area to return is specified by the 'ulx', 'uly', 'w'
        /// and 'h' members of the 'blk' argument, relative to the current
        /// tile. These members are not modified by this method. The 'offset' and
        /// 'scanw' of the returned data can be arbitrary. See the 'DataBlk' class.
        /// 
        /// <P>If the data array in <tt>blk</tt> is <tt>null</tt>, then a new one
        /// is created if necessary. The implementation of this interface may
        /// choose to return the same array or a new one, depending on what is more
        /// efficient. Therefore, the data array in <tt>blk</tt> prior to the
        /// method call should not be considered to contain the returned data, a
        /// new array may have been created. Instead, get the array from
        /// <tt>blk</tt> after the method has returned.
        /// 
        /// <P>The returned data always has its 'progressive' attribute unset
        /// (i.e. false).
        /// 
        /// <P>When an I/O exception is encountered the JJ2KExceptionHandler is
        /// used. The exception is passed to its handleException method. The action
        /// that is taken depends on the action that has been registered in
        /// JJ2KExceptionHandler. See JJ2KExceptionHandler for details.
        /// 
        /// <P>This method implements buffering for the 3 components: When the
        /// first one is asked, all the 3 components are read and stored until they
        /// are needed.
        /// 
        /// </summary>
        /// <param name="blk">Its coordinates and dimensions specify the area to
        /// return. Some fields in this object are modified to return the data.
        /// 
        /// </param>
        /// <param name="c">The index of the component from which to get the data. Only 0,
        /// 1 and 3 are valid.
        /// 
        /// </param>
        /// <returns> The requested DataBlk
        /// 
        /// </returns>
        /// <seealso cref="getCompData">
        /// 
        /// </seealso>
        /// <seealso cref="JJ2KExceptionHandler">
        /// 
        /// </seealso>
        public override DataBlk getInternCompData(DataBlk blk, int c)
        {
            // Check component index
            if (c < 0 || c > 2)
                throw new System.ArgumentException();

            // Check type of block provided as an argument
            if (blk.DataType != DataBlk.TYPE_INT)
            {
                if (intBlk == null)
                    intBlk = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);
                else
                {
                    intBlk.ulx = blk.ulx;
                    intBlk.uly = blk.uly;
                    intBlk.w = blk.w;
                    intBlk.h = blk.h;
                }
                blk = intBlk;
            }

            // If asking a component for the first time for this block, read the 3
            // components
            if ((barr[c] == null) || (dbi.ulx > blk.ulx) || (dbi.uly > blk.uly) || (dbi.ulx + dbi.w < blk.ulx + blk.w) || (dbi.uly + dbi.h < blk.uly + blk.h))
            {
                int k, j, i, mi;
                int[] red, green, blue;

                // Reset data arrays if needed
                if (barr[c] == null || barr[c].Length < blk.w * blk.h)
                {
                    barr[c] = new int[blk.w * blk.h];
                }
                blk.Data = barr[c];

                i = (c + 1) % 3;
                if (barr[i] == null || barr[i].Length < blk.w * blk.h)
                {
                    barr[i] = new int[blk.w * blk.h];
                }
                i = (c + 2) % 3;
                if (barr[i] == null || barr[i].Length < blk.w * blk.h)
                {
                    barr[i] = new int[blk.w * blk.h];
                }

                // set attributes of the DataBlk used for buffering
                dbi.ulx = blk.ulx;
                dbi.uly = blk.uly;
                dbi.w = blk.w;
                dbi.h = blk.h;

                // Check line buffer
                if (buf == null || buf.Length < 3 * blk.w)
                {
                    buf = new byte[3 * blk.w];
                }

                red = barr[0];
                green = barr[1];
                blue = barr[2];

                try
                {
                    // Read line by line
                    mi = blk.uly + blk.h;
                    for (i = blk.uly; i < mi; i++)
                    {
                        // Reposition in input offset takes care of
                        // header offset
                        in_Renamed.Seek(offset + i * 3 * w + 3 * blk.ulx, System.IO.SeekOrigin.Begin);
                        in_Renamed.Read(buf, 0, 3 * blk.w);

                        for (k = (i - blk.uly) * blk.w + blk.w - 1, j = 3 * blk.w - 1; j >= 0; k--)
                        {
                            // Read every third sample
                            blue[k] = (((byte) buf[j--]) & 0xFF) - DC_OFFSET;
                            green[k] = (((byte) buf[j--]) & 0xFF) - DC_OFFSET;
                            red[k] = (((byte) buf[j--]) & 0xFF) - DC_OFFSET;
                        }
                    }
                }
                catch (System.IO.IOException e)
                {
                    JJ2KExceptionHandler.handleException(e);
                }
                barr[0] = red;
                barr[1] = green;
                barr[2] = blue;

                // Set buffer attributes
                blk.Data = barr[c];
                blk.offset = 0;
                blk.scanw = blk.w;
            }
            else
            {
                //Asking for the 2nd or 3rd block component
                blk.Data = barr[c];
                blk.offset = (blk.ulx - dbi.ulx) * dbi.w + blk.ulx - dbi.ulx;
                blk.scanw = dbi.scanw;
            }

            // Turn off the progressive attribute
            blk.progressive = false;
            return blk;
        }
Example #14
0
		/// <summary>General utility used by ctors </summary>
		private void  initialize()
		{
			
			tempInt = new DataBlkInt[ncomps];
			tempFloat = new DataBlkFloat[ncomps];
			
			/* For each component, get the maximum data value, a reference
			* to the pixel data and set up working and temporary DataBlks
			* for both integer and float output.
			*/
			for (int i = 0; i < ncomps; ++i)
			{
				tempInt[i] = new DataBlkInt();
				tempFloat[i] = new DataBlkFloat();
			}
		}
Example #15
0
		/// <summary> Returns the next code-block in the current tile for the specified
		/// component. The order in which code-blocks are returned is not
		/// specified. However each code-block is returned only once and all
		/// code-blocks will be returned if the method is called 'N' times, where
		/// 'N' is the number of code-blocks in the tile. After all the code-blocks
		/// have been returned for the current tile calls to this method will
		/// return 'null'.
		/// 
		/// <p>When changing the current tile (through 'setTile()' or 'nextTile()')
		/// this method will always return the first code-block, as if this method
		/// was never called before for the new current tile.</p>
		/// 
		/// <p>The data returned by this method is the data in the internal buffer
		/// of this object, and thus can not be modified by the caller. The
		/// 'offset' and 'scanw' of the returned data have, in general, some
		/// non-zero value. The 'magbits' of the returned data is not set by this
		/// method and should be ignored. See the 'CBlkWTData' class.</p>
		/// 
		/// <p>The 'ulx' and 'uly' members of the returned 'CBlkWTData' object
		/// contain the coordinates of the top-left corner of the block, with
		/// respect to the tile, not the subband.</p>
		/// 
		/// </summary>
		/// <param name="c">The component for which to return the next code-block.
		/// 
		/// </param>
		/// <param name="cblk">If non-null this object will be used to return the new
		/// code-block. If null a new one will be allocated and returned.
		/// 
		/// </param>
		/// <returns> The next code-block in the current tile for component 'n', or
		/// null if all code-blocks for the current tile have been returned.
		/// 
		/// </returns>
		/// <seealso cref="CBlkWTData">
		/// 
		/// </seealso>
		public override CBlkWTData getNextInternCodeBlock(int c, CBlkWTData cblk)
		{
			int cbm, cbn, cn, cm;
			int acb0x, acb0y;
			SubbandAn sb;
			intData = (filters.getWTDataType(tIdx, c) == DataBlk.TYPE_INT);
			
			//If the source image has not been decomposed 
			if (decomposedComps[c] == null)
			{
				int k, w, h;
				DataBlk bufblk;
				System.Object dst_data;
				
				w = getTileCompWidth(tIdx, c);
				h = getTileCompHeight(tIdx, c);
				
				//Get the source image data
				if (intData)
				{
					decomposedComps[c] = new DataBlkInt(0, 0, w, h);
					bufblk = new DataBlkInt();
				}
				else
				{
					decomposedComps[c] = new DataBlkFloat(0, 0, w, h);
					bufblk = new DataBlkFloat();
				}
				
				// Get data from source line by line (this diminishes the memory
				// requirements on the data source)
				dst_data = decomposedComps[c].Data;
				int lstart = getCompULX(c);
				bufblk.ulx = lstart;
				bufblk.w = w;
				bufblk.h = 1;
				int kk = getCompULY(c);
				for (k = 0; k < h; k++, kk++)
				{
					bufblk.uly = kk;
					bufblk.ulx = lstart;
					bufblk = src.getInternCompData(bufblk, c);
                    // CONVERSION PROBLEM?
					Array.Copy((System.Array)bufblk.Data, bufblk.offset, (System.Array)dst_data, k * w, w);
				}
				
				//Decompose source image
				waveletTreeDecomposition(decomposedComps[c], getAnSubbandTree(tIdx, c), c);
				
				// Make the first subband the current one
				currentSubband[c] = getNextSubband(c);
				
				lastn[c] = - 1;
				lastm[c] = 0;
			}
			
			// Get the next code-block to "send"
			do 
			{
				// Calculate number of code-blocks in current subband
				ncblks = currentSubband[c].numCb;
				// Goto next code-block
				lastn[c]++;
				if (lastn[c] == ncblks.x)
				{
					// Got to end of this row of
					// code-blocks
					lastn[c] = 0;
					lastm[c]++;
				}
				if (lastm[c] < ncblks.y)
				{
					// Not past the last code-block in the subband, we can return
					// this code-block
					break;
				}
				// If we get here we already sent all code-blocks in this subband,
				// goto next subband
				currentSubband[c] = getNextSubband(c);
				lastn[c] = - 1;
				lastm[c] = 0;
				if (currentSubband[c] == null)
				{
					// We don't need the transformed data any more (a priori)
					decomposedComps[c] = null;
					// All code-blocks from all subbands in the current
					// tile have been returned so we return a null
					// reference
					return null;
				}
				// Loop to find the next code-block
			}
			while (true);
			
			
			// Project code-block partition origin to subband. Since the origin is
			// always 0 or 1, it projects to the low-pass side (throught the ceil
			// operator) as itself (i.e. no change) and to the high-pass side
			// (through the floor operator) as 0, always.
			acb0x = cb0x;
			acb0y = cb0y;
			switch (currentSubband[c].sbandIdx)
			{
				
				case Subband.WT_ORIENT_LL: 
					// No need to project since all low-pass => nothing to do
					break;
				
				case Subband.WT_ORIENT_HL: 
					acb0x = 0;
					break;
				
				case Subband.WT_ORIENT_LH: 
					acb0y = 0;
					break;
				
				case Subband.WT_ORIENT_HH: 
					acb0x = 0;
					acb0y = 0;
					break;
				
				default: 
					throw new System.ApplicationException("Internal JJ2000 error");
				
			}
			
			// Initialize output code-block
			if (cblk == null)
			{
				if (intData)
				{
					cblk = new CBlkWTDataInt();
				}
				else
				{
					cblk = new CBlkWTDataFloat();
				}
			}
			cbn = lastn[c];
			cbm = lastm[c];
			sb = currentSubband[c];
			cblk.n = cbn;
			cblk.m = cbm;
			cblk.sb = sb;
			// Calculate the indexes of first code-block in subband with respect
			// to the partitioning origin, to then calculate the position and size
			// NOTE: when calculating "floor()" by integer division the dividend
			// and divisor must be positive, we ensure that by adding the divisor
			// to the dividend and then substracting 1 to the result of the
			// division
			cn = (sb.ulcx - acb0x + sb.nomCBlkW) / sb.nomCBlkW - 1;
			cm = (sb.ulcy - acb0y + sb.nomCBlkH) / sb.nomCBlkH - 1;
			if (cbn == 0)
			{
				// Left-most code-block, starts where subband starts
				cblk.ulx = sb.ulx;
			}
			else
			{
				// Calculate starting canvas coordinate and convert to subb. coords
				cblk.ulx = (cn + cbn) * sb.nomCBlkW - (sb.ulcx - acb0x) + sb.ulx;
			}
			if (cbm == 0)
			{
				// Bottom-most code-block, starts where subband starts
				cblk.uly = sb.uly;
			}
			else
			{
				cblk.uly = (cm + cbm) * sb.nomCBlkH - (sb.ulcy - acb0y) + sb.uly;
			}
			if (cbn < ncblks.x - 1)
			{
				// Calculate where next code-block starts => width
				cblk.w = (cn + cbn + 1) * sb.nomCBlkW - (sb.ulcx - acb0x) + sb.ulx - cblk.ulx;
			}
			else
			{
				// Right-most code-block, ends where subband ends
				cblk.w = sb.ulx + sb.w - cblk.ulx;
			}
			if (cbm < ncblks.y - 1)
			{
				// Calculate where next code-block starts => height
				cblk.h = (cm + cbm + 1) * sb.nomCBlkH - (sb.ulcy - acb0y) + sb.uly - cblk.uly;
			}
			else
			{
				// Bottom-most code-block, ends where subband ends
				cblk.h = sb.uly + sb.h - cblk.uly;
			}
			cblk.wmseScaling = 1f;
			
			// Since we are in getNextInternCodeBlock() we can return a
			// reference to the internal buffer, no need to copy. Just initialize
			// the 'offset' and 'scanw'
			cblk.offset = cblk.uly * decomposedComps[c].w + cblk.ulx;
			cblk.scanw = decomposedComps[c].w;
			
			// For the data just put a reference to our buffer
			cblk.Data = decomposedComps[c].Data;
			// Return code-block
			return cblk;
		}
Example #16
0
		/// <summary> Apply forward component transformation to obtain requested component
		/// from specified block of data. Whatever the type of requested DataBlk,
		/// it always returns a DataBlkInt.
		/// 
		/// </summary>
		/// <param name="blk">Determine the rectangular area to return 
		/// 
		/// </param>
		/// <param name="c">The index of the requested component
		/// 
		/// </param>
		/// <returns> Data of requested component
		/// 
		/// </returns>
		private DataBlk forwRCT(DataBlk blk, int c)
		{
			int k, k0, k1, k2, mink, i;
			int w = blk.w; //width of output block
			int h = blk.h; //height of ouput block
			int[] outdata; //array of output data
			
			//If asking for Yr, Ur or Vr do transform
			if (c >= 0 && c <= 2)
			{
				// Check that request data type is int
				if (blk.DataType != DataBlk.TYPE_INT)
				{
					if (outBlk == null || outBlk.DataType != DataBlk.TYPE_INT)
					{
						outBlk = new DataBlkInt();
					}
					outBlk.w = w;
					outBlk.h = h;
					outBlk.ulx = blk.ulx;
					outBlk.uly = blk.uly;
					blk = outBlk;
				}
				
				//Reference to output block data array
				outdata = (int[]) blk.Data;
				
				//Create data array of blk if necessary
				if (outdata == null || outdata.Length < h * w)
				{
					outdata = new int[h * w];
					blk.Data = outdata;
				}
				
				// Block buffers for input RGB data
				int[] data0, data1, bdata; // input data arrays
				
				if (block0 == null)
					block0 = new DataBlkInt();
				if (block1 == null)
					block1 = new DataBlkInt();
				if (block2 == null)
					block2 = new DataBlkInt();
				block0.w = block1.w = block2.w = blk.w;
				block0.h = block1.h = block2.h = blk.h;
				block0.ulx = block1.ulx = block2.ulx = blk.ulx;
				block0.uly = block1.uly = block2.uly = blk.uly;
				
				//Fill in buffer blocks (to be read only)
				// Returned blocks may have different size and position
				block0 = (DataBlkInt) src.getInternCompData(block0, 0);
				data0 = (int[]) block0.Data;
				block1 = (DataBlkInt) src.getInternCompData(block1, 1);
				data1 = (int[]) block1.Data;
				block2 = (DataBlkInt) src.getInternCompData(block2, 2);
				bdata = (int[]) block2.Data;
				
				// Set the progressiveness of the output data
				blk.progressive = block0.progressive || block1.progressive || block2.progressive;
				blk.offset = 0;
				blk.scanw = w;
				
				//Perform conversion
				
				// Initialize general indexes
				k = w * h - 1;
				k0 = block0.offset + (h - 1) * block0.scanw + w - 1;
				k1 = block1.offset + (h - 1) * block1.scanw + w - 1;
				k2 = block2.offset + (h - 1) * block2.scanw + w - 1;
				
				switch (c)
				{
					
					case 0:  //RGB to Yr conversion
						for (i = h - 1; i >= 0; i--)
						{
							for (mink = k - w; k > mink; k--, k0--, k1--, k2--)
							{
								// Use int arithmetic with 12 fractional bits
								// and rounding
								outdata[k] = (data0[k] + 2 * data1[k] + bdata[k]) >> 2; // Same as / 4
							}
							// Jump to beggining of previous line in input
							k0 -= (block0.scanw - w);
							k1 -= (block1.scanw - w);
							k2 -= (block2.scanw - w);
						}
						break;
					
					
					case 1:  //RGB to Ur conversion
						for (i = h - 1; i >= 0; i--)
						{
							for (mink = k - w; k > mink; k--, k1--, k2--)
							{
								// Use int arithmetic with 12 fractional bits
								// and rounding
								outdata[k] = bdata[k2] - data1[k1];
							}
							// Jump to beggining of previous line in input
							k1 -= (block1.scanw - w);
							k2 -= (block2.scanw - w);
						}
						break;
					
					
					case 2:  //RGB to Vr conversion
						for (i = h - 1; i >= 0; i--)
						{
							for (mink = k - w; k > mink; k--, k0--, k1--)
							{
								// Use int arithmetic with 12 fractional bits
								// and rounding
								outdata[k] = data0[k0] - data1[k1];
							}
							// Jump to beggining of previous line in input
							k0 -= (block0.scanw - w);
							k1 -= (block1.scanw - w);
						}
						break;
					}
			}
			else if (c >= 3)
			{
				// Requesting a component which is not Y, Ur or Vr =>
				// just pass the data            
				return src.getInternCompData(blk, c);
			}
			else
			{
				// Requesting a non valid component index
				throw new System.ArgumentException();
			}
			return blk;
		}
Example #17
0
 public DataBlk getCompData(DataBlk blk, int c)
 {
     var newBlk = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);
     return this.getInternCompData(newBlk, c);
 }
Example #18
0
		/// <summary> Apply forward irreversible component transformation to obtain requested
		/// component from specified block of data. Whatever the type of requested
		/// DataBlk, it always returns a DataBlkFloat.
		/// 
		/// </summary>
		/// <param name="blk">Determine the rectangular area to return 
		/// 
		/// </param>
		/// <param name="c">The index of the requested component
		/// 
		/// </param>
		/// <returns> Data of requested component
		/// 
		/// </returns>
		private DataBlk forwICT(DataBlk blk, int c)
		{
			int k, k0, k1, k2, mink, i;
			int w = blk.w; //width of output block
			int h = blk.h; //height of ouput block
			float[] outdata; //array of output data
			
			if (blk.DataType != DataBlk.TYPE_FLOAT)
			{
				if (outBlk == null || outBlk.DataType != DataBlk.TYPE_FLOAT)
				{
					outBlk = new DataBlkFloat();
				}
				outBlk.w = w;
				outBlk.h = h;
				outBlk.ulx = blk.ulx;
				outBlk.uly = blk.uly;
				blk = outBlk;
			}
			
			//Reference to output block data array
			outdata = (float[]) blk.Data;
			
			//Create data array of blk if necessary
			if (outdata == null || outdata.Length < w * h)
			{
				outdata = new float[h * w];
				blk.Data = outdata;
			}
			
			//If asking for Y, Cb or Cr do transform
			if (c >= 0 && c <= 2)
			{
				
				int[] data0, data1, data2; // input data arrays
				
				if (block0 == null)
				{
					block0 = new DataBlkInt();
				}
				if (block1 == null)
				{
					block1 = new DataBlkInt();
				}
				if (block2 == null)
				{
					block2 = new DataBlkInt();
				}
				block0.w = block1.w = block2.w = blk.w;
				block0.h = block1.h = block2.h = blk.h;
				block0.ulx = block1.ulx = block2.ulx = blk.ulx;
				block0.uly = block1.uly = block2.uly = blk.uly;
				
				// Returned blocks may have different size and position
				block0 = (DataBlkInt) src.getInternCompData(block0, 0);
				data0 = (int[]) block0.Data;
				block1 = (DataBlkInt) src.getInternCompData(block1, 1);
				data1 = (int[]) block1.Data;
				block2 = (DataBlkInt) src.getInternCompData(block2, 2);
				data2 = (int[]) block2.Data;
				
				// Set the progressiveness of the output data
				blk.progressive = block0.progressive || block1.progressive || block2.progressive;
				blk.offset = 0;
				blk.scanw = w;
				
				//Perform conversion
				
				// Initialize general indexes
				k = w * h - 1;
				k0 = block0.offset + (h - 1) * block0.scanw + w - 1;
				k1 = block1.offset + (h - 1) * block1.scanw + w - 1;
				k2 = block2.offset + (h - 1) * block2.scanw + w - 1;
				
				switch (c)
				{
					
					case 0: 
						//RGB to Y conversion
						for (i = h - 1; i >= 0; i--)
						{
							for (mink = k - w; k > mink; k--, k0--, k1--, k2--)
							{
								outdata[k] = 0.299f * data0[k0] + 0.587f * data1[k1] + 0.114f * data2[k2];
							}
							// Jump to beggining of previous line in input
							k0 -= (block0.scanw - w);
							k1 -= (block1.scanw - w);
							k2 -= (block2.scanw - w);
						}
						break;
					
					
					case 1: 
						//RGB to Cb conversion
						for (i = h - 1; i >= 0; i--)
						{
							for (mink = k - w; k > mink; k--, k0--, k1--, k2--)
							{
								outdata[k] = (- 0.16875f) * data0[k0] - 0.33126f * data1[k1] + 0.5f * data2[k2];
							}
							// Jump to beggining of previous line in input
							k0 -= (block0.scanw - w);
							k1 -= (block1.scanw - w);
							k2 -= (block2.scanw - w);
						}
						break;
					
					
					case 2: 
						//RGB to Cr conversion
						for (i = h - 1; i >= 0; i--)
						{
							for (mink = k - w; k > mink; k--, k0--, k1--, k2--)
							{
								outdata[k] = 0.5f * data0[k0] - 0.41869f * data1[k1] - 0.08131f * data2[k2];
							}
							// Jump to beggining of previous line in input
							k0 -= (block0.scanw - w);
							k1 -= (block1.scanw - w);
							k2 -= (block2.scanw - w);
						}
						break;
					}
			}
			else if (c >= 3)
			{
				// Requesting a component which is not Y, Cb or Cr =>
				// just pass the data
				
				// Variables
				DataBlkInt indb = new DataBlkInt(blk.ulx, blk.uly, w, h);
				int[] indata; // input data array
				
				// Get the input data
				// (returned block may be larger than requested one)
				src.getInternCompData(indb, c);
				indata = (int[]) indb.Data;
				
				// Copy the data converting from int to float
				k = w * h - 1;
				k0 = indb.offset + (h - 1) * indb.scanw + w - 1;
				for (i = h - 1; i >= 0; i--)
				{
					for (mink = k - w; k > mink; k--, k0--)
					{
						//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
						outdata[k] = (float) indata[k0];
					}
					// Jump to beggining of next line in input
					k0 += indb.w - w;
				}
				
				// Set the progressivity
				blk.progressive = indb.progressive;
				blk.offset = 0;
				blk.scanw = w;
				return blk;
			}
			else
			{
				// Requesting a non valid component index
				throw new System.ArgumentException();
			}
			return blk;
		}
Example #19
0
        /// <summary> Writes the data of the specified area to the file, coordinates are
        /// relative to the current tile of the source. Before writing, the
        /// coefficients are limited to the nominal range.
        /// 
        /// <p>This method may not be called concurrently from different
        /// threads.</p>
        /// 
        /// <p>If the data returned from the BlkImgDataSrc source is progressive,
        /// then it is requested over and over until it is not progressive
        /// anymore.</p>
        /// 
        /// </summary>
        /// <param name="ulx">The horizontal coordinate of the upper-left corner of the
        /// area to write, relative to the current tile.
        /// 
        /// </param>
        /// <param name="uly">The vertical coordinate of the upper-left corner of the area
        /// to write, relative to the current tile.
        /// 
        /// </param>
        /// <param name="width">The width of the area to write.
        /// 
        /// </param>
        /// <param name="height">The height of the area to write.
        /// 
        /// </param>
        /// <exception cref="IOException">If an I/O error occurs.
        /// 
        /// </exception>
        public override void write(int ulx, int uly, int w, int h)
        {
            int k, j, i, c;
            // In local variables for faster access
            int fracbits;
            // variables used during coeff saturation
            int shift, tmp, maxVal;
            int tOffx, tOffy; // Active tile offset in the X and Y direction

            // Active tiles in all components have same offset since they are at
            // same resolution (PPM does not support anything else)
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            tOffx = src.getCompULX(cps[0]) - (int) System.Math.Ceiling(src.ImgULX / (double) src.getCompSubsX(cps[0]));
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            tOffy = src.getCompULY(cps[0]) - (int) System.Math.Ceiling(src.ImgULY / (double) src.getCompSubsY(cps[0]));

            // Check the array size
            if (db.data_array != null && db.data_array.Length < w)
            {
                // A new one will be allocated by getInternCompData()
                db.data_array = null;
            }

            // Check the line buffer
            if (buf == null || buf.Length < 3 * w)
            {
                buf = new byte[3 * w];
            }

            // Write the data to the file
            // Write line by line
            for (i = 0; i < h; i++)
            {
                // Write into buffer first loop over the three components and
                // write for each
                for (c = 0; c < 3; c++)
                {
                    maxVal = (1 << src.getNomRangeBits(cps[c])) - 1;
                    shift = levShift[c];

                    // Initialize db
                    db.ulx = ulx;
                    db.uly = uly + i;
                    db.w = w;
                    db.h = 1;

                    // Request the data and make sure it is not progressive
                    do
                    {
                        db = (DataBlkInt) src.getInternCompData(db, cps[c]);
                    }
                    while (db.progressive);
                    // Get the fracbits value
                    fracbits = fb[c];
                    // Write all bytes in the line
                    if (fracbits == 0)
                    {
                        for (k = db.offset + w - 1, j = 3 * w - 1 + c - 2; j >= 0; k--)
                        {
                            tmp = db.data_array[k] + shift;
                            buf[j] = (byte) ((tmp < 0)?0:((tmp > maxVal)?maxVal:tmp));
                            j -= 3;
                        }
                    }
                    else
                    {
                        for (k = db.offset + w - 1, j = 3 * w - 1 + c - 2; j >= 0; k--)
                        {
                            tmp = (SupportClass.URShift(db.data_array[k], fracbits)) + shift;
                            buf[j] = (byte) ((tmp < 0)?0:((tmp > maxVal)?maxVal:tmp));
                            j -= 3;
                        }
                    }
                }
                // Write buffer into file
                out_Renamed.Seek(offset + 3 * (this.w * (uly + tOffy + i) + ulx + tOffx), System.IO.SeekOrigin.Begin);
                out_Renamed.Write(buf, 0, 3 * w);
            }
        }
Example #20
0
		/// <summary> Writes the data of the specified area to the file, coordinates are
		/// relative to the current tile of the source. Before writing, the
		/// coefficients are limited to the nominal range and packed into 1,2 or 4
		/// bytes (according to the bit-depth).
		/// 
		/// <p>If the data is unisigned, level shifting is applied adding 2^(bit
		/// depth - 1)</p>
		/// 
		/// <p>This method may not be called concurrently from different
		/// threads.</p> 
		/// 
		/// <p>If the data returned from the BlkImgDataSrc source is progressive,
		/// then it is requested over and over until it is not progressive
		/// anymore.</p>
		/// 
		/// </summary>
		/// <param name="ulx">The horizontal coordinate of the upper-left corner of the
		/// area to write, relative to the current tile.
		/// 
		/// </param>
		/// <param name="uly">The vertical coordinate of the upper-left corner of the area
		/// to write, relative to the current tile.
		/// 
		/// </param>
		/// <param name="width">The width of the area to write.
		/// 
		/// </param>
		/// <param name="height">The height of the area to write.
		/// 
		/// </param>
		/// <exception cref="IOException">If an I/O error occurs.
		/// 
		/// </exception>
		public override void  write(int ulx, int uly, int w, int h)
		{
			int k, i, j;
			int fracbits = fb; // In local variable for faster access
			int tOffx, tOffy; // Active tile offset in the X and Y direction
			
			// Initialize db
			db.ulx = ulx;
			db.uly = uly;
			db.w = w;
			db.h = h;
			// Get the current active tile offset
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			tOffx = src.getCompULX(c) - (int) System.Math.Ceiling(src.ImgULX / (double) src.getCompSubsX(c));
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			tOffy = src.getCompULY(c) - (int) System.Math.Ceiling(src.ImgULY / (double) src.getCompSubsY(c));
			// Check the array size
			if (db.data_array != null && db.data_array.Length < w * h)
			{
				// A new one will be allocated by getInternCompData()
				db.data_array = null;
			}
			// Request the data and make sure it is not
			// progressive
			do 
			{
				db = (DataBlkInt) src.getInternCompData(db, c);
			}
			while (db.progressive);
			
			int tmp;
			
			
			// Check line buffer
			if (buf == null || buf.Length < packBytes * w)
			{
				buf = new byte[packBytes * w]; // Expand buffer
			}
			
			switch (packBytes)
			{
				
				
				case 1:  // Samples packed into 1 byte
					// Write line by line
					for (i = 0; i < h; i++)
					{
						// Skip to beggining of line in file
						out_Renamed.Seek(offset + this.w * (uly + tOffy + i) + ulx + tOffx, System.IO.SeekOrigin.Begin);
						// Write all bytes in the line
						if (fracbits == 0)
						{
							for (k = db.offset + i * db.scanw + w - 1, j = w - 1; j >= 0; k--)
							{
								tmp = db.data_array[k] + levShift;
								buf[j--] = (byte) ((tmp < minVal)?minVal:((tmp > maxVal)?maxVal:tmp));
							}
						}
						else
						{
							for (k = db.offset + i * db.scanw + w - 1, j = w - 1; j >= 0; k--)
							{
								tmp = (SupportClass.URShift(db.data_array[k], fracbits)) + levShift;
								buf[j--] = (byte) ((tmp < minVal)?minVal:((tmp > maxVal)?maxVal:tmp));
							}
						}
						out_Renamed.Write(buf, 0, w);
					}
					break;
				
				
				case 2:  // Samples packed in to 2 bytes (short)
					// Write line by line
					for (i = 0; i < h; i++)
					{
						
						// Skip to beggining of line in file
						out_Renamed.Seek(offset + 2 * (this.w * (uly + tOffy + i) + ulx + tOffx), System.IO.SeekOrigin.Begin);
						// Write all bytes in the line
						if (fracbits == 0)
						{
							for (k = db.offset + i * db.scanw + w - 1, j = (w << 1) - 1; j >= 0; k--)
							{
								tmp = db.data_array[k] + levShift;
								tmp = (tmp < minVal)?minVal:((tmp > maxVal)?maxVal:tmp);
								buf[j--] = (byte) tmp; // no need for 0xFF mask since
								// truncation will do it already
								buf[j--] = (byte) (SupportClass.URShift(tmp, 8));
							}
						}
						else
						{
							for (k = db.offset + i * db.scanw + w - 1, j = (w << 1) - 1; j >= 0; k--)
							{
								tmp = (SupportClass.URShift(db.data_array[k], fracbits)) + levShift;
								tmp = (tmp < minVal)?minVal:((tmp > maxVal)?maxVal:tmp);
								buf[j--] = (byte) tmp; // no need for 0xFF mask since
								// truncation will do it already
								buf[j--] = (byte) (SupportClass.URShift(tmp, 8));
							}
						}
						out_Renamed.Write(buf, 0, w << 1);
					}
					break;
				
				
				case 4: 
					// Write line by line
					for (i = 0; i < h; i++)
					{
						// Skip to beggining of line in file
						out_Renamed.Seek(offset + 4 * (this.w * (uly + tOffy + i) + ulx + tOffx), System.IO.SeekOrigin.Begin);
						// Write all bytes in the line
						if (fracbits == 0)
						{
							for (k = db.offset + i * db.scanw + w - 1, j = (w << 2) - 1; j >= 0; k--)
							{
								tmp = db.data_array[k] + levShift;
								tmp = (tmp < minVal)?minVal:((tmp > maxVal)?maxVal:tmp);
								buf[j--] = (byte) tmp; // No need to use 0xFF
								buf[j--] = (byte) (SupportClass.URShift(tmp, 8)); // masks since truncation
								buf[j--] = (byte) (SupportClass.URShift(tmp, 16)); // will have already the
								buf[j--] = (byte) (SupportClass.URShift(tmp, 24)); // same effect
							}
						}
						else
						{
							for (k = db.offset + i * db.scanw + w - 1, j = (w << 2) - 1; j >= 0; k--)
							{
								tmp = (SupportClass.URShift(db.data_array[k], fracbits)) + levShift;
								tmp = (tmp < minVal)?minVal:((tmp > maxVal)?maxVal:tmp);
								buf[j--] = (byte) tmp; // No need to use 0xFF
								buf[j--] = (byte) (SupportClass.URShift(tmp, 8)); // masks since truncation
								buf[j--] = (byte) (SupportClass.URShift(tmp, 16)); // will have already the
								buf[j--] = (byte) (SupportClass.URShift(tmp, 24)); // same effect
							}
						}
						out_Renamed.Write(buf, 0, w << 2);
					}
					break;
				
				
				default: 
					throw new System.IO.IOException("PGX supports only bit-depth between " + "1 and 31");
				
			}
		}
Example #21
0
        /// <summary> Performs the inverse wavelet transform on the whole component. It
        /// iteratively reconstructs the subbands from leaves up to the root
        /// node. This method is recursive, the first call to it the 'sb' must be
        /// the root of the subband tree. The method will then process the entire
        /// subband tree by calling itslef recursively.
        /// 
        /// </summary>
        /// <param name="img">The buffer for the image/wavelet data.
        /// 
        /// </param>
        /// <param name="sb">The subband to reconstruct.
        /// 
        /// </param>
        /// <param name="c">The index of the component to reconstruct 
        /// 
        /// </param>
        private void waveletTreeReconstruction(DataBlk img, SubbandSyn sb, int c)
        {
            DataBlk subbData;

            // If the current subband is a leaf then get the data from the source
            if (!sb.isNode)
            {
                int i, m, n;
                System.Object src_data, dst_data;
                Coord ncblks;

                if (sb.w == 0 || sb.h == 0)
                {
                    return ; // If empty subband do nothing
                }

                // Get all code-blocks in subband
                if (dtype == DataBlk.TYPE_INT)
                {
                    subbData = new DataBlkInt();
                }
                else
                {
                    subbData = new DataBlkFloat();
                }
                ncblks = sb.numCb;
                dst_data = img.Data;
                for (m = 0; m < ncblks.y; m++)
                {
                    for (n = 0; n < ncblks.x; n++)
                    {
                        subbData = src.getInternCodeBlock(c, m, n, sb, subbData);
                        src_data = subbData.Data;

                        // Copy the data line by line
                        for (i = subbData.h - 1; i >= 0; i--)
                        {
                            // CONVERSION PROBLEM
                            Array.Copy((System.Array)src_data, subbData.offset + i * subbData.scanw, (System.Array)dst_data, (subbData.uly + i) * img.w + subbData.ulx, subbData.w);
                        }
                    }
                }
            }
            else if (sb.isNode)
            {
                // Reconstruct the lower resolution levels if the current subbands
                // is a node

                //Perform the reconstruction of the LL subband
                waveletTreeReconstruction(img, (SubbandSyn) sb.LL, c);

                if (sb.resLvl <= reslvl - maxImgRes + ndl[c])
                {
                    //Reconstruct the other subbands
                    waveletTreeReconstruction(img, (SubbandSyn) sb.HL, c);
                    waveletTreeReconstruction(img, (SubbandSyn) sb.LH, c);
                    waveletTreeReconstruction(img, (SubbandSyn) sb.HH, c);

                    //Perform the 2D wavelet decomposition of the current subband
                    wavelet2DReconstruction(img, (SubbandSyn) sb, c);
                }
            }
        }
Example #22
0
		/// <summary> Constructor of the ROI scaler, takes a Quantizer as source of data to
		/// scale.
		/// 
		/// </summary>
		/// <param name="src">The quantizer that is the source of data.
		/// 
		/// </param>
		/// <param name="mg">The mask generator that will be used for all components
		/// 
		/// </param>
		/// <param name="roi">Flag indicating whether there are rois specified.
		/// 
		/// </param>
		/// <param name="sLev">The resolution levels that belong entirely to ROI
		/// 
		/// </param>
		/// <param name="uba">Flag indicating whether block aligning is used.
		/// 
		/// </param>
		/// <param name="encSpec">The encoder specifications for addition of roi specs
		/// 
		/// </param>
		public ROIScaler(Quantizer src, ROIMaskGenerator mg, bool roi, int sLev, bool uba, EncoderSpecs encSpec):base(src)
		{
			this.src = src;
			this.roi = roi;
			this.useStartLevel = sLev;
			if (roi)
			{
				// If there is no ROI, no need to do this
				this.mg = mg;
				roiMask = new DataBlkInt();
				calcMaxMagBits(encSpec);
				blockAligned = uba;
			}
		}
		/// <summary> This functions gets a DataBlk the size of the current code-block and
		/// fills this block with the ROI mask.
		/// 
		/// <P> In order to get the mask for a particular Subband, the subband tree
		/// is traversed and at each decomposition, the ROI masks are computed. The
		/// roi bondaries for each subband are stored in the SubbandRectROIMask
		/// tree.
		/// 
		/// </summary>
		/// <param name="db">The data block that is to be filled with the mask
		/// 
		/// </param>
		/// <param name="sb">The root of the subband tree to which db belongs
		/// 
		/// </param>
		/// <param name="magbits">The max number of magnitude bits in any code-block
		/// 
		/// </param>
		/// <param name="c">The component for which to get the mask
		/// 
		/// </param>
		/// <returns> Whether or not a mask was needed for this tile
		/// 
		/// </returns>
		public override bool getROIMask(DataBlkInt db, Subband sb, int magbits, int c)
		{
			int x = db.ulx;
			int y = db.uly;
			int w = db.w;
			int h = db.h;
			int[] mask = db.DataInt;
            int i, j, k, r, maxk, maxj; // mink, minj removed
			int ulx = 0, uly = 0, lrx = 0, lry = 0;
			int wrap;
			int maxROI;
			int[] culxs;
			int[] culys;
			int[] clrxs;
			int[] clrys;
			SubbandRectROIMask srm;
			
			// If the ROI bounds have not been calculated for this tile and 
			// component, do so now.
			if (!tileMaskMade[c])
			{
				makeMask(sb, magbits, c);
				tileMaskMade[c] = true;
			}
			
			if (!roiInTile)
			{
				return false;
			}
			
			// Find relevant subband mask and get ROI bounds
			srm = (SubbandRectROIMask) sMasks[c].getSubbandRectROIMask(x, y);
			culxs = srm.ulxs;
			culys = srm.ulys;
			clrxs = srm.lrxs;
			clrys = srm.lrys;
			maxROI = culxs.Length - 1;
			// Make sure that only parts of ROIs within the code-block are used
			// and make the bounds local to this block the LR bounds are counted
			// as the distance from the lower right corner of the block
			x -= srm.ulx;
			y -= srm.uly;
			for (r = maxROI; r >= 0; r--)
			{
				ulx = culxs[r] - x;
				if (ulx < 0)
				{
					ulx = 0;
				}
				else if (ulx >= w)
				{
					ulx = w;
				}
				
				uly = culys[r] - y;
				if (uly < 0)
				{
					uly = 0;
				}
				else if (uly >= h)
				{
					uly = h;
				}
				
				lrx = clrxs[r] - x;
				if (lrx < 0)
				{
					lrx = - 1;
				}
				else if (lrx >= w)
				{
					lrx = w - 1;
				}
				
				lry = clrys[r] - y;
				if (lry < 0)
				{
					lry = - 1;
				}
				else if (lry >= h)
				{
					lry = h - 1;
				}
				
				// Add the masks of the ROI
				i = w * lry + lrx;
				maxj = (lrx - ulx);
				wrap = w - maxj - 1;
				maxk = lry - uly;
				
				for (k = maxk; k >= 0; k--)
				{
					for (j = maxj; j >= 0; j--, i--)
						mask[i] = magbits;
					i -= wrap;
				}
			}
			return true;
		}
Example #24
0
		/// <summary> This functions gets a DataBlk the size of the current code-block an
		/// fills this block with the ROI mask.
		/// 
		/// <P> In order to get the mask for a particular Subband, the subband tree
		/// is traversed and at each decomposition, the ROI masks are computed.
		/// 
		/// <P> The widths of the synthesis filters corresponding to the wavelet
		/// filters used in the wavelet transform are used to expand the ROI masks
		/// in the decompositions.
		/// 
		/// </summary>
		/// <param name="db">The data block that is to be filled with the mask
		/// 
		/// </param>
		/// <param name="sb">The root of the subband tree to which db belongs
		/// 
		/// </param>
		/// <param name="magbits">The max number of magnitude bits in any code-block
		/// 
		/// </param>
		/// <param name="c">The number of the component
		/// 
		/// </param>
		/// <returns> Whether or not a mask was needed for this tile
		/// 
		/// </returns>
		public override bool getROIMask(DataBlkInt db, Subband sb, int magbits, int c)
		{
			int x = db.ulx;
			int y = db.uly;
			int w = db.w;
			int h = db.h;
			int tilew = sb.w;
			int tileh = sb.h;
			int[] maskData = (int[]) db.Data;
			int i, j, k, bi, wrap;
			
			// If the ROI mask has not been calculated for this tile and
			// component, do so now.
			if (!tileMaskMade[c])
			{
				makeMask(sb, magbits, c);
				tileMaskMade[c] = true;
			}
			if (!roiInTile)
				return false;
			
			int[] mask = roiMask[c]; // local copy
			
			// Copy relevant part of the ROI mask to the datablock
			i = (y + h - 1) * tilew + x + w - 1;
			bi = w * h - 1;
			wrap = tilew - w;
			for (j = h; j > 0; j--)
			{
				for (k = w; k > 0; k--, i--, bi--)
				{
					maskData[bi] = mask[i];
				}
				i -= wrap;
			}
			return true;
		}
Example #25
0
        /// <summary> Returns, in the blk argument, a block of image data containing the
        /// specifed rectangular area, in the specified component. The data is
        /// returned, as a copy of the internal data, therefore the returned data
        /// can be modified "in place".
        /// 
        /// <P> After being read the coefficients are level shifted by subtracting
        /// 2^(nominal bit range - 1)
        /// 
        /// <P>The rectangular area to return is specified by the 'ulx', 'uly', 'w'
        /// and 'h' members of the 'blk' argument, relative to the current
        /// tile. These members are not modified by this method. The 'offset' of
        /// the returned data is 0, and the 'scanw' is the same as the block's
        /// width. See the 'DataBlk' class.
        /// 
        /// <P>If the data array in 'blk' is 'null', then a new one is created. If
        /// the data array is not 'null' then it is reused, and it must be large
        /// enough to contain the block's data. Otherwise an 'ArrayStoreException'
        /// or an 'IndexOutOfBoundsException' is thrown by the Java system.
        /// 
        /// <P>The returned data has its 'progressive' attribute unset
        /// (i.e. false).
        /// 
        /// <P>When an I/O exception is encountered the JJ2KExceptionHandler is
        /// used. The exception is passed to its handleException method. The action
        /// that is taken depends on the action that has been registered in
        /// JJ2KExceptionHandler. See JJ2KExceptionHandler for details.
        /// 
        /// </summary>
        /// <param name="blk">Its coordinates and dimensions specify the area to
        /// return. If it contains a non-null data array, then it must have the
        /// correct dimensions. If it contains a null data array a new one is
        /// created. The fields in this object are modified to return the data.
        /// 
        /// </param>
        /// <param name="c">The index of the component from which to get the data. Only
        /// 0,1 and 2 are valid.
        /// 
        /// </param>
        /// <returns> The requested DataBlk
        /// 
        /// </returns>
        /// <seealso cref="getInternCompData">
        /// 
        /// </seealso>
        /// <seealso cref="JJ2KExceptionHandler">
        /// 
        /// </seealso>
        public override DataBlk getCompData(DataBlk blk, int c)
        {
            // NOTE: can not directly call getInterCompData since that returns
            // internally buffered data.
            int ulx, uly, w, h;

            // Check type of block provided as an argument
            if (blk.DataType != DataBlk.TYPE_INT)
            {
                DataBlkInt tmp = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);
                blk = tmp;
            }

            int[] bakarr = (int[])blk.Data;
            // Save requested block size
            ulx = blk.ulx;
            uly = blk.uly;
            w = blk.w;
            h = blk.h;
            // Force internal data buffer to be different from external
            blk.Data = null;
            getInternCompData(blk, c);
            // Copy the data
            if (bakarr == null)
            {
                bakarr = new int[w * h];
            }
            if (blk.offset == 0 && blk.scanw == w)
            {
                // Requested and returned block buffer are the same size
                // CONVERSION PROBLEM?
                Array.Copy((System.Array)blk.Data, 0, (System.Array)bakarr, 0, w * h);
            }
            else
            {
                // Requested and returned block are different
                for (int i = h - 1; i >= 0; i--)
                {
                    // copy line by line
                    // CONVERSION PROBLEM?
                    Array.Copy((System.Array)blk.Data, blk.offset + i * blk.scanw, (System.Array)bakarr, i * w, w);
                }
            }
            blk.Data = bakarr;
            blk.offset = 0;
            blk.scanw = blk.w;
            return blk;
        }
Example #26
0
		/// <summary> This function generates the ROI mask for one tile-component. 
		/// 
		/// <P> Once the mask is generated in the pixel domain. it is decomposed
		/// following the same decomposition scheme as the wavelet transform.
		/// 
		/// </summary>
		/// <param name="sb">The root of the subband tree used in the decomposition
		/// 
		/// </param>
		/// <param name="magbits">The max number of magnitude bits in any code-block
		/// 
		/// </param>
		/// <param name="c">component number
		/// </param>
		public override void  makeMask(Subband sb, int magbits, int c)
		{
			int[] mask; // local copy
			ROI[] rois = this.roi_array; // local copy
            int i, j, k, r, maxj; // mink, minj removed
			int lrx, lry;
			int x, y, w, h;
			int cx, cy, rad;
			int wrap;
			int curScalVal;
			int tileulx = sb.ulcx;
			int tileuly = sb.ulcy;
			int tilew = sb.w;
			int tileh = sb.h;
			int lineLen = (tilew > tileh)?tilew:tileh;
			
			// Make sure there is a sufficiently large mask buffer
			if (roiMask[c] == null || (roiMask[c].Length < (tilew * tileh)))
			{
				roiMask[c] = new int[tilew * tileh];
				mask = roiMask[c];
			}
			else
			{
				mask = roiMask[c];
				for (i = tilew * tileh - 1; i >= 0; i--)
					mask[i] = 0;
			}
			
			// Make sure there are sufficiently large line buffers
			if (maskLineLow == null || (maskLineLow.Length < (lineLen + 1) / 2))
				maskLineLow = new int[(lineLen + 1) / 2];
			if (maskLineHigh == null || (maskLineHigh.Length < (lineLen + 1) / 2))
				maskLineHigh = new int[(lineLen + 1) / 2];
			
			roiInTile = false;
			// Generate ROIs in pixel domain:
			for (r = rois.Length - 1; r >= 0; r--)
			{
				if (rois[r].comp == c)
				{
					curScalVal = magbits;
					
					if (rois[r].arbShape)
					{
						ImgReaderPGM maskPGM = rois[r].maskPGM; // Local copy
						
						if ((src.ImgWidth != maskPGM.ImgWidth) || (src.ImgHeight != maskPGM.ImgHeight))
							throw new System.ArgumentException("Input image and" + " ROI mask must " + "have the same " + "size");
						x = src.ImgULX;
						y = src.ImgULY;
						lrx = x + src.ImgWidth - 1;
						lry = y + src.ImgHeight - 1;
						if ((x > tileulx + tilew) || (y > tileuly + tileh) || (lrx < tileulx) || (lry < tileuly))
						// Roi not in tile
							continue;
						
						// Check bounds
						x -= tileulx;
						lrx -= tileulx;
						y -= tileuly;
						lry -= tileuly;
						
						int offx = 0;
						int offy = 0;
						if (x < 0)
						{
							offx = - x;
							x = 0;
						}
						if (y < 0)
						{
							offy = - y;
							y = 0;
						}
						w = (lrx > (tilew - 1))?tilew - x:lrx + 1 - x;
						h = (lry > (tileh - 1))?tileh - y:lry + 1 - y;
						
						
						// Get shape line by line to reduce memory
						DataBlkInt srcblk = new DataBlkInt();
						int mDcOff = - ImgReaderPGM.DC_OFFSET;
						int nROIcoeff = 0;
						int[] src_data;
						srcblk.ulx = offx;
						srcblk.w = w;
						srcblk.h = 1;
						
						i = (y + h - 1) * tilew + x + w - 1;
						maxj = w;
						wrap = tilew - maxj;
						for (k = h; k > 0; k--)
						{
							srcblk.uly = offy + k - 1;
							srcblk = (DataBlkInt) maskPGM.getInternCompData(srcblk, 0);
							src_data = srcblk.DataInt;
							
							for (j = maxj; j > 0; j--, i--)
							{
								if (src_data[j - 1] != mDcOff)
								{
									mask[i] = curScalVal;
									nROIcoeff++;
								}
							}
							i -= wrap;
						}
						
						if (nROIcoeff != 0)
						{
							roiInTile = true;
						}
					}
					else if (rois[r].rect)
					{
						// Rectangular ROI
						x = rois[r].ulx;
						y = rois[r].uly;
						lrx = rois[r].w + x - 1;
						lry = rois[r].h + y - 1;
						
						if ((x > tileulx + tilew) || (y > tileuly + tileh) || (lrx < tileulx) || (lry < tileuly))
						// Roi not in tile
							continue;
						
						roiInTile = true;
						
						// Check bounds
						x -= tileulx;
						lrx -= tileulx;
						y -= tileuly;
						lry -= tileuly;
						
						x = (x < 0)?0:x;
						y = (y < 0)?0:y;
						w = (lrx > (tilew - 1))?tilew - x:lrx + 1 - x;
						h = (lry > (tileh - 1))?tileh - y:lry + 1 - y;
						
						i = (y + h - 1) * tilew + x + w - 1;
						maxj = w;
						wrap = tilew - maxj;
						for (k = h; k > 0; k--)
						{
							for (j = maxj; j > 0; j--, i--)
							{
								mask[i] = curScalVal;
							}
							i -= wrap;
						}
					}
					else
					{
						// Non-rectangular ROI. So far only circular case 
						cx = rois[r].x - tileulx;
						cy = rois[r].y - tileuly;
						rad = rois[r].r;
						i = tileh * tilew - 1;
						for (k = tileh - 1; k >= 0; k--)
						{
							for (j = tilew - 1; j >= 0; j--, i--)
							{
								if (((j - cx) * (j - cx) + (k - cy) * (k - cy) < rad * rad))
								{
									mask[i] = curScalVal;
									roiInTile = true;
								}
							}
						}
					}
				}
			}
			
			// If wavelet transform is used
			if (sb.isNode)
			{
				// Decompose the mask according to the subband tree
				// Calculate size of padded line buffer
				WaveletFilter vFilter = sb.VerWFilter;
				WaveletFilter hFilter = sb.HorWFilter;
				int lvsup = vFilter.SynLowNegSupport + vFilter.SynLowPosSupport;
				int hvsup = vFilter.SynHighNegSupport + vFilter.SynHighPosSupport;
				int lhsup = hFilter.SynLowNegSupport + hFilter.SynLowPosSupport;
				int hhsup = hFilter.SynHighNegSupport + hFilter.SynHighPosSupport;
				lvsup = (lvsup > hvsup)?lvsup:hvsup;
				lhsup = (lhsup > hhsup)?lhsup:hhsup;
				lvsup = (lvsup > lhsup)?lvsup:lhsup;
				paddedMaskLine = new int[lineLen + lvsup];
				
				if (roiInTile)
					decomp(sb, tilew, tileh, c);
			}
		}
Example #27
0
		/// <summary> Returns, in the blk argument, the block of image data containing the
		/// specifed rectangular area, in the specified component. The data is
		/// returned, as a reference to the internal data, if any, instead of as a
		/// copy, therefore the returned data should not be modified.
		/// 
		/// <P> After being read the coefficients are level shifted by subtracting
		/// 2^(nominal bit range - 1)
		/// 
		/// <P>The rectangular area to return is specified by the 'ulx', 'uly', 'w'
		/// and 'h' members of the 'blk' argument, relative to the current
		/// tile. These members are not modified by this method. The 'offset' and
		/// 'scanw' of the returned data can be arbitrary. See the 'DataBlk' class.
		/// 
		/// <P>If the data array in <tt>blk</tt> is <tt>null</tt>, then a new one
		/// is created if necessary. The implementation of this interface may
		/// choose to return the same array or a new one, depending on what is more
		/// efficient. Therefore, the data array in <tt>blk</tt> prior to the
		/// method call should not be considered to contain the returned data, a
		/// new array may have been created. Instead, get the array from
		/// <tt>blk</tt> after the method has returned.
		/// 
		/// <P>The returned data always has its 'progressive' attribute unset
		/// (i.e. false).
		/// 
		/// <P>When an I/O exception is encountered the JJ2KExceptionHandler is
		/// used. The exception is passed to its handleException method. The action
		/// that is taken depends on the action that has been registered in
		/// JJ2KExceptionHandler. See JJ2KExceptionHandler for details.
		/// 
		/// </summary>
		/// <param name="blk">Its coordinates and dimensions specify the area to
		/// return. Some fields in this object are modified to return the data.
		/// 
		/// </param>
		/// <param name="c">The index of the component from which to get the data. Only 0
		/// is valid.
		/// 
		/// </param>
		/// <returns> The requested DataBlk
		/// 
		/// </returns>
		/// <seealso cref="getCompData">
		/// 
		/// </seealso>
		/// <seealso cref="JJ2KExceptionHandler">
		/// 
		/// </seealso>
		public override DataBlk getInternCompData(DataBlk blk, int c)
		{
			int k, j, i, mi;
			int[] barr;
			
			// Check component index
			if (c != 0)
				throw new System.ArgumentException();
			
			// Check type of block provided as an argument
			if (blk.DataType != DataBlk.TYPE_INT)
			{
				if (intBlk == null)
					intBlk = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);
				else
				{
					intBlk.ulx = blk.ulx;
					intBlk.uly = blk.uly;
					intBlk.w = blk.w;
					intBlk.h = blk.h;
				}
				blk = intBlk;
			}
			
			// Get data array
			barr = (int[]) blk.Data;
			if (barr == null || barr.Length < blk.w * blk.h)
			{
				barr = new int[blk.w * blk.h];
				blk.Data = barr;
			}
			
			// Check line buffer
			if (buf == null || buf.Length < blk.w)
			{
				buf = new byte[blk.w];
			}
			
			try
			{
				// Read line by line
				mi = blk.uly + blk.h;
				for (i = blk.uly; i < mi; i++)
				{
					// Reposition in input
					in_Renamed.Seek(offset + i * w + blk.ulx, System.IO.SeekOrigin.Begin);
					in_Renamed.Read(buf, 0, blk.w);
					for (k = (i - blk.uly) * blk.w + blk.w - 1, j = blk.w - 1; j >= 0; j--, k--)
					{
						barr[k] = (((int) buf[j]) & 0xFF) - DC_OFFSET;
					}
				}
			}
			catch (System.IO.IOException e)
			{
				JJ2KExceptionHandler.handleException(e);
			}
			
			// Turn off the progressive attribute
			blk.progressive = false;
			// Set buffer attributes
			blk.offset = 0;
			blk.scanw = blk.w;
			return blk;
		}
Example #28
0
		/// <summary> Copy constructor. Creates a DataBlkInt which is the copy of the
		/// DataBlkInt given as paramter.
		/// 
		/// </summary>
		/// <param name="DataBlkInt">the object to be copied.
		/// 
		/// </param>
		public DataBlkInt(DataBlkInt src)
		{
			this.ulx = src.ulx;
			this.uly = src.uly;
			this.w = src.w;
			this.h = src.h;
			this.offset = 0;
			this.scanw = this.w;
			this.data_array = new int[this.w * this.h];
			for (int i = 0; i < this.h; i++)
				Array.Copy(src.data_array, i * src.scanw, this.data_array, i * this.scanw, this.w);
		}