示例#1
0
        const int blkSize = ImgInfo.blockSize; // JPEG decoding block size is 8x8

        #endregion Fields

        #region Methods

        internal static void DecodeBlock(BitReader bReader, ImgInfo imgInfo, float[,] img,
            int compIndex, int ofsX, int ofsY, int scaleX, int scaleY)
        {
            int quantIndex = imgInfo.components[compIndex].quantTableId;

            short[] coefZig = GetCoefficients(bReader, imgInfo, compIndex, blkSize * blkSize);
            FileOps.ZigZagToArray(coefZig, coefDctQnt, FileOps.tablasZigzag[blkSize], blkSize);
            ImgOps.Dequant(coefDctQnt, coefDct, imgInfo.quantTables[quantIndex].table, blkSize);
            ImgOps.Fidct(coefDct, blockP, blkSize, blkSize);

            ImgOps.ResizeAndInsertBlock(imgInfo, blockP, img, blkSize, blkSize, ofsX, ofsY, scaleX, scaleY);
        }
示例#2
0
        internal static void ResizeAndInsertBlock(ImgInfo imgInfo, float[,] block, float[,] imagen, int tamX, int tamY, int ofsX, int ofsY, int scaleX, int scaleY)
        {
            // Nearest neighbor interpolation
            // For staircase FTW
            if (ofsX < imgInfo.width && ofsY < imgInfo.height)
            {
                for (int j = 0; j < tamY; j++)
                {
                    for (int i = 0; i < tamX; i++)
                    {
                        for (int jj = 0; jj < scaleY; jj++)
                        {
                            for (int ii = 0; ii < scaleX; ii++)
                            {
                                int posYimg = j * scaleY + ofsY + jj;
                                int posXimg = i * scaleX + ofsX + ii;

                                if (posYimg < imgInfo.height && posXimg < imgInfo.width)
                                {
                                    imagen[posYimg, posXimg] = block[j, i];
                                }
                            }
                        }
                    }
                }
            }
        }
示例#3
0
        public static List<Bitmap> Decode(MemoryStream stream)
        {
            var reader = new BinaryReader(stream);
            var images = new List<Bitmap>();

            stream.Seek(0, SeekOrigin.Begin);

            bool eof = false;

            for (int image = 1; ; image++)
            {
                try
                {
                    ImgInfo imgInfo = new ImgInfo();

                    while (true)
                    {
                        while (reader.ReadByte() != 0xff) ;
                        int markerId = reader.ReadByte();

                        switch ((Markers)markerId)
                        {
                            case Markers.App0:
                                App0.Read(reader, imgInfo);
                                break;
                            case Markers.App14:
                                App14.Read(reader, imgInfo);
                                break;
                            case Markers.Dqt:
                                Dqt.Read(reader, imgInfo);
                                break;
                            case Markers.Sof0:
                                Sof0.Read(reader, imgInfo);
                                break;
                            case Markers.Sof2:
                                Sof2.Read(reader, imgInfo);
                                break;
                            case Markers.Dht:
                                Dht.Read(reader, imgInfo);
                                break;
                            case Markers.Sos:
                                images.Add(Sos.Read(reader, imgInfo));
                                break;
                            case Markers.Soi:
                                imgInfo = new ImgInfo();
                                Logger.Write("Start of Image " + image);
                                Logger.WriteLine(" at: " + (reader.BaseStream.Position - 2).ToString("X"));
                                imgInfo.startOfImageFound = true;
                                break;
                            case Markers.Dri:
                                Dri.Read(reader, imgInfo);
                                break;
                            case Markers.Eoi:
                                Logger.Write("End of Image " + image);
                                Logger.WriteLine(" at: " + (reader.BaseStream.Position - 2).ToString("X"));
                                eof = true;
                                break;
                            // Unknown markers, or markers used outside of their specified area
                            default:
                                Default.Read(reader, imgInfo, (Markers)markerId);
                                break;
                        }

                        if (eof)
                        {
                            eof = false;
                            break;
                        }
                    }
                }
                catch (EndOfStreamException)
                {
                    break;
                }
                catch (Exception ex)
                {
                    Logger.WriteLine(ex.Message);
                }
            }

            reader.Close();
            Logger.Flush();

            return images;
        }
