from PIL import Image, ImageDraw, ImageFont, ImageOps, ExifTags
import os
import piexif
from datetime import datetime

# For generating watermarks

def correct_orientation(image):
    """
    Correct the orientation of an image using its EXIF data.
    """
    for orientation in ExifTags.TAGS.keys():
        if ExifTags.TAGS[orientation] == 'Orientation':
            break

    exif = image._getexif()

    if exif is not None and orientation in exif:
        if exif[orientation] == 3:
            image = image.rotate(180, expand=True)
        elif exif[orientation] == 6:
            image = image.rotate(270, expand=True)
        elif exif[orientation] == 8:
            image = image.rotate(90, expand=True)

    return image

def add_watermark(image_path, text, save_as=None):
    original = Image.open(image_path)
    original = correct_orientation(original)
    txt = Image.new('RGBA', original.size, (255,255,255,0))
    draw = ImageDraw.Draw(txt)

    # Scale the font size based on the image size
    base_width = 800  # Change this to your preferred base width
    font_size = int((min(original.size) / base_width) * 20)
    font_size = max(font_size, 10)  # Set a minimum font size if needed

    font = ImageFont.truetype("arial.ttf", font_size)
    text_x = original.width // 2
    text_y = original.height - 30

    text_position = (text_x, text_y)
    draw.text(text_position, text, fill=(255,255,255,128), font=font, anchor="mm")
    watermarked = Image.alpha_composite(original.convert('RGBA'), txt).convert('RGB')
    
    if save_as:
        watermarked.save(save_as, 'JPEG')
    else:
        watermarked.save(image_path, 'JPEG')

def get_camera_info(exif_data):
    camera_info = {}
    # Only add EXIF data to the dictionary if it is not the default 'Unknown'
    if piexif.ImageIFD.Model in exif_data['0th']:
        camera_info['model'] = exif_data['0th'][piexif.ImageIFD.Model].decode('utf-8')

    if piexif.ExifIFD.ISOSpeedRatings in exif_data['Exif']:
        camera_info['iso'] = str(exif_data['Exif'][piexif.ExifIFD.ISOSpeedRatings])

    if piexif.ExifIFD.FNumber in exif_data['Exif']:
        f_number = exif_data['Exif'][piexif.ExifIFD.FNumber]
        camera_info['fstop'] = f"{f_number[0] / f_number[1]}"

    if piexif.ExifIFD.ExposureTime in exif_data['Exif']:
        exposure_time = exif_data['Exif'][piexif.ExifIFD.ExposureTime]
        camera_info['shutterspeed'] = f"{exposure_time[0]}/{exposure_time[1]} sec"

    if piexif.ExifIFD.DateTimeOriginal in exif_data['Exif']:
        try:
            camera_info['datetime'] = exif_data['Exif'][piexif.ExifIFD.DateTimeOriginal].decode('utf-8')
            camera_info['year'] = datetime.strptime(camera_info['datetime'], '%Y:%m:%d %H:%M:%S').year
        except:
            pass

    return camera_info

def process_images(source_folder_path):
    target_folder_path = '../images/watermark'
    os.makedirs(target_folder_path, exist_ok=True)

    for filename in os.listdir(source_folder_path):
        if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
            image_path = os.path.join(source_folder_path, filename)
            exif_data = piexif.load(image_path)
            camera_info = get_camera_info(exif_data)

            # Construct watermark text
            watermark_elements = [str(camera_info.get('year', ''))]  # Start with the year
            if 'model' in camera_info:
                watermark_elements.append(camera_info['model'])
            if 'iso' in camera_info:
                watermark_elements.append(f"ISO {camera_info['iso']}")
            if 'shutterspeed' in camera_info:
                watermark_elements.append(camera_info['shutterspeed'])

            # Remove empty strings and join with ', '
            watermark_text = "(c) Charles Lehnen " + ', '.join(filter(None, watermark_elements))

            save_as_path = os.path.join(target_folder_path, f"{os.path.splitext(filename)[0]}_watermarked.jpg")
            add_watermark(image_path, watermark_text, save_as=save_as_path)

process_images('../images/no_watermark')
import os
from PIL import Image

# For generating list of files to copy/paste into photos.qmd

# Directory where the images are stored
image_folder = '../images/watermark/'
# Prefix for the path to use in the markdown output
output_path_prefix = 'images/watermark/'

# Categorize images into portrait and landscape
landscape_images = []
portrait_images = []

for filename in os.listdir(image_folder):
    if filename.lower().endswith('.jpg'):
        with Image.open(os.path.join(image_folder, filename)) as img:
            if img.width > img.height:
                landscape_images.append(filename)
            else:
                portrait_images.append(filename)

# Combine the lists, placing landscape images first
images = landscape_images + portrait_images

# Generate markdown output
markdown_output = "::: {layout=\"[[1, 1], [1, 1]]\"}\n"
for image in images:
    image_path = os.path.join(output_path_prefix, image).replace("\\", "/")
    markdown_output += f"![]({image_path}){{group=\"my-gallery\"}}\n\n"
