Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
4d4c334
initial proposal
hellofellowkids Sep 26, 2021
084aa20
proposal edit
hellofellowkids Sep 26, 2021
f56cd47
Added more detail to proposal.md
Matthew7758 Sep 27, 2021
e789691
Added basic server.js script to save time.
Matthew7758 Sep 27, 2021
e582e0f
Added basic server.js script to save time.
Matthew7758 Sep 27, 2021
0b018f8
Upload image and load into canvas works.
Matthew7758 Oct 4, 2021
1efd37f
Download works.
Matthew7758 Oct 4, 2021
25e4a39
Figured out how to add text. Added favicon.
Matthew7758 Oct 4, 2021
29275b4
Line wrap works.
Matthew7758 Oct 4, 2021
ea659aa
Removed useless lines of code.
Matthew7758 Oct 5, 2021
890776f
imported cropper
Matthew7758 Oct 5, 2021
24b8696
Cropper should work now.
Matthew7758 Oct 5, 2021
391304e
Created a new branch, now without the sudden deletion of everything i…
willwht Oct 5, 2021
b20d0fe
Basic CSS styling of most elements, Bootstrap import
willwht Oct 5, 2021
55e3552
Cropper should work now.
Matthew7758 Oct 5, 2021
03881fa
buttons enable/disable as needed.
Matthew7758 Oct 5, 2021
7f8f09d
Added new controls.
Matthew7758 Oct 6, 2021
f2ec307
Fixed flip buttons.
Matthew7758 Oct 6, 2021
bd9b311
Added caman to project.
Matthew7758 Oct 6, 2021
f0b1420
Added caman to project.
Matthew7758 Oct 6, 2021
5c0a6e7
Merge branch 'main' into css
willwht Oct 6, 2021
a8f3722
Updated CSS to match main index file
willwht Oct 6, 2021
5c264c7
greyscale and compress feature
hellofellowkids Oct 6, 2021
6a602af
CSS Styling updates, restructured index.html slightly
willwht Oct 6, 2021
a752f72
Merge pull request #1 from hellofellowkids/css
hellofellowkids Oct 6, 2021
f4ddc8c
Merge branch 'main' into akumar6
hellofellowkids Oct 6, 2021
43d2d7a
Merge pull request #2 from hellofellowkids/akumar6
hellofellowkids Oct 6, 2021
f396a07
updated styling on compress and greyscale buttons
willwht Oct 6, 2021
ddb76de
Why
Matthew7758 Oct 6, 2021
d5e4158
Quick addition of font size option.
Matthew7758 Oct 6, 2021
0b9aa41
Updated .gitignore (sorry)
willwht Oct 6, 2021
e408f8b
Merge branch 'main' into css
willwht Oct 6, 2021
26c7186
Recolored some parts of the app to be more easily visible
willwht Oct 6, 2021
9966669
Added reload button.
Matthew7758 Oct 6, 2021
a28f5c2
Updated styling to look prettier
willwht Oct 6, 2021
8329b2b
Merge branch 'main' into css
willwht Oct 6, 2021
522f527
Replaced grayscale function to use caman.
Matthew7758 Oct 6, 2021
9522e16
Merge branch 'css' of https://github.com/hellofellowkids/final_projec…
Matthew7758 Oct 6, 2021
e16a21b
Greyscale button updated.
Matthew7758 Oct 6, 2021
67beee0
Added a few more filters.
Matthew7758 Oct 6, 2021
6efbc6f
Separated effect buttons into types
willwht Oct 6, 2021
032b85d
Changed filter area background color
willwht Oct 6, 2021
fb87fe4
small change to CSS
Matthew7758 Oct 7, 2021
89fec74
Alerts to large images being uploaded + a little padding around canvas
hellofellowkids Oct 7, 2021
5bafeef
sliders for adjusting the picture
hellofellowkids Oct 7, 2021
feeec31
more sliders initial implementation
hellofellowkids Oct 7, 2021
4d61412
Added CSS positioning for sliders
willwht Oct 7, 2021
dad2a39
Added captions to each section
willwht Oct 7, 2021
d275a7d
Updated README.md
Matthew7758 Oct 7, 2021
9a15333
Updated README.md
Matthew7758 Oct 7, 2021
0447034
Updated README.md
Matthew7758 Oct 7, 2021
7f40bf6
Multiple sliders now work in combination.
Matthew7758 Oct 7, 2021
1e71830
Updated README.md
Matthew7758 Oct 7, 2021
32f4f38
Styled the sliders
willwht Oct 7, 2021
966e397
Added link to video
hellofellowkids Oct 8, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
package-lock.json
76 changes: 25 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,51 +1,25 @@
# Final Project
*Due before the start of class, October 11th (final day of the term)*

