Ответ 1
Метаданные tEXt: представлены в ISO/IEC 8859-1
Попробуйте добавить следующее, прежде чем делать свой запрос:
request.Headers.Add(HttpRequestHeader.AcceptCharset, "ISO-8859-1");
так, измените свой код:
System.Drawing.Image img = null;
//accept Charset "ISO-8859-1"
request.Headers.Add(HttpRequestHeader.AcceptCharset, "ISO-8859-1");
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
Stream stream = response.GetResponseStream();
img = System.Drawing.Image.FromStream(stream);
.......
}
return img;
только для информации, можете ли вы разместить то, что является окном EncodingName в Windows 7/8/10
используйте команду powershell, чтобы знать:
[System.Text.Encoding]::Default.EncodingName
Edit:
Я рассмотрел исходный код DOTNet System.Drawing.Image.FromStream и нашел это утверждение:
// [Obsolete("Use Image.FromStream(stream, useEmbeddedColorManagement)")]
public static Image FromStream(Stream stream) {
return Image.FromStream(stream, false);
}
попробуйте использовать:
Image.FromStream(stream, true);
or
Image.FromStream(stream, true,true);
для получения подробной информации о параметрах:
public static Image FromStream(
Stream stream,
bool useEmbeddedColorManagement,////true to use color management information embedded in the data stream; otherwise, false.
bool validateImageData //true to validate the image data; otherwise, false.
)
Изменить 2:
Я провел эксперимент с файлом изображения PNG с данными TEXT:
Я разработал функцию для измерения размера изображения в байтах, который считывается функцией FromStream(), и я выполнил как win7/win 10.
В следующей таблице представлены реальный размер изображения в байтах в обеих средах:
The file size: 502,888 byte (real size on disk).
win 7 win10 function used
569674 597298 Image.FromStream(stream, true,true)
597343 597298 Image.FromStream(stream, true)
597343 597298 Image.FromStream(stream, false)
Вы обнаружите, что размер отличается в обеих средах и отличается от реальный размер на диске.
Итак, вы ожидаете, что положение метаданных будет изменено (но не потеряно, только перераспределено)
Я использовал шестнадцатеричный редактор для просмотра фрагмента tTEXT.
tEXT находится в позиции 66 (в десятичной форме), начиная с начала файла, и в обеих средах одинаково!
Я использовал свою собственную функцию чтения метаданных, и результат тот же и действителен как для окон 7, так и для окон 10 (NO LOSS OF DATA).
Официальный сайт формата PNG: https://www.w3.org/TR/PNG/
Заключение
Функция Image.FromStream не подходит для чтения метаданных, файл изображения следует читать в формате исходного байта не в формате изображения, потому что функция FromStream перераспределяет необработанные данные в таком состоянии, чтобы сохранить изображение и его данные без искажений (то есть внутренности функции в dotnet).
Чтобы прочитать метаданные, как описано в спецификациях PNG, вы должны прочитать поток в RAW BYTES с самого начала файла, как описано в спецификациях.
Я советую вам использовать библиотеку классов MetadataExtractor для чтения метаданных, и ее результат очень точен как в Windows 7, так и в Windows 10
Вы можете установить библиотеку из nuget. install-Package MetadataExtractor
Изменить 3: Предлагаемое решение
Теперь проблема решена, и следующий класс действителен как для win 7, win 8
Основное изменение - чтение файла изображения в виде Raw bytes
class MetaReader
{
public static Hashtable GetData(string fname)
{
using (FileStream image = new FileStream(fname, FileMode.Open, FileAccess.Read))
{
Hashtable metadata = new Hashtable();
byte[] imageBytes;
using (var memoryStream = new MemoryStream())
{
image.CopyTo(memoryStream);
imageBytes = memoryStream.ToArray();
Console.WriteLine(imageBytes.Length);
}
if (imageBytes.Length <= 8)
{
return null;
}
// Skipping 8 bytes of PNG header
int pointer = 8;
while (pointer < imageBytes.Length)
{
// read the next chunk
uint chunkSize = GetChunkSize(imageBytes, pointer);
pointer += 4;
string chunkName = GetChunkName(imageBytes, pointer);
pointer += 4;
// chunk data -----
if (chunkName.Equals("tEXt"))
{
byte[] data = new byte[chunkSize];
Array.Copy(imageBytes, pointer, data, 0, chunkSize);
StringBuilder stringBuilder = new StringBuilder();
foreach (byte t in data)
{
stringBuilder.Append((char)t);
}
string[] pair = stringBuilder.ToString().Split(new char[] { '\0' });
metadata[pair[0]] = pair[1];
Console.WriteLine(metadata[pair[0]]);
}
pointer += (int)chunkSize + 4;
if (pointer > imageBytes.Length)
break;
}
return metadata;
}
}
private static uint GetChunkSize(byte[] bytes, int pos)
{
byte[] quad = new byte[4];
for (int i = 0; i < 4; i++) { quad[3 - i] = bytes[pos + i]; }
return BitConverter.ToUInt32(quad, 0);
}
private static string GetChunkName(byte[] bytes, int pos)
{
StringBuilder builder = new StringBuilder(); for (int i = 0; i < 4; i++) { builder.Append((char)bytes[pos + i]); }
return builder.ToString();
}
}
Чтение метаданных из веб-службы:
Вы можете загрузить файл изображения с URL-адреса в виде потока и прочитать метаданные "на лету". Кроме того, вы можете создать экземпляр System.Drawing.Image и делать то, что когда-либо обрабатывалось на изображении. Вы можете найти полную демоверсию с исходным кодом по адресу: