//sort pic files from picture_files (by date) and for each on initialise a PicData struct which will contain the name FileInfo and a blank texture (to be loaded on demand later)
        private void prepare_pics()
        {
            List <FileInfo> files = picture_files();

            FileInfo[] sorted_files = files.ToArray();
            Array.Sort(sorted_files, delegate(FileInfo f1, FileInfo f2){
                return(f2.CreationTime.CompareTo(f1.CreationTime));
            });

            pictures.Clear();
            loaded_pics = new bool[files.Count];
            Texture2D placeholder = (Texture2D)StyleSheet.assets["image_placeholder"];

            scroll_pos.y = 0;
            int i = 0;

            foreach (FileInfo file in sorted_files)
            {
                //add a PicData struct for each picture into pictures (struct defines name, file, texture and id)
                //id is used as index in loaded_pics, used for tracking which have had textures loaded
                PicData data = new PicData();
                data.initialize(file.Name, file, Instantiate(placeholder), i);
                pictures.Add(data);
                i++;
            }
            file_count = files.Count;
            group_pics(); //divide pictures into "rows" of x pics_per_row
        }
        private void toggle_large_viewer()
        {
            if (large_viewer)
            {
                GameObject.Destroy(large_viewer);
            }
            else
            {
                float viewer_width = 500f;
                large_viewer = show_dialog(d => {
                    PicData pic = KerbalX.image_selector.pictures[KerbalX.image_selector.large_viewer_index];
                    v_section(viewer_width, outer => {
                        section(w2 => {
                            if (GUILayout.Button("<", "button.large.bold", width(viewer_width * 0.1f)))
                            {
                                KerbalX.image_selector.large_viewer_index--;
                                if (KerbalX.image_selector.large_viewer_index < 0)
                                {
                                    KerbalX.image_selector.large_viewer_index = 0;
                                }
                            }
                            GUILayout.FlexibleSpace();
                            if (GUILayout.Button("Add Pic", "button.large.bold", width(viewer_width * 0.6f)))
                            {
                                toggle_pic(pic);
                            }
                            GUILayout.FlexibleSpace();
                            if (GUILayout.Button(">", "button.large.bold", width(viewer_width * 0.1f)))
                            {
                                KerbalX.image_selector.large_viewer_index++;
                                if (KerbalX.image_selector.large_viewer_index > KerbalX.image_selector.pictures.Count - 1)
                                {
                                    KerbalX.image_selector.large_viewer_index = KerbalX.image_selector.pictures.Count - 1;
                                }
                            }
                            GUILayout.FlexibleSpace();
                            if (GUILayout.Button("X", "button.large.bold", width(viewer_width * 0.1f)))
                            {
                                close_dialog();
                            }
                        });

                        if (KerbalX.image_selector.loaded_pics[pic.id] != true)
                        {
                            KerbalX.log("loading pic");
                            KerbalX.image_selector.loaded_pics[pic.id] = true;
                            StartCoroutine(KerbalX.image_selector.load_image(pic.file.FullName, pic.texture));
                        }
                        GUILayout.Label("Picture " + (large_viewer_index + 1) + "/" + pictures.Count().ToString());
                        section(viewer_width, w2 => {
                            float h = pic.texture.height / (new [] { pic.texture.width, w2 }.Max() / w2);
                            GUILayout.Label(pic.texture, width(viewer_width), height(h));
                            d.window_pos.height = h + 110;
                        });
                    });
                });
                large_viewer.window_pos   = new Rect(this.window_pos.x + this.window_pos.width, KerbalX.upload_gui.window_pos.y + KerbalX.upload_gui.window_pos.height, viewer_width, 20);
                large_viewer.window_title = "Image Viewer";
            }
        }
        //Called from the ImageSelector to add a picture (as PicData) to the list of pictures to upload.
        internal void add_picture(PicData picture)
        {
            errors.Clear();
            int pic_count = 0;

            foreach (PicData pic in pictures)        //count up how many pictures with file data have been added
            {
                if (pic.file != null)
                {
                    pic_count++;
                }
            }
            if (pic_count < max_pics || picture.file == null)    //if the count is under max_pics or the pic doesn't have a file (ie it's url) then add it.
            {
                pictures.Add(picture);
            }
            else
            {
                errors = new List <string>()                     //Otherwise show error message
                {
                    "You can only add " + max_pics + " pictures for upload, (bandwidth limitations, sorry!)",
                    "You can add as many image urls as you like though."
                };
            }
        }
        //removes a selected picture from pictures. Does this by creating a new List<PicData> and adding all other pics into it
        //because using pictures.Remove () causes an error to be shown in the console, (about breaking enumeration).
        internal void remove_picture(PicData picture)
        {
            List <PicData> new_list = new List <PicData>();

            foreach (PicData pic in pictures)
            {
                if (!pic.file.FullName.Equals(picture.file.FullName))
                {
                    new_list.Add(pic);
                }
            }
            pictures = new_list;
            clear_errors();
        }
 //Takes a PicData object and reads the image bytes.
 //If the image is already a jpg then it just returns the bytes, otherwise it is converted into a jpg first
 private byte[] read_as_jpg(PicData pic)
 {
     byte[] original_image = File.ReadAllBytes(pic.file.FullName);
     if (pic.file.Extension.ToLower() == ".jpg")
     {
         return(original_image);
     }
     else
     {
         KerbalX.log("compressing: " + pic.file.Name);
         Texture2D converter = new Texture2D(2, 2);
         converter.LoadImage(original_image);
         return(converter.EncodeToJPG());
     }
 }
        //adds pic to list of selected pics on UploadInterface
        private void toggle_pic(PicData pic)
        {
            List <string> files = new List <string>();

            foreach (PicData p in KerbalX.upload_gui.pictures)
            {
                files.Add(p.file.FullName);
            }

            if (files.Contains(pic.file.FullName))
            {
                KerbalX.upload_gui.remove_picture(pic);
            }
            else
            {
                KerbalX.upload_gui.add_picture(pic);
            }
        }