System designHow-to

Read PNG image data and handle its channels correctly

Read PNG image data with the right file reader, identify grayscale, RGB, indexed and transparent images, and build a threshold mask you can verify.

LumaSpec Vision9 min read Share on LinkedIn

On this page 9 sections
  1. 01What you need and the workflow to follow
  2. 02Open the real PNG, not a hypothetical converted file
  3. 03Inspect the array before choosing a channel
  4. 04Build one deliberate grayscale matrix
  5. 05Normalize the threshold and handle transparency
  6. 06Verify the mask and extract row-column coordinates
  7. 07Diagnose failures by the stage that failed
  8. 08Record the result and plan acquisition separately
  9. 09Questions

A PNG that displays correctly can still fail in a processing script when the script uses the wrong reader or assumes the wrong channel layout. Changing a filename does not convert its format, and an RGB image does not automatically provide a separate brightness matrix.

This workflow is for engineers processing saved inspection images before connecting an acquisition system. You will read the actual file, inspect its decoded arrays, create a deliberate grayscale representation, and verify a threshold mask. The examples use array-oriented image functions such as imread, imfinfo, and rgb2gray; those functions must be available in your installation.

What you need and the workflow to follow

Keep an unchanged copy of the source image and record its full path. Choose a test image containing both bright and dark regions so the threshold produces a meaningful result.

Follow these steps in order:

  1. Open the existing PNG with an image reader that supports PNG.
  2. Inspect its dimensions, numeric class, color map, and transparency output.
  3. Convert grayscale, RGB, or indexed data into one brightness matrix.
  4. Normalize the values and define how transparency affects processing.
  5. Generate the mask, extract coordinates, and compare the output with the image.
  6. Save the interpretation settings alongside your processing result.

An image file contains encoded data and metadata, not simply a rectangular list of pixel values. The distinction is explained in image bytes versus decoded pixel data. Decoding must happen before thresholding or coordinate extraction.

Open the real PNG, not a hypothetical converted file

Use a general image reader for the PNG. A reader dedicated to another format is not a substitute, and a general variable-loading command does not decode an image file.

The following example checks the path before reading:

imageFile = 'inspection.png';

if ~isfile(imageFile)
    error('Image file was not found at the specified path.');
end

info = imfinfo(imageFile);
[raw, map, alpha] = imread(imageFile);

fprintf('Format: %s\n', info.Format);
fprintf('Width: %d, height: %d\n', info.Width, info.Height);
fprintf('Decoded array class: %s\n', class(raw));
disp(size(raw));

Replace the example filename with the file you actually have. A full path removes ambiguity about the current working directory. Keep the extension, but do not rely on the extension alone to prove what the file contains.

If the file is missing, fix the path first. If decoding fails, check that the file opens in an independent image viewer and obtain a fresh copy if necessary. Renaming a damaged file or changing its extension does not repair its contents.

The extra outputs matter. map identifies palette-based image data, while alpha carries transparency when the reader returns it. Ignoring either can make a readable PNG produce misleading threshold results.

Inspect the array before choosing a channel

A PNG is not necessarily an RGB image. It can represent grayscale samples, RGB samples, or indices into a color map. Transparency is another property and should not be mistaken for brightness.

Decoded representation Typical array layout Correct starting point
Grayscale Height × width Process the intensity matrix
RGB Height × width × 3 Choose a channel or create grayscale
Indexed color Height × width, plus a color map Expand the palette before brightness processing
Image with transparency Image data, plus an alpha output Define which pixels are valid

For an illustrative image measuring 640 × 480 pixels, a grayscale array contains 307,200 samples. An RGB array contains 640 × 480 × 3 = 921,600 channel samples. Both represent the same number of image locations, but their array layouts differ.

Do not threshold palette indices as if larger indices meant brighter pixels. Palette entry 20 can be darker than entry 10 because the entries describe colors, not an ordered brightness scale.

Similarly, do not assume the first channel is a brightness component. For RGB data, it is the red channel. A threshold on red answers a different question from a threshold on grayscale brightness.

If channel interpretation becomes uncertain when data crosses software boundaries, use the checks in diagnosing swapped red and blue channels. Confirm the interpretation before making judgments from image appearance.

Build one deliberate grayscale matrix

Convert indexed data through its palette, retain grayscale data directly, and convert RGB data only when brightness is the intended measurement:

