/// <summary> Initializes the header writer with the references to the coding chain. /// /// </summary> /// <param name="origsrc">The original image data (before any component mixing, /// tiling, etc.) /// /// </param> /// <param name="isorigsig">An array specifying for each component if it was /// originally signed or not. /// /// </param> /// <param name="dwt">The discrete wavelet transform module. /// /// </param> /// <param name="tiler">The tiler module. /// /// </param> /// <param name="encSpec">The encoder specifications /// /// </param> /// <param name="roiSc">The ROI scaler module. /// /// </param> /// <param name="ralloc">The post compression rate allocator. /// /// </param> /// <param name="pl">ParameterList instance. /// /// </param> public HeaderEncoder(ImgData origsrc, bool[] isorigsig, ForwardWT dwt, Tiler tiler, EncoderSpecs encSpec, ROIScaler roiSc, PostCompRateAllocator ralloc, ParameterList pl) { pl.checkList(OPT_PREFIX, CSJ2K.j2k.util.ParameterList.toNameArray(pinfo)); if (origsrc.NumComps != isorigsig.Length) { throw new System.ArgumentException(); } this.origSrc = origsrc; this.isOrigSig = isorigsig; this.dwt = dwt; this.tiler = tiler; this.encSpec = encSpec; this.roiSc = roiSc; this.ralloc = ralloc; baos = new System.IO.MemoryStream(); //UPGRADE_TODO: Class 'java.io.DataOutputStream' was converted to 'System.IO.BinaryWriter' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioDataOutputStream'" hbuf = new CSJ2K.Util.EndianBinaryWriter(baos, true); nComp = origsrc.NumComps; enJJ2KMarkSeg = pl.getBooleanParameter("Hjj2000_COM"); otherCOMMarkSeg = pl.getParameter("HCOM"); }
/// <summary> Initializes the EBCOT rate allocator of entropy coded data. The layout /// of layers, and their bitrate constraints, is specified by the 'lyrs' /// parameter. /// /// </summary> /// <param name="src">The source of entropy coded data. /// /// </param> /// <param name="lyrs">The layers layout specification. /// /// </param> /// <param name="writer">The bit stream writer. /// /// </param> /// <seealso cref="ProgressionType"> /// /// </seealso> public EBCOTRateAllocator(CodedCBlkDataSrcEnc src, LayersInfo lyrs, CodestreamWriter writer, EncoderSpecs encSpec, ParameterList pl) : base(src, lyrs.TotNumLayers, writer, encSpec) { int minsbi, maxsbi; int i; SubbandAn sb, sb2; Coord ncblks = null; // If we do timing create necessary structures #if DO_TIMING // If we are timing make sure that 'finalize' gets called. //UPGRADE_ISSUE: Method 'java.lang.System.runFinalizersOnExit' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javalangSystem'" // CONVERSION PROBLEM? //System_Renamed.runFinalizersOnExit(true); // The System.runFinalizersOnExit() method is deprecated in Java // 1.2 since it can cause a deadlock in some cases. However, here // we use it only for profiling purposes and is disabled in // production code. initTime = 0L; buildTime = 0L; writeTime = 0L; #endif // Save the layer specs lyrSpec = lyrs; //Initialize the size of the RD slope rates array RDSlopesRates = new int[RD_SUMMARY_SIZE]; //Get number of tiles, components int nt = src.getNumTiles(); int nc = NumComps; //Allocate the coded code-blocks and truncation points indexes arrays cblks = new CBlkRateDistStats[nt][][][][]; for (int i2 = 0; i2 < nt; i2++) { cblks[i2] = new CBlkRateDistStats[nc][][][]; } truncIdxs = new int[nt][][][][][]; for (int i3 = 0; i3 < nt; i3++) { truncIdxs[i3] = new int[num_Layers][][][][]; for (int i4 = 0; i4 < num_Layers; i4++) { truncIdxs[i3][i4] = new int[nc][][][]; } } int cblkPerSubband; // Number of code-blocks per subband int mrl; // Number of resolution levels int l; // layer index int s; //subband index // Used to compute the maximum number of precincts for each resolution // level int tx0, ty0, tx1, ty1; // Current tile position in the reference grid int tcx0, tcy0, tcx1, tcy1; // Current tile position in the domain of // the image component int trx0, try0, trx1, try1; // Current tile position in the reduced // resolution image domain int xrsiz, yrsiz; // Component sub-sampling factors Coord tileI = null; Coord nTiles = null; int xsiz, ysiz, x0siz, y0siz; int xt0siz, yt0siz; int xtsiz, ytsiz; int cb0x = src.CbULX; int cb0y = src.CbULY; src.setTile(0, 0); for (int t = 0; t < nt; t++) { // Loop on tiles nTiles = src.getNumTiles(nTiles); tileI = src.getTile(tileI); x0siz = ImgULX; y0siz = ImgULY; xsiz = x0siz + ImgWidth; ysiz = y0siz + ImgHeight; xt0siz = src.TilePartULX; yt0siz = src.TilePartULY; xtsiz = src.NomTileWidth; ytsiz = src.NomTileHeight; // Tile's coordinates on the reference grid tx0 = (tileI.x == 0)?x0siz:xt0siz + tileI.x * xtsiz; ty0 = (tileI.y == 0)?y0siz:yt0siz + tileI.y * ytsiz; tx1 = (tileI.x != nTiles.x - 1)?xt0siz + (tileI.x + 1) * xtsiz:xsiz; ty1 = (tileI.y != nTiles.y - 1)?yt0siz + (tileI.y + 1) * ytsiz:ysiz; for (int c = 0; c < nc; c++) { // loop on components //Get the number of resolution levels sb = src.getAnSubbandTree(t, c); mrl = sb.resLvl + 1; // Initialize maximum number of precincts per resolution array if (numPrec == null) { Coord[][][] tmpArray = new Coord[nt][][]; for (int i5 = 0; i5 < nt; i5++) { tmpArray[i5] = new Coord[nc][]; } numPrec = tmpArray; } if (numPrec[t][c] == null) { numPrec[t][c] = new Coord[mrl]; } // Subsampling factors xrsiz = src.getCompSubsX(c); yrsiz = src.getCompSubsY(c); // Tile's coordinates in the image component domain //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'" tcx0 = (int) System.Math.Ceiling(tx0 / (double) (xrsiz)); //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'" tcy0 = (int) System.Math.Ceiling(ty0 / (double) (yrsiz)); //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'" tcx1 = (int) System.Math.Ceiling(tx1 / (double) (xrsiz)); //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'" tcy1 = (int) System.Math.Ceiling(ty1 / (double) (yrsiz)); cblks[t][c] = new CBlkRateDistStats[mrl][][]; for (l = 0; l < num_Layers; l++) { truncIdxs[t][l][c] = new int[mrl][][]; } for (int r = 0; r < mrl; r++) { // loop on resolution levels // Tile's coordinates in the reduced resolution image // domain //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'" trx0 = (int) System.Math.Ceiling(tcx0 / (double) (1 << (mrl - 1 - r))); //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'" try0 = (int) System.Math.Ceiling(tcy0 / (double) (1 << (mrl - 1 - r))); //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'" trx1 = (int) System.Math.Ceiling(tcx1 / (double) (1 << (mrl - 1 - r))); //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'" try1 = (int) System.Math.Ceiling(tcy1 / (double) (1 << (mrl - 1 - r))); // Calculate the maximum number of precincts for each // resolution level taking into account tile specific // options. double twoppx = (double) encSpec.pss.getPPX(t, c, r); double twoppy = (double) encSpec.pss.getPPY(t, c, r); numPrec[t][c][r] = new Coord(); if (trx1 > trx0) { //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'" numPrec[t][c][r].x = (int) System.Math.Ceiling((trx1 - cb0x) / twoppx) - (int) System.Math.Floor((trx0 - cb0x) / twoppx); } else { numPrec[t][c][r].x = 0; } if (try1 > try0) { //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'" numPrec[t][c][r].y = (int) System.Math.Ceiling((try1 - cb0y) / twoppy) - (int) System.Math.Floor((try0 - cb0y) / (double) twoppy); } else { numPrec[t][c][r].y = 0; } minsbi = (r == 0)?0:1; maxsbi = (r == 0)?1:4; cblks[t][c][r] = new CBlkRateDistStats[maxsbi][]; for (l = 0; l < num_Layers; l++) { truncIdxs[t][l][c][r] = new int[maxsbi][]; } for (s = minsbi; s < maxsbi; s++) { // loop on subbands //Get the number of blocks in the current subband sb2 = (SubbandAn) sb.getSubbandByIdx(r, s); ncblks = sb2.numCb; cblkPerSubband = ncblks.x * ncblks.y; cblks[t][c][r][s] = new CBlkRateDistStats[cblkPerSubband]; for (l = 0; l < num_Layers; l++) { truncIdxs[t][l][c][r][s] = new int[cblkPerSubband]; for (i = 0; i < cblkPerSubband; i++) { truncIdxs[t][l][c][r][s][i] = - 1; } } } // End loop on subbands } // End lopp on resolution levels } // End loop on components if (t != nt - 1) { src.nextTile(); } } // End loop on tiles //Initialize the packet encoder pktEnc = new PktEncoder(src, encSpec, numPrec, pl); // The layers array has to be initialized after the constructor since // it is needed that the bit stream header has been entirely written }
/// <summary> Creates a new packet encoder object, using the information from the /// 'infoSrc' object. /// /// </summary> /// <param name="infoSrc">The source of information to construct the object. /// /// </param> /// <param name="encSpec">The encoding parameters. /// /// </param> /// <param name="numPrec">Maximum number of precincts in each tile, component /// and resolution level. /// /// </param> /// <param name="pl">ParameterList instance that holds command line options /// /// </param> public PktEncoder(CodedCBlkDataSrcEnc infoSrc, EncoderSpecs encSpec, Coord[][][] numPrec, ParameterList pl) { this.infoSrc = infoSrc; this.encSpec = encSpec; // Check parameters pl.checkList(OPT_PREFIX, CSJ2K.j2k.util.ParameterList.toNameArray(pinfo)); // Get number of components and tiles int nc = infoSrc.NumComps; int nt = infoSrc.getNumTiles(); // Do initial allocation ttIncl = new TagTreeEncoder[nt][][][][]; for (int i = 0; i < nt; i++) { ttIncl[i] = new TagTreeEncoder[nc][][][]; } ttMaxBP = new TagTreeEncoder[nt][][][][]; for (int i2 = 0; i2 < nt; i2++) { ttMaxBP[i2] = new TagTreeEncoder[nc][][][]; } lblock = new int[nt][][][][]; for (int i3 = 0; i3 < nt; i3++) { lblock[i3] = new int[nc][][][]; } prevtIdxs = new int[nt][][][][]; for (int i4 = 0; i4 < nt; i4++) { prevtIdxs[i4] = new int[nc][][][]; } ppinfo = new PrecInfo[nt][][][]; for (int i5 = 0; i5 < nt; i5++) { ppinfo[i5] = new PrecInfo[nc][][]; } // Finish allocation SubbandAn root, sb; int maxs, mins; int mrl; //Coord tmpCoord = null; int numcb; // Number of code-blocks //System.Collections.ArrayList cblks = null; infoSrc.setTile(0, 0); for (int t = 0; t < nt; t++) { // Loop on tiles for (int c = 0; c < nc; c++) { // Loop on components // Get number of resolution levels root = infoSrc.getAnSubbandTree(t, c); mrl = root.resLvl; lblock[t][c] = new int[mrl + 1][][]; ttIncl[t][c] = new TagTreeEncoder[mrl + 1][][]; ttMaxBP[t][c] = new TagTreeEncoder[mrl + 1][][]; prevtIdxs[t][c] = new int[mrl + 1][][]; ppinfo[t][c] = new PrecInfo[mrl + 1][]; for (int r = 0; r <= mrl; r++) { // Loop on resolution levels mins = (r == 0)?0:1; maxs = (r == 0)?1:4; int maxPrec = numPrec[t][c][r].x * numPrec[t][c][r].y; ttIncl[t][c][r] = new TagTreeEncoder[maxPrec][]; for (int i6 = 0; i6 < maxPrec; i6++) { ttIncl[t][c][r][i6] = new TagTreeEncoder[maxs]; } ttMaxBP[t][c][r] = new TagTreeEncoder[maxPrec][]; for (int i7 = 0; i7 < maxPrec; i7++) { ttMaxBP[t][c][r][i7] = new TagTreeEncoder[maxs]; } prevtIdxs[t][c][r] = new int[maxs][]; lblock[t][c][r] = new int[maxs][]; // Precincts and code-blocks ppinfo[t][c][r] = new PrecInfo[maxPrec]; fillPrecInfo(t, c, r); for (int s = mins; s < maxs; s++) { // Loop on subbands sb = (SubbandAn) root.getSubbandByIdx(r, s); numcb = sb.numCb.x * sb.numCb.y; lblock[t][c][r][s] = new int[numcb]; ArrayUtil.intArraySet(lblock[t][c][r][s], INIT_LBLOCK); prevtIdxs[t][c][r][s] = new int[numcb]; ArrayUtil.intArraySet(prevtIdxs[t][c][r][s], - 1); } } } if (t != nt - 1) infoSrc.nextTile(); } }
/// <summary> Initializes this object with the given source of image data and with /// all the decompositon parameters /// /// </summary> /// <param name="src">From where the image data should be obtained. /// /// </param> /// <param name="encSpec">The encoder specifications /// /// </param> /// <param name="cb0x">The horizontal coordinate of the code-block partition /// origin on the reference grid. /// /// </param> /// <param name="cb0y">The vertical coordinate of the code-block partition origin /// on the reference grid. /// /// </param> /// <seealso cref="ForwardWT"> /// /// </seealso> public ForwWTFull(BlkImgDataSrc src, EncoderSpecs encSpec, int cb0x, int cb0y):base(src) { this.src = src; this.cb0x = cb0x; this.cb0y = cb0y; this.dls = encSpec.dls; this.filters = encSpec.wfs; this.cblks = encSpec.cblks; this.pss = encSpec.pss; int ncomp = src.NumComps; int ntiles = src.getNumTiles(); currentSubband = new SubbandAn[ncomp]; decomposedComps = new DataBlk[ncomp]; subbTrees = new SubbandAn[ntiles][]; for (int i = 0; i < ntiles; i++) { subbTrees[i] = new SubbandAn[ncomp]; } lastn = new int[ncomp]; lastm = new int[ncomp]; }
/// <summary> Calculates the maximum amount of magnitude bits for each /// tile-component, and stores it in the 'maxMagBits' array. This is called /// by the constructor /// /// </summary> /// <param name="encSpec">The encoder specifications for addition of roi specs /// /// </param> private void calcMaxMagBits(EncoderSpecs encSpec) { int tmp; MaxShiftSpec rois = encSpec.rois; int nt = src.getNumTiles(); int nc = src.NumComps; maxMagBits = new int[nt][]; for (int i = 0; i < nt; i++) { maxMagBits[i] = new int[nc]; } src.setTile(0, 0); for (int t = 0; t < nt; t++) { for (int c = nc - 1; c >= 0; c--) { tmp = src.getMaxMagBits(c); maxMagBits[t][c] = tmp; rois.setTileCompVal(t, c, (System.Object) tmp); } if (t < nt - 1) src.nextTile(); } // Reset to current initial tile position src.setTile(0, 0); }
/// <summary> Creates a ForwardWT object with the specified filters, and with other /// options specified in the parameter list 'pl'. /// /// </summary> /// <param name="src">The source of data to be transformed /// /// </param> /// <param name="pl">The parameter list (or options). /// /// </param> /// <param name="kers">The encoder specifications. /// /// </param> /// <returns> A new ForwardWT object with the specified filters and options /// from 'pl'. /// /// </returns> /// <exception cref="IllegalArgumentException">If mandatory parameters are missing /// or if invalid values are given. /// /// </exception> public static ForwardWT createInstance(BlkImgDataSrc src, ParameterList pl, EncoderSpecs encSpec) { int deflev; // defdec removed //System.String decompstr; //System.String wtstr; //System.String pstr; //SupportClass.StreamTokenizerSupport stok; //SupportClass.Tokenizer strtok; //int prefx, prefy; // Partitioning reference point coordinates // Check parameters pl.checkList(OPT_PREFIX, CSJ2K.j2k.util.ParameterList.toNameArray(pinfo)); deflev = ((System.Int32) encSpec.dls.getDefault()); // Code-block partition origin System.String str = ""; if (pl.getParameter("Wcboff") == null) { throw new System.ApplicationException("You must specify an argument to the '-Wcboff' " + "option. See usage with the '-u' option"); } SupportClass.Tokenizer stk = new SupportClass.Tokenizer(pl.getParameter("Wcboff")); if (stk.Count != 2) { throw new System.ArgumentException("'-Wcboff' option needs two" + " arguments. See usage with " + "the '-u' option."); } int cb0x = 0; str = stk.NextToken(); try { cb0x = (System.Int32.Parse(str)); } catch (System.FormatException) { throw new System.ArgumentException("Bad first parameter for the " + "'-Wcboff' option: " + str); } if (cb0x < 0 || cb0x > 1) { throw new System.ArgumentException("Invalid horizontal " + "code-block partition origin."); } int cb0y = 0; str = stk.NextToken(); try { cb0y = (System.Int32.Parse(str)); } catch (System.FormatException) { throw new System.ArgumentException("Bad second parameter for the " + "'-Wcboff' option: " + str); } if (cb0y < 0 || cb0y > 1) { throw new System.ArgumentException("Invalid vertical " + "code-block partition origin."); } if (cb0x != 0 || cb0y != 0) { FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.WARNING, "Code-blocks partition origin is " + "different from (0,0). This is defined in JPEG 2000" + " part 2 and may be not supported by all JPEG 2000 " + "decoders."); } return new ForwWTFull(src, encSpec, cb0x, cb0y); }
/// <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> Creates a ROIScaler object. The Quantizer is the source of data to /// scale. /// /// <p>The ROI Scaler creates a ROIMaskGenerator depending on what ROI /// information is in the ParameterList. If only rectangular ROI are used, /// the fast mask generator for rectangular ROI can be used.</p> /// /// </summary> /// <param name="src">The source of data to scale /// /// </param> /// <param name="pl">The parameter list (or options). /// /// </param> /// <param name="encSpec">The encoder specifications for addition of roi specs /// /// </param> /// <exception cref="IllegalArgumentException">If an error occurs while parsing /// the options in 'pl' /// /// </exception> public static ROIScaler createInstance(Quantizer src, ParameterList pl, EncoderSpecs encSpec) { System.Collections.ArrayList roiVector = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10)); ROIMaskGenerator maskGen = null; // Check parameters pl.checkList(OPT_PREFIX, CSJ2K.j2k.util.ParameterList.toNameArray(pinfo)); // Get parameters and check if there are and ROIs specified System.String roiopt = pl.getParameter("Rroi"); if (roiopt == null) { // No ROIs specified! Create ROIScaler with no mask generator return new ROIScaler(src, null, false, - 1, false, encSpec); } // Check if the lowest resolution levels should belong to the ROI int sLev = pl.getIntParameter("Rstart_level"); // Check if the ROIs are block-aligned bool useBlockAligned = pl.getBooleanParameter("Ralign"); // Check if generic mask generation is specified bool onlyRect = !pl.getBooleanParameter("Rno_rect"); // Parse the ROIs parseROIs(roiopt, src.NumComps, roiVector); ROI[] roiArray = new ROI[roiVector.Count]; roiVector.CopyTo(roiArray); // If onlyRect has been forced, check if there are any non-rectangular // ROIs specified. Currently, only the presence of circular ROIs will // make this false if (onlyRect) { for (int i = roiArray.Length - 1; i >= 0; i--) if (!roiArray[i].rect) { onlyRect = false; break; } } if (onlyRect) { // It's possible to use the fast ROI mask generation when only // rectangular ROIs are specified. maskGen = new RectROIMaskGenerator(roiArray, src.NumComps); } else { // It's necessary to use the generic mask generation maskGen = new ArbROIMaskGenerator(roiArray, src.NumComps, src); } return new ROIScaler(src, maskGen, true, sLev, useBlockAligned, encSpec); }
/// <summary> Creates a Quantizer object for the appropriate type of quantization /// specified in the options in the parameter list 'pl', and having 'src' /// as the source of data to be quantized. The 'rev' flag indicates if the /// quantization should be reversible. /// /// NOTE: At the moment only sources of wavelet data that implement the /// 'CBlkWTDataSrc' interface are supported. /// /// </summary> /// <param name="src">The source of data to be quantized /// /// </param> /// <param name="encSpec">Encoder specifications /// /// </param> /// <exception cref="IllegalArgumentException">If an error occurs while parsing /// the options in 'pl' /// /// </exception> public static Quantizer createInstance(CBlkWTDataSrc src, EncoderSpecs encSpec) { // Instantiate quantizer return new StdQuantizer(src, encSpec); }
public static byte[] EncodeJPEG(Image jpgImage) { Tiler imgtiler; ForwCompTransf fctransf; ImgDataConverter converter; EncoderSpecs encSpec; ForwardWT dwt; Quantizer quant; ROIScaler rois; EntropyCoder ecoder; PostCompRateAllocator ralloc; HeaderEncoder headenc; CodestreamWriter bwriter; float rate = Single.MaxValue; ImgReaderGDI imgsrc = new ImgReaderGDI(jpgImage); imgtiler = new Tiler(imgsrc, 0, 0, 0, 0, jpgImage.Width, jpgImage.Height); int ntiles = imgtiler.getNumTiles(); encSpec = new EncoderSpecs(ntiles, 3, imgsrc, pl); fctransf = new ForwCompTransf(imgtiler, encSpec); converter = new ImgDataConverter(fctransf); dwt = ForwardWT.createInstance(converter, pl, encSpec); quant = Quantizer.createInstance(dwt, encSpec); rois = ROIScaler.createInstance(quant, pl, encSpec); ecoder = EntropyCoder.createInstance(rois, pl, encSpec.cblks, encSpec.pss, encSpec.bms, encSpec.mqrs, encSpec.rts, encSpec.css, encSpec.sss, encSpec.lcs, encSpec.tts); using (MemoryStream stream = new MemoryStream()) { bwriter = new FileCodestreamWriter(stream, Int32.MaxValue); ralloc = PostCompRateAllocator.createInstance(ecoder, pl, rate, bwriter, encSpec); headenc = new HeaderEncoder(imgsrc, new bool[3], dwt, imgtiler, encSpec, rois, ralloc, pl); ralloc.HeaderEncoder = headenc; headenc.encodeMainHeader(); ralloc.initialize(); headenc.reset(); headenc.encodeMainHeader(); bwriter.commitBitstreamHeader(headenc); ralloc.runAndWrite(); bwriter.close(); return stream.ToArray(); } }
/// <summary> Constructs a new ForwCompTransf object that operates on the specified /// source of image data. /// /// </summary> /// <param name="imgSrc">The source from where to get the data to be transformed /// /// </param> /// <param name="encSpec">The encoder specifications /// /// </param> /// <seealso cref="BlkImgDataSrc"> /// /// </seealso> public ForwCompTransf(BlkImgDataSrc imgSrc, EncoderSpecs encSpec):base(imgSrc) { this.cts = encSpec.cts; this.wfs = encSpec.wfs; src = imgSrc; }
/// <summary> Creates a PostCompRateAllocator object for the appropriate rate /// allocation parameters in the parameter list 'pl', having 'src' as the /// source of entropy coded data, 'rate' as the target bitrate and 'bw' as /// the bit stream writer object. /// /// </summary> /// <param name="src">The source of entropy coded data. /// /// </param> /// <param name="pl">The parameter lis (or options). /// /// </param> /// <param name="rate">The target bitrate for the rate allocation /// /// </param> /// <param name="bw">The bit stream writer object, where the bit stream data will /// be written. /// /// </param> public static PostCompRateAllocator createInstance(CodedCBlkDataSrcEnc src, ParameterList pl, float rate, CodestreamWriter bw, EncoderSpecs encSpec) { // Check parameters pl.checkList(OPT_PREFIX, CSJ2K.j2k.util.ParameterList.toNameArray(pinfo)); // Construct the layer specification from the 'Alayers' option LayersInfo lyrs = parseAlayers(pl.getParameter("Alayers"), rate); int nTiles = encSpec.nTiles; int nComp = encSpec.nComp; int numLayers = lyrs.TotNumLayers; // Parse the progressive type encSpec.pocs = new ProgressionSpec(nTiles, nComp, numLayers, encSpec.dls, ModuleSpec.SPEC_TYPE_TILE_COMP, pl); return new EBCOTRateAllocator(src, lyrs, bw, encSpec, pl); }
/// <summary> Initializes the source of entropy coded data. /// /// </summary> /// <param name="src">The source of entropy coded data. /// /// </param> /// <param name="ln">The number of layers to create /// /// </param> /// <param name="pt">The progressive type, as defined in 'ProgressionType'. /// /// </param> /// <param name="bw">The packet bit stream writer. /// /// </param> /// <seealso cref="ProgressionType"> /// /// </seealso> public PostCompRateAllocator(CodedCBlkDataSrcEnc src, int nl, CodestreamWriter bw, EncoderSpecs encSpec):base(src) { this.src = src; this.encSpec = encSpec; num_Layers = nl; bsWriter = bw; }
/// <summary> Initializes the source of wavelet transform coefficients. The /// constructor takes information on whether the quantizer is in /// reversible, derived or expounded mode. If the quantizer is reversible /// the value of 'derived' is ignored. If the source data is not integer /// (int) then the quantizer can not be reversible. /// /// <p>After initializing member attributes, getAnSubbandTree is called for /// all components setting the 'stepWMSE' for all subbands in the current /// tile.</p> /// /// </summary> /// <param name="src">The source of wavelet transform coefficients. /// /// </param> /// <param name="encSpec">The encoder specifications /// /// </param> public StdQuantizer(CBlkWTDataSrc src, EncoderSpecs encSpec):base(src) { qts = encSpec.qts; qsss = encSpec.qsss; gbs = encSpec.gbs; }
public static byte[] ToBytes(BlkImgDataSrc imgsrc, ParameterList parameters = null) { // Initialize default parameters ParameterList defpl = GetDefaultEncoderParameterList(encoder_pinfo); // Create parameter list using defaults ParameterList pl = parameters ?? new ParameterList(defpl); bool useFileFormat = false; bool pphTile = false; bool pphMain = false; bool tempSop = false; bool tempEph = false; // **** Get general parameters **** if (pl.getParameter("file_format").Equals("on")) { useFileFormat = true; if (pl.getParameter("rate") != null && pl.getFloatParameter("rate") != defpl.getFloatParameter("rate")) { warning("Specified bit-rate applies only on the codestream but not on the whole file."); } } if (pl.getParameter("tiles") == null) { error("No tiles option specified", 2); return null; } if (pl.getParameter("pph_tile").Equals("on")) { pphTile = true; if (pl.getParameter("Psop").Equals("off")) { pl["Psop"] = "on"; tempSop = true; } if (pl.getParameter("Peph").Equals("off")) { pl["Peph"] = "on"; tempEph = true; } } if (pl.getParameter("pph_main").Equals("on")) { pphMain = true; if (pl.getParameter("Psop").Equals("off")) { pl["Psop"] = "on"; tempSop = true; } if (pl.getParameter("Peph").Equals("off")) { pl["Peph"] = "on"; tempEph = true; } } if (pphTile && pphMain) error("Can't have packed packet headers in both main and" + " tile headers", 2); if (pl.getBooleanParameter("lossless") && pl.getParameter("rate") != null && pl.getFloatParameter("rate") != defpl.getFloatParameter("rate")) throw new ArgumentException("Cannot use '-rate' and " + "'-lossless' option at " + " the same time."); if (pl.getParameter("rate") == null) { error("Target bitrate not specified", 2); return null; } float rate; try { rate = pl.getFloatParameter("rate"); if (rate == -1) { rate = float.MaxValue; } } catch (FormatException e) { error("Invalid value in 'rate' option: " + pl.getParameter("rate"), 2); return null; } int pktspertp; try { pktspertp = pl.getIntParameter("tile_parts"); if (pktspertp != 0) { if (pl.getParameter("Psop").Equals("off")) { pl["Psop"] = "on"; tempSop = true; } if (pl.getParameter("Peph").Equals("off")) { pl["Peph"] = "on"; tempEph = true; } } } catch (FormatException e) { error("Invalid value in 'tile_parts' option: " + pl.getParameter("tile_parts"), 2); return null; } // **** ImgReader **** var ncomp = imgsrc.NumComps; var ppminput = imgsrc.NumComps > 1; // **** Tiler **** // get nominal tile dimensions SupportClass.StreamTokenizerSupport stok = new SupportClass.StreamTokenizerSupport(new StringReader(pl.getParameter("tiles"))); stok.EOLIsSignificant(false); stok.NextToken(); if (stok.ttype != SupportClass.StreamTokenizerSupport.TT_NUMBER) { error("An error occurred while parsing the tiles option: " + pl.getParameter("tiles"), 2); return null; } var tw = (int)stok.nval; stok.NextToken(); if (stok.ttype != SupportClass.StreamTokenizerSupport.TT_NUMBER) { error("An error occurred while parsing the tiles option: " + pl.getParameter("tiles"), 2); return null; } var th = (int)stok.nval; // Get image reference point var refs = pl.getParameter("ref").Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); int refx; int refy; try { refx = Int32.Parse(refs[0]); refy = Int32.Parse(refs[1]); } catch (IndexOutOfRangeException e) { throw new ArgumentException("Error while parsing 'ref' " + "option"); } catch (FormatException e) { throw new ArgumentException("Invalid number type in " + "'ref' option"); } if (refx < 0 || refy < 0) { throw new ArgumentException("Invalid value in 'ref' " + "option "); } // Get tiling reference point var trefs = pl.getParameter("tref").Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); int trefx; int trefy; try { trefx = Int32.Parse(trefs[0]); trefy = Int32.Parse(trefs[1]); } catch (IndexOutOfRangeException e) { throw new ArgumentException("Error while parsing 'tref' " + "option"); } catch (FormatException e) { throw new ArgumentException("Invalid number type in " + "'tref' option"); } if (trefx < 0 || trefy < 0 || trefx > refx || trefy > refy) { throw new ArgumentException("Invalid value in 'tref' " + "option "); } // Instantiate tiler Tiler imgtiler; try { imgtiler = new Tiler(imgsrc, refx, refy, trefx, trefy, tw, th); } catch (ArgumentException e) { error("Could not tile image" + ((e.Message != null) ? (":\n" + e.Message) : ""), 2); return null; } int ntiles = imgtiler.getNumTiles(); // **** Encoder specifications **** var encSpec = new EncoderSpecs(ntiles, ncomp, imgsrc, pl); // **** Component transformation **** if (ppminput && pl.getParameter("Mct") != null && pl.getParameter("Mct").Equals("off")) { FacilityManager.getMsgLogger() .printmsg( MsgLogger_Fields.WARNING, "Input image is RGB and no color transform has " + "been specified. Compression performance and " + "image quality might be greatly degraded. Use " + "the 'Mct' option to specify a color transform"); } ForwCompTransf fctransf; try { fctransf = new ForwCompTransf(imgtiler, encSpec); } catch (ArgumentException e) { error( "Could not instantiate forward component " + "transformation" + ((e.Message != null) ? (":\n" + e.Message) : ""), 2); return null; } // **** ImgDataConverter **** var converter = new ImgDataConverter(fctransf); // **** ForwardWT **** ForwardWT dwt; try { dwt = ForwardWT.createInstance(converter, pl, encSpec); } catch (ArgumentException e) { error("Could not instantiate wavelet transform" + ((e.Message != null) ? (":\n" + e.Message) : ""), 2); return null; } // **** Quantizer **** Quantizer quant; try { quant = Quantizer.createInstance(dwt, encSpec); } catch (ArgumentException e) { error("Could not instantiate quantizer" + ((e.Message != null) ? (":\n" + e.Message) : ""), 2); return null; } // **** ROIScaler **** ROIScaler rois; try { rois = ROIScaler.createInstance(quant, pl, encSpec); } catch (ArgumentException e) { error("Could not instantiate ROI scaler" + ((e.Message != null) ? (":\n" + e.Message) : ""), 2); return null; } // **** EntropyCoder **** EntropyCoder ecoder; try { ecoder = EntropyCoder.createInstance( rois, pl, encSpec.cblks, encSpec.pss, encSpec.bms, encSpec.mqrs, encSpec.rts, encSpec.css, encSpec.sss, encSpec.lcs, encSpec.tts); } catch (ArgumentException e) { error("Could not instantiate entropy coder" + ((e.Message != null) ? (":\n" + e.Message) : ""), 2); return null; } // **** CodestreamWriter **** using (var outStream = new MemoryStream()) { CodestreamWriter bwriter; try { // Rely on rate allocator to limit amount of data bwriter = new FileCodestreamWriter(outStream, Int32.MaxValue); } catch (IOException e) { error("Could not open output file" + ((e.Message != null) ? (":\n" + e.Message) : ""), 2); return null; } // **** Rate allocator **** PostCompRateAllocator ralloc; try { ralloc = PostCompRateAllocator.createInstance(ecoder, pl, rate, bwriter, encSpec); } catch (ArgumentException e) { error("Could not instantiate rate allocator" + ((e.Message != null) ? (":\n" + e.Message) : ""), 2); return null; } // **** HeaderEncoder **** var imsigned = Enumerable.Repeat(false, ncomp).ToArray(); // TODO Consider supporting signed components. var headenc = new HeaderEncoder(imgsrc, imsigned, dwt, imgtiler, encSpec, rois, ralloc, pl); ralloc.HeaderEncoder = headenc; // **** Write header to be able to estimate header overhead **** headenc.encodeMainHeader(); // **** Initialize rate allocator, with proper header // overhead. This will also encode all the data **** ralloc.initialize(); // **** Write header (final) **** headenc.reset(); headenc.encodeMainHeader(); // Insert header into the codestream bwriter.commitBitstreamHeader(headenc); // **** Now do the rate-allocation and write result **** ralloc.runAndWrite(); // **** Done **** bwriter.close(); // **** Calculate file length **** int fileLength = bwriter.Length; // **** Tile-parts and packed packet headers **** if (pktspertp > 0 || pphTile || pphMain) { try { CodestreamManipulator cm = new CodestreamManipulator( outStream, ntiles, pktspertp, pphMain, pphTile, tempSop, tempEph); fileLength += cm.doCodestreamManipulation(); //String res=""; if (pktspertp > 0) { FacilityManager.getMsgLogger() .println( "Created tile-parts " + "containing at most " + pktspertp + " packets per tile.", 4, 6); } if (pphTile) { FacilityManager.getMsgLogger().println("Moved packet headers " + "to tile headers", 4, 6); } if (pphMain) { FacilityManager.getMsgLogger().println("Moved packet headers " + "to main header", 4, 6); } } catch (IOException e) { error( "Error while creating tileparts or packed packet" + " headers" + ((e.Message != null) ? (":\n" + e.Message) : ""), 2); return null; } } // **** File Format **** if (useFileFormat) { try { int nc = imgsrc.NumComps; int[] bpc = new int[nc]; for (int comp = 0; comp < nc; comp++) { bpc[comp] = imgsrc.getNomRangeBits(comp); } outStream.Seek(0, SeekOrigin.Begin); var ffw = new FileFormatWriter( outStream, imgsrc.ImgHeight, imgsrc.ImgWidth, nc, bpc, fileLength); fileLength += ffw.writeFileFormat(); } catch (IOException e) { throw new InvalidOperationException("Error while writing JP2 file format: " + e.Message); } } // **** Close image readers *** imgsrc.close(); return outStream.ToArray(); } }