Browse Source

Change tabs to spaces, adjust formatting.

Former-commit-id: dc28bb2d7ef6df5f3632a7bfb89462f09cc94da9
Former-commit-id: 78751356195d16bae5ccef1373f6bc11b775a13d
Former-commit-id: d26a9612598636d0b26f80cddc96b7033b6b16c7
pull/1/head
Michael Weber 10 years ago
parent
commit
793aa2c212
  1. 20
      src/ImageProcessorCore/Formats/Jpg/Block.cs
  2. 68
      src/ImageProcessorCore/Formats/Jpg/Colors.cs
  3. 3302
      src/ImageProcessorCore/Formats/Jpg/Decoder.cs
  4. 1239
      src/ImageProcessorCore/Formats/Jpg/Encoder.cs
  5. 234
      src/ImageProcessorCore/Formats/Jpg/FDCT.cs
  6. 310
      src/ImageProcessorCore/Formats/Jpg/IDCT.cs
  7. 18
      src/ImageProcessorCore/Formats/Jpg/JpegDecoder.cs

20
src/ImageProcessorCore/Formats/Jpg/Block.cs

@ -3,16 +3,16 @@ namespace ImageProcessorCore.Formats.Jpg
using System;
using System.IO;
internal class Block
{
public const int blockSize = 64;
private int[] _data;
internal class Block
{
public const int blockSize = 64;
private int[] _data;
public Block()
{
_data = new int[blockSize];
}
public Block()
{
_data = new int[blockSize];
}
public int this[int idx] { get { return _data[idx]; } set { _data[idx] = value; } }
}
public int this[int idx] { get { return _data[idx]; } set { _data[idx] = value; } }
}
}

68
src/ImageProcessorCore/Formats/Jpg/Colors.cs

@ -3,43 +3,43 @@ namespace ImageProcessorCore.Formats.Jpg
using System;
using System.IO;
internal static class Colors
{
public static void RGBToYCbCr(byte r, byte g, byte b, out byte yy, out byte cb, out byte cr)
{
// The JFIF specification says:
// Y' = 0.2990*R + 0.5870*G + 0.1140*B
// Cb = -0.1687*R - 0.3313*G + 0.5000*B + 128
// Cr = 0.5000*R - 0.4187*G - 0.0813*B + 128
// http://www.w3.org/Graphics/JPEG/jfif3.pdf says Y but means Y'.
internal static class Colors
{
public static void RGBToYCbCr(byte r, byte g, byte b, out byte yy, out byte cb, out byte cr)
{
// The JFIF specification says:
// Y' = 0.2990*R + 0.5870*G + 0.1140*B
// Cb = -0.1687*R - 0.3313*G + 0.5000*B + 128
// Cr = 0.5000*R - 0.4187*G - 0.0813*B + 128
// http://www.w3.org/Graphics/JPEG/jfif3.pdf says Y but means Y'.
int iyy = (19595*r + 38470*g + 7471*b + (1<<15)) >> 16;
int icb = (-11056*r - 21712*g + 32768*b + (257<<15)) >> 16;
int icr = (32768*r - 27440*g - 5328*b + (257<<15)) >> 16;
int iyy = (19595*r + 38470*g + 7471*b + (1<<15)) >> 16;
int icb = (-11056*r - 21712*g + 32768*b + (257<<15)) >> 16;
int icr = (32768*r - 27440*g - 5328*b + (257<<15)) >> 16;
if(iyy < 0) yy = 0; else if(iyy > 255) yy = 255; else yy = (byte)iyy;
if(icb < 0) cb = 0; else if(icb > 255) cb = 255; else cb = (byte)icb;
if(icr < 0) cr = 0; else if(icr > 255) cr = 255; else cr = (byte)icr;
}
if(iyy < 0) yy = 0; else if(iyy > 255) yy = 255; else yy = (byte)iyy;
if(icb < 0) cb = 0; else if(icb > 255) cb = 255; else cb = (byte)icb;
if(icr < 0) cr = 0; else if(icr > 255) cr = 255; else cr = (byte)icr;
}
public static void YCbCrToRGB(byte yy, byte cb, byte cr, out byte r, out byte g, out byte b)
{
// The JFIF specification says:
// R = Y' + 1.40200*(Cr-128)
// G = Y' - 0.34414*(Cb-128) - 0.71414*(Cr-128)
// B = Y' + 1.77200*(Cb-128)
// http://www.w3.org/Graphics/JPEG/jfif3.pdf says Y but means Y'.
public static void YCbCrToRGB(byte yy, byte cb, byte cr, out byte r, out byte g, out byte b)
{
// The JFIF specification says:
// R = Y' + 1.40200*(Cr-128)
// G = Y' - 0.34414*(Cb-128) - 0.71414*(Cr-128)
// B = Y' + 1.77200*(Cb-128)
// http://www.w3.org/Graphics/JPEG/jfif3.pdf says Y but means Y'.
int yy1 = yy * 0x10100; // Convert 0x12 to 0x121200.
int cb1 = cb - 128;
int cr1 = cr - 128;
int ir = (yy1 + 91881*cr1) >> 16;
int ig = (yy1 - 22554*cb1 - 46802*cr1) >> 16;
int ib = (yy1 + 116130*cb1) >> 16;
int yy1 = yy * 0x10100; // Convert 0x12 to 0x121200.
int cb1 = cb - 128;
int cr1 = cr - 128;
int ir = (yy1 + 91881*cr1) >> 16;
int ig = (yy1 - 22554*cb1 - 46802*cr1) >> 16;
int ib = (yy1 + 116130*cb1) >> 16;
if(ir < 0) r = 0; else if(ir > 255) r = 255; else r = (byte)ir;
if(ig < 0) g = 0; else if(ig > 255) g = 255; else g = (byte)ig;
if(ib < 0) b = 0; else if(ib > 255) b = 255; else b = (byte)ib;
}
}
if(ir < 0) r = 0; else if(ir > 255) r = 255; else r = (byte)ir;
if(ig < 0) g = 0; else if(ig > 255) g = 255; else g = (byte)ig;
if(ib < 0) b = 0; else if(ib > 255) b = 255; else b = (byte)ib;
}
}
}

