Recursive AI

Convert PNG to JPG in C#

All oneimage recipes

Load the PNG, put it on a background with Flatten (JPEG has no transparency), and save it with a .jpg extension. The extension picks the output format, so the same two lines convert between PNG, JPEG, WebP, GIF, TIFF, BMP and ICO in any direction. The program below converts a transparent PNG logo.

Terminal
dotnet new console -o ConvertImage && cd ConvertImage
dotnet add package RecursiveAI.OneImage --version 1.10.4
curl -L -o logo.png https://recursiveai.org/assets/brand/icon-512.png

OneImage needs the .NET 10 SDK. Put this in Program.cs and run dotnet run:

C#
using OneImage;
 
Image png = Image.Load("logo.png");
 
// JPEG can't store transparency: put the logo on white, then save at quality 90.
png.Flatten(new Rgba32(255, 255, 255, 255))
   .Save("logo.jpg", new SaveOptions
   {
       EncoderOptions = new JpegEncoderOptions { Quality = 90 },
   });
 
// Any other direction is a load and a save; the extension picks the encoder.
Image.Load("logo.jpg").Save("logo-from-jpg.png");
png.Save("logo.bmp");
png.Resize(width: 64).Save("favicon.ico");
 
string[] files =
    ["logo.png", "logo.jpg", "logo-from-jpg.png", "logo.bmp", "favicon.ico"];
foreach (string file in files)
{
    ImageInfo info = Image.Identify(file);
    long kb = new FileInfo(file).Length / 1024;
    string size = $"{info.Width}x{info.Height}";
    Console.WriteLine($"{file}: {info.Format.Name} {size}, {kb} KB");
}
Text
logo.png: png 512x512, 7 KB
logo.jpg: jpeg 512x512, 8 KB
logo-from-jpg.png: png 512x512, 17 KB
logo.bmp: bmp 512x512, 1024 KB
favicon.ico: ico 64x64, 16 KB

The input format is detected from the file’s content, not its name, so a PNG saved as photo.jpg still loads. Without Flatten, the JPEG encoder writes whatever color values the transparent pixels store, which is often black.

Convert to a stream

A stream has no extension, so name the format with its Instance:

C#
using OneImage;
 
using var output = new MemoryStream();
Image.Load("logo.png")
     .Flatten(new Rgba32(255, 255, 255, 255))
     .Save(output, JpegFormat.Instance);
Console.WriteLine($"{output.Length} bytes of JPEG in memory");
Text
6858 bytes of JPEG in memory

The format instances are PngFormat, JpegFormat, WebPFormat, GifFormat, TiffFormat, BmpFormat and IcoFormat. SaveAsync does the same for ASP.NET Core responses.

Limits

  • JPEG is lossy and has no alpha channel. Converting JPEG to PNG makes a larger file, not a better image.
  • JPEG and BMP hold one image. Saving an animated GIF or multipage TIFF as JPEG writes the first frame; see Split a multipage TIFF.
  • ICO entries are at most 256×256, so resize first.
  • Metadata is kept by a plain load and save, including any EXIF GPS position. See Remove EXIF metadata.
  • Not supported: HEIC and AVIF. SVG, PSD and PDF need their add-on packages (SVG to PNG, PSD to PNG, PDF to image).

For web output, WebP is usually smaller than JPEG. Every encoder option is in the guide.