bitbank2 / JPEGDEC

An optimized JPEG decoder for Arduino
Apache License 2.0
365 stars 47 forks source link

extracting pixel 0-255 greyscale value from pDraw->pPixels[i] when using EIGHT_BIT_GRAYSCALE #53

Closed mrcodetastic closed 1 year ago

mrcodetastic commented 1 year ago

Hi Larry. Awesome library as always. I have a large colour JPEG image (Image size: 1600 x 1200, orientation: 0, bpp: 24) that I want to load as a greyscale at 1/8 resolution and then do some basic processing of it values when the drawMCUs function is called over the blocks.

My question is: How does pDraw->pPixels[i] work with an image decoded as 8bit greyscale (given it returns a uint16_t for each pixel)? What bits do I drop from the uint16_t for that pixel?

For each 8bit greyscale pixel (element in pPixels) I'm getting large values like (in binary below):

1010100010101
1011100011001
1100000010011

I would have through the MSB's be 0'd our or something.

The width returned from each call to 'drawMCUs' is 200 which is 1600/8. From looking at the library code, this is correct as it does a whole row when decoding as EIGHT_BIT_GRAYSCALE.

So the question is, which byte do I use?

    jpeg.setPixelType(EIGHT_BIT_GRAYSCALE);
    ....
    if (jpeg.decode(0,0,JPEG_SCALE_EIGHTH))
    {
      lTime = micros() - lTime;
      sprintf(szTemp, "Successfully decoded image in %d us", (int)lTime);
      Serial.println(szTemp);
    }

int drawMCUs(JPEGDRAW *pDraw)
{
  //int x = pDraw->x;
  //int y = pDraw->y;
  int w = pDraw->iWidth;
  int h = pDraw->iHeight;

  for(int i = 0; i < w * h; i++)
  {
    //uint8_t 8bit_greyscale_value = 
    Serial.println(pDraw->pPixels[i], BIN);
    //pDraw->pPixels[i] = (pDraw->pPixels[i] & 0x7e0) >> 5; // extract just the six green channel bits.
  }

  return 1; // returning true (1) tells JPEGDEC to continue decoding. Returning false (0) would quit decoding immediately.
} /* drawMCUs() */
mrcodetastic commented 1 year ago

I think I figured it out. I just use the LSB.

int drawMCUs(JPEGDRAW *pDraw)
{
  int w = pDraw->iWidth;
  int h = pDraw->iHeight;

  for(int i = 0; i < w * h; i++)
  {
    uint8_t value = pDraw->pPixels[i] & 0xFF;
    Serial.print(value, DEC);
    Serial.print(", ");
  }
  Serial.println("");

  return 1; // returning true (1) tells JPEGDEC to continue decoding. Returning false (0) would quit decoding immediately.
} /* drawMCUs() */
bitbank2 commented 1 year ago

You should cast the uint16_t to uint8_t . Each pixel is 8-bits. See JPEGPutMCU8BitGray() in jpeg.inl.