[Question]
  [
Given an image, either as input (possibly in RGB triplets) or with the filename as input (you may assume the image has a specific filename, possibly without an extension), output an image representing a single color channel of the image.
You will also take another input, representing which channel to output. The input can be one of any 3 distinct symbols. However, the symbols must be either a string or a number. You cannot take a matrice to apply to the array as input however. (such as `{1, 0, 0}`, or `{0, 1, 0}`).
You will output the `<input>` channel of the input image. You may either save it to a file or output a set of RGB pairs.
Your program should have no limits on the size of the image (in px), and must support either `.png`, `.jpg`/`.jpeg`/`.JPG`, or RGB triplets as image formats. (it can support as many as you want however)
Test case:
[![violet original](https://i.stack.imgur.com/Rwp0c.png)](https://i.stack.imgur.com/Rwp0c.png)
Red channel:
[![violet red](https://i.stack.imgur.com/O7j1r.png)](https://i.stack.imgur.com/O7j1r.png)
Green channel:
[![violet green](https://i.stack.imgur.com/Qsvo7.png)](https://i.stack.imgur.com/Qsvo7.png)
Blue channel:
[![violet blue](https://i.stack.imgur.com/ZZSiR.png)](https://i.stack.imgur.com/ZZSiR.png)
And another test case, entirely of red. [Original photo](https://i.stack.imgur.com/7rl5Tm.png), [red](https://i.stack.imgur.com/3zvrHm.png), [green](https://i.stack.imgur.com/tHlbjm.png), and [blue](https://i.stack.imgur.com/OSeOWm.png). (warning: the plain and red channel hurt to look at for too long)
2 more test cases:
[Original](https://i.stack.imgur.com/S5CuU.png), [red](https://i.stack.imgur.com/eGP3p.png), [green](https://i.stack.imgur.com/69ivJ.png), [blue](https://i.stack.imgur.com/i4Kup.png).
[Original](https://i.stack.imgur.com/Ov3Gm.png), [red](https://i.stack.imgur.com/ncJux.png), [green](https://i.stack.imgur.com/l6YeK.png), [blue](https://i.stack.imgur.com/Wspfm.png).
The latter two test cases are from [Images with all colors](https://codegolf.stackexchange.com/questions/22144/images-with-all-colors).
  
[Answer]
# JavaScript (ES6), 29 bytes
```
a=>n=>a.map(b=>b.map(c=>c&n))
```
Input is a 2D array of 24-bit integers (e.g. `[[0x0000ff,0x00ff00],[0xff0000,0xffffff]]`) and `16711680` for red, `65280` for green, `255` for blue. If this isn't valid, try this instead:
## JavaScript (ES6), 48 bytes
```
a=>n=>a.map(b=>b.map(c=>c.map((d,i)=>i==n?d:0)))
```
Input is a 3D array of color values and `0` for red, `1` for green, `2` for blue.
[Answer]
## Mathematica, 13 bytes
```
ImageMultiply
```
This should be the legitimate version of JungHwan Min's answer. This function takes the image and one of `Red`, `Green`, `Blue` as input. For example:
[![enter image description here](https://i.stack.imgur.com/CU0td.png)](https://i.stack.imgur.com/CU0td.png)
As a fun-fact, there's also `ColorSeparate` which gives you individual channels, but it returns them as single-channel/greyscale images, so you'd need to multiply them by the colour afterwards anyway.
[Answer]
# [Spectrum](https://github.com/ConorOBrien-Foxx/Spectrum), noncompeting, 1 byte
(Non-competing because this challenge inspired this language.) In reality, Spectrum is an npm library with a language interface for the commands.
```
I
```
Takes input as:
```
<filename>
channel
```
Call the program as:
```
cat input.txt | node spectrum.js "I"
```
Alternatively, you may supply information to the prompts:
```
λ node spectrum.js "I"
input> Ov3Gm.png
input> r
[ Image { 512x512 } ]
```
This leaves the image on the stack. To view it, add `O` at the end, like so:
```
λ node spectrum.js "IO"
input> Ov3Gm.png
input> r
[]
```
---
For some extra fun, try `echo filename | node spectrum.js "wO"`. It performs all three channel isolations at once:
[![warhol](https://i.stack.imgur.com/pWVsZ.png)](https://i.stack.imgur.com/pWVsZ.png)
[Answer]
# Bash + ImageMagick, ~~35~~ ~~32~~ 27 bytes
```
mogrify -channel $1 -fx 0 i
```
Assumes the image is in the file `i` and the script takes one of `RG`, `BG`, `BR` for blue, red, and green respectively; outputs to the file `i`.
[Answer]
## JavaScript (ES6), 29 bytes
```
a=>b=>a.map((v,i)=>i%3^b?0:v)
```
A lot like [ETHproductions' answer](https://codegolf.stackexchange.com/a/114418/67501 "ETHproductions") but with more flexible input than the first method and smaller than the second one.
This defines a function which accepts the image as a 1-dimensional array of numerical colour intensities. This function then returns another function which accepts an integer value representing the desired colour channel.
Colours can be represented by any numerical range as long as 0 indicates a complete absence of colour. E.g. `0.0 - 1.0` or `0 - 255`
**Examples:**
If image data is in the format RGB then calling the function with arguments `(imageData)(0)` will return the image with only the red channel.
If image data is in the format BGR then calling the function with arguments `(imageData)(2)` will also return the image with only the red channel.
[Answer]
# Python 2, 69 bytes
```
from cv2 import*
def f(s,i):k=imread(s);k[:,:,[i,i-1]]=0;imwrite(s,k)
```
Still golfing.
Takes input as `filename, n` (where `n` is 0, 1, or 2). Saves the new image over the old one. `0` is green, `1` is red, and `2` is blue. Thanks to @ovs, @Mikhail and @Rod for bytes off.
[Answer]
# [CJam](https://sourceforge.net/p/cjam), 12 bytes
```
{3,f=f{f.*}}
```
An anonymous block that expects a 3D array of RGB triplets and a number between 0 and 2 inclusive on the stack. Leaves the extracted array on the stack afterward.
```
Red   -> 0
Green -> 1
Blue  -> 2
```
Could possibly be golfed by using a bizarre input format, but I feel like that's cheating a bit.
[Try it online!](https://tio.run/nexus/cjam#K6z7X22sk2abVp2mp1Vb@7@u4H90dLShgpGCcWy0iYKpgllstLmChYJlbKwCieKxCgYA "CJam – TIO Nexus")
The test case is made up just to demonstrate, using the triplets from an actual image would be way too big.
**Explanation**
```
3,          e# The range [0 1 2]
  f=        e# Check each for equality with the RGB indicator, gives the indicator array:
            e#  [1 0 0] for 0, [0 1 0] for 1, [0 0 1] for 2
    f{      e# Map on each row of the array using the indicator array as an extra parameter
      f.*   e#  Perform vectorized multiplication of the indicator array with each triplet.
            e#   For red, multiplies red by 1, and green and blue by 0. Does similarly
            e#   for green and blue.
         }  e# (end of block)
```
[Answer]
# [PowerShell](https://github.com/TryItOnline/TioSetup/wiki/Powershell), 282 bytes
```
$x,$y=$args;1..($a=New-Object System.Drawing.Bitmap $x).Height|%{$h=--$_;1..$a.Width|%{$i=("$($a.GetPixel(--$_,$h)|select R,G,B)"|iex)[$y];$r,$g,$b=(((0,0,$i),(0,$i,0))[$y-eq'G'],($i,0,0))[$y-eq'R'];$a.SetPixel($_,$h,[system.drawing.color]::fromargb($r,$g,$b))}};$a.save("$x$y.png")
```
None of this fancy "golfing the input" or "using built-ins." Phooey on that. ;-)
This here takes the full path of an input PNG (though, strictly speaking, it doesn't *need* to be a PNG, since JPG, BMP, etc. are supported by .NET, but I've only tried it on PNGs), and one of `(R, G, B)` for the color channel, then stores those into `$x` and `$y`. We then create a `New-Object` of type [`System.Drawing.Bitmap`](https://msdn.microsoft.com/en-us/library/system.drawing.bitmap(v=vs.110).aspx) of `$x` and store that into `$a`.
Then we do a double loop over all pixels. First from `1` up to `$a`'s `.Height`, setting `$h` each iteration (it's zero-indexed, so that's why we `--$_`, which saves bytes over `( .height-1)`. Inside, we loop from `1` up to `$a`'s `.Width`.
Each iteration, we're performing a `.GetPixel` on the particular `w,h` coordinates, which returns a [`System.Drawing.Color`](https://msdn.microsoft.com/en-us/library/system.drawing.color(v=vs.110).aspx) object. We `select` out the `R G B` values thereof. The `iex` here is a neat trick that turns this into a hashtable (e.g., something like `@{R=34; G=177; B=76}`) so we can index into that directly with the desired color channel `[$y]`. That value is stored into `$i`.
Next, we set three values `$r, $g, $b` to be the result of some [pseudo-ternary operators](https://codegolf.stackexchange.com/a/79895/42963) based on the letter value of `$y`. So, for example, if `$y` is `R`, then the result here is `$r=$i, $g=0, $b=0`.
Then, we do a `.SetPixel` back onto that particular `w,h` coordinate, constructing a new `System.Drawing.Color` using the static `FromARGB` (which assumes the alpha to be fully opaque). Once we've finished looping, we then simply `.Save` the PNG to a new file.
*Note: This does take a long while, since it's completely independently looping through every pixel and performing a bunch of calculations and calls each iteration.*
Tests:  
[![AdmBorkBork Red](https://i.stack.imgur.com/t2CXX.png)](https://i.stack.imgur.com/t2CXX.png)
[![AdmBorkBork Green](https://i.stack.imgur.com/LloJf.png)](https://i.stack.imgur.com/LloJf.png)
[![AdmBorkBork Blue](https://i.stack.imgur.com/VQd6U.png)](https://i.stack.imgur.com/VQd6U.png)
[Answer]
# Bash + ImageMagick, 41 bytes
```
C="RGB"
mogrify -channel ${C//$1} -fx 0 x
```
Input is a file named `x`, command line parameter one of `R` or `G` or `B`
Output overwrites the input file
Differs from betseg's answer in taking more natural single-letter channel parameter. Also overwriting instead of outputting a new file which betseg is free to steal :)
[Answer]
# [Chip](https://github.com/Phlarx/chip), 78 bytes
```
 ~Z~vS
f/F,^-.
e/E|,-Z.
d/D|>zz^.
a/AMx-x-].
b/BMx-]v-'
c/CM]v-'
 >--v'
G/gh/H
```
[Try it online!](https://tio.run/nexus/chip#@69QF1VXFsyVpu@mE6erx5Wq71qjoxulx5Wi71JjV1UVp8eVqO/oW6FboRurx5Wk7wRkxpbpqnMl6zv7ghkKdrq6Zepc7vrpGfoe//@bGhoZm5iamVtYAgA "Chip – TIO Nexus")
Chip is a 2D language that operates on the component bits of each byte in a byte stream.
### Overview
This particular solution expects the first byte of input to be the control character--to define which channel(s) to keep--and following is the bytes of image data. The image data must be RGB triplets, one byte per channel, 24 bits per pixel:
```
|  1  |  2  |  3  |  4  |  5  |  6  |  7  | ... | 3n-2 |  3n  | 3n+1 |
|     |   First Pixel   |   Second Pixel  | ... |      nth Pixel     |
| Ctl | Red | Grn | Blu | Red | Grn | Blu | ... |  Red |  Grn |  Blu |
```
The control character is interpreted as a bit field, though only the three lowest bits have meaning:
```
0x1  keep Red channel
0x2  keep Green channel
0x4  keep Blue channel
```
This means we can use ASCII characters to select which channel we want:
`1` means red  
`2` means blue  
`4` means green 
Or do something fancier:
`5` keep red and blue, but not green  
`7` keep all channels (image is unchanged)  
`0` drop all channels (image is black) 
### How it works
This solution is rather jumbled up due to golfing, but here goes:
1. Read the three low bits of the first byte with `C`, `B`, and `A`, and store those bits in their corresponding `M`emory cells. Also, `S`uppress output for the first cycle.
2. Loop over those three bits repeatedly. If the current bit it is on, close the `/` switches to output the current input byte, if it is off, open the switches so that we output a zero byte.
3. Continue until input is exhausted.
### Viewing the results
Sure, you could use hexdump or something boring, but it turns out this is (almost) an actual valid image format: [binary Portable PixMap](https://en.wikipedia.org/wiki/Netpbm_format).
Just plop the image data from above (minus the control byte, of course) into the file below, adjust the width/height to be valid, and you can view the image in a proper viewer like IrfanView, though simpler ones (like most browser built-ins) can't handle it.
```
P6
{width as ASCII} {height as ASCII}
255
{binary image data here}
```
For example (using escapes for the raw data):
```
P6
3 1
255
\xff\x00\x00\x00\xff\x00\x00\x00\xff
```
[Answer]
# MATL, ~~21~~ 13 bytes
```
Yi3:iml&!*3YG
```
The color channel should be specified using the following mapping: `1:red`, `2:green`, `3:blue`
The Online interpreters are unable to use `imread` to read images so [here is a slightly modified version where I have hard-coded a random image into the source](https://matl.suever.net/?code=%5B10+15+3%5Dl%24r+255%2a+%27uint8%27Y%25+%25+Create+some+bogus+image+data%0A%0A3%3Aiml%26%21%2a3YG&inputs=2&version=19.8.0).
**Explanation**
```
        % Implicitly grab first input as a string (filename)
Yi      % Read the image in from a filename or URL
3:      % Push the string literal 'rgb' to the stack
i       % Grab the second input as a number
m       % Check for membership. So for example 2 will yield [false, true, false]
l&!     % Permute the dimensions to turn this 1 x 3 array into a 1 x 1 x 3 array
*       % Multiply this with the input RGB image. It will maintain the channel which
        % corresponds with the TRUE values and zero-out the channels that corresponded to
        % the FALSE values
3YG     % Display the image
```
[Answer]
# [APL (Dyalog)](https://www.dyalog.com/), 7 bytes
I/O: array of RGB triplets
```
⎕×⊂⎕=⍳3
```
[Try it online!](https://tio.run/nexus/apl-dyalog#PY@xSgNBEIb7fYopTXFw5Lh0QaxECARMWou9u1mzsJkNu5dwQdKkSIJwYiNWvoGdvoFvMu9gfc4ZtJp/Zr6ff4ZPR9Px08vXKz/upY65/cg6Ph07bt@gXiAQNrWIgAjOEkZA0oXD886WCIVvsILKxpXTWzUo/WoLUbtaPezO6OxqMld3fHgWEjxBYsaelJK024lMuX2HPuwaawiaKr8EWi8LDBFMkGY669GbqaDpL5gmhY4SaanCxtI9XBgf/qwb7dZyZJoM83yglOm94rzM/gXk3H7Kt5mUYT76Jp@UulzgDw "APL (Dyalog Unicode) – TIO Nexus")
`⍳3` first three integers
`⎕=` compare numeric input (the chosen channel) to that
`⊂` enclose (so each image triplet pairs up this entire triplet)
`⎕×` multiply numeric input (the array of triplets) with that
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E), 16 bytes
```
vyvy2ô²è}})¹0ègô
```
[Try it online!](https://tio.run/nexus/05ab1e#@19WWVZpdHjLoU2HV9TWah7aaXB4RfrhLf//R0eru4GBug6Y4eoKZQBFYnXIlozlMgQA "05AB1E – TIO Nexus")
Uses hex colors in a 2D array format and [0,1,2] for each channel.
[Answer]
# Clojure, ~~421~~ 332 bytes
**-89 bytes** by aggressively inlining everything, changing from my ridiculous old method of stripping the channels, and getting rid of an unnecessary accidental import.
```
(import '(java.awt.image BufferedImage)'(clojure.lang Keyword)'(javax.imageio ImageIO)'(java.io File)'(java.awt Color))(fn[p i](doseq[y(range(.getHeight p))x(range(.getWidth p))](.setRGB p x y(.getRGB(apply #(Color. % %2 %3)(#(let[c(Color. %)](assoc [0 0 0]i(([(.getRed c)(.getGreen c)(.getBlue c)]%)i)))(.getRGB p x y))))))(ImageIO/write p"jpg"(File."./o.jpg")))
```
Smacked this out half an hour before my shift started with no idea what I was doing. I have little experience with `BufferedImage`, so there may be a better way of going about this. I'm also abusing `Color` to convert back-and-forth between integer and individual channel representations of colors.
This is comically huge compared to the other answers for a couple reasons (besides the obvious that Clojure isn't a golfing language):
* Instead of just manipulating a byte array, this actually takes as input a picture, alters it, and outputs it.
* I'm using Java-interop, which while handy can be quite verbose at times. The imports alone are larger than many answers.
See the code below for a break down.
```
(ns bits.restrict-channel
  (:import (java.awt.image BufferedImage)
           (clojure.lang Keyword)
           (javax.imageio ImageIO)
           (java.io File)
           (java.awt Color)))
(defn restrict-channel
  "Accepts a BufferedImage and a index between 0 and 2 (inclusive).
  Removes color from all channels EXCEPT the channel indicated by color-i.
  color-i of 0 = keep red
  color-i of 1 = keep green
  color-i of 2 = keep blue"
  [^BufferedImage image ^long color-i]
  (let [; Turn a number representing RGB into a triplet representing [R G B]
        channels #(let [c (Color. %)]
                    [(.getRed c) (.getGreen c) (.getBlue c)])
        ; Create a new triplet that only contains color in the color-i channel
        zero-channels #(assoc [0 0 0] color-i ((channels %) color-i))]
    ; Loop over each pixel
    (doseq [y (range (.getHeight image))
            x (range (.getWidth image))]
      
      ; Grab the current color...
      (let [cur-color (.getRGB image x y)]
        
        ; ... setting it to stripped color triplet returned by zero-channels
        (.setRGB image x y
                 
                          ; This "apply" part is just applying the stripped triplet to the Color constructor
                         ;  This is needed to convert the separate channels into the integer representation that `BufferedImage` uses. 
                 (.getRGB (apply #(Color. % %2 %3) (zero-channels cur-color))))))
    
    ; Save the result to file
    (ImageIO/write image "jpg" (File. "./o.jpg"))))
```
[Answer]
# Lua (love2d Framework), 498 bytes
I did this more as a exercise for myself, so it's not as short as it could be (though I did try to golf), but I wanted to add it to here cause I think I did good. Even if I'm too late.
Here the golfed code, under it is the explained and untangled version.
```
l=love g,p,rm,bm,gm,s=l.graphics,0,1,1,1,[[uniform float m[4];vec4 effect(vec4 co,Image t,vec2 c,vec2 s){vec4 p=Texel(t,c);p.r=p.r*m[0];p.b=p.b*m[1];p.g=p.g*m[2];return p;}]]t=g.setShader h=g.newShader(s)function l.draw()h:send("m",rm,gm,bm)if p~=0 then t(h)g.draw(p)t()end end function l.filedropped(f)a=f:getFilename()p=g.newImage(f)end function l.keypressed(k)if k=="0"then rm,gm,bm=1,1,1 end if k=="1"then rm,gm,bm=1,0,0 end if k=="2"then rm,gm,bm=0,1,0 end if k=="3"then rm,gm,bm=0,0,1 end end
```
Here is the code which has to get a \*.jpg file dropped into it. After the image was inserted you can press the number buttons for red(1) green(2) or blue(3) channels. Also to see the default picture again press 0. Actually it just shows the picture in the window.
```
l=love
g=l.graphics
p=0
rm,bm,gm=1,1,1
s = [[uniform float m[4];
vec4 effect(vec4 co,Image t,vec2 c,vec2 s){vec4 p=Texel(t,c);p.r = p.r * m[0];p.b = p.b * m[1]; p.g = p.g * m[2]; return p;}
]]
sh=g.newShader(s)
function l.draw()
  sh:send("m",rm,gm,bm)
  if p~=0 then
    g.setShader(sh)
    g.draw(p)
    g.setShader()
  end
end
function l.filedropped(f)
  a=f:getFilename()
  p=g.newImage(f)
end
function l.keypressed(k)
  if k=="0"then rm,gm,bm=1,1,1 end
  if k=="1"then rm,gm,bm=1,0,0 end
  if k=="2"then rm,gm,bm=0,1,0 end
  if k=="3"then rm,gm,bm=0,0,1 end
end
```
The important part which does all the work is the shader which is the small string declaration at the beginning or untangled:
```
uniform float m[4];
vec4 effect(vec4 co,Image t,vec2 c,vec2 s)
{
    vec4 p=Texel(t,c);
    p.r = p.r * m[0];
    p.b = p.b * m[1];
    p.g = p.g * m[2]; 
    return p;
}
```
which gets the actual pixel of the image and just shows the channels as needed.
My test image and the different outputs for the channels (also for sure the other ones)
[![default image and channel images merged](https://i.stack.imgur.com/wVWJA.png)](https://i.stack.imgur.com/wVWJA.png)
[Answer]
# C, ~~60~~ 58 bytes
```
main(a,b)char**b;{while(scanf(b[1],&a)>0)printf("%d ",a);}
```
Image input is a list of numbers (in decimal) between 0 and 255 on `stdin`, e.g.
```
255 0 0  192 192 192  31 41 59 ...
```
The channel is specified as the first argument to the program, and is one of
```
red   -> "%d%*d%*d"
green -> "%*d%d%*d"
blue  -> "%*d%*d%d"
```
Example:
```
$ echo "255 0 0" | ./extract "%d%*d%*d"
255 
```
]