Skip to content

Commit

Permalink
o Clarify transformer readme section.
Browse files Browse the repository at this point in the history
  • Loading branch information
hzeller committed Nov 23, 2015
1 parent b100a40 commit 569b142
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 16 deletions.
37 changes: 26 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,22 +309,37 @@ parameters and the coordinate system.
<a href="adapter/"><img src="img/three-parallel-panels-soic.jpg" width="300px"></a>

## Remapping coordinates ##
You can as well chain multiple boards together and then arrange them in a
different layout. Say you have 4 displays with 32x32 -- if we chain
them, we get a display 32 pixel high, (4*32)=128 pixel long. If we arrange
the boards in a square, we get a logical display of 64x64 pixels.

For convenience, we should only deal with the logical coordinates of
64x64 pixels in our program: implement a `CanvasTransformer`
interface to do the coordinate mapping. Have a look at
`class LargeSquare64x64Transformer` for an example and see how it is delegating to
the underlying RGBMatrix with changed coordinates.
You might choose a different physical layout than the wiring provides.

Here is how the wiring would look like:
Say you have 4 displays with 32x32 and only a single output
like with a Raspberry Pi 1 or the Adafruit HAT -- if we chain
them, we get a display 32 pixel high, (4*32)=128 pixel long. If we arrange
the boards in a square, we get a logical display of 64x64 pixels:

<img src="img/chained-64x64.jpg" width="400px"> In action:
[![PixelPusher video][pp-vid]](http://youtu.be/ZglGuMaKvpY)

How can we make this 'folded' 128x32 screen behave like a 64x64 screen ?

In the API, there is an interface to implement,
a [`CanvasTransformer`](./include/canvas.h) that allows to program re-arrangements
of pixels in any way. You can plug such a `CanvasTransformer` into the RGBMatrix
to use the new layout (`void RGBMatrix::SetTransformer(CanvasTransformer *transformer)`).

Sometimes you even need this for the panel itself: In newer panels
(often with 1:4 multiplexing) the pixels are often not mapped in
a straight-forward way, but in a snake arrangement for instance. The CanvasTransformer
allows you to work around that (sorry, I have not seen these panels myself so that
I couldn't test that; but if you come accross one, you might want to send a pull-request
with a new CanvasTransformer).

Back to the 64x64 arrangement:

There is a sample implementation `class LargeSquare64x64Transformer` that maps
the 128x32 pixel logical arrangement into the 64x64 arrangement doing
the coordinate mapping. In the demo program and the `led-image-viewer`, you
can activate this with the `-L` option.

Using the API
-------------
While there is the demo program, the matrix code can be used independently as
Expand Down
10 changes: 5 additions & 5 deletions led-image-viewer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <magick/image.h>

using rgb_matrix::GPIO;
using rgb_matrix::Canvas;
using rgb_matrix::FrameCanvas;
using rgb_matrix::RGBMatrix;
using rgb_matrix::CanvasTransformer;
Expand All @@ -48,13 +49,14 @@ namespace {
class PreprocessedFrame {
public:
PreprocessedFrame(const Magick::Image &img,
rgb_matrix::Canvas *transformed_draw_canvas,
CanvasTransformer *transformer,
rgb_matrix::FrameCanvas *output)
: canvas_(output) {
int delay_time = img.animationDelay(); // in 1/100s of a second.
if (delay_time < 1) delay_time = 1;
delay_micros_ = delay_time * 10000;

Canvas *const transformed_draw_canvas = transformer->Transform(output);
for (size_t y = 0; y < img.rows(); ++y) {
for (size_t x = 0; x < img.columns(); ++x) {
const Magick::Color &c = img.pixelColor(x, y);
Expand Down Expand Up @@ -120,12 +122,10 @@ static void PrepareBuffers(const std::vector<Magick::Image> &images,
RGBMatrix *matrix,
std::vector<PreprocessedFrame*> *frames) {
fprintf(stderr, "Preprocess for display.\n");
CanvasTransformer *transformer = matrix->transformer();
CanvasTransformer *const transformer = matrix->transformer();
for (size_t i = 0; i < images.size(); ++i) {
FrameCanvas *canvas = matrix->CreateFrameCanvas();
frames->push_back(new PreprocessedFrame(images[i],
transformer->Transform(canvas),
canvas));
frames->push_back(new PreprocessedFrame(images[i], transformer, canvas));
}
}

Expand Down

0 comments on commit 569b142

Please sign in to comment.