<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David Miller</title>
    <description>The latest articles on DEV Community by David Miller (@morphio).</description>
    <link>https://dev.to/morphio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4179400%2F09c81e5a-b04c-4ad5-bc95-3aaba5e95a9f.png</url>
      <title>DEV Community: David Miller</title>
      <link>https://dev.to/morphio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/morphio"/>
    <language>en</language>
    <item>
      <title>Map a displayed crop rectangle into intrinsic image coordinates</title>
      <dc:creator>David Miller</dc:creator>
      <pubDate>Wed, 04 Nov 2026 04:00:15 +0000</pubDate>
      <link>https://dev.to/morphio/map-a-displayed-crop-rectangle-into-intrinsic-image-coordinates-38eb</link>
      <guid>https://dev.to/morphio/map-a-displayed-crop-rectangle-into-intrinsic-image-coordinates-38eb</guid>
      <description>&lt;p&gt;A crop picker often displays an image smaller than its source. If the picker reports a rectangle in displayed coordinates, passing those numbers directly to &lt;code&gt;drawImage()&lt;/code&gt; selects the wrong part of the source. Scale the selection into intrinsic image coordinates first.&lt;/p&gt;

&lt;p&gt;For an &lt;code&gt;HTMLImageElement&lt;/code&gt;, &lt;code&gt;drawImage()&lt;/code&gt; uses intrinsic dimensions. &lt;code&gt;image.width&lt;/code&gt; can describe a displayed size, so use &lt;code&gt;naturalWidth&lt;/code&gt; and &lt;code&gt;naturalHeight&lt;/code&gt; when calculating the source rectangle. See &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage#notes" rel="noopener noreferrer"&gt;MDN's drawImage notes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Assume the entire decoded image is displayed in a 600 by 400 coordinate area. Its intrinsic dimensions are 2400 by 1600. A selection beginning at displayed point (150, 100), with displayed width 300 and height 200, maps to source point (600, 400), width 1200 and height 800.&lt;/p&gt;

&lt;p&gt;This helper performs the scaling. The rectangle must already be relative to the displayed image content, excluding borders, padding, and any letterboxing. All arguments are numbers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sourceRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;shownWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;shownHeight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;shownWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;shownHeight&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;isFinite&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="nx"&gt;shownWidth&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;shownHeight&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;naturalWidth&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;naturalHeight&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;shownWidth&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;shownHeight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RangeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Selection must be inside a loaded image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scaleX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;naturalWidth&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;shownWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scaleY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;naturalHeight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;shownHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;scaleX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;scaleY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;scaleX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;scaleY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the result as the four source arguments in the nine-argument &lt;code&gt;drawImage()&lt;/code&gt; overload. Choose the destination width and height separately; those describe the output canvas region, not the selection in the original image.&lt;/p&gt;

&lt;p&gt;This helper does not translate pointer coordinates or model CSS transforms. A picker using &lt;code&gt;object-fit: contain&lt;/code&gt; must first locate the actual image rectangle inside its element. A rotated or mirrored preview also needs its own inverse mapping. Resolve those layout details before calling the helper.&lt;/p&gt;

&lt;p&gt;Put a different mark near each corner of a test image. Select one corner in the reduced preview and inspect the resulting crop. Then repeat at another corner to catch an incorrect offset.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>html</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Validate a contained pixel rectangle before reading a canvas crop</title>
      <dc:creator>David Miller</dc:creator>
      <pubDate>Tue, 03 Nov 2026 02:40:26 +0000</pubDate>
      <link>https://dev.to/morphio/validate-a-contained-pixel-rectangle-before-reading-a-canvas-crop-iok</link>
      <guid>https://dev.to/morphio/validate-a-contained-pixel-rectangle-before-reading-a-canvas-crop-iok</guid>
      <description>&lt;p&gt;A crop rectangle needs a stated coordinate space. If an application requires a rectangle fully inside the drawing buffer, check that requirement before calling getImageData().&lt;/p&gt;

