# How Archify's 4× Native Rasterization Export Pipeline Eliminates Upsampling Blur

> Archify's 4x native rasterization pipeline exports crisp images avoiding upsampling blur by pre-scaling SVG data before browser rendering. Get sharper visuals effortlessly.

- Repository: [tt-a1i/archify](https://github.com/tt-a1i/archify)
- Tags: performance
- Published: 2026-07-14

---

**Archify generates crisp PNG, JPEG, and WebP exports by pre-scaling SVG data to 4× resolution before browser rasterization, completely avoiding the interpolation blur that occurs when images are scaled up after rendering.**

Archify’s open-source diagramming tool converts vector visualizations to raster formats using a **4× native rasterization export pipeline** that renders high-fidelity images without the softness typical of conventional upsampling. Unlike standard approaches that rasterize at screen resolution then enlarge, the pipeline serializes the SVG at the target pixel dimensions upfront according to the `tt-a1i/archify` source code. This technique leverages the browser’s native rendering engine to produce bitmaps at exactly the desired resolution, eliminating the distortion caused by post-raster scaling.

## The Problem with Post-Raster Upscaling

Traditional export workflows often render an SVG at a low base resolution—such as 800×600 pixels—then programmatically scale the resulting bitmap to 3200×2400 pixels to meet high-DPI requirements. This **post-raster upsampling** forces the browser or graphics library to interpolate pixel values, producing the characteristic softness and edge artifacts that degrade diagram clarity. Archify’s pipeline eliminates this step by instructing the browser to rasterize the SVG at the final target size from the start.

## How the 4× Native Rasterization Pipeline Works

The export implementation in [`examples/web-app.html`](https://github.com/tt-a1i/archify/blob/main/examples/web-app.html) processes raster conversion through five precise stages that maintain geometric fidelity from vector to pixel.

### 1. Select a Safe Scale Factor

The pipeline begins by determining the optimal multiplier using `pickSafeScale()`, which selects the largest integer from the set `{4, 3, 2, 1}` that keeps the total canvas area below the **hard memory limit** defined by `MAX_CANVAS_PIXELS = 16,777,216` pixels (16 Mi px). The constant `RASTER_SCALE` defaults to `4`, meaning the system attempts to generate images at four times the SVG’s native viewBox dimensions before falling back to smaller multipliers for complex diagrams.

```javascript
// From examples/web-app.html#L71-L78
function pickSafeScale(vbWidth, vbHeight) {
  const scales = [4, 3, 2, 1];
  for (const scale of scales) {
    if (vbWidth * scale * vbHeight * scale <= MAX_CANVAS_PIXELS) {
      return scale;
    }
  }
  return 1; // Fallback
}

```

### 2. Pre-Scale the SVG Dimensions

Rather than applying a CSS transform or canvas scaling operation, the `serializeSvg(scale)` function creates a new SVG string where the `width` and `height` attributes are multiplied by the chosen scale factor. This **pre-scaling** ensures that when the browser parses the SVG, it treats the document as having the target resolution natively, not as a zoomed version of a smaller canvas.

```javascript
// From examples/web-app.html#L53-L55
function serializeSvg(scale) {
  const svg = document.querySelector('.diagram-container svg');
  const vb = svg.viewBox.baseVal;
  const width = vb.width * scale;
  const height = vb.height * scale;
  // Returns { svgString, width, height }
}

```

### 3. Load as High-Resolution Image

The serialized SVG string is wrapped in a Blob and assigned to an `Image` element via `URL.createObjectURL()`. Because the SVG markup already encodes the high-resolution geometry (e.g., a 400×300 viewBox becomes 1600×1200 at 4×), the browser’s internal rasterizer generates a bitmap at exactly those dimensions without approximation.

```javascript
// From examples/web-app.html#L91-L100
const svgBlob = new Blob([data.svgString], { type: 'image/svg+xml' });
const svgUrl = URL.createObjectURL(svgBlob);
const img = new Image();
img.onload = () => {
  // Canvas setup occurs here
};
img.src = svgUrl;

```

### 4. Draw at Natural Size Without Resampling

The pipeline creates a canvas sized precisely to the pre-scaled dimensions (`data.width`, `data.height`) and executes `ctx.drawImage(img, 0, 0)` without specifying destination width or height parameters. This **1:1 pixel mapping** simply copies the already-high-resolution raster data into the canvas buffer, avoiding any resampling algorithms that would introduce blur.

```javascript
// From examples/web-app.html#L105-L107
const canvas = document.createElement('canvas');
canvas.width = data.width;   // Already scaled (e.g., 1600 instead of 400)
canvas.height = data.height;
ctx.drawImage(img, 0, 0);    // Natural size copy, no scaling

```

### 5. Export the Raw Pixel Buffer

Finally, `canvas.toBlob()` encodes the bitmap in the requested format (PNG, JPEG, or WebP). Since the pixel data was generated at the target resolution from the original vector paths, the exported file contains sharp edges and accurate colors with no interpolation artifacts.

## Memory Safety Through Dynamic Scaling

The **safe scale selection** logic ensures the pipeline never exceeds browser memory constraints while maximizing output quality. By testing the pixel count (width × height × scale²) against `MAX_CANVAS_PIXELS` before rasterization, Archify prevents canvas allocation failures on devices with limited RAM. If a 4× export would exceed 16 million pixels—common with large architecture diagrams—the system automatically selects 3×, 2×, or 1× while still avoiding upsampling blur for that specific resolution.

## Implementation Example

The complete rasterization routine coordinates these steps into a single promise-based export function:

```javascript
// Complete rasterization workflow
function rasterize(format) {
  const svg = document.querySelector('.diagram-container svg');
  const vb = svg.viewBox.baseVal;
  const scale = pickSafeScale(vb.width, vb.height);   // 4× unless too large
  const data = serializeSvg(scale);                  // SVG at target size
  
  return new Promise((resolve) => {
    const img = new Image();
    img.onload = () => {
      const canvas = document.createElement('canvas');
      canvas.width = data.width;
      canvas.height = data.height;
      const ctx = canvas.getContext('2d');
      
      // Background fill for JPEG (no alpha)
      if (format === 'jpeg') {
        ctx.fillStyle = currentBg();
        ctx.fillRect(0, 0, canvas.width, canvas.height);
      }
      
      ctx.drawImage(img, 0, 0);  // Crisp 1:1 copy
      canvas.toBlob(resolve, mimeFor(format));
    };
    img.src = URL.createObjectURL(new Blob([data.svgString], {type:'image/svg+xml'}));
  });
}

// Usage
rasterize('png').then(blob => {
  download(blob, 'diagram.png');
});

```

## Summary

- **Pre-scaling vs. upsampling**: Archify modifies SVG dimensions before rasterization rather than scaling the resulting bitmap, eliminating interpolation blur.
- **4× default with fallback**: The `RASTER_SCALE` constant targets 4× resolution but automatically reduces to 3×, 2×, or 1× via `pickSafeScale()` to respect the 16 Mi px `MAX_CANVAS_PIXELS` limit.
- **Native browser rendering**: The pipeline uses standard `Image` and `Canvas` APIs with 1:1 pixel mapping to preserve vector sharpness in the final export.
- **Zero post-processing**: By drawing the image at its natural size without transform operations, the code avoids the resampling algorithms that soften edges in traditional export workflows.

## Frequently Asked Questions

### Why does upsampling cause blur in raster images?

Upsampling forces the graphics engine to invent new pixel values through interpolation algorithms (typically bicubic or bilinear) when stretching a small image to fit a larger canvas. These algorithms calculate intermediate colors by averaging existing pixels, which softens hard edges and reduces contrast at line boundaries. Archify’s pipeline avoids this entirely by generating the exact target pixel count during the initial SVG rasterization phase.

### What is the maximum export resolution supported?

The theoretical maximum is constrained by `MAX_CANVAS_PIXELS = 16,777,216` pixels (approximately 16 megapixels), enforced in [`examples/web-app.html`](https://github.com/tt-a1i/archify/blob/main/examples/web-app.html). For a square diagram, this translates to roughly 4096×4096 pixels at 1× scale, though the algorithm prefers 4× scaling for smaller diagrams to maximize clarity. Specific limits depend on the source SVG’s aspect ratio and the selected safe scale factor.

### How does the pipeline handle diagrams with transparent backgrounds?

The rasterization logic checks the export format before drawing. For **JPEG** exports, which lack alpha channel support, the code fills the canvas with the current background color (`currentBg()`) before drawing the image. For **PNG** and **WebP**, the canvas defaults to transparent or inherits the CSS background, preserving alpha channels from the original SVG since no background fill operation occurs.

### Can I modify the default 4× scale factor?

Yes. The `RASTER_SCALE` constant in [`examples/web-app.html`](https://github.com/tt-a1i/archify/blob/main/examples/web-app.html) defaults to `4`, but developers can adjust this value or modify the `pickSafeScale()` logic to prioritize different quality-to-performance ratios. Reducing the default to `2` decreases memory usage and processing time for large diagrams while still maintaining sharper results than post-raster upsampling, though `4×` provides optimal clarity for high-DPI displays.