3302
src/ImageProcessorCore/Formats/Jpg/Decoder.cs

File diff suppressed because it is too large

1239
src/ImageProcessorCore/Formats/Jpg/Encoder.cs

File diff suppressed because it is too large

234
src/ImageProcessorCore/Formats/Jpg/FDCT.cs

@ -3,135 +3,135 @@ namespace ImageProcessorCore.Formats.Jpg
using System;
using System.IO;
internal partial class Encoder
{
// Trigonometric constants in 13-bit fixed point format.
private const int fix_0_298631336 = 2446;
private const int fix_0_390180644 = 3196;
private const int fix_0_541196100 = 4433;
private const int fix_0_765366865 = 6270;
private const int fix_0_899976223 = 7373;
private const int fix_1_175875602 = 9633;
private const int fix_1_501321110 = 12299;
private const int fix_1_847759065 = 15137;
private const int fix_1_961570560 = 16069;
private const int fix_2_053119869 = 16819;
private const int fix_2_562915447 = 20995;
private const int fix_3_072711026 = 25172;
private const int constBits = 13;
private const int pass1Bits = 2;
private const int centerJSample = 128;
internal partial class Encoder
{
// Trigonometric constants in 13-bit fixed point format.
private const int fix_0_298631336 = 2446;
private const int fix_0_390180644 = 3196;
private const int fix_0_541196100 = 4433;
private const int fix_0_765366865 = 6270;
private const int fix_0_899976223 = 7373;
private const int fix_1_175875602 = 9633;
private const int fix_1_501321110 = 12299;
private const int fix_1_847759065 = 15137;
private const int fix_1_961570560 = 16069;
private const int fix_2_053119869 = 16819;
private const int fix_2_562915447 = 20995;
private const int fix_3_072711026 = 25172;
private const int constBits = 13;
private const int pass1Bits = 2;
private const int centerJSample = 128;
// fdct performs a forward DCT on an 8x8 block of coefficients, including a
// level shift.
private static void FDCT(Block b)
{
// Pass 1: process rows.
for(int y = 0; y < 8; y++)
{
int x0 = b[y*8+0];
int x1 = b[y*8+1];
int x2 = b[y*8+2];
int x3 = b[y*8+3];
int x4 = b[y*8+4];
int x5 = b[y*8+5];
int x6 = b[y*8+6];
int x7 = b[y*8+7];
// fdct performs a forward DCT on an 8x8 block of coefficients, including a
// level shift.
private static void FDCT(Block b)
{
// Pass 1: process rows.
for(int y = 0; y < 8; y++)
{
int x0 = b[y*8+0];
int x1 = b[y*8+1];
int x2 = b[y*8+2];
int x3 = b[y*8+3];
int x4 = b[y*8+4];
int x5 = b[y*8+5];
int x6 = b[y*8+6];
int x7 = b[y*8+7];
int tmp0 = x0 + x7;
int tmp1 = x1 + x6;
int tmp2 = x2 + x5;
int tmp3 = x3 + x4;
int tmp0 = x0 + x7;
int tmp1 = x1 + x6;
int tmp2 = x2 + x5;
int tmp3 = x3 + x4;
int tmp10 = tmp0 + tmp3;
int tmp12 = tmp0 - tmp3;
int tmp11 = tmp1 + tmp2;
int tmp13 = tmp1 - tmp2;
int tmp10 = tmp0 + tmp3;
int tmp12 = tmp0 - tmp3;
int tmp11 = tmp1 + tmp2;
int tmp13 = tmp1 - tmp2;
tmp0 = x0 - x7;
tmp1 = x1 - x6;
tmp2 = x2 - x5;
tmp3 = x3 - x4;
tmp0 = x0 - x7;
tmp1 = x1 - x6;
tmp2 = x2 - x5;
tmp3 = x3 - x4;
b[y*8+0] = (tmp10 + tmp11 - 8*centerJSample) << pass1Bits;
b[y*8+4] = (tmp10 - tmp11) << pass1Bits;
int z1 = (tmp12 + tmp13) * fix_0_541196100;
z1 += 1 << (constBits - pass1Bits - 1);
b[y*8+2] = (z1 + tmp12*fix_0_765366865) >> (constBits - pass1Bits);
b[y*8+6] = (z1 - tmp13*fix_1_847759065) >> (constBits - pass1Bits);
b[y*8+0] = (tmp10 + tmp11 - 8*centerJSample) << pass1Bits;
b[y*8+4] = (tmp10 - tmp11) << pass1Bits;
int z1 = (tmp12 + tmp13) * fix_0_541196100;
z1 += 1 << (constBits - pass1Bits - 1);
b[y*8+2] = (z1 + tmp12*fix_0_765366865) >> (constBits - pass1Bits);
b[y*8+6] = (z1 - tmp13*fix_1_847759065) >> (constBits - pass1Bits);
tmp10 = tmp0 + tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp0 + tmp2;
tmp13 = tmp1 + tmp3;
z1 = (tmp12 + tmp13) * fix_1_175875602;
z1 += 1 << (constBits - pass1Bits - 1);
tmp0 = tmp0 * fix_1_501321110;
tmp1 = tmp1 * fix_3_072711026;
tmp2 = tmp2 * fix_2_053119869;
tmp3 = tmp3 * fix_0_298631336;
tmp10 = tmp10 * -fix_0_899976223;
tmp11 = tmp11 * -fix_2_562915447;
tmp12 = tmp12 * -fix_0_390180644;
tmp13 = tmp13 * -fix_1_961570560;
tmp10 = tmp0 + tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp0 + tmp2;
tmp13 = tmp1 + tmp3;
z1 = (tmp12 + tmp13) * fix_1_175875602;
z1 += 1 << (constBits - pass1Bits - 1);
tmp0 = tmp0 * fix_1_501321110;
tmp1 = tmp1 * fix_3_072711026;
tmp2 = tmp2 * fix_2_053119869;
tmp3 = tmp3 * fix_0_298631336;
tmp10 = tmp10 * -fix_0_899976223;
tmp11 = tmp11 * -fix_2_562915447;
tmp12 = tmp12 * -fix_0_390180644;
tmp13 = tmp13 * -fix_1_961570560;
tmp12 += z1;
tmp13 += z1;
b[y*8+1] = (tmp0 + tmp10 + tmp12) >> (constBits - pass1Bits);
b[y*8+3] = (tmp1 + tmp11 + tmp13) >> (constBits - pass1Bits);
b[y*8+5] = (tmp2 + tmp11 + tmp12) >> (constBits - pass1Bits);
b[y*8+7] = (tmp3 + tmp10 + tmp13) >> (constBits - pass1Bits);
}
tmp12 += z1;
tmp13 += z1;
b[y*8+1] = (tmp0 + tmp10 + tmp12) >> (constBits - pass1Bits);
b[y*8+3] = (tmp1 + tmp11 + tmp13) >> (constBits - pass1Bits);
b[y*8+5] = (tmp2 + tmp11 + tmp12) >> (constBits - pass1Bits);
b[y*8+7] = (tmp3 + tmp10 + tmp13) >> (constBits - pass1Bits);
}
// Pass 2: process columns.
// We remove pass1Bits scaling, but leave results scaled up by an overall factor of 8.
for(int x = 0; x < 8; x++)
{
int tmp0 = b[0*8+x] + b[7*8+x];
int tmp1 = b[1*8+x] + b[6*8+x];
int tmp2 = b[2*8+x] + b[5*8+x];
int tmp3 = b[3*8+x] + b[4*8+x];
// Pass 2: process columns.
// We remove pass1Bits scaling, but leave results scaled up by an overall factor of 8.
for(int x = 0; x < 8; x++)
{
int tmp0 = b[0*8+x] + b[7*8+x];
int tmp1 = b[1*8+x] + b[6*8+x];
int tmp2 = b[2*8+x] + b[5*8+x];
int tmp3 = b[3*8+x] + b[4*8+x];
int tmp10 = tmp0 + tmp3 + (1<<(pass1Bits-1));
int tmp12 = tmp0 - tmp3;
int tmp11 = tmp1 + tmp2;
int tmp13 = tmp1 - tmp2;
int tmp10 = tmp0 + tmp3 + (1<<(pass1Bits-1));
int tmp12 = tmp0 - tmp3;
int tmp11 = tmp1 + tmp2;
int tmp13 = tmp1 - tmp2;
tmp0 = b[0*8+x] - b[7*8+x];
tmp1 = b[1*8+x] - b[6*8+x];
tmp2 = b[2*8+x] - b[5*8+x];
tmp3 = b[3*8+x] - b[4*8+x];
tmp0 = b[0*8+x] - b[7*8+x];
tmp1 = b[1*8+x] - b[6*8+x];
tmp2 = b[2*8+x] - b[5*8+x];
tmp3 = b[3*8+x] - b[4*8+x];
b[0*8+x] = (tmp10 + tmp11) >> pass1Bits;
b[4*8+x] = (tmp10 - tmp11) >> pass1Bits;
b[0*8+x] = (tmp10 + tmp11) >> pass1Bits;
b[4*8+x] = (tmp10 - tmp11) >> pass1Bits;
int z1 = (tmp12 + tmp13) * fix_0_541196100;
z1 += 1 << (constBits + pass1Bits - 1);
b[2*8+x] = (z1 + tmp12*fix_0_765366865) >> (constBits + pass1Bits);
b[6*8+x] = (z1 - tmp13*fix_1_847759065) >> (constBits + pass1Bits);
int z1 = (tmp12 + tmp13) * fix_0_541196100;
z1 += 1 << (constBits + pass1Bits - 1);
b[2*8+x] = (z1 + tmp12*fix_0_765366865) >> (constBits + pass1Bits);
b[6*8+x] = (z1 - tmp13*fix_1_847759065) >> (constBits + pass1Bits);
tmp10 = tmp0 + tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp0 + tmp2;
tmp13 = tmp1 + tmp3;
z1 = (tmp12 + tmp13) * fix_1_175875602;
z1 += 1 << (constBits + pass1Bits - 1);
tmp0 = tmp0 * fix_1_501321110;
tmp1 = tmp1 * fix_3_072711026;
tmp2 = tmp2 * fix_2_053119869;
tmp3 = tmp3 * fix_0_298631336;
tmp10 = tmp10 * -fix_0_899976223;
tmp11 = tmp11 * -fix_2_562915447;
tmp12 = tmp12 * -fix_0_390180644;
tmp13 = tmp13 * -fix_1_961570560;
tmp10 = tmp0 + tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp0 + tmp2;
tmp13 = tmp1 + tmp3;
z1 = (tmp12 + tmp13) * fix_1_175875602;
z1 += 1 << (constBits + pass1Bits - 1);
tmp0 = tmp0 * fix_1_501321110;
tmp1 = tmp1 * fix_3_072711026;
tmp2 = tmp2 * fix_2_053119869;
tmp3 = tmp3 * fix_0_298631336;
tmp10 = tmp10 * -fix_0_899976223;
tmp11 = tmp11 * -fix_2_562915447;
tmp12 = tmp12 * -fix_0_390180644;
tmp13 = tmp13 * -fix_1_961570560;
tmp12 += z1;
tmp13 += z1;
b[1*8+x] = (tmp0 + tmp10 + tmp12) >> (constBits + pass1Bits);
b[3*8+x] = (tmp1 + tmp11 + tmp13) >> (constBits + pass1Bits);
b[5*8+x] = (tmp2 + tmp11 + tmp12) >> (constBits + pass1Bits);
b[7*8+x] = (tmp3 + tmp10 + tmp13) >> (constBits + pass1Bits);
}
}
}
tmp12 += z1;
tmp13 += z1;
b[1*8+x] = (tmp0 + tmp10 + tmp12) >> (constBits + pass1Bits);
b[3*8+x] = (tmp1 + tmp11 + tmp13) >> (constBits + pass1Bits);
b[5*8+x] = (tmp2 + tmp11 + tmp12) >> (constBits + pass1Bits);
b[7*8+x] = (tmp3 + tmp10 + tmp13) >> (constBits + pass1Bits);
}
}
}
}

