[]
        
(Showing Draft Content)

Work with Image Colors

DsPdfJS provides APIs for manipulating the color characteristics of images. You can automatically adjust color intensity to improve contrast, manually remap histogram levels to control tonal range, and work directly with individual color channels. These operations are performed using methods of the Bitmap class and related image‑processing types.

Adjust Color Intensity of an Image

You can improve the color intensity of an image by automatically adjusting the range of RGB channel intensities. In DsPdfJS, this is done using the autoLevels method of the Bitmap class. The method modifies color intensities so that the full range of values (0–255) is utilized, improving contrast and correcting highlights and shadows. It can also optionally preserve the relative intensities of color channels while clipping extremely low or high values.

autoLevels.png

To adjust the color intensity of an image:

  1. Load the image using the Image.load method.

  2. Convert the image to a bitmap using toBitmap.

  3. Call the autoLevels method to automatically adjust the color intensities.

  4. Save the resulting image.

const img = Image.load(await Util.loadFile("images/house.jpg"));
const bmp = img.toBitmap();

bmp.autoLevels(true, 2, 2);

const result = await Util.combineTwoImages(
    img, "Original Image",
    bmp, "Image after autoLevels"
);

const imgBytes = result.saveAsPng();
Util.saveFile("autoLevels.png", imgBytes, "image/png");


// Helper method used in this sample to display images side by side.
static async combineTwoImages(img1, text1, img2, text2) {

    const om = getCurrentObjectManager();
    pushObjectManager();

    const img1W = img1.width;
    const img1H = img1.height;
    const img2W = img2.width;
    const img2H = img2.height;

    const margin = 10;
    const m2 = margin * 2;
    const header = 40;
    const lw = 1;

    const fmt = new Format({
        font: Font.load(await Util.loadFile("fonts/segoeuib.ttf")),
        fontSize: 16
    });

    const tl1 = new Layout({ runs: [{ text: text1, format: fmt }] });
    const tl2 = new Layout({ runs: [{ text: text2, format: fmt }] });
    tl1.performLayout();
    tl2.performLayout();

    const txt1W = tl1.contentWidth;
    const txt2W = tl2.contentWidth;
    const max1W = img1W > txt1W ? img1W : txt1W;
    const max2W = img2W > txt2W ? img2W : txt2W;
    const maxH = img1H > img2H ? img1H : img2H;

    const ctx = new BmpContext(om, max1W + max2W + lw * 3 + m2 * 2, maxH + m2 + lw * 3 + header, 1, "DarkGray");

    let x1 = lw;
    let x2 = x1 + m2 + max1W + lw;
    let y1 = header + lw * 2;

    ctx.drawRect(x1, lw, max1W + m2, header, { fillColor: "LightGray" });
    ctx.drawRect(x2, lw, max2W + m2, header, { fillColor: "LightGray" });

    ctx.drawRect(x1, y1, max1W + m2, maxH + m2, { fillColor: "GhostWhite" });
    ctx.drawRect(x2, y1, max2W + m2, maxH + m2, { fillColor: "GhostWhite" });

    x1 += margin;
    x2 += margin;
    y1 += margin;

    ctx.drawImage(img1, x1, y1 + (maxH - img1H) / 2, img1W, img1H);
    ctx.drawImage(img2, x2, y1 + (maxH - img2H) / 2, img2W, img2H);

    const y0 = 10;
    ctx.drawLayout(tl1, x1, y0);
    ctx.drawLayout(tl2, x2, y0);

    popObjectManager();
    return ctx.bitmap;
}

Adjust Histogram Levels

Adjusting histogram levels allows you to control the tonal range and brightness distribution of an image. DsPdfJS provides the adjustLevels method of the Bitmap class to map the input color range to a new output range using optional gamma correction.

adjustLevels.png

To adjust histogram levels of an image:

  1. Load the image using the Image.load method.

  2. Convert the image to a bitmap using toBitmap.

  3. Call the adjustLevels method and specify the input and output color ranges.

  4. Save the resulting image.

const img = Image.load(await Util.loadFile("images/house.jpg"));
const bmp = img.toBitmap();

bmp.adjustLevels("Black", "#646464", "#969696", "#FAFAFA");

const result = await Util.combineTwoImages(
    img, "Original Image",
    bmp, "Image after adjustLevels"
);

const imgBytes = result.saveAsPng();
Util.saveFile("adjustLevels.png", imgBytes, "image/png");

Color Channels

Digital images are composed of color channels that represent primary colors. In the RGB color model, each pixel contains red, green, and blue channel data. DsPdfJS allows you to work with these channels individually using the exportColorChannel and importColorChannel methods of the Bitmap class.

The exportColorChannel method extracts data for a specific color channel from an image and stores it in a grayscale bitmap. The importColorChannel method copies channel data from a grayscale bitmap back into a color bitmap. This makes it possible to analyze individual channels or reconstruct images by combining channel data.

