repos/kloeckner.com.ar

Backup of part of my webpage
Commits Files Refs README LICENSE
blog/another-imagemagick-use-case-process-oscilloscope-screenshots/another-imagemagick-use-case-process-oscilloscope-screenshots.md (122 lines)

%% title: "Another ImageMagick Use Case: Process Oscilloscope Screenshots" date: "28-Aug-2026" %%

Another ImageMagick Use Case: Process Oscilloscope Screenshots

It's been a while since the last post (time flies, right?), a lot has happened but recently I bought a portable oscilloscope, the OWON HDS25S (2CH, 25 MHz, 250 MSa/s, 8 kSa memory depth), maybe I will talk about it in a future post, but in this one I want to talk about another use case I found for ImageMagick: process oscilloscope screenshots to change the dark color scheme to a lighter one, making it suitable for reports and if desired, for printing.

Owon HDS25S front Owon HDS25S back

Of course, ImageMagick has an infinite number of uses: converting images from one format to another, compressing images, applying filters, etc. But with these posts, I focus on those uses that are more complex or specific to a particular use case.

So, even though I recently bought the oscilloscope, I've already used it extensively for assignments and lab reports. In particular, I found the oscilloscope's screenshot feature very useful for reports. I also like that two screenshots fit nicely side by side on a PDF page because of the screen's 4:3 aspect ratio.

Sine with frecuency 250 Hz and dark scheme Sine with frequency 637 Hz and dark scheme

As seen in the pictures above, the screenshots are clear and look nice, but when using them in reports, for my personal taste, they look better with a lighter color scheme. This also makes sense if the report needs to be printed, as it uses much less ink since there is no need to print the background.

To convert the screenshots from a dark to a light color scheme, I created a shell script that applies a series of ImageMagick filters to the input file. Part of the resulting shell script can be seen below.

WIDTH=$(magick "$INPUT" -format '%w' info:)
HEIGHT=$(magick "$INPUT" -format '%h' info:)
TRIG_X=$((WIDTH * 975 / 1000))

magick "$INPUT" -negate -colorspace Gray \
    +sigmoidal-contrast 8x65%            \
    -level 20%,90% gray.png

magick "$INPUT" -alpha off -fuzz 5%     \
    -fill transparent +opaque '#F81C00' \
    -fill '#ED0000' -opaque '#F81C00'   \
    red_mask.png

magick "$INPUT" -alpha off -fuzz 5%     \
    -fill transparent +opaque '#00FC00' \
    -fill '#007A3D' -opaque '#00FC00'   \
    green_mask.png

magick "$INPUT" -alpha off -fuzz 5%                   \
    -fill transparent +opaque '#68C4F0'               \
    -fill '#FC0000' -opaque '#68C4F0'                 \
    -region "$((WIDTH-TRIG_X))x${HEIGHT}+${TRIG_X}+0" \
    -fill "#FF6900" -opaque '#FC0000'                 \
    +region blue_mask.png

magick "$INPUT" -alpha off -fuzz 5%                   \
    -fill transparent +opaque '#F8E400'               \
    -fill '#005FFF' -opaque '#F8E400'                 \
    -region "$((WIDTH-TRIG_X))x${HEIGHT}+${TRIG_X}+0" \
    -fill "#FF6900" -opaque '#005FFF'                 \
    +region yellow_mask.png

magick "$INPUT" -alpha off -fuzz 5%     \
    -fill transparent +opaque '#F87C20' \
    -fill "#FF6900" -opaque '#F87C20'   \
    orange_mask.png

magick "$INPUT" -alpha off -fuzz 5%     \
    -fill transparent +opaque '#10F8F0' \
    -fill '#FF00FF' -opaque '#10F8F0'   \
    cyan_mask.png

magick gray.png     -colorspace sRGB         \
    red_mask.png    -compose Over -composite \
    blue_mask.png   -compose Over -composite \
    yellow_mask.png -compose Over -composite \
    green_mask.png  -compose Over -composite \
    orange_mask.png -compose Over -composite \
    cyan_mask.png   -compose Over -composite \
    "$OUTPUT"

The script works, by creating a color-inverted greyscale version of the input image and saving it as gray.png. Then, for the main colors used by the interface: red, blue, green, orange, cyan and yellow, it creates a mask in which only that particular color appears, while the rest of the colors are made transparent. It then replaces that color with the desired new color. For example, for channel one's yellow #F8E400, yellow_mask.png is created with the yellow color replaced with blue #005FFF.

At the end, all the masks are combined on top of the previously created inverted greyscale image, resulting in the final image shown below.

Sine with frecuency 250 Hz and light scheme Sine with frequency 637 Hz and light scheme

