@@ -2,12 +2,10 @@ import fetch from "node-fetch";
22import { encode } from "blurhash" ;
33import sharp from 'sharp' ;
44import sizeOf from "image-size" ;
5- import { URL } from 'url' ;
65
76export interface IOptions {
87 size ?: number ;
98 offline ?: boolean ;
10- timeout ?: number ;
119}
1210
1311export interface IOutput {
@@ -17,89 +15,70 @@ export interface IOutput {
1715}
1816
1917/**
20- * ** Generate a Blurhash string from a given image URL or local path.**
18+ * Generate a Blurhash string from a given image URL or local path.
2119 *
2220 * @param {string } source - The image URL or local path to the image file.
2321 * @param {IOptions } [options] - The optional configuration options.
2422 * @param {number } [options.size=32] - The desired size of the image for encoding the Blurhash.
2523 * @param {boolean } [options.offline=false] - Set to `true` if the image source is a local path, `false` if it's a URL.
26- * @param {number } [options.timeout=30000] - Timeout in milliseconds for fetch requests.
2724 * @returns {Promise<IOutput> } The Promise that resolves to the encoded Blurhash string, along with the image width and height.
28- * @throws {Error } If the source is invalid or if there's an error processing the image.
25+ * @default size 32
26+ * @default offline false
27+ * @example
28+ * ```js
29+ * import { blurhashFromURL } from "blurhash-from-url";
30+ *
31+ * const output = await blurhashFromURL("https://i.imgur.com/NhfEdg2.png", {
32+ * size: 32,
33+ * });
34+ *
35+ * console.log(output);
36+ * ```
2937 */
30-
3138export const blurhashFromURL = async ( source : string , options : IOptions = { } ) : Promise < IOutput > => {
32- const { size = 32 , offline = false , timeout = 30000 } = options ;
33-
34- if ( ! source ) {
35- throw new Error ( "Source is required" ) ;
36- }
37-
38- if ( ! offline ) {
39- try {
40- new URL ( source ) ;
41- } catch {
42- throw new Error ( "Invalid URL provided" ) ;
43- }
44- }
39+ const { size = 32 , offline = false } = options ;
4540
4641 let width , height , returnedBuffer ;
4742
48- try {
49- if ( offline ) {
50- const fs = await import ( "fs" ) . catch ( ( ) => {
51- throw new Error ( "Failed to import 'fs' module. Make sure you're in a Node.js environment." ) ;
52- } ) ;
53- const { width : localWidth , height : localHeight } = sizeOf ( source ) ;
54- width = localWidth ;
55- height = localHeight ;
56- returnedBuffer = await sharp ( fs . readFileSync ( source ) ) . toBuffer ( ) ;
57- } else {
58- const controller = new AbortController ( ) ;
59- const timeoutId = setTimeout ( ( ) => controller . abort ( ) , timeout ) ;
60-
61- try {
62- const response = await fetch ( source , { signal : controller . signal } ) ;
63- if ( ! response . ok ) {
64- throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
65- }
66- const arrayBuffer = await response . arrayBuffer ( ) ;
67- returnedBuffer = Buffer . from ( arrayBuffer ) ;
43+ if ( offline ) {
44+ const fs = await import ( "fs" ) ;
45+ const { width : localWidth , height : localHeight } = sizeOf ( source ) ;
46+ width = localWidth ;
47+ height = localHeight ;
48+ returnedBuffer = await sharp ( fs . readFileSync ( source ) ) . toBuffer ( ) ;
49+ } else {
50+ const response = await fetch ( source ) ;
51+ const arrayBuffer = await response . arrayBuffer ( ) ;
52+ returnedBuffer = Buffer . from ( arrayBuffer ) ;
6853
69- const { width : remoteWidth , height : remoteHeight } = sizeOf ( returnedBuffer ) ;
70- width = remoteWidth ;
71- height = remoteHeight ;
72- } finally {
73- clearTimeout ( timeoutId ) ;
74- }
75- }
54+ const { width : remoteWidth , height : remoteHeight } = sizeOf ( returnedBuffer ) ;
55+ width = remoteWidth ;
56+ height = remoteHeight ;
57+ }
7658
77- const { info, data } = await sharp ( returnedBuffer )
78- . resize ( size , size , {
79- fit : "inside" ,
80- } )
81- . ensureAlpha ( )
82- . raw ( )
83- . toBuffer ( {
84- resolveWithObject : true ,
85- } ) ;
59+ const { info, data } = await sharp ( returnedBuffer )
60+ . resize ( size , size , {
61+ fit : "inside" ,
62+ } )
63+ . ensureAlpha ( )
64+ . raw ( )
65+ . toBuffer ( {
66+ resolveWithObject : true ,
67+ } ) ;
8668
87- const encoded = encode (
88- new Uint8ClampedArray ( data ) ,
89- info . width ,
90- info . height ,
91- 4 ,
92- 4
93- ) ;
69+ const encoded = encode (
70+ new Uint8ClampedArray ( data ) ,
71+ info . width ,
72+ info . height ,
73+ 4 ,
74+ 4
75+ ) ;
9476
95- const output : IOutput = {
96- encoded,
97- width,
98- height,
99- } ;
77+ const output : IOutput = {
78+ encoded,
79+ width,
80+ height,
81+ } ;
10082
101- return output ;
102- } catch ( error ) {
103- throw new Error ( `Failed to process image: ${ error . message } ` ) ;
104- }
105- } ;
83+ return output ;
84+ } ;
0 commit comments