Never judge a book by its cover, never judge music by its cover - but we still do!
Music art covers are designs on music albums in the form of illustrations or generic images. Music covers are just as important as the music itself because a well-designed and attractive music cover can perform marketing functions for the music.
In this article, we will be creating a music art cover in Nuxt.js using Cloudinary’s Neural artwork style transfer add-on. The Neural Style Transfer uses neural networks to transfer and blend the styles from one image (source image) into another image (target image) while maintaining the content of both images with an intricate network.
Nuxt.js is a Vue.js based, open-source JavaScript library that improves building server-rendered Vue.js applications, leading to more performant web applications.
Cloudinary is a cloud-based video and image management platform that offers services for managing and transforming uploaded assets for usage on the web.
Sandbox
We can find the completed project on CodeSandbox. Fork it and run the code.
Github
Check out the complete source code here
Prerequisites
Understanding this article requires the following:
- Installation of Node.js
- Basic knowledge of JavaScript
- Familiarity with Nuxt.js
- A Cloudinary account. (sign up for a free account here).
Creating a Nuxt.js Project
Use npx create-nuxt-app <project-name>
to create a new Nuxt.js project.
The process of scaffolding the project would provide a list of options, which should look like this:
After successful project creation, we'll navigate into our directory and start our application by running the following command:
1cd <project name>2npm run dev
Nuxt.js will, in turn, start a hot-reloading development environment that is accessible by default at http://localhost:3000.
Registering Cloudinary's Neural Style Transfer Add-on
Our project requires the Neural style transfer add-on from Cloudinary. To use the add-on in code, we will need to register for it via the Cloudinary dashboard. We will log into our Cloudinary dashboard to sign up for the add-on. Choose the Add-ons tabs from the available options on the navigation bar.
Clicking on the tab above shows all the available add-ons on Cloudinary, from which we can choose the desired add-on, which in this case is the Neural Artwork Style Transfer add-on:
Choosing the add-on prompts us to view a well-detailed tab about the add-on from where we pick the plan to opt on. We will pick the Free plan for this demo:
Allow Unsigned Add-on Transformations on Cloudinary
To allow people to transform images on the fly without verification using Cloudinary’s authenticated API, we will navigate to the Settings and click on the settings option. This will show a bunch of options for us to activate or deactivate. In our case, we will look out for the Unsigned add-on transformations allowed options and check them like so:
We will save the option, and now we can use the add-on in our Nuxt.js application.
Configuring Cloudinary
To use Cloudinary in our Nuxt.js application, we will need to install the Cloudinary Nuxt SDK in our project, like so:
1npm install @nuxtjs/cloudinary
Configuring nuxt.config
for Cloudinary
We need to configure our Nuxt.js application in the nuxt.config
file before we can use Cloudinary.
To do this, we will need to perform the following steps:
Create a
.env
file in the root of our Nuxt.js project and add our Cloudinary Cloud name. We can find it by navigating to the Cloudinary dashboard.Register the property in our
.env
file like so:
1cloudName='***'
- Register the Cloudinary component for global use in the
nuxt.config.js
file by adding'@nuxtjs/cloudinary'
in themodules
section:
1modules: [ '@nuxtjs/cloudinary' ],
- Add a
cloudinary
section in thenuxt.config.js
like so:
1cloudinary: {2 cloudName: process.env.cloudName,3 useComponent: true,4},
The useComponent
attribute is needed to make Cloudinary components like the cldimage
and cldtransformation
available for usage in Nuxt.js.
NB: *Endeavor to replace all occurrences of “***" with the correct values.
Uploading Images to Cloudinary
We'll upload images from Unsplash to Cloudinary. Cloudinary allows us to upload images via the dashboard by clicking the Media Library tab.
After uploading the images, we will need to copy the public Id
to pick each uploaded image from Cloudinary.
Setting up the Image Store
The project we are building requires two different kinds of images - the first set is for the image cover, to which we will apply Cloudinary transformation, and the second set will be album covers for famous songs.
Thus, we will create a first file named utils/image-covers.json
and another named utils/album-covers.json
. A sample snippet of any of these files should look like this:
1[2 {3 "id": 1,4 "publicId": "oscar-keys"5 }6]
Building out the Project
In building out the project, we will need to display the images from Cloudinary out in the browser. We will do this by setting up the markup, including Cloudinary’s cld-image
and cld-transformation
component, which can be likened to using the native <img>
tag in an HTML document.
To achieve this, we will navigate to the pages/index.vue
file and replace the content with the code below:
https://gist.github.com/MoeRayo/abc7055812a1939a7ad4df6e4cff5782
We achieved the following in the code snippet above:
- Imported the JSON images from the
utils
folder and declared them in the data properties before using Cloudinary images components —<cld-image />
and<cld-transformation />
to render the images in the application - Added a
click
function to the images rendered to show the active image - Created a functional input element to handle user input for the title
- Added an error message to prompt users to select an image and fill the input fields before submission
- Added a
data
property to manage the form data, error message, and other vital properties
After this stage, our page should look like the image below:
Generating the Image
To generate an album cover, we'll create a component that renders the generated album cover when the upload
function linked to the “Generate Image” button is clicked.
We will create a file named GeneratedImageCover.vue
in the components
folder and add the code below to the file:
1<template>2 <div>34 <cld-image ref="ref" name="cat.png" :public-id="publicId">5 <cld-transformation effect="blur:150"/>6 <cld-transformation effect="brightness_hsb:-20"/>7 <cld-transformation :overlay="{fontFamily: 'Metamorphous', fontSize: 80, fontWeight: 'bold', text: text, testAlign: 'center'}" color="#fff" opacity="80" crop="fit" width="550" effect="shadow"/>8 <cld-transformation flags="layer_apply"/>9 </cld-image>1011 </div>12</template>13<script>14export default {15 props: {16 text: {17 type: String,18 required: true19 },20 publicId: {21 type: String,22 required: true23 },24 },25}26</script>
We achieved the following using the snippet above:
- Rendered the generated image using Cloudinary’s
<cld-image />
and<cld-transformation />
- Configured the Cloudinary components to accept the
text
andpublicId
as props - Cloudinary components support asset transformations, which we leveraged by blurring, changing the width, and cropping images, added text transformations like the font family and colors to achieve the desired album image
To render the GeneratedImageCover.vue
component, in our view, we will need to import it into the index.vue
file where it is conditionally rendered. We will add the code below:
https://gist.github.com/MoeRayo/1d3f6ea4292305198bc9fe3cee06a15b
We achieved the following from the code snippet above:
- Added a method called
upload
to the form, executed when the generate image button is triggered - Checked whether an image is selected and if the title was added
- The upload function ran the
prepareFormData
function that contains the form data - Added a data property to manage the error, the
cloudname
,preset
,formdata
, andtags
for better organizing of our assets, e.t.c. - Used Axios to post data to the Cloudinary endpoint using the request object options of the
url
, POSTmethod
, and theformData
- Included functionality to capture if the upload was successful or not, after a successful upload, we got access to some returned data like the
secured_url
used to render the uploaded image back in the browser
At this point, we should have a result that looks like this:
Applying Neural Style Transfer
At this stage, the next thing we need to do is apply neural style transfer using the images in the album with the recently generated image from the step above. To do this, we will create a new file named GeneratedAlbum.vue
in the components
folder and add the code below to the file:
1<template>2 <div>3 <cld-image :public-id="albumId" class="grow" sign-url="true">4 <cld-transformation width="550" crop="fit" />5 <cld-transformation :overlay="publicid" font-size="80" font-weight="bold" />6 <cld-transformation effect="style_transfer" flags="layer_apply" />7 </cld-image>8 </div>9</template>10<script>11export default {12 props: {13 albumId: {14 type: String,15 required: true16 },17 publicid: {18 type: String,19 required: true20 },21 },22}23</script>
Cloudinary provides for style transfer using different transformation properties attached to the component. The required setup for neural style transfer in Cloudinary is:
- The target image: image we would use as the base for the styles to get transferred to
- The source image: image we intend to transfer its style to the target image
- The input image: repainted generated image which is a blend of both the target and the source image
The public-id
will represent the target image, while the overlay
will be the source image. We will also need to specify the overlay effect which is denoted as style_transfer
.
To render the GeneratedAlbum.vue
component, in our view, we will need to import it into the index.vue
file and also apply the Cloudinary transformation.
At this stage, our final code in the index.vue
should look like the below:
https://gist.github.com/MoeRayo/23331d1e6ba20a8548064ffcb4b6d6b7
In turn, the application should look like this:
Conclusion
This article explains creating a music art cover in Nuxt.js using Cloudinary’s neural style transfer add-on.