Since brainstorming has already been outlined in the passion project plan, this notebook will not detail that. I’ve done both frontend and backend so this will be divided into two sections.

Backend

The pillow library contains more than a few image manipulation functions. Entering this, I immediately thought that the most difficult part in the beginning would be to connect the frontend and backend. Despite that, I decided to create a testing function first for a pixelate function. I expected PIL to already have a function to do this, and hence pored over way too much of PIL documentation before realizing there wasn’t one. However, all of this reading allowed me to better create a function to do so.

PIL Documentation: https://pillow.readthedocs.io/en/stable/handbook/index.html

def pixelate(image, size):
    org_size = image.size
    pixelate_lvl = size

    image = image.resize(
        size=(org_size[0] // pixelate_lvl, org_size[1] // pixelate_lvl),
        resample=0)
    image = image.resize(org_size, resample=0)

    return image

def imageToBase64(image):
    buffered = BytesIO()
    image.save(buffered, format="PNG")
    img_str = base64.b64encode(buffered.getvalue())
    img_str = img_str.decode('utf-8')
    return img_str

def base64toImage(base64string):
    img_str = base64.b64decode(base64string)
    image = Image.open(BytesIO(img_str))
    return image

The above pixelate function scales the image down first, by a factor of the selected pixelation size. PIL’s resize function automatically averages out the pixels, so this was perfect for the job. I ultimately decided to keep the size of the image the same, although in the future a function could be implemented to do this as well.

Then, I created two functions for converting to and from base64 to a PIL image. These functions were not difficult to create and mostly involved research and the base64 library. However, I quickly ran into errors and with the help of more research, I learned the BytesIO library was necessary to use to convert.

After testing this function, I placed it inside an API:

    class _Pixelate(Resource):
        def post(self):
            data = request.get_json()  # Get JSON data from the request
            pixelated_image = pixelate(base64toImage(data['base64image']), int(data['pixelate_level']))
            response = jsonify({"base64image": imageToBase64(pixelated_image)})
            createImage(data['image_name'], 'pixelate', imageToBase64(pixelated_image)) # adds to database
            return response

Postman issues

I deployed a test function and the GET request worked fine, but when I ran to test this pixelate function, things quickly went awry. I realized that I should’ve incorporated the convert functions into my pixelate function, but I managed to catch some small errors. In the future and when I implemented the combine function later, I definitely would’ve done this. This was also when I learned what a PUT request was and why I shouldn’t use it since I wouldn’t want a whole image encoded in the URL.

Flask deployment

While trying to deploy to flask I ran into many issues. I had to re-read the instructions multiple times and learned that I wasn’t testing properly with docker desktop. While testing with docker desktop, I kept running into a library not found error with PIL and after research I learned that I needed to put all my libraries into requirements.txt in order for them to be installed. I also learned that debugging errors without docker and running main.py instead is easier as that way errors are actually shown. Through this whole process though, I learned where to find logs and errors, and had a better understanding of this after.

Database

I also worked on the combine function, but that was mostly similar to pixelate except it involved more debugging. The database is currently in progress.

Frontend

Fetch

The first step after setting up the backend was setting up the frontend fetch, which was mostly following the example. However, I had to modify the code with some research to add the body for a post request, as our project required sending base64 data back and forth.

const base64Data = e.target.result.split(',')[1];
                const fileName = file.name;
                uploadedImageName = file.name;
                const fileExtension = fileName.split('.').pop();
                const addToDatabase = addToDatabaseCheckbox.checked;
                // Create the data object to send to the backend
                const data = {
                    "pixelate_level": pixelationLevel,
                    "addToHistory": addToDatabase,
                    "filename": fileName,
                    "base64image": base64Data,
                };
                console.log(data)
                // fetch the API
                const image_options = {...post_options, method: 'POST', body: JSON.stringify(data)};
                fetch(pixelate_url, image_options)

Once the fetch was working, the step was to implement this on all other functions, and add checkboxes to add to database and dropdowns for pixelate and combine. This simply took research and experimentation. The hardest dropdown to implement was probably the color selector, which while I know how to implement without using existing js, it would take a lot of time and testing which I didn’t have, and also would be redundant. I found an existing tutorial for a color selector and its JS, and imported it and modified it to output just the RGB, which itself took awhile:

var red, green, blue
    var colorPicker = new iro.ColorPicker(".colorPicker", {
        width: 100,
        height: 100,
        color: "rgb(255, 0, 0)",
        borderWidth: 1,
        borderColor: "#fff" 
    });
    colorPicker.on(["color:init", "color:change"], function (color) {
        red = color.rgbString.slice(4, -1).split(',')[0];
        green = color.rgbString.slice(4, -1).split(',')[1].slice(1);
        blue = color.rgbString.slice(4, -1).split(',')[2].slice(1);
    });
    const checkbox = document.getElementById('checkbox');
    const textElements = document.querySelectorAll('.p1, .p2, h1');
    checkbox.addEventListener('change', () => {
    document.body.classList.toggle('dark');
    //change the overall theme color.
    textElements.forEach((element) => {
    element.classList.toggle('dark-text');
    element.classList.toggle('light-text');
    //change the overall text color.
    });
    });

CORS

I spent way too long debugging the CORS error, but through the process I learned a lot. CORS needs an Access-Control-Allow-Origin header to be able to send back to frontend. In order to fix this, I needed to add the header using CORS in python, which eventually I found out how to add. However, when I deployed, this broke again, and I was now getting Access-Control-Allow-Origin header has multiple values. After looking around the flask server, I found out why. The nginx automatically adds this header, but when testing with docker on localhost, nginx is not being used and therefore does not add this header and hence I left the line commented out when deploying to flask and when testing on localhost uncommented it.

College Board Quiz Notes

Lots of this was background information a had, a few new things down below: Citizen Science: research conducted with participation from general public Internet Engineering Task Force: Organization responsible for TCP/IP standards. I happened to miss one question, which was just a misclick: Which of the following are true statements about how the Internet enables crowdsourcing?

I. The Internet can provide crowdsourcing participants access to useful tools, information, and professional knowledge.

II. The speed and reach of the Internet can lower geographic barriers, allowing individuals from different locations to contribute to projects.

III. Using the Internet to distribute solutions across many users allows all computational problems to be solved in reasonable time, even for very large input sizes.

Three is incorrect as the time necessary to distribute all solutions most likely would contribute a significant amount of time, and anonymous users on the internet may not be trustworthy and instead end up with skewed data. One and two are both correct as the resources on the internet does enable crowdsourcing and connect people from around the world. I meant to select I and II, but accidentally clicked I and III instead.

Previous knowledge definitely helped a lot on this quiz, but many questions came from things learned and class and for several I did search for resources to confirm my answers.

Reflection

I didn't know exactly what to expect coming into this class, with some experience but that much. It turns out that while background knowledge and experience from extracurriculars such as CP have helped, but there were still many, many foreign things. I hadn't used vscode or github much in the past, and that has definitely changed by the end of this trimester. Setting up the blog in the beginning helped patch any holes that were missing in my knowledge and at the same time allowed me to put my own interests while doing so. It also introduced me to javascript, something that I knew existed but never looked into, which of course I would have to do later in the trimester.

Towards the middle of the trimester, I had to learn what Flask was and how to create the API for our passion project backend, which was by far the most challenging/new thing for me. I had a bit of python experience from various small projects in the past, but I never did any formal coding competitions so my knowledge there was extremely limited, but it was enough to get around and be able to contribute to out passion project well. JavaScript was completely new but I felt that learning it went well considering it has only been a few months, and jumping straight in and then solving errors, which doesn't always work, worked in this case. The team teaches also introduced several new vocabulary and terms, as well as concepts new to me. Working in a team, rather than doing projects on my own as in the past also taught me the benefits and importance of them, as well as the importance to only deploy tested and working code, and the importance of testing often, as anything that did not work would stack, making it even harder to locate the issue.

Our attempt at machine learning towards the end of the trimester unfortunately did not work, but in those few days I was able to learn a lot about that, and is definitely something that I should and do plan to look into in the future. I believe that I was able to identify the error but didn't have enough time to attempt to fix and retrain it. While it wasn't successful, if every new thing in the future goes like this, I will be able to learn a lot, and this is definitely something I would like to look into in the future, although probably with text or integers and not images. Hopefully, that goes as well as this trimester's passion project did. Overall, I learned a lot over the course of this trimester and these new things can definitely be applied to future trimesters. 

Frontend Issues Page:

https://github.com/BearytheGreenBear/fte-frontend/issues/5

Peer Reviews:

https://github.com/JoshThinh/Asian-United-Frontend/issues/1 https://github.com/monke7769/passion/issues/6 https://github.com/DavidL0914/frontend/issues/2

Key Commits:

https://github.com/trevorhuang1/fte-backend/commit/8b4982cd8a4f5eeb75c772b3776d882eafc80b26 https://github.com/BearytheGreenBear/fte-frontend/commit/eb9b9741f89fbabcf7f0b05e5995d19844cca281 https://github.com/BearytheGreenBear/fte-frontend/commit/984aad892a646800b8225a30366db6d0fac7aaa7

Team Teach

Our team teach was about Boolean-If, and I ended up writing the portion about the logic gates. I had a basic understanding of these, but together working with my group and using the provided resources, we were able to learn it well and get ready to teach it. As a test, since we finished early, we planned to explain it to a group member who did a different part of the team teach, and that went well. When we went up, I felt confident with the teaching we did, but I felt that we could have diversified the hacks, and the homework was placed in an unclear way, whch resulted in many cheese solutions, as well as people missing the first two problems. Despite this, we managed to get the homework graded in a timely manner and sent out. I was confident with the quality of our teaching, and during the rest of the lessons I paid attention and did my best to continue to apply what was learned to background knowledge and go above and beyond on my workbook, as well as organize it well for review later.