FJCore Extension

Jan 3, 2010 at 7:11 AM

Hello,

I didn't see the extension method that you mentioned in this post http://kodierer.blogspot.com/2009/11/convert-encode-and-decode-silverlight.html.

As of now, I've added two methods that used FJCore in your library locally. 

Coordinator
Jan 3, 2010 at 10:52 AM
Edited Jan 3, 2010 at 10:53 AM

The JPEG encoding and decoding methods aren't extension methods and I didn't include them in the WriteableBitmapEx project. These JPEG related methods depend upon the 3rd party FJCore library and therefore are out of this projects scope. My Convert, Encode And Decode Silverlight WriteableBitmap Data blog post includes a full listing of the JPEG encoding / decoding methods that can be used freely.

Jan 3, 2010 at 11:30 AM

Hi,

I tested your code below and I found that it's not working. 

 

 public static void EncodeJpeg(this WriteableBitmap bmp, Stream destinationStream)
      {
          // Init buffer in FluxJpeg format
          int w = bmp.PixelWidth;
          int h = bmp.PixelHeight;
          int[] p = bmp.Pixels;
          byte[][,] pixelsForJpeg = new byte[3][,]; // RGB colors
          pixelsForJpeg[0] = new byte[w, h];
          pixelsForJpeg[1] = new byte[w, h];
          pixelsForJpeg[2] = new byte[w, h];
          // Copy WriteableBitmap data into buffer for FluxJpeg
          int i = 0;
          for (int x = 0; x < w; x++)
          {
              for (int y = 0; y < h; y++)
              {
                  int color = p[i++];
                  pixelsForJpeg[0][x, y] = (byte)(color >> 16); // R
                  pixelsForJpeg[1][x, y] = (byte)(color >> 8);  // G
                  pixelsForJpeg[2][x, y] = (byte)(color);       // B
              }
          }
          // Encode Image as JPEG using the FluxJpeg library
          // and write to destination stream
          ColorModel cm = new ColorModel { colorspace = ColorSpace.RGB };
          FluxJpeg.Core.Image jpegImage = new FluxJpeg.Core.Image(cm, pixelsForJpeg);
          JpegEncoder encoder = new JpegEncoder(jpegImage, 95, destinationStream);
          encoder.Encode();
      }

 public static void EncodeJpeg(this WriteableBitmap bmp, Stream destinationStream)

      {

          // Init buffer in FluxJpeg format

          int w = bmp.PixelWidth;

          int h = bmp.PixelHeight;

          int[] p = bmp.Pixels;

          byte[][,] pixelsForJpeg = new byte[3][,]; // RGB colors

          pixelsForJpeg[0] = new byte[w, h];

          pixelsForJpeg[1] = new byte[w, h];

          pixelsForJpeg[2] = new byte[w, h];

 

          // Copy WriteableBitmap data into buffer for FluxJpeg

          int i = 0;

          for (int x = 0; x < w; x++)

          {

              for (int y = 0; y < h; y++)

              {

                  int color = p[i++];

                  pixelsForJpeg[0][x, y] = (byte)(color >> 16); // R

                  pixelsForJpeg[1][x, y] = (byte)(color >> 8);  // G

                  pixelsForJpeg[2][x, y] = (byte)(color);       // B

              }

          }

 

          // Encode Image as JPEG using the FluxJpeg library

          // and write to destination stream

          ColorModel cm = new ColorModel { colorspace = ColorSpace.RGB };

          FluxJpeg.Core.Image jpegImage = new FluxJpeg.Core.Image(cm, pixelsForJpeg);

          JpegEncoder encoder = new JpegEncoder(jpegImage, 95, destinationStream);

          encoder.Encode();

      }

 

As I mentioned in Twitter, I got weird image. 

The code below is working fine. 

 private static void SaveToFile(WriteableBitmap bitmap,Stream fs)

{

            //Convert the Image to pass into FJCore

            int width = bitmap.PixelWidth;

            int height = bitmap.PixelHeight;

            int bands = 3;

 

            byte[][,] raster = new byte[bands][,]; 

 

            for (int i = 0; i < bands; i++)

            {

                raster[i] = new byte[width, height];

            }

 

            for (int row = 0; row < height; row++)

            {

                for (int column = 0; column < width; column++)

                {

                    int pixel = bitmap.Pixels[width * row + column];

                    raster[0][column, row] = (byte)(pixel >> 16);

                    raster[1][column, row] = (byte)(pixel >> 8);

                    raster[2][column, row] = (byte)pixel;

                }

            }

 

            ColorModel model = new ColorModel {colorspace = ColorSpace.RGB };

 

            FluxJpeg.Core.Image img = new FluxJpeg.Core.Image(model, raster);

 

            //Encode the Image as a JPEG

            MemoryStream stream = new MemoryStream();

            FluxJpeg.Core.Encoder.JpegEncoder encoder = new FluxJpeg.Core.Encoder.JpegEncoder(img, 100, stream);

 

            encoder.Encode();

 

            //Move back to the start of the stream

            stream.Seek(0, SeekOrigin.Begin);

 

            //Get the Bytes and write them to the stream

            byte[] binaryData = new Byte[stream.Length];

            long bytesRead = stream.Read(binaryData, 0, (int)stream.Length);

 

            fs.Write(binaryData, 0, binaryData.Length ); 

 

        }

 

 