colorChannels.png

To work with color channels:

  1. Load the image using the Image.load method.

  2. Convert the image to a bitmap using toBitmap.

  3. Export channel data using the exportColorChannel method.

  4. Create or modify a bitmap by importing channel data using importColorChannel.

  5. Save the resulting image.


const original = Image.load(await Util.loadFile("images/tudor.jpg")).toBitmap();
const imgW = 400;
const imgH = 400;

const bmp1 = original.clip({ x: 300, y: 300, width: imgW, height: imgH });

const gsRed = new GrayscaleBitmap(imgW, imgH);
const gsGreen = new GrayscaleBitmap(imgW, imgH);
const gsBlue = new GrayscaleBitmap(imgW, imgH);

bmp1.exportColorChannel(gsRed, ColorChannel.Red);
bmp1.exportColorChannel(gsGreen, ColorChannel.Green);
bmp1.exportColorChannel(gsBlue, ColorChannel.Blue);

const bmp2 = new Bitmap(imgW, imgH, "Black");
bmp2.importColorChannel(gsGreen, ColorChannel.Green);

const bmp3 = new Bitmap(imgW, imgH, "White");
bmp3.importColorChannel(gsBlue, ColorChannel.Red);
bmp3.importColorChannel(gsGreen, ColorChannel.Green);
bmp3.importColorChannel(gsRed, ColorChannel.Blue);

const bmp = await Util.combineThreeImages(
    bmp1, "Original Image",
    bmp2, "Green Channel Only",
    bmp3, "Swap Red and Blue Channels"
);

const imgBytes = bmp.saveAsPng();
Util.saveFile("colorChannels.png", imgBytes, "image/png");

// Helper method used in this sample to display images side by side.
static async combineThreeImages(img1, text1, img2, text2, img3, text3) {

    const om = getCurrentObjectManager();
    pushObjectManager();

    const img1W = img1.width;
    const img1H = img1.height;
    const img2W = img2.width;
    const img2H = img2.height;
    const img3W = img3.width;
    const img3H = img3.height;

    const margin = 10;
    const m2 = margin * 2;
    const header = 40;
    const lw = 1;

    const fmt = new Format({
        font: Font.load(await Util.loadFile("fonts/segoeuib.ttf")),
        fontSize: 16
    });

    const tl1 = new Layout({ runs: [{ text: text1, format: fmt }] });
    const tl2 = new Layout({ runs: [{ text: text2, format: fmt }] });
    const tl3 = new Layout({ runs: [{ text: text3, format: fmt }] });
    tl1.performLayout();
    tl2.performLayout();
    tl3.performLayout();

    const txt1W = tl1.contentWidth;
    const txt2W = tl2.contentWidth;
    const txt3W = tl3.contentWidth;
    const max1W = img1W > txt1W ? img1W : txt1W;
    const max2W = img2W > txt2W ? img2W : txt2W;
    const max3W = img3W > txt3W ? img3W : txt3W;
    let maxH = img1H;
    if (maxH < img2H) maxH = img2H;
    if (maxH < img3H) maxH = img3H;

    const ctx = new BmpContext(om, max1W + max2W + max3W + lw * 4 + m2 * 3, maxH + m2 + lw * 3 + header, 1, "DarkGray");

    let x1 = lw;
    let x2 = x1 + m2 + max1W + lw;
    let x3 = x2 + m2 + max2W + lw;
    let y1 = header + lw * 2;

    ctx.drawRect(x1, lw, max1W + m2, header, { fillColor: "LightGray" });
    ctx.drawRect(x2, lw, max2W + m2, header, { fillColor: "LightGray" });
    ctx.drawRect(x3, lw, max3W + m2, header, { fillColor: "LightGray" });

    ctx.drawRect(x1, y1, max1W + m2, maxH + m2, { fillColor: "GhostWhite" });
    ctx.drawRect(x2, y1, max2W + m2, maxH + m2, { fillColor: "GhostWhite" });
    ctx.drawRect(x3, y1, max3W + m2, maxH + m2, { fillColor: "GhostWhite" });

    x1 += margin;
    x2 += margin;
    x3 += margin;
    y1 += margin;

    ctx.drawImage(img1, x1, y1 + (maxH - img1H) / 2, img1W, img1H);
    ctx.drawImage(img2, x2, y1 + (maxH - img2H) / 2, img2W, img2H);
    ctx.drawImage(img3, x3, y1 + (maxH - img3H) / 2, img3W, img3H);

    const y0 = 10;
    ctx.drawLayout(tl1, x1, y0);
    ctx.drawLayout(tl2, x2, y0);
    ctx.drawLayout(tl3, x3, y0);

    popObjectManager();
    return ctx.bitmap;
}