From 11794749c7af0d68d5bc244d7e0c349e75218a10 Mon Sep 17 00:00:00 2001 From: ajayadav09 Date: Thu, 22 Feb 2024 12:34:18 +0530 Subject: [PATCH 1/3] added background color --- package.json | 1 + .../components/ImageUploaderWithText/index.js | 68 ++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index e363784c6..f43f0dceb 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "@wordpress/style-engine": "^0.11.0", "bytes": "^3.1.2", "classnames": "^2.3.2", + "colorthief": "^2.4.0", "react-router-dom": "^6.20.1" } } diff --git a/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/index.js b/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/index.js index 0dfdd7a3e..30b8eb2ce 100644 --- a/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/index.js +++ b/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/index.js @@ -10,18 +10,72 @@ import bytes from 'bytes'; import { Icon, closeSmall } from '@wordpress/icons'; import { store as nfdOnboardingStore } from '../../../../store'; import { useDispatch } from '@wordpress/data'; +import ColorThief from 'colorthief'; const ImageUploaderWithText = ( { image, imageSetter } ) => { const inputRef = useRef( null ); const { theme } = useContext( ThemeContext ); const [ isUploading, setIsUploading ] = useState( false ); const [ onDragActive, setOnDragActive ] = useState( false ); + const [ bgColor, setBgColor ] = useState( 'transparent' ); const { updateSiteGenErrorStatus } = useDispatch( nfdOnboardingStore ); + /* TODO: need to refactor this to use wordpress iamge url and only for png */ + // Utility function to convert a File object to a Data URL + const fileToDataUrl = ( file ) => { + return new Promise( ( resolve, reject ) => { + // eslint-disable-next-line no-undef + const reader = new FileReader(); + reader.onload = () => resolve( reader.result ); + reader.onerror = ( error ) => reject( error ); + reader.readAsDataURL( file ); + } ); + }; + + // Function to extract the dominant color from an image file + const extractDominantColor = async ( fileData ) => { + const dataUrl = await fileToDataUrl( fileData ); + // eslint-disable-next-line no-undef + const img = new Image(); + img.src = dataUrl; + + return new Promise( ( resolve, reject ) => { + img.onload = () => { + const colorThief = new ColorThief(); + try { + const color = colorThief.getColor( img ); + resolve( color ); + } catch ( error ) { + reject( error ); + } + }; + img.onerror = ( error ) => reject( error ); + // This is necessary for CORS policy, even for local files in some browsers + img.crossOrigin = 'Anonymous'; + } ); + }; + async function updateItem( fileData ) { + debugger; if ( fileData ) { setIsUploading( true ); + extractDominantColor( fileData ) + .then( ( color ) => { + console.log( 'Dominant Color:', color ); + const dominantColor = color; + // You can now use this color to set a dynamic background + // For example, setting state to re-render the component with the new background color + // setBackgroundColor(`rgb(${color[0]}, ${color[1]}, ${color[2]})`); + const contrastColor = + determineContrastColor( dominantColor ); + setBgColor( + `rgb(${ contrastColor[ 0 ] }, ${ contrastColor[ 1 ] }, ${ contrastColor[ 2 ] })` + ); + } ) + .catch( ( error ) => { + console.error( 'Error extracting color:', error ); + } ); const res = await uploadImage( fileData ); if ( ! res?.body ) { updateSiteGenErrorStatus( true ); @@ -29,6 +83,7 @@ const ImageUploaderWithText = ( { image, imageSetter } ) => { } const id = res.body?.id; const url = res.body?.source_url; + console.log( 'fildata', fileData.name ); imageSetter( { id, url, @@ -39,6 +94,14 @@ const ImageUploaderWithText = ( { image, imageSetter } ) => { setIsUploading( false ); } + // This function determines a contrasting color (simplified example) + function determineContrastColor( [ r, g, b ] ) { + // This is a very simplified way to determine contrast, consider more sophisticated approach for production + return r * 0.299 + g * 0.587 + b * 0.114 > 186 + ? [ 0, 0, 0 ] + : [ 255, 255, 255 ]; + } + const handleClick = () => { inputRef?.current.click(); }; @@ -158,7 +221,10 @@ const ImageUploaderWithText = ( { image, imageSetter } ) => { ) } { isImageUploaded && ( -
+
Date: Thu, 22 Feb 2024 18:38:12 +0530 Subject: [PATCH 2/3] set background color black or white on transparent images --- package.json | 1 - .../components/ImageUploaderWithText/index.js | 142 +++++++++--------- .../ImageUploaderWithText/stylesheet.scss | 10 +- 3 files changed, 82 insertions(+), 71 deletions(-) diff --git a/package.json b/package.json index 19d8225f6..ef702e456 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,6 @@ "@wordpress/style-engine": "^0.11.0", "bytes": "^3.1.2", "classnames": "^2.3.2", - "colorthief": "^2.4.0", "react-router-dom": "^6.20.1" } } diff --git a/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/index.js b/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/index.js index 30b8eb2ce..d5e237244 100644 --- a/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/index.js +++ b/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/index.js @@ -10,72 +10,74 @@ import bytes from 'bytes'; import { Icon, closeSmall } from '@wordpress/icons'; import { store as nfdOnboardingStore } from '../../../../store'; import { useDispatch } from '@wordpress/data'; -import ColorThief from 'colorthief'; const ImageUploaderWithText = ( { image, imageSetter } ) => { const inputRef = useRef( null ); const { theme } = useContext( ThemeContext ); const [ isUploading, setIsUploading ] = useState( false ); const [ onDragActive, setOnDragActive ] = useState( false ); - const [ bgColor, setBgColor ] = useState( 'transparent' ); + const [ pngLogoBgColor, setPngLogoBgColor ] = useState( 'transparent' ); const { updateSiteGenErrorStatus } = useDispatch( nfdOnboardingStore ); - /* TODO: need to refactor this to use wordpress iamge url and only for png */ - // Utility function to convert a File object to a Data URL - const fileToDataUrl = ( file ) => { - return new Promise( ( resolve, reject ) => { - // eslint-disable-next-line no-undef - const reader = new FileReader(); - reader.onload = () => resolve( reader.result ); - reader.onerror = ( error ) => reject( error ); - reader.readAsDataURL( file ); - } ); - }; - - // Function to extract the dominant color from an image file - const extractDominantColor = async ( fileData ) => { - const dataUrl = await fileToDataUrl( fileData ); + const getDominantColor = ( imageSrc, callback ) => { // eslint-disable-next-line no-undef const img = new Image(); - img.src = dataUrl; + img.crossOrigin = 'Anonymous'; + /* Registering on load before src to so that event listener is ready capture when image loads */ + img.onload = () => { + const canvas = document.createElement( 'canvas' ); + const ctx = canvas.getContext( '2d' ); + canvas.width = img.width; + canvas.height = img.height; + ctx.drawImage( img, 0, 0 ); + const imageData = ctx.getImageData( + 0, + 0, + canvas.width, + canvas.height + ); + const data = imageData.data; + let r = 0, + g = 0, + b = 0, + count = 0; - return new Promise( ( resolve, reject ) => { - img.onload = () => { - const colorThief = new ColorThief(); - try { - const color = colorThief.getColor( img ); - resolve( color ); - } catch ( error ) { - reject( error ); + /* skip transparent areas as the 0 alpha value leads to lower rgb values even in white logos */ + for ( let i = 0; i < data.length; i += 4 ) { + const alpha = data[ i + 3 ]; + if ( alpha > 0 ) { + r += data[ i ]; + g += data[ i + 1 ]; + b += data[ i + 2 ]; + count++; } - }; - img.onerror = ( error ) => reject( error ); - // This is necessary for CORS policy, even for local files in some browsers - img.crossOrigin = 'Anonymous'; - } ); + } + + /* Get the average rgb value of the image */ + if ( count > 0 ) { + // To avoid division by zero + r = Math.floor( r / count ); + g = Math.floor( g / count ); + b = Math.floor( b / count ); + } + + // Callback with the avrage dominant color + callback( `rgb(${ r }, ${ g }, ${ b })` ); + }; + img.src = imageSrc; + }; + + const getContrastingColor = ( color ) => { + /* if the contrast value more than 150 it should have black bg, otherwise white */ + const [ r, g, b ] = color.match( /\d+/g ).map( Number ); + const contrastValue = 0.2126 * r + 0.7152 * g + 0.0722 * b; + return contrastValue > 160 ? 'black' : 'white'; }; async function updateItem( fileData ) { - debugger; if ( fileData ) { setIsUploading( true ); - extractDominantColor( fileData ) - .then( ( color ) => { - console.log( 'Dominant Color:', color ); - const dominantColor = color; - // You can now use this color to set a dynamic background - // For example, setting state to re-render the component with the new background color - // setBackgroundColor(`rgb(${color[0]}, ${color[1]}, ${color[2]})`); - const contrastColor = - determineContrastColor( dominantColor ); - setBgColor( - `rgb(${ contrastColor[ 0 ] }, ${ contrastColor[ 1 ] }, ${ contrastColor[ 2 ] })` - ); - } ) - .catch( ( error ) => { - console.error( 'Error extracting color:', error ); - } ); const res = await uploadImage( fileData ); if ( ! res?.body ) { updateSiteGenErrorStatus( true ); @@ -83,7 +85,15 @@ const ImageUploaderWithText = ( { image, imageSetter } ) => { } const id = res.body?.id; const url = res.body?.source_url; - console.log( 'fildata', fileData.name ); + + if ( fileData && fileData.type === 'image/png' ) { + // Process the image to find the dominant color + getDominantColor( url, ( dominantColor ) => { + const contrastingColor = + getContrastingColor( dominantColor ); + setPngLogoBgColor( contrastingColor ); + } ); + } imageSetter( { id, url, @@ -94,14 +104,6 @@ const ImageUploaderWithText = ( { image, imageSetter } ) => { setIsUploading( false ); } - // This function determines a contrasting color (simplified example) - function determineContrastColor( [ r, g, b ] ) { - // This is a very simplified way to determine contrast, consider more sophisticated approach for production - return r * 0.299 + g * 0.587 + b * 0.114 > 186 - ? [ 0, 0, 0 ] - : [ 255, 255, 255 ]; - } - const handleClick = () => { inputRef?.current.click(); }; @@ -221,18 +223,20 @@ const ImageUploaderWithText = ( { image, imageSetter } ) => { ) } { isImageUploaded && ( -
- { +
+
+ { +

{ image.fileName } diff --git a/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/stylesheet.scss b/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/stylesheet.scss index 77148a5ef..9631fac57 100644 --- a/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/stylesheet.scss +++ b/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/stylesheet.scss @@ -93,10 +93,18 @@ display: flex; flex-direction: row; + &__wrapper { + background-color: transparent; + display: flex; + justify-content: center; + align-items: center; + border-radius: 2px; + } + &__image { width: 130px; height: 100px; - object-fit: cover; + object-fit: contain; border-radius: 4px; } From d4a0b7ea189c46deb261209ba563afd451aee678 Mon Sep 17 00:00:00 2001 From: ajayadav09 Date: Thu, 22 Feb 2024 18:42:31 +0530 Subject: [PATCH 3/3] fix lint --- .../ImageUploader/components/ImageUploaderWithText/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/index.js b/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/index.js index d5e237244..0123832d8 100644 --- a/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/index.js +++ b/src/OnboardingSPA/components/ImageUploader/components/ImageUploaderWithText/index.js @@ -71,7 +71,7 @@ const ImageUploaderWithText = ( { image, imageSetter } ) => { const getContrastingColor = ( color ) => { /* if the contrast value more than 150 it should have black bg, otherwise white */ const [ r, g, b ] = color.match( /\d+/g ).map( Number ); - const contrastValue = 0.2126 * r + 0.7152 * g + 0.0722 * b; + const contrastValue = ( 0.2126 * r ) + ( 0.7152 * g ) + ( 0.0722 * b ); return contrastValue > 160 ? 'black' : 'white'; };