[
  {
    "path": ".gitignore",
    "content": "venv/\nvenv\n__pycache__/\ncolorpalette/__pycache__\n.idea\n*.pyc\n.vscode/\n\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 Mayank Nader\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Procfile",
    "content": "web: gunicorn colorpalette:app\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <img height=200 src=\"https://github.com/makkoncept/colorpalette/blob/master/.readme_assets/color-palette.png?raw=true\"><br>\n  <h1 align=\"center\">ColorPalette</h2>\n  <p align=\"center\">A simple web app to extract dominant colors from an image.<p>\n  <p align=\"center\">\n    <a href=\"https://github.com/makkoncept/colorpalette/blob/master/LICENSE\">\n      <img alt=\"MIT License\" src=\"https://img.shields.io/github/license/makkoncept/colorpalette.svg?color=brightgreen\" />\n    </a>\n    <a href=\"https://github.com/makkoncept/colorpalette/pulls\">\n\t    <img src=\"https://img.shields.io/badge/PRs-welcome-brightgreen.svg\" alt=\"prs welcome\">\n    </a>\n  </p>\n</p>\n\n# Demo\n\n<p align=\"center\">\n  <img src=\"https://github.com/makkoncept/colorpalette/blob/master/.readme_assets/demo.gif?raw=true\">\n</p>\n\n# Live\n\nView it live at : https://colorpalettedemo.herokuapp.com/\n\nYou can deploy your own instance on heroku by clicking the following button\n\n[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)\n\n\n## What it do\n\nExtracts 10 dominating colors from the image and adds the palette to the bottom of the image (inspired by [colorpalette.cinema](https://www.instagram.com/colorpalette.cinema/?hl=en)). You can adjust the palette height, outline color, and width to match your image dimension. Another independent image of the palette with the hex codes of colors is also generated.\n\nThe app does not depend on any APIs for extracting colors. `color.py` contains the code for it with [Pillow](https://pillow.readthedocs.io/en/stable/) as the only dependency.\n\n## Some samples\n\n1. <span>Photo by <a href=\"https://unsplash.com/@lukaodak?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Luka Odak</a> on <a href=\"https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Unsplash</a></span>\n\n<p align=\"center\">\n  <img width=80% src=\"https://i.imgur.com/zw0SenV.jpg\"><br><br>\n  <img width=80% src=\"https://i.imgur.com/KNg06TY.jpg\">\n</p>\n\n2. <span>Photo by <a href=\"https://unsplash.com/@goodspleen?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Alexandre Chambon</a> on <a href=\"https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Unsplash</a></span>\n\n<p align=\"center\">\n  <img width=80% src=\"https://i.imgur.com/ngBiV0t.jpg\"><br><br>\n  <img width=80% src=\"https://i.imgur.com/xmn52P0.jpg\">\n</p>\n\n3. <span>Photo by <a href=\"https://unsplash.com/@federyka?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Federica Diliberto</a> on <a href=\"https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Unsplash</a></span>\n\n<p align=\"center\">\n  <img height=1000px src=\"https://i.imgur.com/vZTtGEb.jpg\"><br><br>\n  <img width=80% src=\"https://i.imgur.com/kvt0gNS.jpg\">\n</p>\n\n4. <span>Photo by <a href=\"https://unsplash.com/@randomlies?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Ashim D’Silva</a> on <a href=\"https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Unsplash</a></span>\n\n<p align=\"center\">\n  <img width=80% src=\"https://i.imgur.com/QCnXUAf.jpg\"><br><br>\n  <img width=80% src=\"https://i.imgur.com/jjcv5OV.jpg\">\n</p>\n\n## Directory Structure\n\n<pre>\n\n|-- Procfile\n|-- README.md\n|-- app.json\n|-- colorpalette\n|   |-- __init__.py\n|   |-- color.py\n|   |-- forms.py\n|   |-- routes.py\n|   |-- static\n|   |   |-- css\n|   |   |-- font\n|   |   |-- images\n|   |   |   |-- favicon\n|   |   `-- js\n|   `-- templates\n|       |-- 413.html\n|       |-- base.html\n|       |-- index.html\n|       `-- picture.html\n|-- config.py\n|-- requirements.txt\n|-- run.py    \n`-- LICENSE\n\n</pre>\n\n## Run locally\n\n1. Clone the repostory:\n\n```\ngit clone https://github.com/makkoncept/colorpalette.git\n```\n\n2. Navigate to the project root and create a virtual environment:\n\n```\npython3 -m venv venv\n```\n\n3. Activate the virtual environment:\n\nLinux:\n\n```\nsource venv/bin/activate\n```\n\nWindows cmd:\n\n```\nvenv\\Scripts\\activate.bat\n```\n\n4. Install requirements:\n\n```\npip install -r requirements.txt\n```\n\n5. Run the development server:\n\n```\npython run.py\n```\n\n6. View on [localhost:5000](http://127.0.0.1:5000)\n\n## Attribution\n\nIcon made by <a href=\"https://www.flaticon.com/authors/freepik\" title=\"Freepik\">Freepik</a> from <a href=\"https://www.flaticon.com/\" title=\"Flaticon\"> www.flaticon.com</a>\n"
  },
  {
    "path": "app.json",
    "content": "{\n  \"name\": \"ColorPalette\",\n  \"description\": \"Extracts dominating colors from an image and present them as a palette.\",\n  \"repository\": \"https://github.com/makkoncept/colorpalette\",\n  \"logo\": \"https://raw.githubusercontent.com/makkoncept/colorpalette/master/.readme_assets/color-palette.png\",\n  \"keywords\": [\"Flask\", \"Python\", \"Colors\"]\n}\n"
  },
  {
    "path": "colorpalette/__init__.py",
    "content": "from flask import Flask\nfrom dotenv import load_dotenv, find_dotenv\nfrom config import Config\n\nload_dotenv(find_dotenv())\n\napp = Flask(__name__)\napp.config.from_object(Config)\n\n\nfrom colorpalette import routes\n"
  },
  {
    "path": "colorpalette/color.py",
    "content": "from PIL import Image, ImageDraw, ImageFont\nfrom webcolors import rgb_to_hex\nimport os\n\n\ndef get_dominant_colors(infile):\n    image = Image.open(infile)\n    small_image = image.resize((80, 80))\n    result = small_image.convert(\n        \"P\", palette=Image.ADAPTIVE, colors=10\n    )  # image with only 10 dominating colors\n\n    # Find dominant colors\n    palette = result.getpalette()\n    color_counts = sorted(result.getcolors(), reverse=True)\n    colors = list()\n\n    for i in range(10):\n        palette_index = color_counts[i][1]\n        dominant_color = palette[palette_index * 3 : palette_index * 3 + 3]\n        colors.append(tuple(dominant_color))\n\n    # print(colors)\n    return colors\n\n\ndef process_uploaded_image(\n    infile, outline_width, pallete_division_factor, outline_color, numcolors=10\n):\n    # width of the pallete that will be an independent image itself\n    independent_pallete_width = 100\n\n    original_image = Image.open(infile)\n    width, height = original_image.size\n\n    # height for the pallete that will be pasted under the image\n    img_palette_height = int(height / pallete_division_factor)\n    img_palette_width = width / 10\n\n    processed_image = Image.new(\n        \"RGB\", (width, height + img_palette_height)\n    )  # blank canvas(original image + palette)\n\n    pallete_under_image = Image.new(\"RGB\", (width, img_palette_height))\n\n    # blank canvas for pallete. <mode, size, color>\n    independent_pallete = Image.new(\n        \"RGB\",\n        (numcolors * independent_pallete_width, independent_pallete_width + 20),\n        color=\"rgb(255, 255, 255)\",\n    )\n\n    draw = ImageDraw.Draw(pallete_under_image)\n    draw2 = ImageDraw.Draw(independent_pallete)\n\n    posx = 0\n    posx2 = 0\n\n    fonts_path = os.path.join(\n        os.path.dirname(os.path.dirname(__file__)),\n        \"colorpalette/static/font/Roboto-Bold.ttf\",\n    )\n    # create font object with the font file\n    font = ImageFont.truetype(fonts_path, size=16)\n\n    colors = get_dominant_colors(infile)\n    # making the palettes\n    for color in colors:\n        draw.rectangle(\n            [posx, 0, posx + img_palette_width, img_palette_height],\n            fill=color,\n            width=outline_width,\n            outline=outline_color,\n        )\n\n        # drawing one pallete at a time on independent pallete canvas\n        draw2.rectangle(\n            [posx2, 0, posx2 + independent_pallete_width, independent_pallete_width],\n            fill=color,\n        )\n\n        # write the hex code under the pallete\n        draw2.text(\n            (posx2 + 20, independent_pallete_width),\n            rgb_to_hex(color[:3]),\n            fill=\"rgb(0, 0, 0)\",\n            font=font,\n        )\n\n        # move the pointer to the beginning of next pallete color\n        posx = posx + img_palette_width\n        posx2 = posx2 + independent_pallete_width\n\n    del draw\n    del draw2\n    box = (0, height, width, height + img_palette_height)\n\n    # pasting image and palette on the canvas\n    processed_image.paste(original_image)\n    processed_image.paste(pallete_under_image, box)\n\n    return processed_image, independent_pallete\n"
  },
  {
    "path": "colorpalette/forms.py",
    "content": "from flask_wtf import FlaskForm\nfrom flask_wtf.file import FileField, FileRequired, FileAllowed\nfrom flask_wtf.html5 import NumberInput\nfrom wtforms import IntegerField\nfrom wtforms.validators import NumberRange\n\n\nclass PhotoForm(FlaskForm):\n    photo = FileField(\n        \"Upload Image\", validators=[FileRequired(), FileAllowed([\"jpg\", \"png\", \"jpeg\"])]\n    )\n    palette_height = IntegerField(\n        \"Palette Height\", validators=[NumberRange(1, 8)], widget=NumberInput()\n    )\n    palette_outline_width = IntegerField(\n        \"Palette Outline Width\", validators=[NumberRange(1, 40)], widget=NumberInput()\n    )\n"
  },
  {
    "path": "colorpalette/routes.py",
    "content": "from colorpalette import app\nfrom colorpalette.color import process_uploaded_image\nfrom colorpalette.forms import PhotoForm\nfrom flask import render_template, redirect, url_for, request, session\nfrom werkzeug.utils import secure_filename\nfrom webcolors import hex_to_rgb\nimport os\nimport uuid\n\n\n@app.route(\"/\", methods=[\"GET\", \"POST\"])\ndef index():\n    form = PhotoForm()\n    if form.validate_on_submit():\n        image = form.photo.data\n\n        filename = secure_filename(image.filename)  # sanitize image name\n        _, ext = os.path.splitext(filename)\n        new_filename = uuid.uuid4().hex + ext  # creating a random name\n\n        image_with_palette, pallete = process_uploaded_image(\n            image,\n            pallete_division_factor=11 - form.palette_height.data,\n            outline_width=form.palette_outline_width.data,\n            outline_color=hex_to_rgb(request.form.get(\"palette_outline_color\")),\n        )\n\n        image_with_pallete_path = os.path.join(\n            app.root_path, \"static/images\", new_filename\n        )\n        pallete_path = os.path.join(\n            app.root_path, \"static/images\", \"pal\" + new_filename\n        )\n\n        # saving image and pallete\n        image_with_palette.save(image_with_pallete_path)\n        pallete.save(pallete_path)\n\n        return redirect(\n            url_for(\n                \"picture\",\n                name=new_filename,\n            )\n        )\n\n    return render_template(\"index.html\", form=form, src=\"default\")\n\n\n@app.route(\"/picture/<name>\")\ndef picture(name):\n    processed_img_relative_path = url_for(\"static\", filename=\"images/\" + name)\n    pallete_relative_path = url_for(\"static\", filename=\"images/\" + \"pal\" + name)\n\n    return render_template(\n        \"picture.html\",\n        src=processed_img_relative_path,\n        src2=pallete_relative_path,\n    )\n\n\n@app.errorhandler(413)\ndef error413(e):\n    return render_template(\"413.html\"), 413\n"
  },
  {
    "path": "colorpalette/static/css/style.css",
    "content": "*,\n*::before,\n*::after {\n  padding: 0;\n  margin: 0;\n  box-sizing: border-box;\n}\n\n:root {\n  --primary-color: #ea538c;\n  --primary-color-light: #ffcde0;\n}\n\nbody {\n  background-color: rgb(245, 245, 245);\n  color: #0c0c07;\n  font-weight: 500;\n  font-family: \"Raleway\", sans-serif;\n}\n\nh1 {\n  font-size: 3.3rem;\n  font-weight: 400;\n}\n\nh2 {\n  font-size: 2.5rem;\n  font-weight: 400;\n}\n\n.container {\n  padding: 2rem 5rem;\n}\n\n.image-showcase {\n  display: flex;\n  padding: 2rem 0 4rem 0;\n\n  justify-content: space-evenly;\n  align-items: center;\n}\n\nform {\n  display: flex;\n  flex-direction: column;\n  justify-content: flex-end;\n  align-items: center;\n  width: 90%;\n  margin: 0 auto;\n}\n\n.image-upload-wrapper {\n  margin: 1.5rem 0 3rem 0;\n  height: 11rem;\n  position: relative;\n  width: 100%;\n}\n\n.image-upload {\n  display: flex;\n  width: 100%;\n  height: 100%;\n  align-items: center;\n  justify-content: center;\n  flex-direction: column;\n  border: 4px dashed var(--primary-color);\n  border-radius: 0.5rem;\n  transition: background-color 0.25s ease-out;\n}\n\n.image-upload:hover {\n  background-color: var(--primary-color-light);\n}\n\n.image-input {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  opacity: 0;\n  outline: none;\n  cursor: pointer;\n}\n\n.image-upload-wrapper .undertext {\n  font-size: 0.9rem;\n  color: #991c19;\n  float: right;\n}\n\n.number-input {\n  width: 100%;\n  display: flex;\n\n  align-items: center;\n  padding-bottom: 1rem;\n}\n\n.number-input label {\n  display: inline-block;\n\n  width: 50%;\n  padding-right: 2rem;\n  font-size: 1.3rem;\n  text-align: right;\n}\n\n.number-input input[type=\"number\"] {\n  width: 30%;\n  font-size: 2rem;\n  font-weight: 400;\n  padding-left: 0.6rem;\n  border-radius: 2px;\n  border: 2px solid rgb(192, 192, 192);\n}\n\n.submit-button {\n  color: #fff;\n  background-color: var(--primary-color);\n  border-color: var(--primary-color);\n\n  display: inline-block;\n  height: 2.5rem;\n  padding: 0 30px;\n  text-align: center;\n  font-size: 1rem;\n  font-weight: 600;\n  line-height: 38px;\n  letter-spacing: 0.1rem;\n  text-transform: uppercase;\n  text-decoration: none;\n  white-space: nowrap;\n  border-radius: 4px;\n  border: 1px solid #bbb;\n  cursor: pointer;\n}\n\n/* pictures.html */\n.image-wrapper {\n  width: 70%;\n  margin: auto;\n  position: relative;\n}\n\n.image-wrapper img {\n  display: block;\n  margin: auto;\n  max-width: 100%;\n  max-height: 100%;\n}\n\n.download-image-button {\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  transform: translate(-50%, -50%);\n  z-index: 1;\n  opacity: 0;\n\n  color: #fff;\n  background-color: var(--primary-color);\n\n  font-size: 1.1rem;\n  font-weight: 500;\n  line-height: 1.1;\n  text-transform: capitalize;\n  text-decoration: none !important;\n  text-align: center;\n\n  border: 0 none;\n  border-radius: 4px;\n  padding: 12px 12px;\n  cursor: pointer;\n  user-select: none;\n}\n\n.download-image-button:hover {\n  color: #fff;\n}\n\n.overlay {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  background: rgba(0, 0, 0, 0);\n  transition: background 0.5s ease;\n}\n\n.image-wrapper:hover .overlay {\n  display: block;\n  background: rgba(0, 0, 0, 0.3);\n}\n\n.image-wrapper:hover .download-image-button {\n  opacity: 1;\n}\n\n/* github fork ribbon : https://github.com/simonwhitaker/github-fork-ribbon-css */\n.github-fork-ribbon::before {\n  background-color: #333;\n}\n\n/* utils */\n.text-align-center {\n  text-align: center;\n}\n\n.margin-bottom-large {\n  margin-bottom: 4rem;\n}\n\n.margin-bottom-normal {\n  margin-bottom: 2rem;\n}\n\n.margin-top-large {\n  margin-top: 4rem;\n}\n"
  },
  {
    "path": "colorpalette/static/images/favicon/site.webmanifest",
    "content": "{\"name\":\"\",\"short_name\":\"\",\"icons\":[{\"src\":\"/android-chrome-192x192.png\",\"sizes\":\"192x192\",\"type\":\"image/png\"},{\"src\":\"/android-chrome-512x512.png\",\"sizes\":\"512x512\",\"type\":\"image/png\"}],\"theme_color\":\"#ffffff\",\"background_color\":\"#ffffff\",\"display\":\"standalone\"}"
  },
  {
    "path": "colorpalette/static/js/script.js",
    "content": "const imageUpload = document.querySelector(\".image-upload\");\nconst imageInput = document.querySelector(\".image-input\");\nconst imageNameDiv = document.querySelector(\".image-name\");\nconst legalFileTypes = [\"image/png\", \"image/jpg\", \"image/jpeg\"];\n\nimageUpload.addEventListener(\"change\", handleImageUpload);\n\nfunction handleImageUpload(event) {\n  console.log(event.target.files[0]);\n  const FileSize = event.target.files[0].size / 1024 / 1024; // in MB\n  const fileType = event.target.files[0].type;\n  if (FileSize > 2) {\n    alert(\"File size exceeds 2 MB\");\n  } else if (!legalFileTypes.includes(fileType)) {\n    alert(\"Only file of type 'jpeg', 'jpg', or 'png' allowed\");\n  } else {\n    const imageName = event.target.files[0].name;\n    imageNameDiv.innerText = imageName;\n  }\n}\n"
  },
  {
    "path": "colorpalette/templates/413.html",
    "content": "{% extends \"base.html\" %} {% block content %}\n<div>\n  <h3 style=\"text-align: center\">\n    Your image is too large. Please <a href=\"{{url_for('index')}}\">upload</a> a smaller image.\n  </h3>\n</div>\n{% endblock %}\n"
  },
  {
    "path": "colorpalette/templates/base.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"description\" content=\"Extracts dominant colors from an image and present them as a palette.\" />\n    <meta name=\"author\" content=\"Mayank Nader\" />\n    <meta property=\"og:locale\" content=\"en_US\" />\n    <meta property=\"og:site_name\" content=\"ColorPalette\" />\n    <meta property=\"og:title\" content=\"ColorPalette\" />\n    <meta property=\"og:description\" content=\"Extracts dominant colors from an image and present them as a palette.\" />\n    <meta name=\"twitter:card\" content=\"summary\" />\n    <meta name=\"twitter:title\" content=\"ColorPalette\" />\n    <meta name=\"twitter:description\" content=\"Extracts dominant colors from an image and present them as a palette.\" />\n    <meta property=\"og:url\" content=\"https://colorpalette.xyz\" />\n\n    <title>ColorPalette</title>\n\n    <link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/static/images/favicon/apple-touch-icon.png\" />\n    <link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/static/images/favicon/favicon-32x32.png\" />\n    <link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/static/images/favicon/favicon-16x16.png\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"/static/images/favicon/favicon.ico\" />\n    <link rel=\"manifest\" href=\"/static/images/favicon/site.webmanifest\" />\n\n    <link href=\"//fonts.googleapis.com/css?family=Raleway:400,500,600\" rel=\"stylesheet\" type=\"text/css\" />\n    <link\n      rel=\"stylesheet\"\n      href=\"https://cdnjs.cloudflare.com/ajax/libs/github-fork-ribbon-css/0.2.3/gh-fork-ribbon.min.css\"\n    />\n\n    <link rel=\"stylesheet\" href=\"/static/css/style.css\" />\n  </head>\n  <body>\n    <a\n      class=\"github-fork-ribbon\"\n      href=\"https://github.com/makkoncept/colorpalette\"\n      data-ribbon=\"Fork me on GitHub\"\n      title=\"Fork me on GitHub\"\n      >Fork me on GitHub</a\n    >\n\n    <div class=\"container\">{% block content %}{% endblock %}</div>\n\n    <script src=\"/static/js/script.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "colorpalette/templates/index.html",
    "content": "{% extends \"base.html\" %} {% block content %}\n<div class=\"introduction text-align-center\">\n  <h1>Color Palette</h1>\n  <p>Extracts dominating colors from your image</p>\n</div>\n<div class=\"image-showcase\">\n  <img\n    src=\"{{url_for('static', filename='images/image-before-processing.jpg')}}\"\n    width=\"450\"\n    height=\"310\"\n    alt=\"image before processing\"\n  />\n  <img src=\"{{url_for('static', filename='images/right-arrow.png')}}\" height=\"115\" />\n  <img\n    src=\"{{url_for('static', filename='images/image-after-processing.jpg')}}\"\n    width=\"450\"\n    height=\"310\"\n    alt=\"image after processing\"\n  />\n</div>\n<h2 class=\"text-align-center\">Try It Now</h2>\n<form method=\"POST\" enctype=\"multipart/form-data\">\n  <div class=\"image-upload-wrapper\">\n    {{form.hidden_tag()}}\n    <!-- prettier-ignore -->\n    <div class=\"image-upload\">\n              {{form.photo(class=\"image-input\")}} \n              <img src=\"/static/images/image-icon.png\" alt=\"image icon\">\n              <div class=\"subtitle\">Upload Image</div>\n              <div class=\"image-name\"></div>\n              {% for error in form.photo.errors %}\n              <span style=\"color: red\">{{ error}}</span>\n              {% endfor %}\n            </div>\n    <p class=\"undertext\">*Image size must be less than 2Mb</p>\n  </div>\n  <div class=\"number-input\">\n    <label>Palette Height(1-8)</label>\n    {{form.palette_height(value=6, min=1, max=8)}}\n    <!-- prettier-ignore -->\n    {% for error in form.palette_height.errors %}\n    <span style=\"color: red\">{{ error}}</span>\n    {% endfor %}\n  </div>\n  <div class=\"number-input\">\n    <label>Palette Outline Width in Pixels (1-40)</label>\n    {{form.palette_outline_width(class=\"u-full-width\", value=10, min=1, max=40)}}\n    <!-- prettier-ignore -->\n    {% for error in form.palette_outline_width.errors %}\n    <span style=\"color: red\">{{ error}}</span>\n    {% endfor %}\n  </div>\n  <div class=\"number-input\">\n    <label>Palette Outline color</label>\n    <input type=\"color\" name=\"palette_outline_color\" value=\"white\" />\n  </div>\n  <input class=\"submit-button\" type=\"submit\" value=\"submit\" />\n</form>\n\n{% endblock %}\n"
  },
  {
    "path": "colorpalette/templates/picture.html",
    "content": "{% extends \"base.html\" %} {% block content %}\n\n<div class=\"text-align-center margin-bottom-large\">\n  <h2>Try <a href=\"{{url_for('index')}}\">Again</a>?</h2>\n</div>\n<div class=\"image-wrapper\">\n  <img src=\"{{src}}\" />\n  <div class=\"overlay\"></div>\n  <a href=\"{{src}}\" class=\"download-image-button\" download=\"image-with-palette\">Download Image</a>\n</div>\n\n<div>\n  <h2 class=\"margin-top-large margin-bottom-normal text-align-center\">Palette with hex codes</h2>\n  <div class=\"image-wrapper\">\n    <img src=\"{{src2}}\" />\n    <div class=\"overlay\"></div>\n    <a href=\"{{src2}}\" class=\"download-image-button\" download=\"palette\">Download Image</a>\n  </div>\n</div>\n\n{% endblock %}\n"
  },
  {
    "path": "config.py",
    "content": "import os\n\n\nclass Config(object):\n    SECRET_KEY = os.environ.get(\"SECRET_KEY\") or \"N6q067SQG7894Yw28d85BqWu4\"\n    MAX_CONTENT_LENGTH = 2 * 1024 * 1024  # image size upload limit (2 MB)\n"
  },
  {
    "path": "requirements.txt",
    "content": "Click==7.0\nFlask==1.0.2\nFlask-WTF==0.14.2\ngunicorn==19.9.0\nitsdangerous==1.1.0\nJinja2==2.10.1\nMarkupSafe==1.1.1\nPillow==7.2.0\nwebcolors==1.8.1\nWerkzeug==0.15.5\nWTForms==2.2.1\npython-dotenv==0.14.0\n"
  },
  {
    "path": "run.py",
    "content": "from colorpalette import app\n\nif __name__ == \"__main__\":\n    app.run(debug=True)\n"
  }
]