@primestyleai/tryon 5.10.103 → 5.10.104

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -139,10 +139,21 @@ export type ViewState = "idle" | "welcome" | "body-profile" | "estimation-review
139
139
  export type DrawerType = "profiles" | "history" | null;
140
140
  export interface PrimeStyleTryonProps {
141
141
  productImage: string;
142
- /** Optional gallery of product photos for the active color/variant. Shown
143
- * as an auto-cycling carousel on the single-garment SizeResultView while
144
- * the try-on image is being generated, to keep the user entertained. */
142
+ /** Optional gallery of product photos for the active color/variant.
143
+ *
144
+ * - Shown as an auto-cycling carousel on the single-garment
145
+ * SizeResultView while the try-on image is being generated.
146
+ * - At try-on time the SDK runs MediaPipe BlazePose on every entry in
147
+ * parallel and forwards the highest-scoring "model wearing the
148
+ * garment" shot to Gemini as image 2. Flat-lays / close-up details
149
+ * score ~0 and are skipped. The first image still shows in the UI
150
+ * unchanged. */
145
151
  productImages?: string[];
152
+ /** Optional explicit override — if you already know which image in the
153
+ * gallery is the model-wearing-the-garment shot, pass it here and the
154
+ * SDK skips the MediaPipe-based auto-pick. Falls through to auto-pick
155
+ * (or to `productImage`) when omitted. */
156
+ garmentReferenceImage?: string;
146
157
  productTitle?: string;
147
158
  /** Stable product identifier — used to cache size recommendations per (profile, product) */
148
159
  productId?: string;
@@ -0,0 +1 @@
1
+ export declare function pickBestGarmentImage(images: string[] | null | undefined): Promise<string | null>;
@@ -10588,6 +10588,45 @@ function getUnitLabel(unit) {
10588
10588
  if (unit === "mm") return "mm";
10589
10589
  return "";
10590
10590
  }
10591
+ const cache = /* @__PURE__ */ new Map();
10592
+ function scoreLandmarks(lm) {
10593
+ if (!lm) return 0;
10594
+ let joints = 0;
10595
+ for (const [k2, v2] of Object.entries(lm)) {
10596
+ if (k2 === "imageWidth" || k2 === "imageHeight") continue;
10597
+ if (v2 && typeof v2 === "object" && typeof v2.x === "number") joints++;
10598
+ }
10599
+ let score = joints * 10;
10600
+ if (lm.nose) score += 50;
10601
+ if (lm.leftAnkle && lm.rightAnkle) score += 5;
10602
+ return score;
10603
+ }
10604
+ async function scoreImage(url) {
10605
+ try {
10606
+ const lm = await detectBodyLandmarks(url);
10607
+ return scoreLandmarks(lm);
10608
+ } catch {
10609
+ return 0;
10610
+ }
10611
+ }
10612
+ async function pickBestGarmentImage(images) {
10613
+ if (!images || !images.length) return null;
10614
+ if (images.length === 1) return images[0];
10615
+ const cacheKey = images.join("|");
10616
+ const cached = cache.get(cacheKey);
10617
+ if (cached) return cached;
10618
+ const t0 = Date.now();
10619
+ const scored = await Promise.all(images.map(async (url) => ({
10620
+ url,
10621
+ score: await scoreImage(url)
10622
+ })));
10623
+ scored.sort((a, b) => b.score - a.score);
10624
+ const best = (scored[0]?.score ?? 0) > 0 ? scored[0].url : images[0];
10625
+ cache.set(cacheKey, best);
10626
+ console.log(`[ps-sdk:garment-pick] ${Date.now() - t0}ms — chose ${images.indexOf(best)}/${images.length}`);
10627
+ for (const s of scored) console.log(`[ps-sdk:garment-pick] ${s.score.toString().padStart(4, " ")} ${s.url}`);
10628
+ return best;
10629
+ }
10591
10630
  function cx(base, override) {
10592
10631
  return override ? `${base} ${override}` : base;
10593
10632
  }
@@ -27672,6 +27711,7 @@ function measurementTypeToVtoCategory(type) {
27672
27711
  function PrimeStyleTryonInner({
27673
27712
  productImage,
27674
27713
  productImages,
27714
+ garmentReferenceImage,
27675
27715
  productTitle = "Product",
27676
27716
  productId,
27677
27717
  productDescription,
@@ -28837,9 +28877,19 @@ function PrimeStyleTryonInner({
28837
28877
  fitInfo = buildFitInfo(effectiveMatchDetails, modelPoseRef.current, unit);
28838
28878
  }
28839
28879
  console.log("[ps-sdk:tryon] fitInfo built", { count: fitInfo?.length || 0, areas: fitInfo?.map((f2) => `${f2.area}(${f2.fit})`) });
28880
+ let garmentImage = productImage;
28881
+ if (garmentReferenceImage) {
28882
+ garmentImage = garmentReferenceImage;
28883
+ } else if (productImages && productImages.length > 1) {
28884
+ const best = await pickBestGarmentImage(productImages);
28885
+ if (best && best !== productImage) {
28886
+ console.log(`[ps-sdk:tryon] auto-picked garment reference: ${best}`);
28887
+ garmentImage = best;
28888
+ }
28889
+ }
28840
28890
  const response = await apiRef.current.submitTryOn(
28841
28891
  modelImage,
28842
- productImage,
28892
+ garmentImage,
28843
28893
  fitInfo,
28844
28894
  vtoCategory ?? "apparel",
28845
28895
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primestyleai/tryon",
3
- "version": "5.10.103",
3
+ "version": "5.10.104",
4
4
  "description": "PrimeStyle Virtual Try-On SDK — React component & Web Component",
5
5
  "type": "module",
6
6
  "main": "dist/primestyle-tryon.js",