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.
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:
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"); }
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:
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");
6858 bytes of JPEG in memoryThe 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.