HEIC (High Efficiency Image Container) is the default photo format on iPhones since iOS 11. Windows doesn't include a HEIC decoder in base .NET, and Linux has no native HEIC support at all. In practice, Magick.NET is the standard .NET solution because it bundles libheif as a NuGet package. The ChangeThisFile API is the fallback for services where you want zero native deps.
Method 1: Magick.NET (libheif bundled, cross-platform)
Magick.NET includes libheif in the NuGet package. No OS codec, no system packages — install the NuGet and HEIC decode works on Windows, Linux, and macOS.
dotnet add package Magick.NET-Q16-AnyCPU
using ImageMagick;
public static class HeicToJpg
{
/// <summary>Converts a HEIC file to JPG. Works on Linux/macOS without OS codecs.</summary>
public static void Convert(string inputPath, string outputPath, int quality = 90)
{
using var image = new MagickImage(inputPath);
image.Format = MagickFormat.Jpg;
image.Quality = (uint)quality;
// Flatten any transparency to white background
image.BackgroundColor = MagickColors.White;
image.Alpha(AlphaOption.Remove);
// Auto-orient based on EXIF rotation data
image.AutoOrient();
image.Write(outputPath);
}
/// <summary>Batch convert a directory of HEIC files to JPG.</summary>
public static void ConvertDirectory(
string inputDir,
string outputDir,
int quality = 90)
{
Directory.CreateDirectory(outputDir);
foreach (var file in Directory.EnumerateFiles(inputDir, "*.heic",
SearchOption.TopDirectoryOnly)
.Concat(Directory.EnumerateFiles(inputDir, "*.HEIC",
SearchOption.TopDirectoryOnly)))
{
var outPath = Path.Combine(
outputDir,
Path.GetFileNameWithoutExtension(file) + ".jpg");
Convert(file, outPath, quality);
}
}
}
// Single file
HeicToJpg.Convert("IMG_1234.heic", "IMG_1234.jpg");
// Batch
HeicToJpg.ConvertDirectory("./heics", "./jpgs");
AutoOrient() is critical — iPhone HEIC files store rotation in EXIF rather than rotating the pixel data. Without AutoOrient(), landscape photos may appear sideways.
Magick.NET is AGPL — for commercial SaaS, check whether you need to purchase an ImageMagick commercial license from Imagemagick Studio.
Method 2: ChangeThisFile API (HttpClient, no libheif)
POST the HEIC file, receive JPG. The API runs libheif server-side. Free tier: 1,000 conversions/month.
# Verify with curl first
curl -X POST https://changethisfile.com/v1/convert \
-H "Authorization: Bearer ctf_sk_your_key" \
-F "file=@IMG_1234.heic" \
-F "target=jpg" \
--output IMG_1234.jpg
using System.Net.Http;
using System.Net.Http.Headers;
// Register in Program.cs:
// builder.Services.AddHttpClient("ctf",
// c => c.BaseAddress = new Uri("https://changethisfile.com"));
public class HeicConvertService
{
private readonly HttpClient _http;
private const string ApiKey = "ctf_sk_your_key_here";
public HeicConvertService(IHttpClientFactory factory)
=> _http = factory.CreateClient("ctf");
public async Task<byte[]> ConvertAsync(
Stream heicStream,
string fileName,
CancellationToken ct = default)
{
using var form = new MultipartFormDataContent();
var fileContent = new StreamContent(heicStream);
fileContent.Headers.ContentType =
new MediaTypeHeaderValue("image/heic");
form.Add(fileContent, "file", fileName);
form.Add(new StringContent("jpg"), "target");
using var request = new HttpRequestMessage(HttpMethod.Post, "/v1/convert")
{
Content = form,
Headers = { Authorization =
new AuthenticationHeaderValue("Bearer", ApiKey) }
};
using var response = await _http.SendAsync(request, ct);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsByteArrayAsync(ct);
}
}
When to use each
| Approach | Best for | Tradeoff |
|---|---|---|
| Magick.NET | On-premise batch processing, EXIF-aware rotation, no network calls | AGPL; large NuGet package with native libs |
| ChangeThisFile API | Minimal containers, serverless, free tier for upload-and-convert flows | Network latency; 25MB file limit on free tier |
Production tips
- Always call AutoOrient(). iPhone photos store rotation in EXIF without rotating pixels. Skipping AutoOrient() produces sideways landscape photos in the JPG output.
- Use IHttpClientFactory for the API. Register a named client in
Program.cswith a 30-second timeout and injectIHttpClientFactoryinto your service. - Pass CancellationToken. Wire it from
HttpContext.RequestAbortedin ASP.NET controllers — if the user closes the upload mid-way, the API call cancels instead of completing unnecessarily. - Handle HEIF vs HEIC file extensions. Apple uses .heic, but the standard file extension is also .heif. Both contain HEVC-encoded images. Enumerate both extensions in batch jobs:
*.heic+*.heif+ uppercase variants. - Quality 85–90 is the right JPG target. HEIC is typically higher quality than JPEG at the same visual fidelity. Converting to JPG at 80–90 preserves the visual quality while keeping file sizes reasonable.
Magick.NET is the only .NET library that handles HEIC decode reliably across all platforms without OS-level codecs. Call AutoOrient() or you'll have sideways photos. For minimal-footprint containers, the ChangeThisFile API removes the dependency entirely. Free tier: 1,000 conversions/month.