Skip to content

Commit a1581be

Browse files
Merge pull request #10 from Shitanshukumar607/improve-generate
improve generate func, fix support for other file imgs
2 parents ad16071 + d3bf96f commit a1581be

File tree

4 files changed

+57
-36
lines changed

4 files changed

+57
-36
lines changed

app/api/upload/route.ts

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { v2 as cloudinary, UploadApiResponse } from "cloudinary";
33
import ImageTracer from "imagetracerjs";
44
import { NextResponse } from "next/server";
55
import fetch from "node-fetch";
6-
import { PNG } from "pngjs";
6+
import sharp from "sharp";
77

88
cloudinary.config({
99
cloud_name: process.env.CLOUDINARY_CLOUD_NAME!,
@@ -17,44 +17,67 @@ async function cloudinaryToSVG(imageUrl: string, options = { scale: 5 }) {
1717
throw new Error(`Failed to fetch image: ${response.statusText}`);
1818
const buffer = Buffer.from(await response.arrayBuffer());
1919

20-
const png = PNG.sync.read(buffer);
20+
const image = sharp(buffer).ensureAlpha(); // ensures RGBA format
21+
const { width, height } = await image.metadata();
22+
23+
if (!width || !height) {
24+
throw new Error("Unable to read image metadata.");
25+
}
26+
27+
const raw = await image.raw().toBuffer();
2128

2229
const myImageData = {
23-
width: png.width,
24-
height: png.height,
25-
data: png.data,
30+
width,
31+
height,
32+
data: raw,
2633
};
2734

2835
const svgstring = ImageTracer.imagedataToSVG(myImageData, options);
2936
return svgstring;
3037
}
3138

3239
export async function POST(req: Request) {
33-
const formData = await req.formData();
34-
const file = formData.get("image") as File;
40+
try {
41+
const formData = await req.formData();
42+
const file = formData.get("image") as File;
3543

36-
if (!file) {
37-
return NextResponse.json({ error: "No file uploaded" }, { status: 400 });
38-
}
44+
if (!file) {
45+
return NextResponse.json({ error: "No file uploaded" }, { status: 400 });
46+
}
3947

40-
// Read file as buffer
41-
const bytes = await file.arrayBuffer();
42-
const buffer = Buffer.from(bytes);
43-
44-
const cloudinaryResponse: UploadApiResponse = await new Promise(
45-
(resolve, reject) => {
46-
const uploadStream = cloudinary.uploader.upload_stream((err, result) => {
47-
if (err || !result) return reject(err);
48-
resolve(result);
49-
});
50-
uploadStream.end(buffer);
51-
},
52-
);
53-
54-
const svgString = await cloudinaryToSVG(cloudinaryResponse.secure_url);
55-
56-
return NextResponse.json(
57-
{ url: cloudinaryResponse.secure_url, svg: svgString, success: true },
58-
{ status: 201 },
59-
);
48+
const bytes = await file.arrayBuffer();
49+
const buffer = Buffer.from(bytes);
50+
51+
const cloudinaryResponse: UploadApiResponse = await new Promise(
52+
(resolve, reject) => {
53+
const uploadStream = cloudinary.uploader.upload_stream(
54+
{ resource_type: "image" },
55+
(err, result) => {
56+
if (err || !result) return reject(err);
57+
resolve(result);
58+
},
59+
);
60+
uploadStream.end(buffer);
61+
},
62+
);
63+
64+
const svgString = await cloudinaryToSVG(cloudinaryResponse.secure_url);
65+
66+
return NextResponse.json(
67+
{
68+
url: cloudinaryResponse.secure_url,
69+
svg: svgString,
70+
success: true,
71+
},
72+
{ status: 201 },
73+
);
74+
} catch (err: unknown) {
75+
console.error("Upload error:", err);
76+
const errorMessage =
77+
err instanceof Error ? err.message : "Internal Server Error";
78+
return NextResponse.json(
79+
{ success: false, error: errorMessage },
80+
{ status: 500 },
81+
);
82+
}
6083
}

app/generate/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
Upload,
1313
X,
1414
} from "lucide-react";
15-
import Image from "next/image";
1615
import { useCallback, useEffect, useRef, useState } from "react";
1716

1817
interface UploadedFile {
@@ -334,10 +333,11 @@ export default function UploadPage() {
334333
{/* Image Preview */}
335334
<div className="mb-4">
336335
<div className="bg-slate-100 dark:bg-neutral-700 rounded-lg p-4 flex items-center justify-center min-h-[200px]">
337-
<Image
336+
<img
338337
src={file.preview}
339338
alt={file.name}
340339
className="max-w-full max-h-64 object-contain rounded-lg shadow-sm"
340+
loading="lazy"
341341
/>
342342
</div>
343343
<p className="text-xs text-slate-500 dark:text-neutral-400 mt-2 text-center">

package-lock.json

Lines changed: 1 addition & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"pngjs": "^7.0.0",
3030
"react": "19.1.0",
3131
"react-dom": "19.1.0",
32+
"sharp": "^0.34.4",
3233
"tailwind-merge": "^3.3.1"
3334
},
3435
"devDependencies": {

0 commit comments

Comments
 (0)