310
src/ImageProcessorCore/Formats/Jpg/IDCT.cs

@ -3,159 +3,159 @@ namespace ImageProcessorCore.Formats.Jpg
using System;
using System.IO;
internal partial class Decoder
{
private const int w1 = 2841; // 2048*sqrt(2)*cos(1*pi/16)
private const int w2 = 2676; // 2048*sqrt(2)*cos(2*pi/16)
private const int w3 = 2408; // 2048*sqrt(2)*cos(3*pi/16)
private const int w5 = 1609; // 2048*sqrt(2)*cos(5*pi/16)
private const int w6 = 1108; // 2048*sqrt(2)*cos(6*pi/16)
private const int w7 = 565; // 2048*sqrt(2)*cos(7*pi/16)
private const int w1pw7 = w1 + w7;
private const int w1mw7 = w1 - w7;
private const int w2pw6 = w2 + w6;
private const int w2mw6 = w2 - w6;
private const int w3pw5 = w3 + w5;
private const int w3mw5 = w3 - w5;
private const int r2 = 181; // 256/sqrt(2)
// idct performs a 2-D Inverse Discrete Cosine Transformation.
//
// The input coefficients should already have been multiplied by the
// appropriate quantization table. We use fixed-point computation, with the
// number of bits for the fractional component varying over the intermediate
// stages.
//
// For more on the actual algorithm, see Z. Wang, "Fast algorithms for the
// discrete W transform and for the discrete Fourier transform", IEEE Trans. on
// ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984.
private static void IDCT(Block src)
{
// Horizontal 1-D IDCT.
for(int y = 0; y < 8; y++)
{
int y8 = y * 8;
// If all the AC components are zero, then the IDCT is trivial.
if(src[y8+1] == 0 && src[y8+2] == 0 && src[y8+3] == 0 &&
src[y8+4] == 0 && src[y8+5] == 0 && src[y8+6] == 0 && src[y8+7] == 0)
{
int dc = src[y8+0] << 3;
src[y8+0] = dc;
src[y8+1] = dc;
src[y8+2] = dc;
src[y8+3] = dc;
src[y8+4] = dc;
src[y8+5] = dc;
src[y8+6] = dc;
src[y8+7] = dc;
continue;
}
// Prescale.
int x0 = (src[y8+0] << 11) + 128;
int x1 = src[y8+4] << 11;
int x2 = src[y8+6];
int x3 = src[y8+2];
int x4 = src[y8+1];
int x5 = src[y8+7];
int x6 = src[y8+5];
int x7 = src[y8+3];
// Stage 1.
int x8 = w7 * (x4 + x5);
x4 = x8 + w1mw7*x4;
x5 = x8 - w1pw7*x5;
x8 = w3 * (x6 + x7);
x6 = x8 - w3mw5*x6;
x7 = x8 - w3pw5*x7;
// Stage 2.
x8 = x0 + x1;
x0 -= x1;
x1 = w6 * (x3 + x2);
x2 = x1 - w2pw6*x2;
x3 = x1 + w2mw6*x3;
x1 = x4 + x6;
x4 -= x6;
x6 = x5 + x7;
x5 -= x7;
// Stage 3.
x7 = x8 + x3;
x8 -= x3;
x3 = x0 + x2;
x0 -= x2;
x2 = (r2*(x4+x5) + 128) >> 8;
x4 = (r2*(x4-x5) + 128) >> 8;
// Stage 4.
src[y8+0] = (x7 + x1) >> 8;
src[y8+1] = (x3 + x2) >> 8;
src[y8+2] = (x0 + x4) >> 8;
src[y8+3] = (x8 + x6) >> 8;
src[y8+4] = (x8 - x6) >> 8;
src[y8+5] = (x0 - x4) >> 8;
src[y8+6] = (x3 - x2) >> 8;
src[y8+7] = (x7 - x1) >> 8;
}
// Vertical 1-D IDCT.
for(int x = 0; x < 8; x++)
{
// Similar to the horizontal 1-D IDCT case, if all the AC components are zero, then the IDCT is trivial.
// However, after performing the horizontal 1-D IDCT, there are typically non-zero AC components, so
// we do not bother to check for the all-zero case.
// Prescale.
int y0 = (src[8*0+x] << 8) + 8192;
int y1 = src[8*4+x] << 8;
int y2 = src[8*6+x];
int y3 = src[8*2+x];
int y4 = src[8*1+x];
int y5 = src[8*7+x];
int y6 = src[8*5+x];
int y7 = src[8*3+x];
// Stage 1.
int y8 = w7*(y4+y5) + 4;
y4 = (y8 + w1mw7*y4) >> 3;
y5 = (y8 - w1pw7*y5) >> 3;
y8 = w3*(y6+y7) + 4;
y6 = (y8 - w3mw5*y6) >> 3;
y7 = (y8 - w3pw5*y7) >> 3;
// Stage 2.
y8 = y0 + y1;
y0 -= y1;
y1 = w6*(y3+y2) + 4;
y2 = (y1 - w2pw6*y2) >> 3;
y3 = (y1 + w2mw6*y3) >> 3;
y1 = y4 + y6;
y4 -= y6;
y6 = y5 + y7;
y5 -= y7;
// Stage 3.
y7 = y8 + y3;
y8 -= y3;
y3 = y0 + y2;
y0 -= y2;
y2 = (r2*(y4+y5) + 128) >> 8;
y4 = (r2*(y4-y5) + 128) >> 8;
// Stage 4.
src[8*0+x] = (y7 + y1) >> 14;
src[8*1+x] = (y3 + y2) >> 14;
src[8*2+x] = (y0 + y4) >> 14;
src[8*3+x] = (y8 + y6) >> 14;
src[8*4+x] = (y8 - y6) >> 14;
src[8*5+x] = (y0 - y4) >> 14;
src[8*6+x] = (y3 - y2) >> 14;
src[8*7+x] = (y7 - y1) >> 14;
}
}
}
internal partial class Decoder
{
private const int w1 = 2841; // 2048*sqrt(2)*cos(1*pi/16)
private const int w2 = 2676; // 2048*sqrt(2)*cos(2*pi/16)
private const int w3 = 2408; // 2048*sqrt(2)*cos(3*pi/16)
private const int w5 = 1609; // 2048*sqrt(2)*cos(5*pi/16)
private const int w6 = 1108; // 2048*sqrt(2)*cos(6*pi/16)
private const int w7 = 565; // 2048*sqrt(2)*cos(7*pi/16)
private const int w1pw7 = w1 + w7;
private const int w1mw7 = w1 - w7;
private const int w2pw6 = w2 + w6;
private const int w2mw6 = w2 - w6;
private const int w3pw5 = w3 + w5;
private const int w3mw5 = w3 - w5;
private const int r2 = 181; // 256/sqrt(2)
// idct performs a 2-D Inverse Discrete Cosine Transformation.
//
// The input coefficients should already have been multiplied by the
// appropriate quantization table. We use fixed-point computation, with the
// number of bits for the fractional component varying over the intermediate
// stages.
//
// For more on the actual algorithm, see Z. Wang, "Fast algorithms for the
// discrete W transform and for the discrete Fourier transform", IEEE Trans. on
// ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984.
private static void IDCT(Block src)
{
// Horizontal 1-D IDCT.
for(int y = 0; y < 8; y++)
{
int y8 = y * 8;
// If all the AC components are zero, then the IDCT is trivial.
if(src[y8+1] == 0 && src[y8+2] == 0 && src[y8+3] == 0 &&
src[y8+4] == 0 && src[y8+5] == 0 && src[y8+6] == 0 && src[y8+7] == 0)
{
int dc = src[y8+0] << 3;
src[y8+0] = dc;
src[y8+1] = dc;
src[y8+2] = dc;
src[y8+3] = dc;
src[y8+4] = dc;
src[y8+5] = dc;
src[y8+6] = dc;
src[y8+7] = dc;
continue;
}
// Prescale.
int x0 = (src[y8+0] << 11) + 128;
int x1 = src[y8+4] << 11;
int x2 = src[y8+6];
int x3 = src[y8+2];
int x4 = src[y8+1];
int x5 = src[y8+7];
int x6 = src[y8+5];
int x7 = src[y8+3];
// Stage 1.
int x8 = w7 * (x4 + x5);
x4 = x8 + w1mw7*x4;
x5 = x8 - w1pw7*x5;
x8 = w3 * (x6 + x7);
x6 = x8 - w3mw5*x6;
x7 = x8 - w3pw5*x7;
// Stage 2.
x8 = x0 + x1;
x0 -= x1;
x1 = w6 * (x3 + x2);
x2 = x1 - w2pw6*x2;
x3 = x1 + w2mw6*x3;
x1 = x4 + x6;
x4 -= x6;
x6 = x5 + x7;
x5 -= x7;
// Stage 3.
x7 = x8 + x3;
x8 -= x3;
x3 = x0 + x2;
x0 -= x2;
x2 = (r2*(x4+x5) + 128) >> 8;
x4 = (r2*(x4-x5) + 128) >> 8;
// Stage 4.
src[y8+0] = (x7 + x1) >> 8;
src[y8+1] = (x3 + x2) >> 8;
src[y8+2] = (x0 + x4) >> 8;
src[y8+3] = (x8 + x6) >> 8;
src[y8+4] = (x8 - x6) >> 8;
src[y8+5] = (x0 - x4) >> 8;
src[y8+6] = (x3 - x2) >> 8;
src[y8+7] = (x7 - x1) >> 8;
}
// Vertical 1-D IDCT.
for(int x = 0; x < 8; x++)
{
// Similar to the horizontal 1-D IDCT case, if all the AC components are zero, then the IDCT is trivial.
// However, after performing the horizontal 1-D IDCT, there are typically non-zero AC components, so
// we do not bother to check for the all-zero case.
// Prescale.
int y0 = (src[8*0+x] << 8) + 8192;
int y1 = src[8*4+x] << 8;
int y2 = src[8*6+x];
int y3 = src[8*2+x];
int y4 = src[8*1+x];
int y5 = src[8*7+x];
int y6 = src[8*5+x];
int y7 = src[8*3+x];
// Stage 1.
int y8 = w7*(y4+y5) + 4;
y4 = (y8 + w1mw7*y4) >> 3;
y5 = (y8 - w1pw7*y5) >> 3;
y8 = w3*(y6+y7) + 4;
y6 = (y8 - w3mw5*y6) >> 3;
y7 = (y8 - w3pw5*y7) >> 3;
// Stage 2.
y8 = y0 + y1;
y0 -= y1;
y1 = w6*(y3+y2) + 4;
y2 = (y1 - w2pw6*y2) >> 3;
y3 = (y1 + w2mw6*y3) >> 3;
y1 = y4 + y6;
y4 -= y6;
y6 = y5 + y7;
y5 -= y7;
// Stage 3.
y7 = y8 + y3;
y8 -= y3;
y3 = y0 + y2;
y0 -= y2;
y2 = (r2*(y4+y5) + 128) >> 8;
y4 = (r2*(y4-y5) + 128) >> 8;
// Stage 4.
src[8*0+x] = (y7 + y1) >> 14;
src[8*1+x] = (y3 + y2) >> 14;
src[8*2+x] = (y0 + y4) >> 14;
src[8*3+x] = (y8 + y6) >> 14;
src[8*4+x] = (y8 - y6) >> 14;
src[8*5+x] = (y0 - y4) >> 14;
src[8*6+x] = (y3 - y2) >> 14;
src[8*7+x] = (y7 - y1) >> 14;
}
}
}
}