For your final project, you'll implement a web application that exhibits understanding of the course materials.
This project should provide an opportunity to both be creative and to pursue individual research and learning goals.

## General description
Your project should consist of a complete Web application, exhibiting facets of the three main sections of the course material:

- Static Web page content and design. You should have a project that is accessible, easily navigable, and features significant content.
- Dynamic behavior implemented with JavaScript (TypeScript is also allowed if your group wants to explore it).
- Server-side programming *using Node.js*. Typically this will take the form of some sort of persistent data (database), authentication, and possibly server-side computation.
- A video (less than five minutes) where each group member explains some aspect of the project. An easy way to produce this video is for you all the groups members to join a Zoom call that is recorded; each member can share their screen when they discuss the project or one member can "drive" the interface while other members narrate (this second option will probably work better.) The video should be posted on YouTube or some other accessible video hosting service. Make sure your video is less than five minutes, but long enough to successfully explain your project and show it in action. There is no minimum video length.

## Project ideation
Excellent projects typically serve someone/some group; for this assignment you need to define your users and stakeholders. I encourage you to identify projects that will have impact, either artistically, politically, or in terms of productivity.

## Logistics
### Team size
Students are will work in teams of 3-5 students for the project; teams of two can be approved with the permission of the instructor. Working in teams should help enable you to build a good project in a limited amount of time. Use the `#project-logistics` channel in Discord to pitch ideas for final projects and/or find fellow team members as needed.

Teams must be in place by end of day on Saturday, September 25th. If you have not identified a team at this point, you will be assigned a team. You will be given some class time on Monday to work on your proposal, but please plan on reserving additional time as needed.

### Deliverables

__Proposal:__
Provide an outline of your project direction and the names of associated team members.
The outline should have enough detail so that staff can determine if it meets the minimum expectations, or if it goes too far to be reasonable by the deadline. Please include a general description of a project, and list of key technologies/libraries you plan on using (e.g. React, Three.js, Svelte, TypeScript etc.). Name the file proposal.md and submit a pull request.
Submit a PR to turn it in by Monday, September 27th at11:59 PM. Only one pull request is required per team.

There are no other scheduled checkpoints for your project.

#### Turning in Your Outline / Project
Submit a second PR on the final project repo to turn in your app and code. Again, only one pull request per team.

Deploy your app, in the form of a webpage, to Glitch/Heroku/Digital Ocean or some other service; it is critical that the application functions correctly wherever you post it.

The README for your second pull request doesn’t need to be a formal report, but it should contain:

1. A brief description of what you created, and a link to the project itself (two paragraphs of text)
2. Any additional instructions that might be needed to fully use your project (login information etc.)
3. An outline of the technologies you used and how you used them.
4. What challenges you faced in completing the project.
5. What each group member was responsible for designing / developing.
6. A link to your project video.

Think of 1,3, and 4 in particular in a similar vein to the design / tech achievements for A1—A4… make a case for why what you did was challenging and why your implementation deserves a grade of 100%.

## FAQs

- **Can I use XYZ framework?** You can use any web-based frameworks or tools available, but for your server programming you need to use Node.js. Your client-side scripting language should be either JavaScript or TypeScript.
### CS4241 Final Project

Group #: 21

Group Members: Aditya Kumar, Matthew Malone, William White