示例#4
0
        internal static Bitmap DecodeImage(BinaryReader reader, ImgInfo imgInfo)
        {
            // Used for reading those nasty variable length codes
            BitReader bReader = new BitReader(reader);
            float[][,] img = new float[imgInfo.numOfComponents][,];

            imgInfo.deltaDc = new short[imgInfo.numOfComponents];

            for (int ch = 0; ch < imgInfo.numOfComponents; ch++)
                img[ch] = new float[imgInfo.height, imgInfo.width];

            try
            {
                // Determine the width of height of the MCU, based on the read subsampling
                // values from all channels (don't know if this is the correct way for all cases)
                // but it works for the most common ones
                var componentMax = imgInfo.components.Aggregate((a, b) =>
                {
                    return new Markers.ComponentInfo()
                    {
                        samplingFactorX = Math.Max(a.samplingFactorX, b.samplingFactorX),
                        samplingFactorY = Math.Max(a.samplingFactorY, b.samplingFactorY)
                    };
                });

                int sizeMcuX = blkSize * componentMax.samplingFactorX;
                int sizeMcuY = blkSize * componentMax.samplingFactorY;

                int numMcusX = (imgInfo.width + sizeMcuX - 1) / sizeMcuX;
                int numMcusY = (imgInfo.height + sizeMcuY - 1) / sizeMcuY;

                for (int mcu = 0; mcu < numMcusX * numMcusY; mcu = NextMcuPos(imgInfo, bReader, mcu, numMcusX, numMcusY))
                {
                    // X and Y coordinates of current MCU
                    int mcuX = mcu % numMcusX;
                    int mcuY = mcu / numMcusX;
                    // Starting X and Y pixels of current MCU
                    int ofsX = mcuX * sizeMcuX;
                    int ofsY = mcuY * sizeMcuY;

                    for (int ch = 0; ch < imgInfo.numOfComponents; ch++)
                    {
                        int scaleX = componentMax.samplingFactorX / imgInfo.components[ch].samplingFactorX;
                        int scaleY = componentMax.samplingFactorY / imgInfo.components[ch].samplingFactorY;

                        for (int sy = 0; sy < imgInfo.components[ch].samplingFactorY; sy++)
                        {
                            for (int sx = 0; sx < imgInfo.components[ch].samplingFactorX; sx++)
                            {
                                DecodeBlock(bReader, imgInfo, img[ch], ch, ofsX + blkSize * sx, ofsY + blkSize * sy,
                                    scaleX, scaleY);
                            }
                        }
                    }

                    if (bReader.PastEndOfFile) break;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLine(ex.Message);
                Logger.WriteLine(ex.StackTrace);
            }

            Color2[,] imagen = MergeChannels(imgInfo, img);
            Bitmap bmp = new Bitmap(imgInfo.width, imgInfo.height);
            BmpData conv = new BmpData(bmp);

            bReader.StopReading();
            conv.SetImage(imagen);

            return bmp;
        }
示例#5
0
 // If we found a restart marker, reset all DC prediction deltas, so we can
 // start anew and not depend on previous (possibly corrupted) data
 internal static void ResetDeltas(ImgInfo imgInfo)
 {
     for (int i = 0; i < imgInfo.numOfComponents; i++)
     {
         imgInfo.deltaDc[i] = 0;
     }
 }
示例#6
0
        internal static int NextMcuPos(ImgInfo imgInfo, BitReader bReader, int mcu, int numMcusX, int numMcusY)
        {
            // If we are expecting a restart marker, find it in the stream,
            // reset the DC prediction variables and calculate the new MCU position
            // otherwise, just increment the position by one
            if (imgInfo.hasRestartMarkers &&
               (mcu % imgInfo.restartInterval) == imgInfo.restartInterval - 1 &&
               (mcu < numMcusX * numMcusY - 1))
            {
                Pixz.Markers currRestMarker = bReader.SyncStreamToNextRestartMarker();

                if (currRestMarker == Pixz.Markers.Eoi) // If EOI marker was found
                    return numMcusX * numMcusY; // Early terminate the decoding process

                int difference = currRestMarker - imgInfo.prevRestMarker;

                if (difference <= 0) difference += Markers.Dri.RestartMarkerPeriod;

                // For non corrupted images, difference should be always 1
                ResetDeltas(imgInfo);
                imgInfo.mcuStrip += difference;
                imgInfo.prevRestMarker = currRestMarker;

                return imgInfo.mcuStrip * imgInfo.restartInterval;
            }
            else if (bReader.WasEoiFound())
            {
                return numMcusX * numMcusY;
            }
            else
            {
                return ++mcu;
            }
        }
示例#7
0
        /// <summary>
        /// Converts from their colorspace to RGB and combines all previously decoded channels
        /// </summary>
        /// <param name="imgInfo"></param>
        /// <param name="imgS"></param>
        /// <returns>A 2D array representing the color data from the image</returns>
        internal static Color2[,] MergeChannels(ImgInfo imgInfo, float[][,] imgS)
        {
            Color2[,] img = new Color2[imgInfo.height, imgInfo.width];
            IColorspaceConverter converter;

            if (imgInfo.app14MarkerFound)
            {
                switch (imgInfo.colorMode)
                {
                    case Markers.App14ColorMode.Unknown:
                        if (imgInfo.numOfComponents == 3)
                        {
                            converter = new Rgb();
                        }
                        else
                        {
                            converter = new YCbCr();
                        }
                        break;
                    case Markers.App14ColorMode.YCbCr:
                        converter = new YCbCr();
                        break;
                    case Markers.App14ColorMode.YCCK:
                        converter = new YCbCr();
                        break;
                    default:
                        converter = new Rgb();
                        break;
                }
            }
            else
            {
                converter = new Colorspaces.YCbCr();
            }

            for (int y = 0; y < imgInfo.height; y++)
            {
                for (int x = 0; x < imgInfo.width; x++)
                {
                    Info info;

                    if (imgInfo.numOfComponents == 1) // Y
                    {
                        info.a = imgS[0][y, x];
                        info.b = 0;
                        info.c = 0;
                    }
                    else // YCbCr
                    {
                        info.a = imgS[0][y, x];
                        info.b = imgS[1][y, x];
                        info.c = imgS[2][y, x];
                    }

                    img[y, x] = converter.ConvertToRgb(info);
                }
            }

            return img;
        }
示例#8
0
        internal static short[] GetCoefficients(BitReader bReader, ImgInfo imgInfo, int compIndex, int numCoefs)
        {
            var coefZig = new short[numCoefs];
            int acIndex = imgInfo.components[compIndex].acHuffmanTable;
            int dcIndex = imgInfo.components[compIndex].dcHuffmanTable;

            // DC coefficient
            uint runAmplitude = Huffman.ReadRunAmplitude(bReader, imgInfo.huffmanTables[0, dcIndex]);

            uint run = runAmplitude >> 4; // Upper nybble
            uint amplitude = runAmplitude & 0xf; // Lower nybble

            coefZig[0] = (short)(Huffman.ReadCoefValue(bReader, amplitude) + imgInfo.deltaDc[compIndex]);

            imgInfo.deltaDc[compIndex] = coefZig[0];

            // AC coefficients
            uint pos = 0;

            while (pos < blkSize * blkSize - 1)
            {
                runAmplitude = Huffman.ReadRunAmplitude(bReader, imgInfo.huffmanTables[1, acIndex]);

                // 0x00 is End of Block
                if (runAmplitude == 0x00) break;

                run = runAmplitude >> 4;
                amplitude = runAmplitude & 0xf;
                pos += run + 1;

                if (pos >= blkSize * blkSize) break;

                coefZig[pos] = Huffman.ReadCoefValue(bReader, amplitude);
            }

            return coefZig;
        }