&lt;p&gt;The browser API can return transparent black for the part of a requested rectangle outside the canvas. A stricter application rule can reject that rectangle instead. This example accepts only positive, integer-sized rectangles with nonnegative integer origins.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;containedPixelRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canvasWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canvasHeight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rect&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Expected a rectangle object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canvasWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canvasHeight&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isSafeInteger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="nx"&gt;canvasWidth&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;canvasHeight&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;canvasWidth&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;canvasHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RangeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rectangle must fit inside the drawing buffer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;containedPixelRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// In browser code, after obtaining a 2D context:&lt;/span&gt;
&lt;span class="c1"&gt;// const pixels = ctx.getImageData(rect.x, rect.y, rect.width, rect.height);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the canvas drawing-buffer dimensions for this check. A rectangle expressed in displayed CSS coordinates needs to be mapped into that coordinate space first. Perform that mapping before using this validator.&lt;/p&gt;

&lt;p&gt;Passing the numeric check also does not grant permission to read a canvas containing restricted cross-origin image content. Handle the actual read failure at the call site. Keep that failure distinct from a rejected rectangle so a report can say which condition stopped the operation.&lt;/p&gt;

&lt;p&gt;I work on &lt;a href="https://morphio.online/" rel="noopener noreferrer"&gt;Morphio&lt;/a&gt;. For an image crop request associated with that project, I would state the coordinate space and the containment rule with the rectangle values.&lt;/p&gt;

&lt;p&gt;API reference: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData" rel="noopener noreferrer"&gt;getImageData()&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Do not treat image complete as a successful decode result</title>
      <dc:creator>David Miller</dc:creator>
      <pubDate>Mon, 02 Nov 2026 00:32:15 +0000</pubDate>
      <link>https://dev.to/morphio/do-not-treat-image-complete-as-a-successful-decode-result-23pf</link>
      <guid>https://dev.to/morphio/do-not-treat-image-complete-as-a-successful-decode-result-23pf</guid>
      <description>&lt;p&gt;&lt;code&gt;HTMLImageElement.complete&lt;/code&gt; can be &lt;code&gt;true&lt;/code&gt; for a broken image. It can also be true when the element has no source, so it cannot establish that an image loaded successfully.&lt;/p&gt;

&lt;p&gt;For an image-processing step, handle the operation you actually need. If the next step requires decoding, await &lt;code&gt;decode()&lt;/code&gt; and handle rejection before replacing the preview. Keep the selected job identifier available when your application allows another file to be chosen during that wait.&lt;/p&gt;

&lt;p&gt;The following is an illustrative boundary around an existing image element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;requireDecodedImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Handle rejection in the caller. A rejected promise should leave the previous preview intact when that is the intended interface behavior. Do not label an export ready merely because an earlier &lt;code&gt;complete&lt;/code&gt; check returned true.&lt;/p&gt;

&lt;p&gt;Keep load or decode status separate from the later canvas drawing and export result. Successful decoding does not establish that every subsequent operation will succeed. Name the failing stage in the interface so a missing image and a failed export are distinguishable.&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/complete" rel="noopener noreferrer"&gt;MDN complete&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>html</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Label File.lastModified as a file timestamp in an image list</title>
      <dc:creator>David Miller</dc:creator>
      <pubDate>Sun, 01 Nov 2026 02:43:29 +0000</pubDate>
      <link>https://dev.to/morphio/label-filelastmodified-as-a-file-timestamp-in-an-image-list-3c3d</link>
      <guid>https://dev.to/morphio/label-filelastmodified-as-a-file-timestamp-in-an-image-list-3c3d</guid>
      <description>&lt;p&gt;Keep the label for &lt;code&gt;File.lastModified&lt;/code&gt; specific: it is a file modification timestamp. A photograph's capture time needs a separate source.&lt;/p&gt;

&lt;p&gt;The value is a number of milliseconds since the Unix epoch. You can format it with &lt;code&gt;new Date(file.lastModified).toISOString()&lt;/code&gt; when a UTC display suits the interface. Keep the numeric value in the job record if later comparisons depend on it.&lt;/p&gt;

&lt;p&gt;A file created in JavaScript can receive an explicit &lt;code&gt;lastModified&lt;/code&gt; option. When that option is omitted, it is normally assigned the current time at creation; this makes it unsuitable as proof of when the image was photographed. A file without a known modification date can also report the current date.&lt;/p&gt;