1. This project is a simple photo editor using Javascript. The user can upload an image, and then manipulate it. The user can crop, rotate, and transform the image. Various filter and color manipulation options are also offered. We created a custom function that allows a user to "Jpegify" an image and introduce artifacts in order to distort it. The website can be found hosted on glitch at [Meme Machine](https://group21-meme-machine.glitch.me).
2. Simply click the upload button and upload an image of reasonable size. The program will inform you if your image is too large. Note that because this uses the processing power of the client's computer, depending on the specs large images may cause lag or crashes, hence the automatic limiting of image sizes.
3. We used three different libraries to do the bulk of the work in the project. We also used a CSS library to do the styling.
1. Canvas: We used canvas to display the image and make real time edits to it. This was difficult to implement as we had to make it dynamically update with any changes made to the photo, and keep it working with all the libraries.
2. Cropper-JS: CropperJS was chosen as a cropping tool library because of its integration to canvas. This allows the user to crop out sections of an image, rotate, and transform images. This was difficult to get working because we needed to get it imported to the client somehow. We wound up having to use Helmet-CSP to get all our scripts working properly. We also had to dynamically program all the controls to enable/disable themselves as necessary.
3. Caman: Caman is a third party library used to manipulate photos. It was chosen because of its easy integration to canvas. It was used to make all the sliders for editing brightness, saturation, etc. It was also used to apply several filters to the image. This was challenging to implement simply because the documentation wasn't that great, so we had to do a lot of experimentation to get it to work properly. It was implemented by use of buttons and sliders.
4. We used basic javascript photo manipulation to add a button that repeatedly converts an image into a jpeg to introduce artifacts. This can be used to distort any image and can be found by clicking the Compress button.
5. Bootstrap was used to design the layout and styling of the websites. It was used to make buttons look nicer, and we also used it to style sliders and div containers.
6. Helmet-CSP was used to set content security policy headers to allow inline scripts to be included from Javascript CDNs.
4. Challenges:
1. The first challenge we found was getting the scripts to the client. We found out that we needed to set content security policy headers to get the Caman and CropperJS libraries included. We wound up using Helmet-CSP to set content security policy headers for the project.
2. The second challenge we faced was getting the libraries to cooperate with canvas. Cropper for example is good for making edits to a photo file, but we needed to write code to dynamically update the canvas to reflect changes to the image data.
3. Bootstrap was a completely new experience for us, so we needed to learn how to use it from scratch for this project.
4. The fourth challenge we encountered was that we needed a concise way to implement multiple listeners for the Caman JS sliders and make them apply in combination to each other. This was accomplished by writing one listener and applying it to the entire array of sliders.
5. What each team member was responsible for:
1. Matthew Malone: Responsible for server backend, cropperJS implementation, and canvas setup. Creation of HTML controls for CropperJS.
2. Aditya Kumar: Responsible for Caman setup and sliders/filters. Video creation and editing. Creation of HTML controls for CamanJS.
3. Will White: Responsible for all styling of webpages. Learned and used bootstrap to accomplish styling of the editor.
6. [Project Video](https://drive.google.com/file/d/1e4F3sxtnmZ6tdkjJp6dVW4bQ-zrbjwna/view?usp=sharing)
25 changes: 25 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "a4-final-project",
"version": "1.0.0",
"description": "Submission for Group 21",
"author": "God",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"repository": "https://github.com/hellofellowkids/final_project",
"dependencies": {
"express": "^4.17.1",
"express-validator": "^6.12.1",
"morgan": "^1.10.0",
"cors": "^2.8.5",
"browserify": "^17.0.0",
"cropperjs": "^1.5.12",
"helmet-csp": "^3.4.0",
"caman": "^4.1.2"
},
"engines": {
"node": "14.x"
},
"license": "NONE"
}
Binary file added pictures/mock_up.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
CS4241 Final Project Proposal
---

Group #: 21 <br>
Group Members: Aditya Kumar, Matthew Malone, William White

## Project Idea

We want to create a website that will host a simple photo manipulation / editor tool. While there are websites and software that manipulate photos, we find a majority of them to be too intricate or pricey to use. We believe that we can deliver a photo manipulation website that is accessible and simple to use.
We will use primarily Javascript for this project.

Some simple photo manipulation features we'd like to include (given the deadline):
- Apply Filters
- Add Text
- Crop / Morph

If more time allows, we can add more features to make the website more robust.

## Libraries we can use to accomplish this:
- Pica --Resize images
- Lena.js --Image processing
- Jimp --Another image processing library written entirely in JS
- Grade.js --Make gradient from supplied image.
- Compressor.js --Javascript image compressor

## General Logic Flow for App

1) Client uploads a photo to edit via file select prompt
2) Website displays uploaded photo and toolbar widget
3) Client interacts with toolbar widget to manipulate the photo.
4) For each manipulation, the photo display will be updated to show a preview of the final product
5) Client is satisfied with manipulated photo, they click an "Export" button to download the final manipulated photo.

## Initial Website Mock-up

![image info](./pictures/mock_up.png)
Binary file added public/img/favicon.ico
Binary file not shown.
95 changes: 95 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<!DOCTYPE html>
<html lang="en">

<head>
<link rel=icon href='./img/favicon.ico' type="image/ico">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.12/cropper.css"
integrity="sha512-+VDbDxc9zesADd49pfvz7CgsOl2xREI/7gnzcdyA9XjuTxLXrdpuz21VVIqc5HPfZji2CypSbxx1lgD7BgBK5g=="
crossorigin="anonymous" referrerpolicy="no-referrer"/>
<meta charset="UTF-8">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
<link href="style.css" rel="stylesheet">
<title>Meme Machine</title>
</head>

