Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #1

Merged
merged 3 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ The `parentRef` is used to fit the ascii art in the parent element, so you need
element like a `div`, you can check the example to see how to use it.

> **Warning**
> Be careful when using this package, the camera must be working before enabling the Image stream.
> Be careful when using this package, the image must be loaded before enabling the Image Ascii component, otherwise it
> will not work.
> If you want to set the ascii art with a correct aspect ratio, follow the examples (webcam or Image player).

The `artType` is used to choose the type of the ascii art, you can choose between `ASCII`, `ASCII_COLOR`
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "image-ascii-art",
"version": "1.0.3",
"version": "1.2.0",
"description": "Convert image to ascii art",
"homepage": "https://im-rises.github.io/image-ascii-art-website",
"repository": {
Expand Down
23 changes: 20 additions & 3 deletions src/canvas-handler/image-canvas-ascii.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@

const incrementFontValue = 0.1; // The value to increment the font size with
const initFontSize = 1.0;// Init font size for calculation (a value to small will make the text not visible on some devices)
const lineSpacing = 0.6;// Set the line spacing for equal distance between the lines and the letters (use em to fit the font size)
const lineSpacing = 0.25;// Set the line spacing for equal distance between the lines and the letters (use em to fit the font size)
const lineHeight = 0.8;// Set the line height for equal distance between the lines and the letters (use em to fit the font size)

// eslint-disable-next-line no-warning-comments
// TODO: The font size function calculateAndSetFontSize has issues with a line height below 1.0
Dismissed Show dismissed Hide dismissed
// When using a value below 1.0 the text will be cut off at the bottom

const calculateAndSetFontSize = (pretag: HTMLPreElement, charsPerLine: number, charsPerColumn: number, parentWidth: number, parentHeight: number) => {
// Create one string with, one line of text filled with W
Expand All @@ -60,6 +65,7 @@
preElementBuffer.style.fontSize = `${fontSize}px`;
preElementBuffer.style.fontFamily = 'monospace';
preElementBuffer.style.letterSpacing = `${lineSpacing}em`;
preElementBuffer.style.lineHeight = `${lineHeight}em`;

// Hide the pre buffer element (display: none, or visibility: hidden, or opacity: 0, or width: 0, or height: 0)
// preElementBuffer.style.display = 'none';// Setting to none will crash the browser as it becomes null or the height is 0
Expand All @@ -68,7 +74,7 @@
// preElementBuffer.style.width = '0%';
// preElementBuffer.style.height = '0%';
// preElementBuffer.style.opacity = '0';
preElementBuffer.style.position = 'absolute';// Setting the position to absolute will in each case set the height
preElementBuffer.style.position = 'absolute';

// Filled the pre element with `filledStringLine` for each line
for (let i = 0; i < charsPerColumn; i++) {
Expand Down Expand Up @@ -103,7 +109,10 @@
pretag.style.fontSize = `${fontSize}px`;

// Debug
console.log('calculateAndSetFontSize');
console.log(`Setting font size to ${fontSize}`);
console.log(`parentHeight: ${parentHeight}, preHeight: ${preHeight}`);
console.log(`parentWidth: ${parentWidth}, preWidth: ${preWidth}`);
};

const canvasImgToUrl = (canvas: HTMLCanvasElement) => {
Expand All @@ -121,4 +130,12 @@
return canvasImgToUrl(canvas);
};

export {getAsciiFromImage, calculateAndSetFontSize, getAsciiFromImageColor, lineSpacing, canvasImgToUrl, videoImgToUrl};
export {
getAsciiFromImage,
calculateAndSetFontSize,
getAsciiFromImageColor,
lineSpacing,
canvasImgToUrl,
videoImgToUrl,
lineHeight,
};
29 changes: 24 additions & 5 deletions src/components/ImageAscii.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {asciiChars} from '../constants/pixel-ascii';
import {
calculateAndSetFontSize, canvasImgToUrl,
getAsciiFromImage,
getAsciiFromImageColor,
getAsciiFromImageColor, lineHeight,
lineSpacing,
} from '../canvas-handler/image-canvas-ascii';

Expand All @@ -22,12 +22,14 @@ type Props = {
backgroundColor: string;
artType: ArtTypeEnum;
preTagRef?: React.RefObject<HTMLPreElement>;
flipY?: boolean;
};

export const ImageAscii = (props: Props) => {
const canvasVideoBufferRef = useRef<HTMLCanvasElement>(null);
const preTagRef = props.preTagRef ?? useRef<HTMLPreElement>(null);
const imageRef = useRef<HTMLImageElement>(null);
const flipY = props.flipY ?? false;

const [asciiText, setAsciiText] = useState('');

Expand Down Expand Up @@ -70,7 +72,7 @@ export const ImageAscii = (props: Props) => {
case ArtTypeEnum.ASCII_COLOR_BG_IMAGE:
setAsciiText(getAsciiFromImage(imageData, asciiChars));
preTagRef.current!.style.backgroundImage = `url(${canvasImgToUrl(canvas).src})`;
// preTagRef.current!.style.backgroundImage = `url(${videoImgToUrl(props.videoStreaming).src})`;
// preTagRef.current!.style.backgroundImage = `url(${props.imageSrc})`;
break;
default:
break;
Expand Down Expand Up @@ -98,6 +100,9 @@ export const ImageAscii = (props: Props) => {
padding: 0,
margin: 0,
letterSpacing: `${lineSpacing}em`,
lineHeight: `${lineHeight}em`,
transform: `scaleX(${flipY ? -1 : 1})`,
overflow: 'hidden',
}}>
{asciiText}
</pre>
Expand All @@ -111,25 +116,39 @@ export const ImageAscii = (props: Props) => {
padding: 0,
margin: 0,
letterSpacing: `${lineSpacing}em`,
lineHeight: `${lineHeight}em`,
transform: `scaleX(${flipY ? -1 : 1})`,
overflow: 'hidden',
}}
></pre>
);
case ArtTypeEnum.ASCII_COLOR_BG_IMAGE:
return (
<div style={{width: '100%', height: '100%'}}>
<span>
{
/*
This span is important for the browser, it helps differentiate
the other pre tag from the one with the background image when
toggling the artType. If the pre tag is not present, the browser
might think that the change of pre tag is an update not a replace
*/
}
<pre ref={preTagRef} style={{
padding: 0,
margin: 0,
letterSpacing: `${lineSpacing}em`,
backgroundSize: 'cover',
lineHeight: `${lineHeight}em`,
backgroundSize: '100% 100%',
backgroundClip: 'text',
WebkitBackgroundClip: 'text',
color: 'transparent',
transform: `scaleX(${flipY ? -1 : 1})`,
overflow: 'hidden',
// backgroundImage: `url(${props.videoStreaming.src})`,
}}>
{asciiText}
</pre>
</div>
</span>
);
default:
return (<p>ERROR</p>);
Expand Down