Modifying XMP data with C #

I am using C # in ASP.NET version 2. I am trying to open an image file, read (and change) the XMP header and close it again. I cannot update ASP, so the WIC is missing and I just cannot figure out how to do it.

Here's what I have so far:

Bitmap bmp = new Bitmap(Server.MapPath(imageFile));

MemoryStream ms = new MemoryStream();

StreamReader sr = new StreamReader(Server.MapPath(imageFile));

*[stuff with find and replace here]*

byte[] data = ToByteArray(sr.ReadToEnd());

ms = new MemoryStream(data);

originalImage = System.Drawing.Image.FromStream(ms);

      

Any suggestions?

+1


a source to share


3 answers


How about this kind?

byte[] data = File.ReadAllBytes(path);
... find & replace bit here ...
File.WriteAllBytes(path, data);

      

Also, I really recommend not using System.Bitmap in an asp.net process as it leaks memory and crashes / accidentally crashes from time to time (even MS admits this)



Here's a bit from MS on why System.Drawing.Bitmap is unstable:

http://msdn.microsoft.com/en-us/library/system.drawing.aspx

"Warning: Classes in the System.Drawing namespace are not supported for use in a Windows service or ASP.NET. Attempting to use these classes from one of these application types may cause unexpected problems such as reduced service efficiency and runtime exceptions."

+1


a source


Part 1 of the XMP 2012 spec, page 10 specifically talks about how to edit a file in place without requiring an understanding of the surrounding format (although they suggest this as a last resort). The built-in XMP package looks like this:

<?xpacket begin="■" id="W5M0MpCehiHzreSzNTczkc9d"?>
    ... the serialized XMP as described above: ...
    <x:xmpmeta xmlns:x="adobe:ns:meta/">
    <rdf:RDF xmlns:rdf= ...>
        ...
    </rdf:RDF>
    </x:xmpmeta>
    ... XML whitespace as padding ...
<?xpacket end="w"?>

      



In this example, 'is a Unicode "zero-width non-gap character" (U + FEFF) used as a byte order marker.

(XMP Spec 2010, Part 3, page 12) also gives specific byte patterns (UTF-8, UTF16, big / small endian) to search when scanning bytes. This will complement Chris's answer about reading a file as a giant stream of bytes.

+1


a source


You can use the following functions to read / write binary data:

    public byte[] GetBinaryData(string path, int bufferSize)
    {
        MemoryStream ms = new MemoryStream();
        using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read))
        {
            int bytesRead;
            byte[] buffer = new byte[bufferSize];
            while((bytesRead = fs.Read(buffer,0,bufferSize))>0)
            {
                ms.Write(buffer,0,bytesRead);
            }
        }
        return(ms.ToArray());
    }

    public void SaveBinaryData(string path, byte[] data, int bufferSize)
    {
        using (FileStream fs = File.Open(path, FileMode.Create, FileAccess.Write))
        {
            int totalBytesSaved = 0;
            while (totalBytesSaved<data.Length)
            {
                int remainingBytes = Math.Min(bufferSize, data.Length - totalBytesSaved);
                fs.Write(data, totalBytesSaved, remainingBytes);
                totalBytesSaved += remainingBytes;
            }
        }
    }

      

However, loading entire images into memory will require quite a lot of RAM. I don't know much about XMP headers, but if possible, you should:

  • Load only headers in memory
  • Manipulate headers in memory
  • Write the headers to a new file
  • Copy the remaining data from the original file
0


a source







All Articles