kopia lustrzana https://github.com/pimoroni/pimoroni-pico
				
				
				
			Merge pull request #427 from pimoroni/patch-picographics-1bit-dither
PicoGraphics/JPEGDEC: Use PicoGraphics dither.pull/431/head
						commit
						c697bc8600
					
				| 
						 | 
				
			
			@ -157,10 +157,10 @@ namespace pimoroni {
 | 
			
		|||
  public:
 | 
			
		||||
    void busy_wait();
 | 
			
		||||
    void reset();
 | 
			
		||||
    void power_off();
 | 
			
		||||
  
 | 
			
		||||
    // DisplayDriver API
 | 
			
		||||
    bool is_busy() override;
 | 
			
		||||
    void power_off() override;
 | 
			
		||||
    void update(PicoGraphics *graphics) override;
 | 
			
		||||
    void partial_update(PicoGraphics *graphics, Rect region) override;
 | 
			
		||||
    bool set_update_speed(int update_speed) override;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ namespace pimoroni {
 | 
			
		|||
  int PicoGraphics::create_pen(uint8_t r, uint8_t g, uint8_t b) {return -1;};
 | 
			
		||||
  void PicoGraphics::set_pixel_dither(const Point &p, const RGB &c) {};
 | 
			
		||||
  void PicoGraphics::set_pixel_dither(const Point &p, const RGB565 &c) {};
 | 
			
		||||
  void PicoGraphics::set_pixel_dither(const Point &p, const uint8_t &c) {};
 | 
			
		||||
  void PicoGraphics::scanline_convert(PenType type, conversion_callback_func callback) {};
 | 
			
		||||
  void PicoGraphics::sprite(void* data, const Point &sprite, const Point &dest, const int scale, const int transparent) {};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -217,6 +217,7 @@ namespace pimoroni {
 | 
			
		|||
    virtual int reset_pen(uint8_t i);
 | 
			
		||||
    virtual void set_pixel_dither(const Point &p, const RGB &c);
 | 
			
		||||
    virtual void set_pixel_dither(const Point &p, const RGB565 &c);
 | 
			
		||||
    virtual void set_pixel_dither(const Point &p, const uint8_t &c);
 | 
			
		||||
    virtual void scanline_convert(PenType type, conversion_callback_func callback);
 | 
			
		||||
    virtual void sprite(void* data, const Point &sprite, const Point &dest, const int scale, const int transparent);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -431,6 +432,7 @@ namespace pimoroni {
 | 
			
		|||
      virtual bool set_update_speed(int update_speed) {return false;};
 | 
			
		||||
      virtual void set_backlight(uint8_t brightness) {};
 | 
			
		||||
      virtual bool is_busy() {return false;};
 | 
			
		||||
      virtual void power_off() {};
 | 
			
		||||
      virtual void cleanup() {};
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,11 +11,11 @@ namespace pimoroni {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  void PicoGraphics_Pen1Bit::set_pen(uint c) {
 | 
			
		||||
    color = c != 0 ? 1 : 0;
 | 
			
		||||
    color = c;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void PicoGraphics_Pen1Bit::set_pen(uint8_t r, uint8_t g, uint8_t b) {
 | 
			
		||||
    color = r != 0 || g != 0 || b != 0 ? 1 : 0;
 | 
			
		||||
    color = std::max(r, std::max(g, b)) >> 4;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void PicoGraphics_Pen1Bit::set_pixel(const Point &p) {
 | 
			
		||||
| 
						 | 
				
			
			@ -25,35 +25,32 @@ namespace pimoroni {
 | 
			
		|||
 | 
			
		||||
    uint bo = 7 - (p.x & 0b111);
 | 
			
		||||
 | 
			
		||||
    uint8_t _dc = 0;
 | 
			
		||||
 | 
			
		||||
    if(color == 0) {
 | 
			
		||||
      _dc = 0;
 | 
			
		||||
    } else if (color == 15) {
 | 
			
		||||
      _dc = 1;
 | 
			
		||||
    } else {
 | 
			
		||||
      uint8_t _dmv = dither16_pattern[(p.x & 0b11) | ((p.y & 0b11) << 2)];
 | 
			
		||||
      _dc = color > _dmv ? 1 : 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // forceably clear the bit
 | 
			
		||||
    *f &= ~(1U << bo); 
 | 
			
		||||
 | 
			
		||||
    // set pixel
 | 
			
		||||
    *f |= (color << bo);
 | 
			
		||||
    *f |= (_dc << bo);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void PicoGraphics_Pen1Bit::set_pixel_span(const Point &p, uint l) {
 | 
			
		||||
    // pointer to byte in framebuffer that contains this pixel
 | 
			
		||||
    uint8_t *buf = (uint8_t *)frame_buffer;
 | 
			
		||||
    uint8_t *f = &buf[(p.x / 8) + (p.y * bounds.w / 8)];
 | 
			
		||||
 | 
			
		||||
    uint bo = 7 - (p.x & 0b111);
 | 
			
		||||
 | 
			
		||||
    // TODO: this could trivially be sped up by processing single bits only at 
 | 
			
		||||
    // the start and the end of the span and writing full bytes (8 pixels at
 | 
			
		||||
    // a time) in the middle portion of the span. would only be more efficient
 | 
			
		||||
    // for longer spans (probably around 20 pixels or more)
 | 
			
		||||
    Point lp = p;
 | 
			
		||||
    if(p.x + (int)l >= bounds.w) {
 | 
			
		||||
      l = bounds.w - p.x;
 | 
			
		||||
    }
 | 
			
		||||
    while(l--) {
 | 
			
		||||
      // forceably clear the bit and then set to the correct value
 | 
			
		||||
      *f &= ~(1U << bo); 
 | 
			
		||||
      *f |= (color << bo);
 | 
			
		||||
 | 
			
		||||
      if(bo == 0) { // last bit of this byte?
 | 
			
		||||
        // move to next byte in framebuffer and reset the bit offset
 | 
			
		||||
        f++; bo = 8;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      bo--;
 | 
			
		||||
        set_pixel(lp);
 | 
			
		||||
        lp.x++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,11 +11,11 @@ namespace pimoroni {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  void PicoGraphics_Pen1BitY::set_pen(uint c) {
 | 
			
		||||
    color = c != 0 ? 1 : 0;
 | 
			
		||||
    color = c;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void PicoGraphics_Pen1BitY::set_pen(uint8_t r, uint8_t g, uint8_t b) {
 | 
			
		||||
    color = r != 0 || g != 0 || b != 0 ? 1 : 0;
 | 
			
		||||
    color = std::max(r, std::max(g, b));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void PicoGraphics_Pen1BitY::set_pixel(const Point &p) {
 | 
			
		||||
| 
						 | 
				
			
			@ -25,18 +25,32 @@ namespace pimoroni {
 | 
			
		|||
 | 
			
		||||
    uint bo = 7 - (p.y & 0b111);
 | 
			
		||||
 | 
			
		||||
    uint8_t _dc = 0;
 | 
			
		||||
 | 
			
		||||
    if(color == 0) {
 | 
			
		||||
      _dc = 0;
 | 
			
		||||
    } else if (color == 15) {
 | 
			
		||||
      _dc = 1;
 | 
			
		||||
    } else {
 | 
			
		||||
      uint8_t _dmv = dither16_pattern[(p.x & 0b11) | ((p.y & 0b11) << 2)];
 | 
			
		||||
      _dc = color > _dmv ? 1 : 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // forceably clear the bit
 | 
			
		||||
    *f &= ~(1U << bo); 
 | 
			
		||||
 | 
			
		||||
    // set pixel
 | 
			
		||||
    *f |= (color << bo);
 | 
			
		||||
    *f |= (_dc << bo);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void PicoGraphics_Pen1BitY::set_pixel_span(const Point &p, uint l) {
 | 
			
		||||
    Point po(p);
 | 
			
		||||
    Point lp = p;
 | 
			
		||||
    if(p.x + (int)l >= bounds.w) {
 | 
			
		||||
      l = bounds.w - p.x;
 | 
			
		||||
    }
 | 
			
		||||
    while(l--) {
 | 
			
		||||
      set_pixel(po);
 | 
			
		||||
      po.x++;
 | 
			
		||||
        set_pixel(lp);
 | 
			
		||||
        lp.x++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ typedef struct _ModPicoGraphics_obj_t {
 | 
			
		|||
typedef struct _JPEG_obj_t {
 | 
			
		||||
    mp_obj_base_t base;
 | 
			
		||||
    JPEGDEC *jpeg;
 | 
			
		||||
    void *dither_buffer;
 | 
			
		||||
    mp_obj_t file;
 | 
			
		||||
    mp_buffer_info_t buf;
 | 
			
		||||
    ModPicoGraphics_obj_t *graphics;
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +86,16 @@ MICROPY_EVENT_POLL_HOOK
 | 
			
		|||
    // "pixel" is slow and clipped,
 | 
			
		||||
    // guaranteeing we wont draw jpeg data out of the framebuffer..
 | 
			
		||||
    // Can we clip beforehand and make this faster?
 | 
			
		||||
    if(pDraw->iBpp == 4) {
 | 
			
		||||
    if(pDraw->iBpp == 8) {
 | 
			
		||||
        uint8_t *pixel = (uint8_t *)pDraw->pPixels;
 | 
			
		||||
        for(int y = 0; y < pDraw->iHeight; y++) {
 | 
			
		||||
            for(int x = 0; x < pDraw->iWidth; x++) {
 | 
			
		||||
                current_graphics->set_pen((uint8_t)(*pixel >> 4));
 | 
			
		||||
                current_graphics->set_pixel({pDraw->x + x, pDraw->y + y});
 | 
			
		||||
                pixel++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else if(pDraw->iBpp == 4) {
 | 
			
		||||
        uint8_t *pixels = (uint8_t *)pDraw->pPixels;
 | 
			
		||||
        for(int y = 0; y < pDraw->iHeight; y++) {
 | 
			
		||||
            for(int x = 0; x < pDraw->iWidth; x++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -146,6 +156,7 @@ mp_obj_t _JPEG_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, c
 | 
			
		|||
    self->base.type = &JPEG_type;
 | 
			
		||||
    self->jpeg = m_new_class(JPEGDEC);
 | 
			
		||||
    self->graphics = (ModPicoGraphics_obj_t *)MP_OBJ_TO_PTR(args[ARG_picographics].u_obj);
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -234,10 +245,8 @@ mp_obj_t _JPEG_decode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args
 | 
			
		|||
            break;
 | 
			
		||||
        // TODO 2-bit is currently unsupported
 | 
			
		||||
        case PicoGraphics::PEN_P2:
 | 
			
		||||
            self->jpeg->setPixelType(TWO_BIT_DITHERED);
 | 
			
		||||
            break;
 | 
			
		||||
        case PicoGraphics::PEN_1BIT:
 | 
			
		||||
            self->jpeg->setPixelType(ONE_BIT_DITHERED);
 | 
			
		||||
            self->jpeg->setPixelType(EIGHT_BIT_GRAYSCALE);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -245,13 +254,7 @@ mp_obj_t _JPEG_decode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args
 | 
			
		|||
    // since the JPEGDRAW struct has no userdata
 | 
			
		||||
    current_graphics = self->graphics->graphics;
 | 
			
		||||
 | 
			
		||||
    if(self->graphics->graphics->pen_type == PicoGraphics::PEN_P4 || self->graphics->graphics->pen_type == PicoGraphics::PEN_1BIT) {
 | 
			
		||||
        uint8_t *buf = new uint8_t[2048];
 | 
			
		||||
        result = self->jpeg->decodeDither(x, y, buf, f);
 | 
			
		||||
        delete[] buf;
 | 
			
		||||
    } else {
 | 
			
		||||
        result = self->jpeg->decode(x, y, f);
 | 
			
		||||
    }
 | 
			
		||||
    result = self->jpeg->decode(x, y, f);
 | 
			
		||||
 | 
			
		||||
    current_graphics = nullptr;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -454,6 +454,8 @@ mp_obj_t ModPicoGraphics_update(mp_obj_t self_in) {
 | 
			
		|||
    #endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    self->display->power_off();
 | 
			
		||||
 | 
			
		||||
    return mp_const_none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue