text: // Copyright (c) Drew Noakes and contributors. All Rights Reserved. Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
  
  using System;
  using System.Collections.Generic;
  using System.Diagnostics.CodeAnalysis;
  using System.Linq;
  
  namespace MetadataExtractor.Formats.Jpeg
  {
      /// <summary>An enumeration of the known segment types found in JPEG files.</summary>
      /// <remarks>
      /// <list type="bullet">
      ///   <item>http://www.ozhiker.com/electronics/pjmt/jpeg_info/app_segments.html</item>
      ///   <item>http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html</item>
      ///   <item>http://lad.dsc.ufcg.edu.br/multimidia/jpegmarker.pdf</item>
      ///   <item>http://dev.exiv2.org/projects/exiv2/wiki/The_Metadata_in_JPEG_files</item>
      /// </list>
      /// </remarks>
      /// <author>Drew Noakes https://drewnoakes.com</author>
      [SuppressMessage("ReSharper", "UnusedMember.Global")]
      public enum JpegSegmentType : byte
      {
          /// <summary>For temporary use in arithmetic coding.</summary>
          /// <remarks>No length or parameter sequence follows this marker.</remarks>
          Tem = 0x01,
  
          /// <summary>Start-of-Frame, non-differential Huffman coding frame, baseline DCT.</summary>
          /// <remarks>
          /// Indicates that this is a baseline DCT-based JPEG, and specifies the width,
          /// height, number of components, and component subsampling (e.g., 4:2:0).
          /// </remarks>
          Sof0 = 0xC0,
  
          /// <summary>Start-of-Frame, non-differential Huffman coding frame, extended sequential DCT.</summary>
          Sof1 = 0xC1,
  
          /// <summary>Start-of-Frame, non-differential Huffman coding frame, progressive DCT.</summary>
          /// <remarks>
          /// Indicates that this is a progressive DCT-based JPEG, and specifies the width,
          /// height, number of components, and component subsampling (e.g., 4:2:0).
          /// </remarks>
          Sof2 = 0xC2,
  
          /// <summary>Start-of-Frame, non-differential Huffman coding frame, lossless sequential.</summary>
          Sof3 = 0xC3,
  
          /// <summary>Define Huffman Table(s).</summary>
          /// <remarks>Specifies one or more Huffman tables.</remarks>
          Dht = 0xC4,
  
          /// <summary>Start-of-Frame, differential Huffman coding frame, differential sequential DCT.</summary>
          Sof5 = 0xC5,
  
          /// <summary>Start-of-Frame, differential Huffman coding frame, differential progressive DCT.</summary>
          Sof6 = 0xC6,
  
          /// <summary>Start-of-Frame, differential Huffman coding frame, differential lossless.</summary>
          Sof7 = 0xC7,
  
          /// <summary>Start-of-Frame, non-differential arithmetic coding frame, extended sequential DCT.</summary>
          Sof9 = 0xC9,
  
          /// <summary>Start-of-Frame, non-differential arithmetic coding frame, progressive DCT.</summary>
          Sof10 = 0xCA,
  
          /// <summary>Start-of-Frame, non-differential arithmetic coding frame, lossless sequential.</summary>
          Sof11 = 0xCB,
  
          /// <summary>Define Arithmetic Coding table(s).</summary>
          Dac = 0xCC,
  
          /// <summary>Start-of-Frame, differential arithmetic coding frame, differential sequential DCT.</summary>
          Sof13 = 0xCD,
  
          /// <summary>Start-of-Frame, differential arithmetic coding frame, differential progressive DCT.</summary>
          Sof14 = 0xCE,
  
          /// <summary>Start-of-Frame, differential arithmetic coding frame, differential lossless.</summary>
          Sof15 = 0xCF,
  
          /// <summary>Restart.</summary>
          /// <remarks>No length or parameter sequence follows this marker.</remarks>
          Rst0 = 0xD0,
  
          /// <summary>Restart.</summary>
          /// <remarks>No length or parameter sequence follows this marker.</remarks>
          Rst1 = 0xD1,
  
          /// <summary>Restart.</summary>
          /// <remarks>No length or parameter sequence follows this marker.</remarks>
          Rst2 = 0xD2,
  
          /// <summary>Restart.</summary>
          /// <remarks>No length or parameter sequence follows this marker.</remarks>
          Rst3 = 0xD3,
  
          /// <summary>Restart.</summary>
          /// <remarks>No length or parameter sequence follows this marker.</remarks>
          Rst4 = 0xD4,
  
          /// <summary>Restart.</summary>
          /// <remarks>No length or parameter sequence follows this marker.</remarks>
          Rst5 = 0xD5,
  
          /// <summary>Restart.</summary>
          /// <remarks>No length or parameter sequence follows this marker.</remarks>
          Rst6 = 0xD6,
  
          /// <summary>Restart.</summary>
          /// <remarks>No length or parameter sequence follows this marker.</remarks>
          Rst7 = 0xD7,
  
          /// <summary>Start Of Image segment. Begins the compressed JPEG data stream.</summary>
          /// <remarks>No length or parameter sequence follows this marker.</remarks>
          Soi = 0xD8,
  
          /// <summary>End-of-Image. Terminates the JPEG compressed data stream that started at <see cref="Soi"/>.</summary>
          /// <remarks>No length or parameter sequence follows this marker.</remarks>
          Eoi = 0xD9,
  
          /// <summary>Start-of-Scan.</summary>
          /// <remarks>
          /// Begins a top-to-bottom scan of the image.
          /// In baseline DCT JPEG images, there is generally a single scan.
          /// Progressive DCT JPEG images usually contain multiple scans.
          /// This marker specifies which slice of data it will contain, and is
          /// immediately followed by entropy-coded data.
          /// </remarks>
          Sos = 0xDA,
  
          /// <summary>Define Quantization Table.</summary>
          /// <remarks>Specifies one or more quantization tables.</remarks>
          Dqt = 0xDB,
  
          /// <summary>Define Number of Lines.</summary>
          Dnl = 0xDC,
  
          /// <summary>Define Restart Interval.</summary>
          /// <remarks>
          /// Specifies the interval between RSTn markers, in macroblocks.
          /// This marker is followed by two bytes indicating the fixed size so
          /// it can be treated like any other variable size segment.
          /// </remarks>
          Dri = 0xDD,
  
          /// <summary>Define Hierarchical Progression.</summary>
          Dhp = 0xDE,
  
          /// <summary>Expand reference components.</summary>
          Exp = 0xDF,
  
          /// <summary>Application specific, type 0. Commonly contains JFIF, JFXX.</summary>
          App0 = 0xE0,
  
          /// <summary>Application specific, type 1. Commonly contains Exif. XMP data is also kept in here, though usually in a second instance.</summary>
          App1 = 0xE1,
  
          /// <summary>Application specific, type 2. Commonly contains ICC.</summary>
          App2 = 0xE2,
  
          /// <summary>Application specific, type 3.</summary>
          App3 = 0xE3,
  
          /// <summary>Application specific, type 4.</summary>
          App4 = 0xE4,
  
          /// <summary>Application specific, type 5.</summary>
          App5 = 0xE5,
  
          /// <summary>Application specific, type 6.</summary>
          App6 = 0xE6,
  
          /// <summary>Application specific, type 7.</summary>
          App7 = 0xE7,
  
          /// <summary>Application specific, type 8.</summary>
          App8 = 0xE8,
  
          /// <summary>Application specific, type 9.</summary>
          App9 = 0xE9,
  
          /// <summary>Application specific, type A. Can contain Unicode comments, though <see cref="Com"/> is more commonly used for comments.</summary>
          AppA = 0xEA,
  
          /// <summary>Application specific, type B.</summary>
          AppB = 0xEB,
  
          /// <summary>Application specific, type C.</summary>
          AppC = 0xEC,
  
          /// <summary>Application specific, type D. Commonly contains IPTC, Photoshop data.</summary>
          AppD = 0xED,
  
          /// <summary>Application specific, type E. Commonly contains Adobe data.</summary>
          AppE = 0xEE,
  
          /// <summary>Application specific, type F.</summary>
          AppF = 0xEF,
  
          /// <summary>JPEG comment (text).</summary>
          Com = 0xFE
      }
  
      /// <summary>
      /// Extension methods for <see cref="JpegSegmentType"/> enum.
      /// </summary>
      public static class JpegSegmentTypeExtensions
      {
          /// <summary>Gets whether this JPEG segment type might contain metadata.</summary>
          /// <remarks>Used to exclude large image-data-only segment from certain types of processing.</remarks>
          public static bool CanContainMetadata(this JpegSegmentType type)
          {
              switch (type)
              {
                  case JpegSegmentType.Soi:
                  case JpegSegmentType.Dac:
                  case JpegSegmentType.Dhp:
                  case JpegSegmentType.Dht:
                  case JpegSegmentType.Dnl:
                  case JpegSegmentType.Dqt:
                  case JpegSegmentType.Dri:
                  case JpegSegmentType.Exp:
                      return false;
                  default:
                      return true;
              }
          }
  
          /// <summary>Gets JPEG segment types that might contain metadata.</summary>
  #if NET35
          public static IEnumerable<JpegSegmentType> CanContainMetadataTypes { get; }
  #else
          public static IReadOnlyList<JpegSegmentType> CanContainMetadataTypes { get; }
  #endif
              = Enum.GetValues(typeof(JpegSegmentType)).Cast<JpegSegmentType>().Where(type => type.CanContainMetadata()).ToList();
  
          /// <summary>Gets whether this JPEG segment type's marker is followed by a length indicator.</summary>
          public static bool ContainsPayload(this JpegSegmentType type)
          {
              // ReSharper disable once SwitchStatementMissingSomeCases
              switch (type)
              {
                  case JpegSegmentType.Soi:
                  case JpegSegmentType.Eoi:
                  case JpegSegmentType.Rst0:
                  case JpegSegmentType.Rst1:
                  case JpegSegmentType.Rst2:
                  case JpegSegmentType.Rst3:
                  case JpegSegmentType.Rst4:
                  case JpegSegmentType.Rst5:
                  case JpegSegmentType.Rst6:
                  case JpegSegmentType.Rst7:
                      return false;
  
                  default:
                      return true;
              }
          }
  
          /// <summary>Gets whether this JPEG segment is intended to hold application specific data.</summary>
          public static bool IsApplicationSpecific(this JpegSegmentType type) => type >= JpegSegmentType.App0 && type <= JpegSegmentType.AppF;
      }
  }
  