This class apply component transformations to the tiles depending on user specifications. These transformations can be used to improve compression efficiency but are not related to colour transforms used to map colour values for display purposes. JPEG 2000 part I defines 2 component transformations: RCT (Reversible Component Transformation) and ICT (Irreversible Component Transformation).
Inheritance: CSJ2K.j2k.image.ImgDataAdapter, BlkImgDataSrc
Exemplo n.º 1
0
        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();
            }
        }
Exemplo n.º 2
0
        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();
            }
        }