markdown_output += ":::"

print(markdown_output)


::: {layout="[[1, 1], [1, 1]]"}
![](images/watermark/IMG_3895_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_4626_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_4660_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_4667_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_4801_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_4808_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_4825_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_4844_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_5437_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_5444_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_5670_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_5868_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_7778_watermarked.jpg){group="my-gallery"}

![](images/watermark/PANO0009_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2662_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2666_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2674_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2703_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2735_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2740_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2743_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2777_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2783_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2784_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2796_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2810_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2821_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2825_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2842_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2909_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2914_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2946_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3004_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3016_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3025_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3044_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3079_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3089_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3095_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3163_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3183_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3195_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3208_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3219_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3224_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3232_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3254_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3255_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3258_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3263_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3312_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3322_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3324_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3330_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3349_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3354_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3358_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3369_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3378_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3414_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3433_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3444_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3451_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3458_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3459_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3467_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3476_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3480_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3482_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3484_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3485_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3490_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3494_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3495_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3503_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3506_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3521_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3525_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3542_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3544_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3552_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3558_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3586_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3590_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3594_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3608_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3637_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3666_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3675_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3685_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3690_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3692_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3726_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3737_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3759_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3823_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3879_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3886_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3889_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3938_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3941_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC4090_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC4093_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC4166_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC4169_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC4197_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_0110_watermarked.jpg){group="my-gallery"}

![](images/watermark/IMG_5902_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2707_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC2712_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3100_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3246_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3247_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3257_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3371_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3528_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC3587_watermarked.jpg){group="my-gallery"}

![](images/watermark/_DSC4231_watermarked.jpg){group="my-gallery"}

:::

import pandas as pd

try:
    projects_df = pd.read_csv('../documents/projects.csv')
except UnicodeDecodeError:
    # If a UnicodeDecodeError is encountered, try reading with 'latin1' encoding
    projects_df = pd.read_csv('../documents/projects.csv', encoding='latin1')

# Generate the server function script for the Shiny app using the DataFrame

# Template for a single marker in the server function
marker_template = """
      addMarkers(
        lng = {lng}, 
        lat = {lat}, 
        popup = "{popup}", 
        icon = {icon_name}Icon
      ) %>%
"""

# Initialize the base of the server function string
server_function_script = "server <- function(input, output, session) {\n"

# Generate the makeIcon function calls for each unique icon
icon_template = """
{icon_name}Icon <- makeIcon(
  iconUrl = "https://raw.githubusercontent.com/CharlesLehnen/portfolio/main/images/icons/{icon_file}",
  iconWidth = {icon_width}, iconHeight = {icon_height},
  iconAnchorX = 25, iconAnchorY = 50
)
"""

# Assuming icons are 50x50 by default, you can add conditional logic for different sizes if necessary
for icon_file in projects_df['Icon'].unique():
    icon_name = icon_file.split('.')[0]  # Assuming the file name before the extension is the icon name
    server_function_script += icon_template.format(
        icon_name=icon_name,
        icon_file=icon_file,
        icon_width=50,  # Default width
        icon_height=50  # Default height
    )

# Add the leaflet rendering function call
server_function_script += "  output$map <- renderLeaflet({\n    leaflet() %>%\n      addProviderTiles(\"Esri.NatGeoWorldMap\") %>%"  # Added %>%

# Add markers for each project
for _, row in projects_df.iterrows():
    icon_name = row['Icon'].split('.')[0]
    server_function_script += marker_template.format(
        lng=row['Longitude'],
        lat=row['Latitude'],
        popup=row['Description'].replace('"', '\\"'),  # Escape double quotes in the description
        icon_name=icon_name
    )

# Remove the extra %>% from the last marker_template
server_function_script = server_function_script.rstrip("%>\n")

# Close the leaflet render function and the server function
server_function_script += "\n   })     \n}"

