// Given an artwork, construct a ready-to-append XmlElement (including assets, etc). // This method performs no validation on the artwork, so be sure to validate before calling. public static XmlElement XmlElementFromValidArtwork(XmlDocument doc, artwork aw) { XmlElement el = doc.CreateElement("Image"); el.SetAttribute("path", "" + aw.uniqueName); el.SetAttribute("title", "" + aw.title); el.SetAttribute("year", "" + aw.year); el.SetAttribute("artist", "" + aw.artist); el.SetAttribute("medium", "" + aw.medium); // TODO: Do we want this? // newEntry.SetAttribute("description", "" + aw.); // If there are keywords, add them. if (aw.keywords.Count > 0) { XmlElement keywords = doc.CreateElement("Keywords"); foreach (string keyword in aw.keywords) { XmlElement keyword_val = doc.CreateElement("Keyword"); keyword_val.SetAttribute("Value", "" + keyword); keywords.AppendChild(keyword_val); } el.AppendChild(keywords); } // If there are metadata assets, add them. if (aw.validatedAssets.Count > 0) { XmlElement metadata_element = doc.CreateElement("Metadata"); XmlElement group_element = doc.CreateElement("Group"); group_element.SetAttribute("name", "A"); foreach (asset ass in aw.validatedAssets) { XmlElement item_element = doc.CreateElement("Item"); item_element.SetAttribute("Filename", ass.uniqueName); item_element.SetAttribute("Name", ass.name); item_element.SetAttribute("Description", ass.description); // TODO: Implement Type = "Web" item_element.SetAttribute("Type", "Image"); group_element.AppendChild(item_element); } metadata_element.AppendChild(group_element); el.AppendChild(metadata_element); } return el; }
// Attempts to validate the artwork, throwing an exception at the first invalid occurence. // This doesn't attempt to actually load images for artworks or assets: that check is performed // later implicitly, when the DeepZoom images/thumbnails are created. // An artwork is invalid if: // - Its path is not an existing image file. // - Its title is missing. // - Its year is not a valid number between -9999 and 9999 public static void validateArtwork(artwork aw) { // Convert the image path to an absolute path to eliminate ambiguities. // If the path is relative, it should be relative to the CSV directory. if (!Path.IsPathRooted(aw.path)) { aw.path = Path.GetDirectoryName(inputCSVPath) + "\\" + aw.path; } if (!Helpers.staticIsImageFile(aw.path) || !File.Exists(aw.path)) throw new InvalidCSVArtworkException("Artwork path is not an existing image file."); if (String.IsNullOrWhiteSpace(aw.title)) throw new InvalidCSVArtworkException("Artwork title missing."); if (aw.year < -9999 || aw.year > 9999) throw new InvalidCSVArtworkException("Artwork year must be a valid number from -9999 to 9999."); for (int i = 0; i < aw.assets.Count; i++) { asset ass = aw.assets[i]; try { validateAsset(ass); } catch (Exception e) { csvLog("Error validating asset at: " + ass.path + ".\nMessage: " + e.Message); } } // Also do things that are handled in AddNewImageControl.Browse_Click(), namely: // - Generate a unique name for this instance of this file aw.uniqueName = generateUniqueName(aw.path, "Data/Images/"); }
// Parses a CSV file into a list of artwork structs. public static List<artwork> parseCSV(string path) { List<artwork> artworks = new List<artwork>(); using (CsvReader csv = new CsvReader(new StreamReader(path), true)) { // The CSV exported from excel will generally have rows of identical lengths, even though our rows in the excel // document will be of variable length. Thus there will be a large number of empty cells. int fieldCount = csv.FieldCount; while (csv.ReadNextRecord()) { fieldCount = csv.FieldCount; artwork aw = new artwork(); // Parse the artwork. aw.path = csv[IMAGE_PATH_INDEX]; aw.thumbPath = csv[IMAGE_THUMB_INDEX]; aw.title = csv[TITLE_INDEX]; try { aw.year = Convert.ToInt32(csv[YEAR_INDEX]); } catch (Exception e) { throw new InvalidCSVArtworkException("Year for artwork at " + aw.path + " is not a number."); } aw.artist = csv[ARTIST_INDEX]; aw.medium = csv[MEDIUM_INDEX]; aw.keywords = parseKeywords(csv[KEYWORDS_INDEX]); aw.assets = new List<asset>(); for (int i = FIRST_ASSET_INDEX; i < fieldCount; i++) { try { if (!String.IsNullOrWhiteSpace(csv[i])) aw.assets.Add(parseAsset(csv[i])); } catch (Exception e) { throw new InvalidCSVArtworkException("Error parsing asset " + (i - FIRST_ASSET_INDEX + 1) + " for artwork at " + aw.path + "." + Environment.NewLine + " Message: " + e.Message); } } artworks.Add(aw); } } return artworks; }
// Saves both thumbnails for an artwork. public static void saveThumbs(artwork aw) { String dataDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\Data\\"; string thumbPath = dataDir + "Images/Thumbnail/" + aw.uniqueName; string imgPath = dataDir + "Images/" + aw.uniqueName; if (aw.path.Equals(thumbPath)) { throw new InvalidCSVArtworkException("Artwork thumbnails already exist."); } // If a thumbnail path is provided, attempt to use it. // If this fails, we cascade to the general case rather than throwing an exception. if (!String.IsNullOrWhiteSpace(aw.thumbPath)) { string customThumbPath = aw.thumbPath; // Convert to absolute path. If relative, it's relative to the CSV directory. if (!Path.IsPathRooted(customThumbPath)) { customThumbPath = Path.GetDirectoryName(inputCSVPath) + "\\" + customThumbPath; } try { File.Delete(thumbPath); File.Delete(imgPath); System.Drawing.Image img = Helpers.getThumbnail(customThumbPath, 800); img.Save(thumbPath); img.Save(imgPath); img.Dispose(); return; } catch (Exception e) { csvLog("Error in loading custom thumbnail." + Environment.NewLine + " Message: " + e.Message + Environment.NewLine + "Attempting to automatically generate a thumbnail from the image."); } } // The general case. try { File.Delete(thumbPath); File.Delete(imgPath); // TODO: Get thumbnail from thumbnail image instead, if it exists! System.Drawing.Image img = Helpers.getThumbnail(aw.path, 800); img.Save(thumbPath); img.Save(imgPath); img.Dispose(); } catch (Exception e) { throw new InvalidCSVArtworkException("Error creating thumbnail for artwork. Message: " + e.Message); } }
// Creates the DeepZoom images. // Should throw an exception if the DeepZoom creation fails (for instance if the image is broken) public static void createDeepZoomImages(artwork aw) { string imagePath = aw.path; string imageName = aw.uniqueName; string destFolderPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\Data\\Images\\DeepZoom"; ImageCreator ic = new ImageCreator(); ic.TileFormat = ImageFormat.Jpg; ic.TileOverlap = 1; ic.TileSize = 256; ic.ImageQuality = 0.92; ic.UseOptimizations = true; Directory.CreateDirectory(destFolderPath + "\\" + imageName); string target = destFolderPath + "\\" + imageName + "\\dz.xml"; ic.Create(imagePath, target); ic = null; System.GC.Collect(); }