我想在图像元数据块的特定标记下添加一些字符串。由于.NET不支持自定义元数据字段,因此必须在字节级别上执行此操作。
该块的结构类似于1C 02 XX YY YY ZZ ZZ ZZ ...
,其中XX是我需要追加的字段ID,YY YY是其大小,ZZ=数据。
我想象中应该可以读取到此标记(1C 02 XX)之前的所有图像数据,然后增加大小字节(YY YY),在ZZ的末尾添加数据,然后添加原始文件的其余部分?这正确吗?
我该如何进行?它需要尽可能快地处理4-5 MB的JPEG文件。
我想在图像元数据块的特定标记下添加一些字符串。由于.NET不支持自定义元数据字段,因此必须在字节级别上执行此操作。
该块的结构类似于1C 02 XX YY YY ZZ ZZ ZZ ...
,其中XX是我需要追加的字段ID,YY YY是其大小,ZZ=数据。
我想象中应该可以读取到此标记(1C 02 XX)之前的所有图像数据,然后增加大小字节(YY YY),在ZZ的末尾添加数据,然后添加原始文件的其余部分?这正确吗?
我该如何进行?它需要尽可能快地处理4-5 MB的JPEG文件。
使用以下代码解决了这个问题:
List<byte> dataNew = new List<byte>();
byte[] data = File.ReadAllBytes(jpegFilePath);
int j = 0;
for (int i = 1; i < data.Length; i++)
{
if (data[i - 1] == (byte)0x1C) // 1C IPTC
{
if (data[i] == (byte)0x02) // 02 IPTC
{
if (data[i + 1] == (byte)fileByte) // IPTC field_number, i.e. 0x78 = IPTC_120
{
j = i;
break;
}
}
}
}
for (int i = 0; i < j + 2; i++) // add data from file before this field
dataNew.Add(data[i]);
int countOld = (data[j + 2] & 255) << 8 | (data[j + 3] & 255); // curr field length
int countNew = valueToAdd.Length; // new string length
int newfullSize = countOld + countNew; // sum
byte[] newSize = BitConverter.GetBytes((Int16)newfullSize); // Int16 on 2 bytes (to use 2 bytes as size)
Array.Reverse(newSize); // changes order 10 00 to 00 10
for (int i = 0; i < newSize.Length; i++) // add changed size
dataNew.Add(newSize[i]);
for (int i = j + 4; i < j + 4 + countOld; i++) // add old field value
dataNew.Add(data[i]);
byte[] newString = ASCIIEncoding.ASCII.GetBytes(valueToAdd);
for (int i = 0; i < newString.Length; i++) // append with new field value
dataNew.Add(newString[i]);
for (int i = j + 4 + newfullSize; i < data.Length; i++) // add rest of the file
dataNew.Add(data[i]);
byte[] finalArray = dataNew.ToArray();
File.WriteAllBytes(Path.Combine(Path.GetDirectoryName(jpegFilePath), "newfile.jpg"), finalArray);
public void ExpandFile(FileStream stream, long offset, int extraBytes)
{
// https://dev59.com/2HA75IYBdhLWcg3w6Nr8
const int SIZE = 4096;
var buffer = new byte[SIZE];
var length = stream.Length;
// Expand file
stream.SetLength(length + extraBytes);
var pos = length;
int to_read;
while (pos > offset)
{
to_read = pos - SIZE >= offset ? SIZE : (int)(pos - offset);
pos -= to_read;
stream.Position = pos;
stream.Read(buffer, 0, to_read);
stream.Position = pos + extraBytes;
stream.Write(buffer, 0, to_read);
}
需要检查,不过...