if ~isempty(map)
    rgb = ind2rgb(raw, map);
    gray = rgb2gray(rgb);
elseif ismatrix(raw)
    gray = raw;
elseif ndims(raw) == 3 && size(raw, 3) == 3
    gray = rgb2gray(raw);
else
    error('Unsupported decoded image layout.');
end

This produces a two-dimensional matrix named gray. Its values represent image brightness according to the selected conversion, not an independently measured physical quantity.

An RGB-to-grayscale conversion combines the color channels using a defined weighting. It is not the same as taking the red channel, averaging every channel indiscriminately, or requesting a brightness component that was never stored separately.

For some inspections, grayscale is the wrong choice. A red mark and a green background can become similar after conversion even though their colors are readily distinguishable. In that case, choose a channel or a color-based criterion that separates the feature from its background.

If your task involves thermal imagery, distinguish rendered pictures from measurement arrays before processing. The article on retaining temperature data during thermal and RGB fusion explains that separation.

Normalize the threshold and handle transparency

A threshold must use the same numeric scale as the matrix being tested. The value 150 has a different meaning in an unsigned integer image than in a floating-point image normalized between 0 and 1.

Use im2double to normalize supported integer image classes. Floating-point image values are not automatically stretched by this function, so validate the range explicitly:

gray01 = im2double(gray);

if any(~isfinite(gray01(:))) || ...
        any(gray01(:) < 0 | gray01(:) > 1)
    error('Expected finite grayscale values between zero and one.');
end

validPixels = true(size(gray01));

if ~isempty(alpha)
    if ~isequal(size(alpha), size(gray01))
        error('Transparency dimensions do not match the image.');
    end
    validPixels = alpha > 0;
end

threshold01 = 150 / 255;
mask = validPixels & (gray01 >= threshold01);

Here, fully transparent pixels are excluded. Partially transparent pixels remain eligible, and their stored image values are tested without compositing them against a background.

That policy is deliberate, not universal. If the inspection concerns appearance against a white or black background, composite the image onto that background first. If only fully opaque pixels are acceptable, change the validity rule accordingly.

For an 8-bit brightness threshold, the scale conversion is:

Maximum 8-bit value = 2^8 - 1 = 255 Normalized threshold = 150 / 255 ≈ 0.5882

A normalized brightness of 0.60 passes this threshold, while 0.58 does not. Using >= includes values equal to the threshold; using > excludes them. Choose one boundary rule and retain it in the inspection specification.

The normalized scale also makes the intended threshold easier to carry between supported integer representations. It does not make images radiometrically equivalent: exposure, lighting, processing, and grayscale conversion can still change brightness.

Verify the mask and extract row-column coordinates

Display the decoded brightness and the mask separately. Then extract locations from the logical mask rather than from the original multichannel array:

figure;
imshow(gray01);
title('Normalized grayscale image');

figure;
imshow(mask);
title('Pixels meeting the threshold');

[rows, columns] = find(mask);

thresholded = gray01;
thresholded(~mask) = 0;

figure;
imshow(thresholded);
title('Thresholded brightness image');

fprintf('Passing pixels: %d\n', nnz(mask));

rows and columns refer to image-array coordinates. A row describes vertical position, while a column describes horizontal position. These coordinates are not calibrated distances, and they do not automatically match a plotting system that uses a different origin.

Verify the arithmetic with a small synthetic matrix before trusting a large image:

testImage = uint8([100 150 200; 0 149 255]);
testMask = im2double(testImage) >= 150 / 255;
[testRows, testColumns] = find(testMask);

The expected passing locations are row 1, column 2; row 1, column 3; and row 2, column 3. There are 3 passing pixels out of 6, giving a passing fraction of 3 / 6 = 0.50, or 50%.

The returned coordinate order follows array traversal, not a geometric sorting rule. Compare the coordinate pairs as locations rather than assuming they arrive left-to-right across each row.

For a surface plot, supply the two-dimensional brightness matrix, not the RGB array. Start with a small image or a limited crop because plotting every sample can become expensive. A surface plot is a visualization of pixel values, not evidence that those values represent surface height.

Diagnose failures by the stage that failed

Separate file access, decoding, interpretation, and thresholding. Changing all four at once makes a simple mistake difficult to isolate.

