Exemple #1
0
        void DecodeARW(ImageBinaryReader input, long w, long h)
        {
            BitPumpMSB bits = new BitPumpMSB(input);

            int sum = 0;

            for (long x = w; (x--) != 0;)
            {
                for (int y = 0; y < h + 1; y += 2)
                {
                    bits.Fill();
                    if (y == h)
                    {
                        y = 1;
                    }
                    int len = 4 - (int)bits.GetBits(2);
                    if (len == 3 && bits.GetBit() != 0)
                    {
                        len = 0;
                    }
                    if (len == 4)
                    {
                        while (len < 17 && bits.GetBit() == 0)
                        {
                            len++;
                        }
                    }
                    int diff = (int)bits.GetBits(len);
                    if (len != 0 && (diff & (1 << (len - 1))) == 0)
                    {
                        diff -= (1 << len) - 1;
                    }
                    sum += diff;
                    Debug.Assert((sum >> 12) == 0);
                    if (y < h)
                    {
                        rawImage.fullSize.rawView[x + y * rawImage.fullSize.dim.width] = (ushort)sum;
                    }
                }
            }
        }
Exemple #2
0
        /* This is probably the slowest decoder of them all.
         * I cannot see any way to effectively speed up the prediction
         * phase, which is by far the slowest part of this algorithm.
         * Also there is no way to multithread this code, since prediction
         * is based on the output of all previous pixel (bar the first four)
         */
        private void DecodeCompressed(ImageBinaryReader s, uint width, uint height)
        {
            int  nbits;
            long left0, nw0, left1, nw1;
            long sign, low, high;

            long[] acarry0 = new long[3], acarry1 = new long[3];
            long   pred, diff;

            //uint pitch = rawImage.pitch;

            /* Build a table to quickly look up "high" value */
            byte[] bittable = new byte[4096];
            for (int i = 0; i < 4096; i++)
            {
                int b = i;
                for (high = 0; high < 12; high++)
                {
                    if (((b >> (11 - (int)high)) & 1) != 0)
                    {
                        break;
                    }
                }
                bittable[i] = (byte)Math.Min(12, high);
            }
            left0 = nw0 = left1 = nw1 = 0;
            s.ReadBytes(7);
            BitPumpMSB bits = new BitPumpMSB(s);

            for (int y = 0; y < height; y++)
            {
                var pos = y * rawImage.fullSize.UncroppedDim.width;
                acarry0 = new long[3];
                acarry1 = new long[3];
                bool y_border = y < 2;
                bool border   = true;
                for (int x = 0; x < width; x++)
                {
                    bits.Fill();
                    int i = 0;
                    if (acarry0[2] < 3)
                    {
                        i = 2;
                    }

                    for (nbits = 2 + i; acarry0[0] >> (nbits + i) != 0; nbits++)
                    {
                        ;
                    }

                    uint b = bits.PeekBits(15);
                    sign = (b >> 14) * -1;
                    low  = (b >> 12) & 3;
                    high = bittable[b & 4095];

                    // Skip bytes used above or read bits
                    if (high == 12)
                    {
                        bits.SkipBits(15);
                        high = bits.GetBits(16 - nbits) >> 1;
                    }
                    else
                    {
                        bits.SkipBits((int)high + 1 + 3);
                    }

                    acarry0[0] = (high << nbits) | bits.GetBits(nbits);
                    diff       = (acarry0[0] ^ sign) + acarry0[1];
                    acarry0[1] = (diff * 3 + acarry0[1]) >> 5;
                    acarry0[2] = acarry0[0] > 16 ? 0 : acarry0[2] + 1;

                    if (border)
                    {
                        if (y_border && x < 2)
                        {
                            pred = 0;
                        }
                        else if (y_border)
                        {
                            pred = left0;
                        }
                        else
                        {
                            pred = nw0 = rawImage.fullSize.rawView[pos - rawImage.fullSize.UncroppedDim.width + x];
                        }
                        rawImage.fullSize.rawView[pos + x] = (ushort)(pred + ((diff << 2) | low));
                        // Set predictor
                        left0 = rawImage.fullSize.rawView[pos + x];
                    }
                    else
                    {
                        // Have local variables for values used several tiles
                        // (having a "UInt16 *dst_up" that caches dest[-pitch+((int)x)] is actually slower, probably stack spill or aliasing)
                        int  up          = rawImage.fullSize.rawView[pos - rawImage.fullSize.UncroppedDim.width + x];
                        long leftMinusNw = left0 - nw0;
                        long upMinusNw   = up - nw0;
                        // Check if sign is different, and one is not zero
                        if (leftMinusNw * upMinusNw < 0)
                        {
                            if (Other_abs(leftMinusNw) > 32 || Other_abs(upMinusNw) > 32)
                            {
                                pred = left0 + upMinusNw;
                            }
                            else
                            {
                                pred = (left0 + up) >> 1;
                            }
                        }
                        else
                        {
                            pred = Other_abs(leftMinusNw) > Other_abs(upMinusNw) ? left0 : up;
                        }

                        rawImage.fullSize.rawView[pos + x] = (ushort)(pred + ((diff << 2) | low));
                        // Set predictors
                        left0 = rawImage.fullSize.rawView[pos + x];
                        nw0   = up;
                    }

                    // ODD PIXELS
                    x += 1;
                    bits.Fill();
                    i = 0;
                    if (acarry1[2] < 3)
                    {
                        i = 2;
                    }

                    for (nbits = 2 + i; acarry1[0] >> (nbits + i) != 0; nbits++)
                    {
                        ;
                    }
                    b    = bits.PeekBits(15);
                    sign = (b >> 14) * -1;
                    low  = (b >> 12) & 3;
                    high = bittable[b & 4095];

                    // Skip bytes used above or read bits
                    if (high == 12)
                    {
                        bits.SkipBits(15);
                        high = bits.GetBits(16 - nbits) >> 1;
                    }
                    else
                    {
                        bits.SkipBits((int)high + 1 + 3);
                    }

                    acarry1[0] = (high << nbits) | bits.GetBits(nbits);
                    diff       = (acarry1[0] ^ sign) + acarry1[1];
                    acarry1[1] = (diff * 3 + acarry1[1]) >> 5;
                    acarry1[2] = acarry1[0] > 16 ? 0 : acarry1[2] + 1;

                    if (border)
                    {
                        if (y_border && x < 2)
                        {
                            pred = 0;
                        }
                        else if (y_border)
                        {
                            pred = left1;
                        }
                        else
                        {
                            pred = nw1 = rawImage.fullSize.rawView[pos - rawImage.fullSize.UncroppedDim.width + x];
                        }
                        rawImage.fullSize.rawView[pos + x] = (ushort)(left1 = pred + ((diff << 2) | low));
                    }
                    else
                    {
                        int  up          = rawImage.fullSize.rawView[pos - rawImage.fullSize.UncroppedDim.width + x];
                        long leftminusNw = left1 - nw1;
                        long upminusNw   = up - nw1;

                        // Check if sign is different, and one is not zero
                        if (leftminusNw * upminusNw < 0)
                        {
                            if (Other_abs(leftminusNw) > 32 || Other_abs(upminusNw) > 32)
                            {
                                pred = left1 + upminusNw;
                            }
                            else
                            {
                                pred = (left1 + up) >> 1;
                            }
                        }
                        else
                        {
                            pred = Other_abs(leftminusNw) > Other_abs(upminusNw) ? left1 : up;
                        }

                        rawImage.fullSize.rawView[pos + x] = (ushort)(left1 = pred + ((diff << 2) | low));
                        nw1 = up;
                    }
                    border = y_border;
                }
            }
        }