&lt;p&gt;Keep any capture date under a separate field with its own source and uncertainty. Leave a missing capture date empty instead of substituting the file timestamp. If the user is comparing two exports, identify which timestamp was inspected and which file it belongs to.&lt;/p&gt;

&lt;p&gt;I work on &lt;a href="https://morphio.online/" rel="noopener noreferrer"&gt;Morphio&lt;/a&gt; and write about browser image workflows. This distinction concerns the file record and does not claim that a conversion tool preserves or reads camera metadata. Reference: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/File/lastModified" rel="noopener noreferrer"&gt;MDN File.lastModified&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Let the browser set the multipart boundary for an image upload</title>
      <dc:creator>David Miller</dc:creator>
      <pubDate>Sat, 31 Oct 2026 07:41:15 +0000</pubDate>
      <link>https://dev.to/morphio/let-the-browser-set-the-multipart-boundary-for-an-image-upload-444f</link>
      <guid>https://dev.to/morphio/let-the-browser-set-the-multipart-boundary-for-an-image-upload-444f</guid>
      <description>&lt;p&gt;Leave &lt;code&gt;Content-Type&lt;/code&gt; unset in the request options when &lt;code&gt;fetch()&lt;/code&gt; sends &lt;code&gt;FormData&lt;/code&gt;. The browser adds the multipart boundary needed by that body.&lt;/p&gt;

&lt;p&gt;Build the form with &lt;code&gt;const data = new FormData(); data.append("image", file);&lt;/code&gt; and pass it as the request body. A manually supplied &lt;code&gt;Content-Type: multipart/form-data&lt;/code&gt; omits the boundary that the browser normally adds. Apply this rule to requests whose body is &lt;code&gt;FormData&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Check a shared request helper for an unconditional JSON or multipart header before blaming the image bytes. Keep any authorization headers your application actually requires. Inspect the request and the server's response using a small non-sensitive test image.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects" rel="noopener noreferrer"&gt;MDN FormData guide&lt;/a&gt; explains the boundary requirement. In a bug report, identify the body type and header construction without copying credentials into the report.&lt;/p&gt;

&lt;p&gt;I work on Morphio, our image project at &lt;a href="https://morphio.online/" rel="noopener noreferrer"&gt;https://morphio.online/&lt;/a&gt;. These notes describe image preparation and review; they do not require a particular editing tool.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Keep the filename separate when appending a Blob to FormData</title>
      <dc:creator>David Miller</dc:creator>
      <pubDate>Fri, 30 Oct 2026 03:47:49 +0000</pubDate>
      <link>https://dev.to/morphio/keep-the-filename-separate-when-appending-a-blob-to-formdata-5hj7</link>
      <guid>https://dev.to/morphio/keep-the-filename-separate-when-appending-a-blob-to-formdata-5hj7</guid>
      <description>&lt;p&gt;Keep a Blob's uploaded filename explicit in FormData. A plain Blob has no File name, so supply the name as append()'s third argument. The Blob contains data and a type, but has no File name.&lt;/p&gt;

&lt;p&gt;The third argument to append() supplies the name reported to the server. For example, form.append("image", blob, "preview.png") names the uploaded part. The default name for a plain Blob is "blob"; a File uses its own filename unless another is supplied.&lt;/p&gt;

&lt;p&gt;Choose the extension from the output format you actually produced. Giving the part a .png name does not convert its bytes. When reading the server's upload report, check the field name image and filename preview.png separately.&lt;/p&gt;

&lt;p&gt;Test with a small sample and inspect the name the server receives. Keep server-side validation in place; a supplied filename is descriptive metadata.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/FormData/append" rel="noopener noreferrer"&gt;MDN FormData.append()&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Treat a file input accept attribute as a chooser hint</title>
      <dc:creator>David Miller</dc:creator>
      <pubDate>Thu, 29 Oct 2026 02:33:47 +0000</pubDate>
      <link>https://dev.to/morphio/treat-a-file-input-accept-attribute-as-a-chooser-hint-354d</link>
      <guid>https://dev.to/morphio/treat-a-file-input-accept-attribute-as-a-chooser-hint-354d</guid>
      <description>&lt;p&gt;An image file input still needs validation when it has an accept attribute. The attribute supplies a picker hint; it does not verify the chosen file.&lt;/p&gt;