Symptom Likely cause Test Fix
File cannot be opened Wrong path or nonexistent filename Check isfile and inspect the full path Point to the existing PNG
Reader rejects the file Wrong reader or damaged contents Check format metadata and an independent viewer Use a PNG-capable reader or replace the file
Threshold creates several planes RGB array used directly Inspect size(raw) Select a channel or create grayscale
Indexed image gives strange regions Palette indices treated as brightness Check whether map is empty Expand through the palette first
Nearly every pixel passes Threshold and data use different scales Inspect class, minimum, and maximum Normalize and document the threshold scale
Invisible regions are detected Transparency ignored Inspect alpha Apply a validity or compositing policy

A correct decode does not guarantee a useful inspection. Shadows, highlights, colored markings, and background texture can overlap the target's brightness range. If no threshold separates the classes, improve image formation or change the feature being measured.

Avoid repeatedly converting, saving, and rereading intermediate images while debugging. Keep the decoded source array unchanged and create named processing arrays. This makes each transformation inspectable and prevents an accidental conversion from becoming the new baseline.

Record the result and plan acquisition separately

Before accepting the workflow, keep this short checklist with the image:

  • Record the file path and decoded dimensions so the input is identifiable.
  • Record whether the source was grayscale, RGB, or indexed color.
  • Record the numeric class and normalization method so thresholds remain interpretable.
  • Record the grayscale or channel-selection rule so another run uses the same measurement.
  • Record the transparency policy and comparison boundary.
  • Save the mask separately from a display screenshot when downstream software needs pixel locations.

You do not need a new camera to correct a PNG-reading error. If saved-image testing later becomes an acquisition project, start with area scan cameras and the camera finder. Select the acquisition hardware from the actual motion, field-of-view, exposure, and interface requirements rather than from the file extension.

The LS-CMR-0053 is a GigE area scan camera to consider when evaluating that interface.

Area scan cameras12 MP GigE area scan camera, IMX226, 1/1.7" rolling shutter, 9 fps (LS-CMR-0053)LS-CMR-0053
Sensor format
1/1.7"
Lens mount
C-mount
Interface
GigE
Resolution
12 MP
$560.00View partBuild a system with it

The LS-CMR-0166 is a USB3 area scan camera for an alternative acquisition path.

Area scan cameras12 MP USB3 area scan camera, IMX226, 1/1.7" rolling shutter, 30 fps, 4000 × 3000 resolution (LS-CMR-0166)LS-CMR-0166
Sensor format
1/1.7"
Interface
USB3
Resolution
12 MP
Shutter
Rolling
$560.00View partBuild a system with it

These are acquisition options, not PNG-processing remedies. Check the complete software export path separately; a camera interface does not establish which saved image formats an application provides.

Before ordering, confirm the required image dimensions, lens compatibility, motion behavior, host interface, and software support. Use the camera configuration starting point for a new acquisition setup, or contact applications support with the decoded array layout and intended threshold behavior.

Questions

Why does a PNG fail when another image opens with the same script?

A format-specific reader expects the structure of its supported format, not merely a filename. Use a PNG-capable image reader and point it at the file that actually exists. Changing an extension or inventing a converted filename does not create a valid conversion.

How can I tell whether a PNG is grayscale, RGB, or indexed?

Check both the decoded array dimensions and any returned color map. A two-dimensional array can contain grayscale samples or palette indices. An RGB image normally has three channel planes. A nonempty color map means you should interpret the samples through that palette before brightness processing.

Can I apply a brightness threshold directly to an RGB array?

Only if the RGB channels are the measurements you intend to compare. Testing an entire RGB array produces channel-level decisions rather than one decision per image location. For brightness segmentation, create grayscale first; for color discrimination, choose an explicit channel or color criterion.

Why do transparent areas appear in my threshold mask?

Transparency can hide stored pixel colors without removing those values from the image data. Define whether to exclude fully transparent pixels, accept only opaque pixels, or composite against a specified background. The appropriate choice depends on whether you inspect stored samples or displayed appearance.

Can grayscale values from a colored PNG be treated as temperature?

Not from appearance alone. A rendered palette or screenshot usually represents display colors rather than a calibrated measurement matrix. Recovering physical quantities requires the original measurement data or a documented, valid mapping with its scale and limitations preserved.