mirror of https://github.com/SixLabors/ImageSharp
2 changed files with 154 additions and 9 deletions
@ -0,0 +1,150 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.InteropServices; |
|||
using SixLabors.ImageSharp.Formats.Jxl.IO.Jpeg.Data; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Processing.Decoder; |
|||
|
|||
internal class JxlToJpegDecoder |
|||
{ |
|||
/// <summary>
|
|||
/// Returns the number of EXIF markers in the JPEG file.
|
|||
/// </summary>
|
|||
/// <param name="jpegData">Input parsed JPEG data</param>
|
|||
/// <returns>Number of EXIFs in the JPEG</returns>
|
|||
public static int NumExifMarkers(JpegData jpegData) => jpegData.AppMarkerTypes.Count(x => x == JpegAppMarkerType.Exif); |
|||
|
|||
/// <summary>
|
|||
/// Returns the number of XMP markers in the JPEG file.
|
|||
/// </summary>
|
|||
/// <param name="jpegData">Input parsed JPEG data</param>
|
|||
/// <returns>Number of XMPs in the JPEG</returns>
|
|||
public static int NumXmpMarkers(JpegData jpegData) => jpegData.AppMarkerTypes.Count(x => x == JpegAppMarkerType.Xmp); |
|||
|
|||
/// <summary>
|
|||
/// Attempts to set EXIF data in the JPEG file.
|
|||
/// </summary>
|
|||
/// <param name="data">EXIF data</param>
|
|||
/// <param name="jpegData">JPEG file for EXIF data</param>
|
|||
/// <returns>If EXIF data was set, true; returns false if no EXIF marker is present, or is present but not enough data</returns>
|
|||
public static bool TrySetExif(Span<byte> data, JpegData jpegData) |
|||
{ |
|||
int size = data.Length; |
|||
ReadOnlySpan<byte> exifTag = JpegDataConstants.ExifTag; |
|||
int exifTagSize = exifTag.Length; |
|||
|
|||
for (int i = 0; i < jpegData.AppData.Count; ++i) |
|||
{ |
|||
if (jpegData.AppMarkerTypes[i] == JpegAppMarkerType.Exif) |
|||
{ |
|||
Span<byte> dataSpan = CollectionsMarshal.AsSpan(jpegData.AppData[i]); |
|||
|
|||
if (dataSpan.Length != size + 3 + exifTagSize - 4) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
// The first 9 bytes are used for JPEG marker header.
|
|||
dataSpan[0] = 0xE1; |
|||
|
|||
// The second and third byte are already filled in correctly
|
|||
exifTag.CopyTo(dataSpan[3..]); |
|||
|
|||
// The first 4 bytes are the TIFF header from the box contents, and are
|
|||
// not included in the JPEG
|
|||
data[4..].CopyTo(dataSpan[(3 + exifTagSize)..]); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Attempts to set XMP data in the JPEG file.
|
|||
/// </summary>
|
|||
/// <param name="data">XMP data</param>
|
|||
/// <param name="jpegData">JPEG file for XMP data</param>
|
|||
/// <returns>If XMP data was set, true; returns false if no XMP marker is present, or is present but not enough data</returns>
|
|||
public static bool TrySetXmp(Span<byte> data, JpegData jpegData) |
|||
{ |
|||
int size = data.Length; |
|||
ReadOnlySpan<byte> xmpTag = JpegDataConstants.XmpTag; |
|||
int xmpTagSize = xmpTag.Length; |
|||
|
|||
for (int i = 0; i < jpegData.AppData.Count; ++i) |
|||
{ |
|||
if (jpegData.AppMarkerTypes[i] == JpegAppMarkerType.Xmp) |
|||
{ |
|||
Span<byte> dataSpan = CollectionsMarshal.AsSpan(jpegData.AppData[i]); |
|||
|
|||
if (dataSpan.Length != size + 3 + xmpTagSize) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
// The first 9 bytes are used for JPEG marker header.
|
|||
dataSpan[0] = 0xE1; |
|||
|
|||
// The second and third byte are already filled in correctly
|
|||
xmpTag.CopyTo(dataSpan[3..]); |
|||
|
|||
data.CopyTo(dataSpan[(3 + xmpTagSize)..]); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public static bool ExifBoxContentSize(JpegData jpegData, ref long size) |
|||
{ |
|||
size = 0; |
|||
int exifTagLength = JpegDataConstants.ExifTag.Length; |
|||
|
|||
for (int i = 0; i < jpegData.AppData.Count; ++i) |
|||
{ |
|||
if (jpegData.AppMarkerTypes[i] == JpegAppMarkerType.Exif) |
|||
{ |
|||
if (jpegData.AppData[i].Count < 3 + exifTagLength) |
|||
{ |
|||
// too small for app marker header
|
|||
return false; |
|||
} |
|||
|
|||
// The first 4 bytes are the TIFF header from the box contents, and are
|
|||
// not included in the JPEG
|
|||
size = jpegData.AppData[i].Count + 4 - 3 - exifTagLength; |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public static bool XmpBoxContentSize(JpegData jpegData, ref long size) |
|||
{ |
|||
size = 0; |
|||
int xmpTagLength = JpegDataConstants.XmpTag.Length; |
|||
|
|||
for (int i = 0; i < jpegData.AppData.Count; ++i) |
|||
{ |
|||
if (jpegData.AppMarkerTypes[i] == JpegAppMarkerType.Xmp) |
|||
{ |
|||
if (jpegData.AppData[i].Count < 3 + xmpTagLength) |
|||
{ |
|||
// too small for app marker header
|
|||
return false; |
|||
} |
|||
|
|||
size = jpegData.AppData[i].Count - 3 - xmpTagLength; |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue