Example #1
0
static void
maskedSubsample(const GPixmap* img,
                const GBitmap *p_mask,
                GPixmap& subsampled_image,
                GBitmap& subsampled_mask,
                int gridwidth, int inverted_mask, 
                int minpixels=1
                )
{
  const GPixmap& image= *img;
  const GBitmap& mask = *p_mask;
  int imageheight = image.rows();
  int imagewidth = image.columns();
  // compute the size of the resulting subsampled image
  int subheight = imageheight/gridwidth;
  if(imageheight%gridwidth)
    subheight++;
  int subwidth = imagewidth/gridwidth;
  if(imagewidth%gridwidth)
    subwidth++;
  // set the sizes unless in incremental mode
  subsampled_image.init(subheight, subwidth);
  subsampled_mask.init(subheight, subwidth);
  // go subsampling
  int row, col;  // row and col in the subsampled image
  int posx, posxend, posy, posyend; // corresponding square in the original image
  for(row=0, posy=0; row<subheight; row++, posy+=gridwidth)
    {
      GPixel* subsampled_image_row = subsampled_image[row]; // row row of subsampled image
      unsigned char* subsampled_mask_row = subsampled_mask[row]; // row row of subsampled mask
      posyend = posy+gridwidth;
      if(posyend>imageheight)
        posyend = imageheight;
      for(col=0, posx=0; col<subwidth; col++, posx+=gridwidth) 
        {
          posxend = posx+gridwidth;
          if(posxend>imagewidth)
            posxend = imagewidth;
          int count = 0;
          int r = 0;
          int g = 0;
          int b = 0;
          for(int y=posy; y<posyend; y++)
            {
              const unsigned char* mask_y = mask[y]; // Row y of the mask
              for(int x=posx; x<posxend; x++)
                {
                  unsigned char masked = (inverted_mask ? !mask_y[x] :mask_y[x]);
                  if(!masked)
                    {
                      GPixel p = image[y][x];
                      r += p.r;
                      g += p.g;
                      b += p.b;
                      count ++;
                    }
                }
            }
          /* minpixels pixels are enough to give the color */
          /* so set it, and do not mask this point */
          if(count >= minpixels)   
            {
              GPixel p;
              p.r = r/count;
              p.g = g/count;
              p.b = b/count;
              subsampled_image_row[col] = p;
              subsampled_mask_row[col] = 0;
            } 
          else /* make it bright red and masked */ 
            {
              subsampled_image_row[col] = GPixel::RED;
              subsampled_mask_row[col] = 1;
            }
        }
    }
}
Example #2
0
void
JPEGDecoder::decode(ByteStream & bs,GPixmap &pix)
{
  struct jpeg_decompress_struct cinfo;

  /* We use our private extension JPEG error handler. */
  struct djvu_error_mgr jerr;

  JSAMPARRAY buffer;    /* Output row buffer */
  int row_stride;   /* physical row width in output buffer */
  int full_buf_size;
  int isGrey,i;

  cinfo.err = jpeg_std_error(&jerr.pub);

  jerr.pub.error_exit = djvu_error_exit;

  if (setjmp(jerr.setjmp_buffer))
  {

    jpeg_destroy_decompress(&cinfo);
    G_THROW( ERR_MSG("GPixmap.unk_PPM") );
  }

  jpeg_create_decompress(&cinfo);

  Impl::jpeg_byte_stream_src(&cinfo, bs);

  (void) jpeg_read_header(&cinfo, TRUE);

  jpeg_start_decompress(&cinfo);
  
  /* We may need to do some setup of our own at this point before reading
   * the data.  After jpeg_start_decompress() we have the correct scaled
   * output image dimensions available, as well as the output colormap
   * if we asked for color quantization.
   * In this example, we need to make an output work buffer of the right size.
   */

  /* JSAMPLEs per row in output buffer */
  row_stride = cinfo.output_width * cinfo.output_components;
  full_buf_size = row_stride * cinfo.output_height;

  /* Make a one-row-high sample array that will go away when done with image */
  buffer = (*cinfo.mem->alloc_sarray)
    ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);

  GP<ByteStream> goutputBlock=ByteStream::create();
  ByteStream &outputBlock=*goutputBlock;
  outputBlock.format("P6\n%d %d\n%d\n",cinfo.output_width, 
                                 cinfo.output_height,255);

  isGrey = ( cinfo.out_color_space == JCS_GRAYSCALE) ? 1 : 0; 

  while (cinfo.output_scanline < cinfo.output_height)
  {
    (void) jpeg_read_scanlines(&cinfo, buffer, 1);

    if ( isGrey == 1 )
    {
      for (i=0; i<row_stride; i++)
      {
        outputBlock.write8((char)buffer[0][i]); 
        outputBlock.write8((char)buffer[0][i]); 
        outputBlock.write8((char)buffer[0][i]); 
      }
    }else
    {
      for (i=0; i<row_stride; i++) 
        outputBlock.write8((char)buffer[0][i]); 
    }
  }

  (void) jpeg_finish_decompress(&cinfo);   

  jpeg_destroy_decompress(&cinfo);
  
  outputBlock.seek(0,SEEK_SET);

  pix.init(outputBlock);
}