Jan 3, 2010 at 12:35 PM

I tried to change your for-loop as below and it works. Strange.

 

 public static void EncodeJpeg(this WriteableBitmap bmp, Stream destinationStream)
      {
          // Init buffer in FluxJpeg format
          int w = bmp.PixelWidth;
          int h = bmp.PixelHeight;
          int[] p = bmp.Pixels;
          byte[][,] pixelsForJpeg = new byte[3][,]; // RGB colors
          pixelsForJpeg[0] = new byte[w, h];
          pixelsForJpeg[1] = new byte[w, h];
          pixelsForJpeg[2] = new byte[w, h];
          // Copy WriteableBitmap data into buffer for FluxJpeg
          //int i = 0;
          //for (int x = 0; x < w; x++)
          //{
          //    for (int y = 0; y < h; y++)
          //    {
          //        int color = p[i++];
          //        pixelsForJpeg[0][x, y] = (byte)(color >> 16); // R
          //        pixelsForJpeg[1][x, y] = (byte)(color >> 8);  // G
          //        pixelsForJpeg[2][x, y] = (byte)(color);       // B
          //    }
          //}
          for (int row = 0; row < h; row++)
          {
              for (int column = 0; column < w; column++)
              {
                  int pixel = p[w * row + column];
                  pixelsForJpeg[0][column, row] = (byte)(pixel >> 16);
                  pixelsForJpeg[1][column, row] = (byte)(pixel >> 8);
                  pixelsForJpeg[2][column, row] = (byte)pixel;
              }
          }
          // Encode Image as JPEG using the FluxJpeg library
          // and write to destination stream
          ColorModel cm = new ColorModel { colorspace = ColorSpace.RGB };
          FluxJpeg.Core.Image jpegImage = new FluxJpeg.Core.Image(cm, pixelsForJpeg);
          JpegEncoder encoder = new JpegEncoder(jpegImage, 95, destinationStream);
          encoder.Encode();
      }

 public static void EncodeJpeg(this WriteableBitmap bmp, Stream destinationStream)

      {

          // Init buffer in FluxJpeg format

          int w = bmp.PixelWidth;

          int h = bmp.PixelHeight;

          int[] p = bmp.Pixels;

          byte[][,] pixelsForJpeg = new byte[3][,]; // RGB colors

          pixelsForJpeg[0] = new byte[w, h];

          pixelsForJpeg[1] = new byte[w, h];

          pixelsForJpeg[2] = new byte[w, h];

 

          // Copy WriteableBitmap data into buffer for FluxJpeg

          //int i = 0;

          //for (int x = 0; x < w; x++)

          //{

          //    for (int y = 0; y < h; y++)

          //    {

          //        int color = p[i++];

          //        pixelsForJpeg[0][x, y] = (byte)(color >> 16); // R

          //        pixelsForJpeg[1][x, y] = (byte)(color >> 8);  // G

          //        pixelsForJpeg[2][x, y] = (byte)(color);       // B

          //    }

          //}

 

          for (int row = 0; row < h; row++)

          {

              for (int column = 0; column < w; column++)

              {

                  int pixel = p[w * row + column];

                  pixelsForJpeg[0][column, row] = (byte)(pixel >> 16);

                  pixelsForJpeg[1][column, row] = (byte)(pixel >> 8);

                  pixelsForJpeg[2][column, row] = (byte)pixel;

              }

          }

 

          // Encode Image as JPEG using the FluxJpeg library

          // and write to destination stream

          ColorModel cm = new ColorModel { colorspace = ColorSpace.RGB };

          FluxJpeg.Core.Image jpegImage = new FluxJpeg.Core.Image(cm, pixelsForJpeg);

          JpegEncoder encoder = new JpegEncoder(jpegImage, 95, destinationStream);

          encoder.Encode();

      }

 

Coordinator
Jan 3, 2010 at 6:33 PM

There was indeed a bug in my code and thanks for letting me know.

It's a pretty obvious failure. :(  I had the loops for the rows (y) and the columns (x) in the wrong order.
The wrong code was:

int i = 0;
for (int x = 0; x < w; x++)
{
  for (int y = 0; y < h; y++)
  {
	 int color = p[i++];
	 pixelsForJpeg[0][x, y] = (byte)(color >> 16); // R
	 pixelsForJpeg[1][x, y] = (byte)(color >> 8);  // G
	 pixelsForJpeg[2][x, y] = (byte)(color);       // B
  }
}

 

And the new corrected version with the swapped for-loops:

int i = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
int color = p[i++];
pixelsForJpeg[0][x, y] = (byte)(color >> 16); // R pixelsForJpeg[1][x, y] = (byte)(color >> 8); // G pixelsForJpeg[2][x, y] = (byte)(color); // B } }

I always used quadratic images so I never encountered that bug. I updated my Convert, Encode And Decode Silverlight WriteableBitmap Data blog post with the fixed version of the method.