You can use addressable LEDs that allow chaining from one LED to another using a serial protocol.
Like this :

This would alow you to set the first row blue, the second purple, each one can be controled independently.
Take a look at Ada Fruit's neopixels to start. These are basically skillfully branded WS2811 & WS2812 LEDs, but they are very well documented and well built. They feature 8 bit per channel RGB color (24 bit color) and take care of PWM internally. You could even chain the end of one strip to another, allowing all control to come from two pins of an arduino.
Assuming you go this route, consider the following:
You will need enough RAM to store the full array of pixels in memory, which is 3 bytes per pixel. Alternatively, you can create a custom library with reduced bit depth, or one that stores pixels in clusters, because at the end of the day you are just operating a giant shift register.
You will need to supply enough current (60mA per led), and supply it at several points along longer strips. You will likely need to use external power sources. You can drive a decent amount of LEDs from Vin (before the power regulator), but not anything near 19 strips.
Now if you already have the strips, and they are analog strips, I think you can find similar drivers that output more power to drive strips, but still use a serial protocol.
You can use my example code here:
// NeoPixel Demo minimum
// By leo etchaas
// released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library
#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
#define PIN 6
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 55
// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
int delayval = 500; // delay for half a second
void setup() {
// This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
// End of trinket special code
pixels.begin(); // This initializes the NeoPixel library.
}
void loop() {
// For a set of NeoPixels the first NeoPixel is 0, second is 1, all the way up to the count of pixels minus one.
for(int i=0;i<NUMPIXELS;i++){
// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
pixels.setPixelColor(i, pixels.Color(25,255,255)); // Moderately bright green color.
pixels.show(); // This sends the updated pixel color to the hardware.
delay(delayval); // Delay for a period of time (in milliseconds).
}for(int i;i>0;i-=1){
// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
pixels.setPixelColor(i, pixels.Color(255,5,255)); // Moderately bright green color.
pixels.show(); // This sends the updated pixel color to the hardware.
delay(delayval); // Delay for a period of time (in milliseconds).
}
}