使用Picasa,我从我的Google+相册中检索一张照片,并试图更改时间戳(我的手机上的时间不对,所以试图修复它):
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)。
我错过了一些简单的东西吗?还有其他方法来完成同样的事情吗?我也会满足于改变照片的时区。
发布于 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条目的日期,并将它们缓存在一个列表中,以便在下载的图像上重新应用它们),但它确实涵盖了棘手的部分。
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时,它们对您还是有帮助的。
因为我不知道这段代码是从哪里来的,所以如果他/她这样做了,请写一个评论,所以我也可以在这里添加这些信息。
https://stackoverflow.com/questions/29852580
复制相似问题