mirror of
https://github.com/lifegpc/pixiv_downloader.git
synced 2026-07-08 01:32:41 +08:00
add exif support
This commit is contained in:
49
src/data/data.rs
Normal file
49
src/data/data.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
use crate::pixiv_link::ToPixivID;
|
||||
use crate::pixiv_link::PixivID;
|
||||
use json::JsonValue;
|
||||
use std::convert::TryInto;
|
||||
|
||||
/// Pixiv's basic data
|
||||
pub struct PixivData {
|
||||
/// ID
|
||||
pub id: PixivID,
|
||||
/// The title
|
||||
pub title: Option<String>,
|
||||
/// The author
|
||||
pub author: Option<String>,
|
||||
}
|
||||
|
||||
impl PixivData {
|
||||
pub fn new<T: ToPixivID>(id: T) -> Option<Self> {
|
||||
let i = id.to_pixiv_id();
|
||||
if i.is_none() {
|
||||
return None;
|
||||
}
|
||||
Some(Self {
|
||||
id: i.unwrap(),
|
||||
title: None,
|
||||
author: None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Read data from JSON object.
|
||||
/// The object is from https://www.pixiv.net/artworks/<id>
|
||||
/// * `value` - The JSON object
|
||||
/// * `allow_overwrite` - Allow overwrite the data existing.
|
||||
pub fn from_web_page_data(&mut self, value: &JsonValue, allow_overwrite: bool) {
|
||||
let id: u64 = (&self.id).try_into().unwrap();
|
||||
let ids = format!("{}", id);
|
||||
if self.title.is_none() || allow_overwrite {
|
||||
let title = value["illust"][ids.as_str()]["illustTitle"].as_str();
|
||||
if title.is_some() {
|
||||
self.title = Some(String::from(title.unwrap()));
|
||||
}
|
||||
}
|
||||
if self.author.is_none() || allow_overwrite {
|
||||
let author = value["illust"][ids.as_str()]["userName"].as_str();
|
||||
if author.is_some() {
|
||||
self.author = Some(String::from(author.unwrap()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
60
src/data/exif.rs
Normal file
60
src/data/exif.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
use crate::data::data::PixivData;
|
||||
use crate::exif::ExifData;
|
||||
use crate::exif::ExifImage;
|
||||
use crate::exif::ExifKey;
|
||||
use crate::exif::ExifTypeID;
|
||||
use crate::exif::ExifValue;
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::OsStr;
|
||||
use utf16string::LittleEndian;
|
||||
use utf16string::WString;
|
||||
|
||||
fn add_image_id(data: &mut ExifData, d: &PixivData) -> Result<(), ()> {
|
||||
let link = d.id.to_link();
|
||||
let key = ExifKey::try_from("Exif.Image.ImageID")?;
|
||||
let mut value = ExifValue::try_from(ExifTypeID::AsciiString)?;
|
||||
value.read(link.as_bytes(), None)?;
|
||||
data.add(&key, &value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_image_title(data: &mut ExifData, d: &PixivData) -> Result<(), ()> {
|
||||
if d.title.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
let title = d.title.as_ref().unwrap();
|
||||
let key = ExifKey::try_from("Exif.Image.ImageDescription")?;
|
||||
let mut value = ExifValue::try_from(ExifTypeID::AsciiString)?;
|
||||
value.read(title.as_bytes(), None)?;
|
||||
data.add(&key, &value)?;
|
||||
let key = ExifKey::try_from("Exif.Image.XPTitle")?;
|
||||
let mut value = ExifValue::try_from(ExifTypeID::BYTE)?;
|
||||
let s: WString<LittleEndian> = WString::from(title);
|
||||
value.read(s.as_bytes(), None)?;
|
||||
data.add(&key, &value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_image_author(data: &mut ExifData, d: &PixivData) -> Result<(), ()> {
|
||||
if d.author.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
let author = d.author.as_ref().unwrap();
|
||||
let key = ExifKey::try_from("Exif.Image.XPAuthor")?;
|
||||
let mut value = ExifValue::try_from(ExifTypeID::BYTE)?;
|
||||
let s: WString<LittleEndian> = WString::from(author);
|
||||
value.read(s.as_bytes(), None)?;
|
||||
data.add(&key, &value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_exifdata_to_image<S: AsRef<OsStr> + ?Sized>(file_name: &S, data: &PixivData) -> Result<(), ()> {
|
||||
let mut f = ExifImage::new(file_name)?;
|
||||
let mut d = ExifData::new()?;
|
||||
add_image_id(&mut d, data)?;
|
||||
add_image_title(&mut d, data)?;
|
||||
add_image_author(&mut d, data)?;
|
||||
f.set_exif_data(&d)?;
|
||||
f.write_metadata()?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
use crate::data::data::PixivData;
|
||||
use crate::gettext;
|
||||
use crate::pixiv_link::PixivID;
|
||||
use crate::pixiv_link::ToPixivID;
|
||||
use json::JsonValue;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::From;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs::File;
|
||||
use std::fs::remove_file;
|
||||
@@ -20,6 +22,7 @@ pub struct JSONDataFile {
|
||||
}
|
||||
|
||||
impl JSONDataFile {
|
||||
#[allow(dead_code)]
|
||||
pub fn new<T: ToPixivID>(id: T) -> Option<Self> {
|
||||
let i = id.to_pixiv_id();
|
||||
if i.is_none() {
|
||||
@@ -31,6 +34,16 @@ impl JSONDataFile {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add<T: ToJson>(&mut self, key: &str, value: T) -> Result<(), ()> {
|
||||
let v = value.to_json();
|
||||
if v.is_some() {
|
||||
self.maps.insert(String::from(key), v.unwrap());
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save<S: AsRef<OsStr> + ?Sized>(&self, path: &S) -> bool {
|
||||
let p = Path::new(path);
|
||||
if p.exists() {
|
||||
@@ -60,6 +73,28 @@ impl JSONDataFile {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PixivData> for JSONDataFile {
|
||||
fn from(p: PixivData) -> Self {
|
||||
JSONDataFile::from(&p)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&PixivData> for JSONDataFile {
|
||||
fn from(p: &PixivData) -> Self {
|
||||
let mut f = Self {
|
||||
id: p.id.clone(),
|
||||
maps: HashMap::new(),
|
||||
};
|
||||
if p.title.is_some() {
|
||||
f.add("title", p.title.as_ref().unwrap()).unwrap();
|
||||
}
|
||||
if p.author.is_some() {
|
||||
f.add("author", p.author.as_ref().unwrap()).unwrap();
|
||||
}
|
||||
f
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for JSONDataFile {
|
||||
fn to_json(&self) -> Option<JsonValue> {
|
||||
let mut value = json::object! {};
|
||||
@@ -74,3 +109,15 @@ impl ToJson for JSONDataFile {
|
||||
Some(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for &str {
|
||||
fn to_json(&self) -> Option<JsonValue> {
|
||||
Some(JsonValue::String(String::from(*self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for &String {
|
||||
fn to_json(&self) -> Option<JsonValue> {
|
||||
Some(JsonValue::String((*self).to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
pub mod data;
|
||||
#[cfg(feature = "exif")]
|
||||
pub mod exif;
|
||||
pub mod json;
|
||||
|
||||
Reference in New Issue
Block a user