Bodmer / JPEGDecoder

A JPEG decoder library
Other
220 stars 64 forks source link

Suggested Improvement on drawSdJpeg #74

Open SL06 opened 1 year ago

SL06 commented 1 year ago

Thanks for the program.
I have use it to draw a series of 3 x 3 jpeg map tiles, 256 x 256 pixel, each on a 320 x 480 TFT. By adding the following line : if ((mcu_x >= 0) && (mcu_y >= 0)) // SL add

I was able to use negative xpos, ypos number to center the 3x3 tiles collection on the screen, and remove the excedent of the image.

`/ Draw a JPEG on the TFT, images will be cropped on the right/bottom sides if they do not fit //#################################################################################################### // This function assumes xpos,ypos is a valid screen coordinate. For convenience images that do not // fit totally on the screen are cropped to the nearest MCU size and may leave right/bottom borders. void jpegRender(int xpos, int ypos) {

uint16_t *pImg; uint16_t mcu_w = JpegDec.MCUWidth; uint16_t mcu_h = JpegDec.MCUHeight; uint32_t max_x = JpegDec.width; uint32_t max_y = JpegDec.height;

//Serial.println( String( "mcu_w : " + String(mcu_w) + " mcu_h : " + String(mcu_h))); //Serial.println( String( "max_x : " + String(max_x) + " max_y : " + String(max_y)));

//17:43:35.502 -> mcu_w : 16 mcu_h : 16 // 17:43:35.502 -> max_x : 256 max_y : 256

bool swapBytes = tft.getSwapBytes(); tft.setSwapBytes(true);

// Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs) // Typically these MCUs are 16x16 pixel blocks // Determine the width and height of the right and bottom edge image blocks uint32_t min_w = jpg_min(mcu_w, max_x % mcu_w); uint32_t min_h = jpg_min(mcu_h, max_y % mcu_h);

//Serial.println( String( "min_w : " + String(min_w) + " min_h : " + String(min_h)) ); // 17:43:35.502 -> min_w : 0 min_h : 0*/

// save the current image block size uint32_t win_w = mcu_w; uint32_t win_h = mcu_h;

// record the current time so we can measure how long it takes to draw an image uint32_t drawTime = millis();

// save the coordinate of the right and bottom edges to assist image cropping // to the screen size max_x += xpos; // largeur de l'image + position initial si different de 0 max_y += ypos;

// Fetch data from the file, decode and display while (JpegDec.read()) { // While there is more data in the file pImg = JpegDec.pImage; // Decode a MCU (Minimum Coding Unit, typically a 8x8 or 16x16 pixel block)

// Calculate coordinates of top left corner of current MCU
int mcu_x = JpegDec.MCUx * mcu_w + xpos;
int mcu_y = JpegDec.MCUy * mcu_h + ypos;

//Serial.println( String( "Top left mcu_x : " + String(mcu_x) + "   mcu_y : " + String(mcu_y)) );
if ((mcu_x >= 0) && (mcu_y >= 0))  // SL add
{

  // check if the image block size needs to be changed for the right edge
  if (mcu_x + mcu_w <= max_x) win_w = mcu_w;
  else win_w = min_w;

  // check if the image block size needs to be changed for the bottom edge
  if (mcu_y + mcu_h <= max_y) win_h = mcu_h;
  else win_h = min_h;

  // copy pixels into a contiguous block
  if (win_w != mcu_w) {
    uint16_t *cImg;
    int p = 0;
    cImg = pImg + win_w;
    for (int h = 1; h < win_h; h++) {
      p += mcu_w;
      for (int w = 0; w < win_w; w++) {
        *cImg = *(pImg + w + p);
        cImg++;
      }
    }
  }

  // calculate how many pixels must be drawn
  uint32_t mcu_pixels = win_w * win_h;

  // draw image MCU block only if it will fit on the screen
  if ((mcu_x + win_w) <= tft.width() && (mcu_y + win_h) <= tft.height())
    tft.pushImage(mcu_x, mcu_y, win_w, win_h, pImg);
  else if ((mcu_y + win_h) >= tft.height())
    JpegDec.abort();  // Image has run off bottom of screen so abort decoding
}

}

tft.setSwapBytes(swapBytes);

showTime(millis() - drawTime); // These lines are for sketch testing only }

`