Example #1
0
 public IFDEntry(ushort tag, ExifValueType type, uint count, uint offset)
 {
     Tag    = tag;
     Type   = type;
     Count  = count;
     Offset = offset;
 }
Example #2
0
        /// <summary>
        /// Determines whether the values fit in the offset field.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="count">The count.</param>
        /// <returns>
        /// <see langword="true"/> if the values fit in the offset field; otherwise, <see langword="false"/>.
        /// </returns>
        public static bool ValueFitsInOffsetField(ExifValueType type, uint count)
        {
            switch (type)
            {
            case ExifValueType.Byte:
            case ExifValueType.Ascii:
            case ExifValueType.Undefined:
            case (ExifValueType)6:     // SByte
                return(count <= 4);

            case ExifValueType.Short:
            case ExifValueType.SShort:
                return(count <= 2);

            case ExifValueType.Long:
            case ExifValueType.SLong:
            case ExifValueType.Float:
            case (ExifValueType)13:     // IFD
                return(count <= 1);

            case ExifValueType.Rational:
            case ExifValueType.SRational:
            case ExifValueType.Double:
            default:
                return(false);
            }
        }
Example #3
0
        /// <summary>
        /// Gets the size in bytes of a <see cref="TagDataType"/> value.
        /// </summary>
        /// <param name="type">The tag type.</param>
        /// <returns>
        /// The size of the value in bytes.
        /// </returns>
        public static int GetSizeInBytes(ExifValueType type)
        {
            switch (type)
            {
            case ExifValueType.Byte:
            case ExifValueType.Ascii:
            case ExifValueType.Undefined:
            case (ExifValueType)6:     // SByte
                return(1);

            case ExifValueType.Short:
            case ExifValueType.SShort:
                return(2);

            case ExifValueType.Long:
            case ExifValueType.SLong:
            case ExifValueType.Float:
            case (ExifValueType)13:     // IFD
                return(4);

            case ExifValueType.Rational:
            case ExifValueType.SRational:
            case ExifValueType.Double:
                return(8);

            default:
                return(0);
            }
        }