# Output the generated script for copy/paste
print(server_function_script)
server <- function(input, output, session) {

COTOIcon <- makeIcon(
  iconUrl = "https://raw.githubusercontent.com/CharlesLehnen/portfolio/main/images/icons/COTO.png",
  iconWidth = 50, iconHeight = 50,
  iconAnchorX = 25, iconAnchorY = 50
)

blandingsIcon <- makeIcon(
  iconUrl = "https://raw.githubusercontent.com/CharlesLehnen/portfolio/main/images/icons/blandings.png",
  iconWidth = 50, iconHeight = 50,
  iconAnchorX = 25, iconAnchorY = 50
)

GalapTortIcon <- makeIcon(
  iconUrl = "https://raw.githubusercontent.com/CharlesLehnen/portfolio/main/images/icons/GalapTort.png",
  iconWidth = 50, iconHeight = 50,
  iconAnchorX = 25, iconAnchorY = 50
)

flyIcon <- makeIcon(
  iconUrl = "https://raw.githubusercontent.com/CharlesLehnen/portfolio/main/images/icons/fly.png",
  iconWidth = 50, iconHeight = 50,
  iconAnchorX = 25, iconAnchorY = 50
)

arthropodsIcon <- makeIcon(
  iconUrl = "https://raw.githubusercontent.com/CharlesLehnen/portfolio/main/images/icons/arthropods.png",
  iconWidth = 50, iconHeight = 50,
  iconAnchorX = 25, iconAnchorY = 50
)

elmIcon <- makeIcon(
  iconUrl = "https://raw.githubusercontent.com/CharlesLehnen/portfolio/main/images/icons/elm.png",
  iconWidth = 50, iconHeight = 50,
  iconAnchorX = 25, iconAnchorY = 50
)

JEPIcon <- makeIcon(
  iconUrl = "https://raw.githubusercontent.com/CharlesLehnen/portfolio/main/images/icons/JEP.png",
  iconWidth = 50, iconHeight = 50,
  iconAnchorX = 25, iconAnchorY = 50
)

mojaveIcon <- makeIcon(
  iconUrl = "https://raw.githubusercontent.com/CharlesLehnen/portfolio/main/images/icons/mojave.png",
  iconWidth = 50, iconHeight = 50,
  iconAnchorX = 25, iconAnchorY = 50
)
  output$map <- renderLeaflet({
    leaflet() %>%
      addProviderTiles("Esri.NatGeoWorldMap") %>%
      addMarkers(
        lng = -107.303802, 
        lat = 33.12007, 
        popup = "We evaluated the ecological significance of abandoned mines in New Mexico as habitats for bats to recommend them for closure or federal protection. This included the collection of habitat, LiDAR imagery, and disease metrics. Field techniques involved off-roading, hiking, and ropework, with additional avian surveys at mine closures.", 
        icon = COTOIcon
      ) %>%

      addMarkers(
        lng = -92.161371, 
        lat = 43.880424, 
        popup = "I independently monitored nesting sites of the endangered Blanding's Turtles at Murphy-Hanrehan Park, assisting with road crossings, health observations, photographic documentation, and egg translocation relocation since Blanding's exhibit natal homing", 
        icon = blandingsIcon
      ) %>%

      addMarkers(
        lng =  -95.810074, 
        lat = -0.344018, 
        popup = "My doctoral research, in collaboration with the Galapagos Conservancy and Iniciativa Galápagos, explores the impact of introducing Española Giant Tortoises to Santa Fe Island to restore its ecosystem. Using drone imagery, isotope analysis, and camera traps, this project aims to take a mult-faceted approach to quantify the cascading ecological effects on this introduction.", 
        icon = GalapTortIcon
      ) %>%

      addMarkers(
        lng = -88.352343, 
        lat = -0.382326, 
        popup = "I spearheaded a 4-year comprehensive study on the natural history across five Galapagos islands, significantly contributing to the Philornis Working Group's efforts against the invasive Philornis downsi fly. This work, pivotal for understanding the ecology of Galapagos Diptera, informed P. downsi control strategies and non-target biocontrol testing. Previously, the reproductive ecology of Galapagos Diptera were largely unknown.", 
        icon = flyIcon
      ) %>%

      addMarkers(
        lng = -120.89189, 
        lat = 37.430757, 
        popup = "In collaboration with the  Los Angeles Natural History Museum (NHM) and Cal State, we examined the impact of various factors on arthropod diversity across Los Angeles, analyzing topographical, abiotic, and anthropogenic drivers. We explored the complex responses within and between six arthropod groups, revealing high regional diversity and variable spatial composition. This research underscores the nuanced relationship between urban development and biodiversity, contributing valuable insights for urban ecology and land management practices.", 
        icon = arthropodsIcon
      ) %>%

      addMarkers(
        lng = -95.146029, 
        lat = 48.112037, 
        popup = "I assisted in research on Dutch elm disease, nursery techniques, and urban forestry, gaining expertise in plant propagation and tree care, from seed to adult tree. Collaborating closely with Saint Paul Parks and Recreation foresters, I collected seeds and collected data across study sites. I managed 8 acres of nursery and experimental plots.", 
        icon = elmIcon
      ) %>%

      addMarkers(
        lng = -116.4529, 
        lat = 33.978195, 
        popup = "I led the WonderKids virtual afterschool program, creating and implementing a semester long STEM curriculum for K-5 students that highlights diversity in science with guest speakers and virtual lab tours. This approach aimed to inspire students through hands-on experiments and exposure to a variety of specific scientific careers, emphasizing inclusivity in science education.", 
        icon = JEPIcon
      ) %>%

      addMarkers(
        lng = -112.123846, 
        lat = 40.359941, 
        popup = "For USFWS, I collected georeferenced biometric data on vulnerable Mojave desert tortoise populations across Nevada using line-distance sampling, adhering to sterile techniques. This included assessing body condition scores, checking for Mycoplasma infection, and taking morphological measurements, with strict protocols to prevent hypothermia, dehydration, and disease spread among tortoises.", 
        icon = mojaveIcon
      ) 
   })     
}