&lt;p&gt;For an image form, accept="image/*" can make selection easier, while the application still needs to check the file it receives. Keep the destination's supported formats explicit in the interface instead of treating the broad image filter as its complete policy.&lt;/p&gt;

&lt;p&gt;Validate the expected requirement on the server too. Keep server validation in place when adding a client-side selection check. If the destination rejects a file, preserve its error rather than treating the presence of an image extension as proof of acceptance.&lt;/p&gt;

&lt;p&gt;Test a supported sample and a deliberately unsuitable sample through the same form. Record the selected filename and the actual response for each attempt.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/accept" rel="noopener noreferrer"&gt;MDN accept&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I work on &lt;a href="https://morphio.online/" rel="noopener noreferrer"&gt;Morphio&lt;/a&gt;, and this note is part of the image-workflow guidance I maintain.&lt;/p&gt;

</description>
      <category>html</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Compare image file limits in bytes before formatting the size</title>
      <dc:creator>David Miller</dc:creator>
      <pubDate>Wed, 28 Oct 2026 02:22:02 +0000</pubDate>
      <link>https://dev.to/morphio/compare-image-file-limits-in-bytes-before-formatting-the-size-2288</link>
      <guid>https://dev.to/morphio/compare-image-file-limits-in-bytes-before-formatting-the-size-2288</guid>
      <description>&lt;p&gt;Check an image file against the exact byte limit before rounding its size for display. File.size supplies the byte count used by that comparison.&lt;/p&gt;

&lt;p&gt;Keep the limit as a number in the validation code. For a hypothetical form with a stated limit of 2,000,000 bytes, the condition file.size &amp;gt; 2_000_000 rejects files above that value. Equality remains accepted under that particular rule. Use the destination's actual requirement instead of assuming what its MB label means.&lt;/p&gt;

&lt;p&gt;Format a separate value for the interface after the comparison. Keep the unit clear if you display decimal megabytes or binary mebibytes. A file that rounds to the displayed limit can still exceed the exact byte count.&lt;/p&gt;

&lt;p&gt;This check establishes only the local size comparison. The destination can reject an upload for another reason. Preserve its error message and check the accepted preview separately.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob/size" rel="noopener noreferrer"&gt;MDN Blob.size&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Match settled image jobs to their original inputs</title>
      <dc:creator>David Miller</dc:creator>
      <pubDate>Tue, 27 Oct 2026 04:19:22 +0000</pubDate>
      <link>https://dev.to/morphio/match-settled-image-jobs-to-their-original-inputs-109o</link>
      <guid>https://dev.to/morphio/match-settled-image-jobs-to-their-original-inputs-109o</guid>
      <description>&lt;p&gt;Pair Promise.allSettled() outcomes with a captured copy of the input list. The records keep input order even when an image job started earlier finishes later.&lt;/p&gt;

&lt;p&gt;Use the status field before reading a result. A fulfilled record has a value; a rejected record has a reason. Keep the corresponding source identifier with either kind of record so a failed image job is not silently removed from the batch report.&lt;/p&gt;

&lt;p&gt;The returned order does not impose a concurrency limit or establish that a produced image was downloaded by the user. Those are separate parts of the workflow. If the interface permits another selection while work runs, keep the running batch's list unchanged.&lt;/p&gt;

&lt;p&gt;Before showing the summary, compare the number of outcome records with the captured input list. Display failures alongside successful jobs, with wording that describes what the application actually confirmed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled" rel="noopener noreferrer"&gt;Reference: MDN Promise.allSettled()&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Published by &lt;a href="https://morphio.online/" rel="noopener noreferrer"&gt;Morphio&lt;/a&gt; as part of our practical image workflow notes.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Release an image preview object URL when its owner removes it</title>
      <dc:creator>David Miller</dc:creator>
      <pubDate>Mon, 26 Oct 2026 00:34:39 +0000</pubDate>
      <link>https://dev.to/morphio/release-an-image-preview-object-url-when-its-owner-removes-it-3n69</link>
      <guid>https://dev.to/morphio/release-an-image-preview-object-url-when-its-owner-removes-it-3n69</guid>
      <description>&lt;p&gt;Keep each object URL with the image preview that owns it. Release the URL when that preview is removed and its consumers no longer need it.&lt;/p&gt;

