首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何更新照片上的时间戳或在Google+照片上添加时区?

如何更新照片上的时间戳或在Google+照片上添加时区?
EN

Stack Overflow用户
提问于 2015-04-24 16:18:34
回答 1查看 1.2K关注 0票数 12

使用Picasa,我从我的Google+相册中检索一张照片,并试图更改时间戳(我的手机上的时间不对,所以试图修复它):

代码语言:javascript
复制
var service = new PicasaService("exampleCo-exampleApp-1");
service.setUserCredentials("uid", "pwd");
AlbumQuery query = new AlbumQuery(PicasaQuery.CreatePicasaUri("default"));

PicasaFeed feed = service.Query(query);
var entry = (PicasaEntry)feed.Entries.SingleOrDefault(f => f.Title.Text == "Trip to Italy - ALL");

var ac = new AlbumAccessor(entry);

var photoQuery = new PhotoQuery(PicasaQuery.CreatePicasaUri("default", ac.Id));
PicasaFeed photoFeed = service.Query(photoQuery);

PicasaEntry picasaEntry = photoFeed.Entries[0];

ulong timestamp = Convert.ToUInt64(picasaEntry.GetPhotoExtensionValue("timestamp"));

// deduct 9 hours
DateTime dt = FromUnixTime(pa.Timestamp).AddHours(-9);
picasaEntry.SetPhotoExtensionValue("timestamp", Convert.ToString(ToUnixTime(dt)));

var updatedEntry = (PicasaEntry) picasaEntry.Update();

不幸的是,虽然.Update方法成功了,但时间戳并没有改变。我还试图更改照片的时区(例如,用户手动做的事情,比如这个http://i.imgur.com/pxYSi9S.png)。

我错过了一些简单的东西吗?还有其他方法来完成同样的事情吗?我也会满足于改变照片的时区。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-05 10:17:14

我也曾尝试过你的问题,所以让我在这里分享一下我对情况的评估:

Google似乎从图像的Exif标记中获取显示的元信息。尽管在查看Google时设置Exif标记似乎是可能的(我甚至对.net程序集进行了反编译,以确保所有内容都是正确的),但是在发布更新时,Google根本不会将它们重新嵌入到图片中。

所以我的方法是下载所有的图片,更改他们的Exif信息,然后重新上传(就像线虫建议的那样)。不幸的是,谷歌确实删除了所有下载的文件的Exif标签(thx大G!)并将其替换为人工值(例如,应用程序名称"Google")和空值(创建时间=空)。在.net中从零开始生成 Exif信息是很麻烦的(必须强制构造System.Drawing.Imaging.PropertyItem的实例,它有内部构造函数,可以完成并正确地参数化)。但是,由于我已经做了类似的事情(从现有的图片获取Exif信息,再生图片和重新添加Exif到新图片),在我的主要工作中的一个应用程序的成像模块中,我认为这种方法是可行的。

这是一些概念代码的证明。它并不是一帆风顺的(一个完整的解决方案应该读取现有picasa条目的日期,并将它们缓存在一个列表中,以便在下载的图像上重新应用它们),但它确实涵盖了棘手的部分。

代码语言:javascript
复制
private void button1_Click(object sender, EventArgs e)
{
    var service = new PicasaService("exampleCo-exampleApp-1");
    service.setUserCredentials("me.myself@gmail.com", "-secret-");
    AlbumQuery query = new AlbumQuery(PicasaQuery.CreatePicasaUri("default"));


    PicasaFeed feed = service.Query(query);
    var entry = (PicasaEntry)feed.Entries.SingleOrDefault(f => f.Title.Text == "Testalbum");

    var ac = new AlbumAccessor(entry);

    var photoQuery = new PhotoQuery(PicasaQuery.CreatePicasaUri("default", ac.Id));
    PicasaFeed photoFeed = service.Query(photoQuery);

    DirectoryInfo srcdir = Directory.CreateDirectory("C:\\Temp\\Testalbum");
    DownloadAllPhotos("C:\\Temp\\Testalbum", photoFeed.Entries);

    foreach (PicasaEntry oldentry in photoFeed.Entries)
    {
        oldentry.Delete();
    }

    DirectoryInfo tgtdir = Directory.CreateDirectory("C:\\Temp\\Converted");
    foreach (FileInfo imagefile in srcdir.EnumerateFiles())
    {
        Image img = Image.FromFile(imagefile.FullName);

        PropertyItem PiDtOrig = null;
        try
        {
            PiDtOrig = img.GetPropertyItem(0x9003); // id 0x9003 is "DateTimeOriginal"
        }
        catch (System.ArgumentException ex) // this exception is thrown when PropertyItem does not exist 
        {
            PiDtOrig = NewPropertyItem();
            PiDtOrig.Id = 0x9003;
            PiDtOrig.Type = 7;
            PiDtOrig.Len = 4;
        }

        PiDtOrig.Value = BitConverter.GetBytes(DateTimeToInt(DateTime.Now));
        img.SetPropertyItem(PiDtOrig);
        string ConvImgName = tgtdir.FullName + "\\" + imagefile.Name;
        img.Save(ConvImgName);

        //ExifTagCollection exif = new ExifTagCollection(img);
        //Debug.WriteLine(exif);

        Uri postUri = new Uri(PicasaQuery.CreatePicasaUri("hommel.peter@gmail.com", ac.Id));
        FileStream fileStream = imagefile.OpenRead();

        PicasaEntry newentry = (PicasaEntry)service.Insert(postUri, fileStream, "image/jpeg", ConvImgName);

        fileStream.Close();
        fileStream.Dispose();
    }
}

private PropertyItem NewPropertyItem()
{
    Type t = typeof (PropertyItem);
    ConstructorInfo ctor = t.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0];
    Object o = ctor.Invoke(new Object[] { });
    return (PropertyItem) o;
}