<body class="d-flex flex-row">
<div class="editor">
<input type="file" id="imageInput" class="btn btn-outline-primary" accept="image/*"/>
<button class="btn btn-success" id="download">Download</button>
<button class="btn btn-danger" id="resetButton">Reset</button>
<br/>
<canvas id="imgCanvas" width="1000" height="800" style="padding-top: 10px; padding-right: 10px;">Your browser does not support canvas.</canvas>
</div>
<div class="imageHolder">

</div>
<div class="controlHolder">
<label class="sectionLabel">Captions</label>
<div class="textInputs">
<input type="text" class="form-control" id="topText" placeholder="TOP TEXT">
<label for="topText" class="input-group mb-3">
<input type="number" id="topTextSize" class="form-control" placeholder="Text Size">
<button class="btn btn-primary" id="topTextBtn">Add Text</button>
</label>
<br/>
<input type="text" class="form-control" id="bottomText" placeholder="BOTTOM TEXT">
<label for="bottomText" class="input-group mb-3">
<input type="number" id="bottomTextSize" class="form-control" placeholder="Text Size">
<button class="btn btn-primary" id="bottomTextBtn">Add Text</button>
</label>
</div>
<label class="sectionLabel">Image Transformations</label>
<div class="cropControls">
<button disabled class="btn btn-secondary" id="startCropBtn" value="Start Cropping">Start Cropping</button>
<button disabled class="btn btn-secondary" id="cropBtn" type="button" value="Crop">Crop Image</button>
<button disabled class="btn btn-secondary" id="restoreCropBtn" type="button" value="Restore">Reset Image</button>
</div>
<div class="rotators">
<button disabled class="btn btn-secondary" id="rotateLeft" type="button" value="Rotate Left">RotateLeft</button>
<button disabled class="btn btn-secondary" id="rotateRight" type="button" value="Rotate Right">RotateRight</button>
</div>
<div class="flippers">
<button disabled class="btn btn-secondary" id="flipX" type="button" value="Flip X">Flip X</button>
<button disabled class="btn btn-secondary" id="flipY" type="button" value="Flip Y">Flip Y</button>
</div>
<label class="sectionLabel">Color Edits</label>
<div class="sliderGroup">
<div class="sliderGroupLeft">
<label class="form-range"> Brightness: <input id="brightnessSlider" type="range" class="range-field" min="-100" max="100" value="0"> </label>
<label class="form-range"> Saturation: <input id="saturationSlider" type="range" class="range-field" min="-100" max="100" value="0"> </label>
<label class="form-range"> Vibrance: <input id="vibranceSlider" type="range" class="range-field" min="-100" max="100" value="0"> </label>
<label class="form-range"> Exposure: <input id="exposureSlider" type="range" class="range-field" min="-100" max="100" value="0"> </label>
<label class="form-range"> Hue: <input id="hueSlider" type="range" class="range-field" min="0" max="100" value="0"> </label>
</div>
<div class="sliderGroupRight">
<label class="form-range"> Sepia: <input id="sepiaSlider" type="range" class="range-field" min="0" max="100" value="0"> </label>
<label class="form-range"> Gamma: <input id="gammaSlider" type="range" class="range-field" min="1" max="10" value="1"> </label>
<label class="form-range"> Noise: <input id="noiseSlider" type="range" class="range-field" min="0" max="100" value="0"> </label>
<label class="form-range"> Clip: <input id="clipSlider" type="range" class="range-field" min="0" max="100" value="0"> </label>
<label class="form-range"> Sharpen: <input id="sharpenSlider" type="range" class="range-field" min="0" max="100" value="0"> </label>
</div>
</div>
<label class="sectionLabel">Premade Filters</label>
<div class="filtersHolder">
<div class="filterSubgroup">
<button id="compressBtn" class="btn btn-success" value="Compress">Compress</button>
<button id="greyscaleBtn" class="btn btn-success" value="Greyscale">Greyscale</button>
</div>
<div class="filterSubgroup">
<button id="embossBtn" class="btn btn-success" value="Emboss">Emboss</button>
</div>
<div class="filterSubgroup">
<button id="herMajestyBtn" class="btn btn-success" value="Her Majesty">Her Majesty</button>
<button id="orangePeelBtn" class="btn btn-success" value="Orange Peel">Orange Peel</button>
<button id="sinCityBtn" class="btn btn-success" value="Sin City">Sin City</button>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/caman"></script>
<script src="https://cdn.jsdelivr.net/npm/cropperjs"></script>
<script src="./scripts/editor.js"></script>

</body>

</html>
Loading