&lt;p&gt;Calling URL.revokeObjectURL() releases the object URL created by URL.createObjectURL(). Revoking a URL as soon as it is assigned can be too early if user interactions still need it.&lt;/p&gt;

&lt;p&gt;When replacing a preview, give the new preview its own URL and retire the previous one according to the same ownership rule. Include cleanup when the containing view is closed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL_static" rel="noopener noreferrer"&gt;Reference: MDN revokeObjectURL()&lt;/a&gt;&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Give same-named image files separate batch IDs</title>
      <dc:creator>David Miller</dc:creator>
      <pubDate>Sun, 25 Oct 2026 04:37:25 +0000</pubDate>
      <link>https://dev.to/morphio/give-same-named-image-files-separate-batch-ids-31gj</link>
      <guid>https://dev.to/morphio/give-same-named-image-files-separate-batch-ids-31gj</guid>
      <description>&lt;p&gt;Assign image-batch rows identifiers that do not depend on File.name being unique. MDN documents that name excludes the path. A name does not establish that two selected files are the same file.&lt;/p&gt;

&lt;p&gt;Assign the row IDs when accepting the batch. Display the original filename separately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeBatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;batchId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;batchId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The caller must supply a batchId that is unique among batches retained by the application. The index distinguishes rows within that batch. It is not a content hash and does not deduplicate files.&lt;/p&gt;

&lt;p&gt;Use the row ID to attach each result or error to its input. Reordering the visible list should not change the ID assigned when the row was created.&lt;/p&gt;

&lt;p&gt;I work on &lt;a href="https://morphio.online/" rel="noopener noreferrer"&gt;Morphio&lt;/a&gt;, an image conversion project. The bookkeeping pattern here is a design suggestion. It does not describe the project's implementation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/File/name" rel="noopener noreferrer"&gt;Reference: MDN File.name&lt;/a&gt;&lt;/p&gt;

</description>
      <category>coding</category>
      <category>javascript</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Reject invalid output sizes before assigning canvas.width</title>
      <dc:creator>David Miller</dc:creator>
      <pubDate>Sat, 24 Oct 2026 03:33:56 +0000</pubDate>
      <link>https://dev.to/morphio/reject-invalid-output-sizes-before-assigning-canvaswidth-3p4</link>
      <guid>https://dev.to/morphio/reject-invalid-output-sizes-before-assigning-canvaswidth-3p4</guid>
      <description>&lt;p&gt;Validate the requested dimensions before changing a canvas. Decide which sizes your application accepts, and report an invalid request before it changes the preview.&lt;/p&gt;

&lt;p&gt;This example accepts numbers and numeric strings. After conversion, each side must be an integer from 1 to 4096. The cap is a sample application policy, not a portable limit for browsers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkedSide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isSafeInteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RangeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Output side must be an integer from 1 to 4096&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeOutputCanvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkedSide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkedSide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function checks both inputs before creating an output canvas. Passing an empty string fails because it converts to zero. Passing "512" succeeds. If your form requires a stricter text format, replace that conversion rule with the parsing policy you intend to support.&lt;/p&gt;

&lt;p&gt;Creating a separate output canvas leaves the existing preview alone. Setting the width of an existing canvas clears its buffer and resets the drawing context, even if you assign its current width again.&lt;/p&gt;

&lt;p&gt;A valid request can still fail later. Choose limits with the total pixel count and concurrent work in mind, and handle errors when you obtain a context or export the result. The integer check alone does not establish that the browser can allocate the image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/width" rel="noopener noreferrer"&gt;Reference: MDN canvas.width&lt;/a&gt;&lt;/p&gt;

</description>
      <category>coding</category>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