It is true that simply inverting the image would have been enough, but I think it was worth the effort to write the script, given that the colors can be specified arbitrarily and the final result is better.

   1 %%
   2 title: "Another ImageMagick Use Case: Process Oscilloscope Screenshots"
   3 date: "28-Aug-2026"
   4 %%
   5 
   6 # Another ImageMagick Use Case: Process Oscilloscope Screenshots
   7 
   8 It's been a while since the last post (time flies, right?), a lot has happened
   9 but recently I bought a portable oscilloscope, the OWON HDS25S (2CH, 25 MHz, 250
  10 MSa/s, 8 kSa memory depth), maybe I will talk about it in a future post, but in
  11 this one I want to talk about another use case I found for ImageMagick: process
  12 oscilloscope screenshots to change the dark color scheme to a lighter one,
  13 making it suitable for reports and if desired, for printing.
  14 
  15 <!--
  16 <div class="centered-img">
  17     <img style="width: 38%" src="hds25s.png" alt="OWON HDS25s">
  18 </div>
  19 -->
  20 
  21 <div class="side-by-side">
  22     <img style="max-width: 33%"  src="hds25s.webp" alt="Owon HDS25S front">
  23     <img style="max-width: 55%" src="hds25s_back_trim.webp" alt="Owon HDS25S back">
  24 </div>
  25 
  26 Of course, ImageMagick has an infinite number of uses: converting images from
  27 one format to another, compressing images, applying filters, etc. But with these
  28 posts, I focus on those uses that are more complex or specific to a particular
  29 use case.
  30 
  31 So, even though I recently bought the oscilloscope, I've already used it
  32 extensively for assignments and lab reports. In particular, I found the
  33 oscilloscope's screenshot feature very useful for reports. I also like that two
  34 screenshots fit nicely side by side on a PDF page because of the screen's 4:3
  35 aspect ratio.
  36 
  37 <div class="side-by-side">
  38   <img src="sine_250.png" alt="Sine with frecuency 250 Hz and dark scheme">
  39   <img src="sine_637.png" alt="Sine with frequency 637 Hz and dark scheme">
  40 </div>
  41 
  42 As seen in the pictures above, the screenshots are clear and look nice, but when
  43 using them in reports, for my personal taste, they look better with a lighter
  44 color scheme. This also makes sense if the report needs to be printed, as it
  45 uses much less ink since there is no need to print the background.
  46 
  47 To convert the screenshots from a dark to a light color scheme, I created a
  48 shell script that applies a series of ImageMagick filters to the input file.
  49 Part of the resulting shell script can be seen below.
  50 
  51 ```shell
  52 WIDTH=$(magick "$INPUT" -format '%w' info:)
  53 HEIGHT=$(magick "$INPUT" -format '%h' info:)
  54 TRIG_X=$((WIDTH * 975 / 1000))
  55 
  56 magick "$INPUT" -negate -colorspace Gray \
  57     +sigmoidal-contrast 8x65%            \
  58     -level 20%,90% gray.png
  59 
  60 magick "$INPUT" -alpha off -fuzz 5%     \
  61     -fill transparent +opaque '#F81C00' \
  62     -fill '#ED0000' -opaque '#F81C00'   \
  63     red_mask.png
  64 
  65 magick "$INPUT" -alpha off -fuzz 5%     \
  66     -fill transparent +opaque '#00FC00' \
  67     -fill '#007A3D' -opaque '#00FC00'   \
  68     green_mask.png
  69 
  70 magick "$INPUT" -alpha off -fuzz 5%                   \
  71     -fill transparent +opaque '#68C4F0'               \
  72     -fill '#FC0000' -opaque '#68C4F0'                 \
  73     -region "$((WIDTH-TRIG_X))x${HEIGHT}+${TRIG_X}+0" \
  74     -fill "#FF6900" -opaque '#FC0000'                 \
  75     +region blue_mask.png
  76 
  77 magick "$INPUT" -alpha off -fuzz 5%                   \
  78     -fill transparent +opaque '#F8E400'               \
  79     -fill '#005FFF' -opaque '#F8E400'                 \
  80     -region "$((WIDTH-TRIG_X))x${HEIGHT}+${TRIG_X}+0" \
  81     -fill "#FF6900" -opaque '#005FFF'                 \
  82     +region yellow_mask.png
  83 
  84 magick "$INPUT" -alpha off -fuzz 5%     \
  85     -fill transparent +opaque '#F87C20' \
  86     -fill "#FF6900" -opaque '#F87C20'   \
  87     orange_mask.png
  88 
  89 magick "$INPUT" -alpha off -fuzz 5%     \
  90     -fill transparent +opaque '#10F8F0' \
  91     -fill '#FF00FF' -opaque '#10F8F0'   \
  92     cyan_mask.png
  93 
  94 magick gray.png     -colorspace sRGB         \
  95     red_mask.png    -compose Over -composite \
  96     blue_mask.png   -compose Over -composite \
  97     yellow_mask.png -compose Over -composite \
  98     green_mask.png  -compose Over -composite \
  99     orange_mask.png -compose Over -composite \
 100     cyan_mask.png   -compose Over -composite \
 101     "$OUTPUT"
 102 ```
 103 
 104 The script works, by creating a color-inverted greyscale version of the input
 105 image and saving it as `gray.png`. Then, for the main colors used by the
 106 interface: red, blue, green, orange, cyan and yellow, it creates a mask in which
 107 only that particular color appears, while the rest of the colors are made
 108 transparent. It then replaces that color with the desired new color. For
 109 example, for channel one's yellow `#F8E400`, `yellow_mask.png` is created with
 110 the yellow color replaced with blue `#005FFF`.
 111 
 112 At the end, all the masks are combined on top of the previously created inverted
 113 greyscale image, resulting in the final image shown below.
 114 
 115 <div class="side-by-side">
 116   <img src="sine_250_light.png" alt="Sine with frecuency 250 Hz and light scheme">
 117   <img src="sine_637_light.png" alt="Sine with frequency 637 Hz and light scheme">
 118 </div>
 119 
 120 It is true that simply inverting the image would have been enough, but I think
 121 it was worth the effort to write the script, given that the colors can be
 122 specified arbitrarily and the final result is better.