Example #4
0
            private string GetValueStringFromOffset()
            {
                string valueString;

                ExifValueType type   = entry.Type;
                uint          count  = entry.Count;
                uint          offset = entry.Offset;

                if (count == 0)
                {
                    return(string.Empty);
                }

                int typeSizeInBytes = ExifValueTypeUtil.GetSizeInBytes(type);

                if (typeSizeInBytes == 1)
                {
                    byte[] bytes = new byte[count];

                    if (offsetIsBigEndian)
                    {
                        switch (count)
                        {
                        case 1:
                            bytes[0] = (byte)((offset >> 24) & 0x000000ff);
                            break;

                        case 2:
                            bytes[0] = (byte)((offset >> 24) & 0x000000ff);
                            bytes[1] = (byte)((offset >> 16) & 0x000000ff);
                            break;

                        case 3:
                            bytes[0] = (byte)((offset >> 24) & 0x000000ff);
                            bytes[1] = (byte)((offset >> 16) & 0x000000ff);
                            bytes[2] = (byte)((offset >> 8) & 0x000000ff);
                            break;

                        case 4:
                            bytes[0] = (byte)((offset >> 24) & 0x000000ff);
                            bytes[1] = (byte)((offset >> 16) & 0x000000ff);
                            bytes[2] = (byte)((offset >> 8) & 0x000000ff);
                            bytes[3] = (byte)(offset & 0x000000ff);
                            break;
                        }
                    }
                    else
                    {
                        switch (count)
                        {
                        case 1:
                            bytes[0] = (byte)(offset & 0x000000ff);
                            break;

                        case 2:
                            bytes[0] = (byte)(offset & 0x000000ff);
                            bytes[1] = (byte)((offset >> 8) & 0x000000ff);
                            break;

                        case 3:
                            bytes[0] = (byte)(offset & 0x000000ff);
                            bytes[1] = (byte)((offset >> 8) & 0x000000ff);
                            bytes[2] = (byte)((offset >> 16) & 0x000000ff);
                            break;

                        case 4:
                            bytes[0] = (byte)(offset & 0x000000ff);
                            bytes[1] = (byte)((offset >> 8) & 0x000000ff);
                            bytes[2] = (byte)((offset >> 16) & 0x000000ff);
                            bytes[3] = (byte)((offset >> 24) & 0x000000ff);
                            break;
                        }
                    }

                    if (type == ExifValueType.Ascii)
                    {
                        valueString = Encoding.UTF8.GetString(bytes).TrimEnd('\0');
                    }
                    else if (count == 1)
                    {
                        valueString = bytes[0].ToString(CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        StringBuilder builder = new();

                        uint lastItemIndex = count - 1;

                        for (int i = 0; i < count; i++)
                        {
                            builder.Append(bytes[i].ToString(CultureInfo.InvariantCulture));

                            if (i < lastItemIndex)
                            {
                                builder.Append(',');
                            }
                        }

                        valueString = builder.ToString();
                    }
                }
                else if (typeSizeInBytes == 2)
                {
                    ushort[] values = new ushort[count];
                    if (offsetIsBigEndian)
                    {
                        switch (count)
                        {
                        case 1:
                            values[0] = (ushort)((offset >> 16) & 0x0000ffff);
                            break;

                        case 2:
                            values[0] = (ushort)((offset >> 16) & 0x0000ffff);
                            values[1] = (ushort)(offset & 0x0000ffff);
                            break;
                        }
                    }
                    else
                    {
                        switch (count)
                        {
                        case 1:
                            values[0] = (ushort)(offset & 0x0000ffff);
                            break;

                        case 2:
                            values[0] = (ushort)(offset & 0x0000ffff);
                            values[1] = (ushort)((offset >> 16) & 0x0000ffff);
                            break;
                        }
                    }

                    if (count == 1)
                    {
                        switch (type)
                        {
                        case ExifValueType.SShort:
                            valueString = ((short)values[0]).ToString(CultureInfo.InvariantCulture);
                            break;

                        case ExifValueType.Short:
                        default:
                            valueString = values[0].ToString(CultureInfo.InvariantCulture);
                            break;
                        }
                    }
                    else
                    {
                        switch (type)
                        {
                        case ExifValueType.SShort:
                            valueString = ((short)values[0]).ToString(CultureInfo.InvariantCulture) + "," +
                                          ((short)values[1]).ToString(CultureInfo.InvariantCulture);
                            break;

                        case ExifValueType.Short:
                        default:
                            valueString = values[0].ToString(CultureInfo.InvariantCulture) + "," +
                                          values[1].ToString(CultureInfo.InvariantCulture);
                            break;
                        }
                    }
                }
                else
                {
                    valueString = offset.ToString(CultureInfo.InvariantCulture);
                }

                return(valueString);
            }
Example #5
0
            public unsafe byte[] GetValueBytesFromOffset()
            {
                if (!OffsetFieldContainsValue)
                {
                    return(null);
                }

                ExifValueType type   = entry.Type;
                uint          count  = entry.Count;
                uint          offset = entry.Offset;

                if (count == 0)
                {
                    return(Array.Empty <byte>());
                }

                // Paint.NET always stores data in little-endian byte order.
                byte[] bytes;
                if (type == ExifValueType.Byte ||
                    type == ExifValueType.Ascii ||
                    type == (ExifValueType)6 || // SByte
                    type == ExifValueType.Undefined)
                {
                    bytes = new byte[count];

                    if (offsetIsBigEndian)
                    {
                        switch (count)
                        {
                        case 1:
                            bytes[0] = (byte)((offset >> 24) & 0x000000ff);
                            break;

                        case 2:
                            bytes[0] = (byte)((offset >> 24) & 0x000000ff);
                            bytes[1] = (byte)((offset >> 16) & 0x000000ff);
                            break;

                        case 3:
                            bytes[0] = (byte)((offset >> 24) & 0x000000ff);
                            bytes[1] = (byte)((offset >> 16) & 0x000000ff);
                            bytes[2] = (byte)((offset >> 8) & 0x000000ff);
                            break;

                        case 4:
                            bytes[0] = (byte)((offset >> 24) & 0x000000ff);
                            bytes[1] = (byte)((offset >> 16) & 0x000000ff);
                            bytes[2] = (byte)((offset >> 8) & 0x000000ff);
                            bytes[3] = (byte)(offset & 0x000000ff);
                            break;
                        }
                    }
                    else
                    {
                        switch (count)
                        {
                        case 1:
                            bytes[0] = (byte)(offset & 0x000000ff);
                            break;

                        case 2:
                            bytes[0] = (byte)(offset & 0x000000ff);
                            bytes[1] = (byte)((offset >> 8) & 0x000000ff);
                            break;

                        case 3:
                            bytes[0] = (byte)(offset & 0x000000ff);
                            bytes[1] = (byte)((offset >> 8) & 0x000000ff);
                            bytes[2] = (byte)((offset >> 16) & 0x000000ff);
                            break;

                        case 4:
                            bytes[0] = (byte)(offset & 0x000000ff);
                            bytes[1] = (byte)((offset >> 8) & 0x000000ff);
                            bytes[2] = (byte)((offset >> 16) & 0x000000ff);
                            bytes[3] = (byte)((offset >> 24) & 0x000000ff);
                            break;
                        }
                    }
                }
                else if (type == ExifValueType.Short || type == ExifValueType.SShort)
                {
                    int byteArrayLength = unchecked ((int)count) * sizeof(ushort);
                    bytes = new byte[byteArrayLength];

                    fixed(byte *ptr = bytes)
                    {
                        ushort *ushortPtr = (ushort *)ptr;

                        if (offsetIsBigEndian)
                        {
                            switch (count)
                            {
                            case 1:
                                ushortPtr[0] = (ushort)((offset >> 16) & 0x0000ffff);
                                break;

                            case 2:
                                ushortPtr[0] = (ushort)((offset >> 16) & 0x0000ffff);
                                ushortPtr[1] = (ushort)(offset & 0x0000ffff);
                                break;
                            }
                        }
                        else
                        {
                            switch (count)
                            {
                            case 1:
                                ushortPtr[0] = (ushort)(offset & 0x0000ffff);
                                break;

                            case 2:
                                ushortPtr[0] = (ushort)(offset & 0x0000ffff);
                                ushortPtr[1] = (ushort)((offset >> 16) & 0x0000ffff);
                                break;
                            }
                        }
                    }
                }
                else
                {
                    bytes = new byte[4];

                    fixed(byte *ptr = bytes)
                    {
                        // The offset is stored as little-endian in memory.
                        *(uint *)ptr = offset;
                    }
                }

                return(bytes);
            }