miałem iść w swoim problemem sam, więc pozwól mi podzielić się moją ocenę sytuacji tutaj:
Google wydaje się mieć wyświetloną meta informacje z tagów EXIF obrazu. Mimo że ustawienie tagów Exif wydaje się możliwe, patrząc na API .net (nawet dekompilowałem zespoły Google, aby upewnić się, że wszystko jest w porządku), Google po prostu nie umieszcza ich ponownie w obrazie podczas wydawania aktualizacji.
Moje podejście polega więc na pobieraniu wszystkich zdjęć, zmianie ich danych Exif i ponownym ich przesłaniu (jak sugeruje nemesv). Niestety Google usuwa wszystkie pobrane pliki ich tagów Exif (thx big G!) I zastępuje je sztucznymi (np. Nazwa aplikacji "Google") i wartościami pustymi (czas utworzenia = null). Generowanie Exif info od zera w .net jest w najlepszym wypadku hackowate (trzeba przymusowo konstruować wystąpienia System.Drawing.Imaging.PropertyItem [ma wewnętrzny konstruktor, można to zrobić] i poprawnie je sparametryzować). Ale, jak już zrobiłem coś takiego (wziąłem Exif info z istniejącego obrazu, zregenerowanego obrazu i ponownie dodałem Exif do nowego zdjęcia) w module obrazowania aplikacji w mojej głównej pracy, uważam, że to podejście jest wykonalne.
Oto kilka dowodów kodu idei dla ciebie. Nie idzie do końca (kompletne rozwiązanie powinno odczytywać daty istniejących wpisów Picasa i umieszczać je w pamięci podręcznej na liście, aby ponownie je stosować na pobranych obrazach), ale obejmuje ono trudne części.
private void button1_Click(object sender, EventArgs e)
{
var service = new PicasaService("exampleCo-exampleApp-1");
service.setUserCredentials("me.mys[email protected]", "-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("[email protected]", 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();
}
}
Proszę o cierpliwość za opublikowanie nieco zabrudzonego kodu, ale bardzo szybko to wymyśliłem.
Znajdziesz dwa skomentowane linie w powyższym kodzie, które używają niektórych klas Exif, które znalazłem gdzieś w sieci jakiś czas temu. Gdy gdzie zbyt dużo kodu ujawniają tu bezpośrednio, mam przesłanych im Pastebin:
http://pastebin.com/pkZMVZ9i
Choć pozwalają one tylko do odczytu Exif, ale mimo to może być przydatne dla Ciebie, gdy próbuje znaleźć właściwą PropertyItem koncentruje się na innych znacznikach Exif.
Ponieważ nie wiem, skąd wziął się ten kod, proszę, proszę, jeśli ktoś napisze komentarz, to ja też mogę dodać tę informację.
Nie jestem ekspertem od Google Api, ale grałem z nim trochę i wygląda na to, że nie jest to udokumentowane, ale nie można zaktualizować wszystkich pól zdjęcia. Na przykład nie można zmienić informacji o exif, ani rozmiaru zdjęcia, długości ani ** znacznika czasu **. Interfejs API klienta .NET (także Java) obsługuje zmianę ** znacznika czasu **. na powierzchni, ale serwer odmówi jej aktualizacji.Dlatego te właściwości można ustawić tylko raz podczas tworzenia zdjęcia, dlatego obejściem byłoby programowe pobieranie, usuwanie i ponowne tworzenie zdjęć z poprawnym znacznikiem czasu. – nemesv
@nemesv Wszystko co mówisz ma sens. Możesz jednak przejść do szczegółów zdjęcia w witrynie Zdjęcia Google+ i łatwo zmienić sygnaturę czasową, strefę czasową i całą masę innych rzeczy. Jest to możliwe. Tylko pytanie, jak. – AngryHacker
Tak, jeśli zaznaczysz kartę sieci w konsoli przeglądarki, ** Google + zdjęcia nie używają interfejsu Picasa Web API **, ale innego (prawdopodobnie wewnętrznego) interfejsu API, dlatego właśnie możesz zmienić sygnaturę czasową ... – nemesv