def run_preprocess(proj: dict):
    """
    Perform the complete raw image preprocess task. This includes cropping and
    resizing the images, and reading and applying metadata to exif from a 
    separate file (eg metadata.csv). All processed images will be converted to
    jpeg and written to the 'processed_img' folder. The original raw images will
    not be modified.
    """
    paths = proj["paths"]
    print(f"using metadata at {paths['metadata']}")
    meta = load_metadata(paths["metadata"])  # assumes .tif extension

    for row in meta.to_dict(orient="records"):
        raw = Path(paths["raw_img"], row["file"])
        if not raw.exists():
            continue
        print(f"updating {raw}")
        pre = proj["image_preprocess"]
        # crop and resize
        modified = crop(str(raw), amount=pre["crop"])
        modified = resize(modified, proportion=pre["resize"])
        # convert to jpeg, save to new path
        dst_path = Path(paths["processed_img"], raw.name)
        new_name = convert_to_jpg(modified, dest_filepath=str(
            dst_path), jpgquality=pre["jpeg_quality"])
        # write metadata
        update_exif(str(new_name), row)
        print(f"   wrote {new_name}")