18
src/ImageProcessorCore/Formats/Jpg/JpegDecoder.cs

@ -8,7 +8,7 @@ namespace ImageProcessorCore.Formats
using System;
using System.IO;
using System.Threading.Tasks;
using ImageProcessorCore.Formats.Jpg;
using ImageProcessorCore.Formats.Jpg;
/// <summary>
/// Image decoder for generating an image out of a jpg stream.
@ -95,22 +95,22 @@ namespace ImageProcessorCore.Formats
Guard.NotNull(image, "image");
Guard.NotNull(stream, "stream");
Decoder decoder = new Decoder();
decoder.decode(stream, false);
Decoder decoder = new Decoder();
decoder.decode(stream, false);
int pixelWidth = decoder.width;
int pixelHeight = decoder.height;
float[] pixels = new float[pixelWidth * pixelHeight * 4];
if(decoder.nComp == 1)
{
if(decoder.nComp == 1)
{
Parallel.For(
0,
pixelHeight,
y =>
{
var yoff = decoder.img1.get_row_offset(y);
var yoff = decoder.img1.get_row_offset(y);
for (int x = 0; x < pixelWidth; x++)
{
int offset = ((y * pixelWidth) + x) * 4;
@ -121,15 +121,15 @@ namespace ImageProcessorCore.Formats
pixels[offset + 3] = 1;
}
});
}
else if(decoder.nComp == 3)
}
else if(decoder.nComp == 3)
{
Parallel.For(
0,
pixelHeight,
y =>
{
var yoff = decoder.imgrgb.get_row_offset(y);
var yoff = decoder.imgrgb.get_row_offset(y);
for (int x = 0; x < pixelWidth; x++)
{
int offset = ((y * pixelWidth) + x) * 4;

Loading…
Cancel
Save