// Load a JPEG image from the specified stream. The first 4 bytes // have already been read and discarded. public static void Load(Stream stream, Image image, byte[] prime, int primeLen) { // Determine if we actually have the JPEG library. if (!JpegLib.JpegLibraryPresent()) { throw new FormatException("libjpeg is not available"); } // Create the decompression object. JpegLib.jpeg_decompress_struct cinfo; cinfo = new JpegLib.jpeg_decompress_struct(); cinfo.err = JpegLib.CreateErrorHandler(); JpegLib.jpeg_create_decompress(ref cinfo); // Initialize the source manager. JpegLib.StreamToSourceManager (ref cinfo, stream, prime, primeLen); // Read the JPEG header. JpegLib.jpeg_read_header(ref cinfo, (Int)1); // Set the decompression parameters the way we want them. cinfo.out_color_space = JpegLib.J_COLOR_SPACE.JCS_RGB; // Start the decompression process. JpegLib.jpeg_start_decompress(ref cinfo); // Initialize the image to 24-bit RGB, to match the JPEG file. image.Width = (int)(cinfo.output_width); image.Height = (int)(cinfo.output_height); image.PixelFormat = PixelFormat.Format24bppRgb; if (prime[3] == 0xE1) { image.LoadFormat = Image.Exif; } else { image.LoadFormat = Image.Jpeg; } Frame frame = image.AddFrame(); // Read the scanlines from the image. int posn, width, offset, stride, y, twidth; width = frame.Width; twidth = width * 3; stride = frame.Stride; byte[] data = frame.Data; IntPtr buf = Marshal.AllocHGlobal(width * 3); byte * pbuf = (byte *)buf; y = 0; while (((int)(cinfo.output_scanline)) < ((int)(cinfo.output_height))) { JpegLib.jpeg_read_scanlines (ref cinfo, ref buf, (UInt)1); offset = (y++) * stride; for (posn = 0; posn < twidth; posn += 3) { // Convert the JPEG RGB data into BGR for the frame. data[offset] = pbuf[posn + 2]; data[offset + 1] = pbuf[posn + 1]; data[offset + 2] = pbuf[posn]; offset += 3; } } Marshal.FreeHGlobal(buf); // Finish the decompression process. JpegLib.jpeg_finish_decompress(ref cinfo); // Clean everything up. JpegLib.FreeSourceManager(ref cinfo); JpegLib.jpeg_destroy_decompress(ref cinfo); JpegLib.FreeErrorHandler(cinfo.err); }
// Save a JPEG image to the specified stream. public static void Save(Stream stream, Image image) { // Determine if we actually have the JPEG library. if (!JpegLib.JpegLibraryPresent()) { throw new FormatException("libjpeg is not available"); } // Create the compression object. JpegLib.jpeg_compress_struct cinfo; cinfo = new JpegLib.jpeg_compress_struct(); cinfo.err = JpegLib.CreateErrorHandler(); JpegLib.jpeg_create_compress(ref cinfo); // Initialize the destination manager. JpegLib.StreamToDestinationManager(ref cinfo, stream); // Get the frame to be written. Frame frame = image.GetFrame(0); // Set the JPEG compression parameters. cinfo.image_width = (UInt)(frame.Width); cinfo.image_height = (UInt)(frame.Height); cinfo.input_components = (Int)3; cinfo.in_color_space = JpegLib.J_COLOR_SPACE.JCS_RGB; JpegLib.jpeg_set_defaults(ref cinfo); // Start the compression process. JpegLib.jpeg_start_compress(ref cinfo, (Int)1); // Write the scanlines to the image. int posn, width, offset, stride; width = frame.Width; stride = frame.Stride; byte[] data = frame.Data; PixelFormat format = frame.PixelFormat; IntPtr buf = Marshal.AllocHGlobal(width * 3); byte * pbuf = (byte *)buf; while (((int)(cinfo.next_scanline)) < ((int)(cinfo.image_height))) { // Convert the source scanline into the JCS_RGB format. offset = ((int)(cinfo.next_scanline)) * stride; switch (format) { case PixelFormat.Format16bppRgb555: case PixelFormat.Format16bppArgb1555: { Rgb555(data, offset, width, pbuf); } break; case PixelFormat.Format16bppRgb565: { Rgb565(data, offset, width, pbuf); } break; case PixelFormat.Format24bppRgb: { Rgb24bpp(data, offset, width, pbuf); } break; case PixelFormat.Format32bppRgb: case PixelFormat.Format32bppArgb: case PixelFormat.Format32bppPArgb: { Rgb32bpp(data, offset, width, pbuf); } break; case PixelFormat.Format1bppIndexed: { Rgb1bpp(data, offset, width, pbuf, frame.Palette); } break; case PixelFormat.Format4bppIndexed: { Rgb4bpp(data, offset, width, pbuf, frame.Palette); } break; case PixelFormat.Format8bppIndexed: { Rgb8bpp(data, offset, width, pbuf, frame.Palette); } break; case PixelFormat.Format16bppGrayScale: { GrayScale16bpp(data, offset, width, pbuf); } break; case PixelFormat.Format48bppRgb: { Rgb48bpp(data, offset, width, pbuf); } break; case PixelFormat.Format64bppPArgb: case PixelFormat.Format64bppArgb: { Rgb64bpp(data, offset, width, pbuf); } break; } // Write the scanline to the buffer. JpegLib.jpeg_write_scanlines (ref cinfo, ref buf, (UInt)1); } Marshal.FreeHGlobal(buf); // Finish the compression process. JpegLib.jpeg_finish_compress(ref cinfo); // Clean everything up. JpegLib.FreeDestinationManager(ref cinfo); JpegLib.jpeg_destroy_compress(ref cinfo); JpegLib.FreeErrorHandler(cinfo.err); }