These are chat archives for Makuna/NeoPixelBus

2nd
Oct 2016
Scott Franzyshen
@sfranzyshen
Oct 02 2016 01:18 UTC
    void Blt(NeoBufferContext<T_COLOR_FEATURE> destBuffer,
        uint16_t indexPixel,
        int16_t xSrc,
        int16_t ySrc,
        int16_t wSrc,
    bool mirror = false)
    {
        const uint16_t destPixelCount = destBuffer.PixelCount();
        typename T_COLOR_FEATURE::ColorObject color(0);
        xSrc = constrainX(xSrc);
        ySrc = constrainY(ySrc);

        if (seek(xSrc, ySrc))
        {
            for (int16_t x = 0; x < wSrc && indexPixel < destPixelCount; x++, indexPixel++)
            {
                if (xSrc < _width)
                {
                    if (readPixel(&color))
                    {
                        xSrc++;
                    }
                }

        if(mirror)
            T_COLOR_FEATURE::applyPixelColor(destBuffer.Pixels, ((destPixelCount -1) - indexPixel), color);
        else
                    T_COLOR_FEATURE::applyPixelColor(destBuffer.Pixels, indexPixel, color);
            }
        }
    }
I would like to expand the NeoBitmapFile function blt() to pass a bool param to add a feature for mirroring the image (flipping horizontally) effectivly reversing the pattern animation ...
Michael Miller
@Makuna
Oct 02 2016 01:54 UTC
That's not the way to do it; but let me do some thinking/research on the best way that fits my design goals of the library.
Michael Miller
@Makuna
Oct 02 2016 02:03 UTC
I am thinking the best way is to change blt() into a template function, that takes a template reflection class. Then implement the two reflection classes (none, reflecthorizontal) that expose a method to "calculate" the target index from the given index and destPixelCount.
This design will translate into the 2d blt function well were it would have reflect H, reflect V, reflect HV.
Scott Franzyshen
@sfranzyshen
Oct 02 2016 02:17 UTC
I would also like to use the bitmap file as an intensity file only and apply a color to it after the fact (on the fly) .... the bitmap file would still be 24bit but each channel (RGB) would all be the same (grey-scale). But during applyPixelColor I want to mask those colors with something like r=100% g=0% b=0% to change the final out (to red in this case)
Michael Miller
@Makuna
Oct 02 2016 02:20 UTC
I think what you are really asking for a Palletized Bitmap support. Where each pixel is a 0-255 (or even just 0-16) and they represent a lookup into a palette of colors. Then you could just swap palettes.
Scott Franzyshen
@sfranzyshen
Oct 02 2016 02:21 UTC
this way I could have a single grey scale image (animation) that I could change to many colors
Michael Miller
@Makuna
Oct 02 2016 02:22 UTC
In your case, a palette would just be a single color ranging from low intensity to full intensity. Look up in my Wiki about GammaCorrection as a side note.
What do you use to make your bitmaps?
Michael Miller
@Makuna
Oct 02 2016 02:32 UTC
Another thought could be blt take a second template class for "operation", that will have a method that takes the source pixel color, destination pixel color, an operation parameter (your color?) and then have it apply the operation. This sort of feature is handy for other things, like inverting colors, apply masks that modify the destination, etc.
Scott Franzyshen
@sfranzyshen
Oct 02 2016 02:41 UTC
I’m using gimp to create the images ...
Mehrdad K
@mkeyno
Oct 02 2016 07:52 UTC
Michael how can I print content of (uint32_t*)strip.Pixels() to be sure correct color inside the object
it seems empty data loaded from my loop function
void loop() {
  server.handleClient();   
  webSocket.loop();  
   if(SHOW)// sensor data 
  {
    if( (millis()- OpenlastTime) >DURATION[image_index]*1000)
    {      
     if(image_index>=IMAGE_NUM) image_index=0; 
     _memory_pointer=start_address_of_imagefile[image_index];
     Serial.printf("File number=%u name:%s address:%u duration:%u\n",
     image_index,IMAGES[image_index].c_str(),start_address_of_imagefile[image_index],DURATION[image_index]);
     Current_imageLine=0; 
     frame_time=0;   
     image_index++; 
     OpenlastTime=millis();
    }

    ESP.flashRead(_memory_pointer, (uint32_t*)strip.Pixels(),NUM_LEDS*3 );
     // uint8_t* LED_BUFFER = new uint8_t[NUM_LEDS*3];delete [] LED_BUFFER; 
     // ESP.flashRead(_memory_pointer,(uint32_t *) LED_BUFFER,NUM_LEDS*3 );  
       //memcpy(strip.Pixels(),LED_BUFFER,NUM_LEDS*3);
    // if((micros()-lastLineShow)> lineInterval){ 
                                        strip.Show();
                                        _memory_pointer+=(NUM_LEDS*3);
                                        Current_imageLine++;
                                        lastLineShow=micros();
        //                             }
    if(Current_imageLine>=IMAGES_LINES)
    {
      Serial.printf("\nFrame took %u ms line=%d  RPM=%d\n",  millis() - frame_time,Current_imageLine,RPM*IMAGES_LINES);
      webSocket.sendTXT(client_num,"RPM$"+String(RPM*IMAGES_LINES));
      Current_imageLine=0;
      _memory_pointer=start_address_of_imagefile[image_index-1];
      frame_time=millis();
    }

  } 
//optimistic_yield(1000);   
//if(Start_new_round){
 // webSocket.sendTXT(client_num,"RPM$"+String(RPM*IMAGES_LINES));
  //Serial.println("detect");
 // Start_new_round=false;}
}
Michael Miller
@Makuna
Oct 02 2016 08:20 UTC
You can iterate over the pixels and call getPixelColor() and then print the color; OR
If you know that they are truly only three bytes each (your assuming such in your code above when you call ESP.flashRead) then just create a local pointer init'ed to strip.Pixels() and then iterate over that pointer; grouping visually every three bytes
Mehrdad K
@mkeyno
Oct 02 2016 11:01 UTC
Michael , I put following code to check whether read data or not , the print shows the data but I don't know why it doesn't show any effect
for( int i = 0;i<strip.PixelCount(); i++) Serial.print((char)strip.GetPixelColor(i).R);Serial.println();
Modifying the data behind the pointer doesn't tell the NeoPixelBus the data was modified; it just gives you access to the buffer. You need to mark it dirty after any modification. When you call Show() the dirty flag is cleared.
Mehrdad K
@mkeyno
Oct 02 2016 17:57 UTC
so you said I should call dirty before calling show
Michael Miller
@Makuna
Oct 02 2016 17:58 UTC
Well, yes and no. What I said is when you modify the data pointed at by Pixels(), you need to call Dirty().
I make this distinction because calling SetPixelColor() requires no call to Dirty().
Mehrdad K
@mkeyno
Oct 02 2016 18:00 UTC
strip.Dirty(); before strip.show();
Michael Miller
@Makuna
Oct 02 2016 18:01 UTC
sigh, are you being difficult on purpose or is this just a communication problem?
Mehrdad K
@mkeyno
Oct 02 2016 18:01 UTC
I'm sorry Michael just trying to figure out what code needed to be add to solve my problem ,
Michael Miller
@Makuna
Oct 02 2016 18:02 UTC
The correct way to say AND think about the solution is, call strip.Dirty() after modifiying the data in strip.Pixels().
Mehrdad K
@mkeyno
Oct 02 2016 18:02 UTC
also consider I'm not fluent in English as you are
Michael Miller
@Makuna
Oct 02 2016 18:03 UTC
(communications problem then)
The Dirty() method is really only used when calling Pixels() and modifying the data that it points too.
Mehrdad K
@mkeyno
Oct 02 2016 18:04 UTC
so it must be after flash reading
Michael Miller
@Makuna
Oct 02 2016 18:04 UTC
ESP.flashRead(_memory_pointer, (uint32_t*)strip.Pixels(),NUM_LEDS*3 );
strip.Dirty();
Scott Franzyshen
@sfranzyshen
Oct 02 2016 20:32 UTC
is there a way I can adjust the animation duration when looping the animation using RestartAnimation() from within my AnimUpdateCallback ... do I need to call StartAnimation() again with the modified duration and the current value of param.index?
Scott Franzyshen
@sfranzyshen
Oct 02 2016 20:40 UTC
    void RestartAnimation(uint16_t indexAnimation, uint16_t duration = NULL)
    {
        if (indexAnimation >= _countAnimations || _animations[indexAnimation]._duration == 0)
        {
            return;
        }
    if(duration != NULL)
            StartAnimation(indexAnimation, duration, (_animations[indexAnimation]._fnCallback));
    else
            StartAnimation(indexAnimation, _animations[indexAnimation]._duration, (_animations[indexAnimation]._fnCallback));
    }
Michael Miller
@Makuna
Oct 02 2016 20:52 UTC
Different periods of time are considered different animations. In general you should avoid branching inside the animation update as much as possible (other than complete tests) and rely on different animations to handle different state.
An example, you want LEDs to first brighten in 10 seconds, then dim in 3 seconds. Two animations, one to brighten, and when ends triggers the second animation to dim.
Do you have a specific scenario? I can give you feedback on a better approach if I know the scenario.
Scott Franzyshen
@sfranzyshen
Oct 02 2016 21:05 UTC
my scenario is I'm using a bitmapfile from spiffs looping over and over again (NeoPixelBitmap example) and want to change playback speed (from a web interface) on the fly ... from my AnimUpdate callback ... animations.RestartAnimation(param.index, animSpeed);
Michael Miller
@Makuna
Oct 02 2016 22:16 UTC
Then just call StartAnimation with the new time.