private int DateTimeToInt(DateTime theDate)
{
    return (int)(theDate.Date - new DateTime(1900, 1, 1)).TotalDays + 2;
}

// taken from https://codethis.wordpress.com/2008/11/ and modified for this example
static void DownloadAllPhotos(string DirectoryName, AtomEntryCollection photoList)
{
    DirectoryInfo dirInfo = Directory.CreateDirectory(DirectoryName);

    int photoNum = 1;
    foreach (AtomEntry photo in photoList)
    {
        HttpWebRequest photoRequest = WebRequest.Create(photo.Content.AbsoluteUri) as HttpWebRequest;
        HttpWebResponse photoResponse = photoRequest.GetResponse() as
           HttpWebResponse;

        BufferedStream bufferedStream = new BufferedStream(
           photoResponse.GetResponseStream(), 1024);
        BinaryReader reader = new BinaryReader(bufferedStream);

        FileStream imgOut = File.Create(dirInfo.FullName + "\\image" +
           photoNum++ + ".jpg");
        BinaryWriter writer = new BinaryWriter(imgOut);

        int bytesRead = 1;
        byte[] buffer = new byte[1024];
        while (bytesRead > 0)
        {
            bytesRead = reader.Read(buffer, 0, buffer.Length);
            writer.Write(buffer, 0, bytesRead);
        }
        reader.Close();
        reader.Dispose();
        writer.Flush();
        writer.Close();
        writer.Dispose();
    }
}

请原谅我发布了一些肮脏的代码,但是我很快就把它们组合在一起了。

您将在上面的代码中找到两行注释,它们使用了我不久前在网上找到的Exif类。由于有太多的代码在这里直接披露,我已经将它们上传到Pastebin:

http://pastebin.com/pkZMVZ9i

尽管它们只允许Exif阅读,但在试图为其他Exif标记找到合适的PropertyItem conents时,它们对您还是有帮助的。

因为我不知道这段代码是从哪里来的,所以如果他/她这样做了,请写一个评论,所以我也可以在这里添加这些信息。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29852580

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档