int LibRaw::raw2image(void)
{

  CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);

  try {
    raw2image_start();

    if (is_phaseone_compressed())
      {
        phase_one_allocate_tempbuffer();
        int rc = phase_one_subtract_black((ushort*)imgdata.rawdata.raw_alloc,imgdata.rawdata.raw_image);
	if(rc == 0)
	  rc = phase_one_correct();
	if(rc!=0)
	{
	  phase_one_free_tempbuffer();
	  return rc;
	}
      }

    // free and re-allocate image bitmap
    if(imgdata.image)
      {
        imgdata.image = (ushort (*)[4]) realloc (imgdata.image,S.iheight*S.iwidth *sizeof (*imgdata.image));
        memset(imgdata.image,0,S.iheight*S.iwidth *sizeof (*imgdata.image));
      }
    else
      imgdata.image = (ushort (*)[4]) calloc (S.iheight*S.iwidth, sizeof (*imgdata.image));

    merror (imgdata.image, "raw2image()");

    libraw_decoder_info_t decoder_info;
    get_decoder_info(&decoder_info);

    // Move saved bitmap to imgdata.image
    if( imgdata.idata.filters || P1.colors == 1)
      {
        if (IO.fuji_width) {
          unsigned r,c;
          int row,col;
          for (row=0; row < S.raw_height-S.top_margin*2; row++) {
            for (col=0; col < IO.fuji_width << !libraw_internal_data.unpacker_data.fuji_layout; col++) {
              if (libraw_internal_data.unpacker_data.fuji_layout) {
                r = IO.fuji_width - 1 - col + (row >> 1);
                c = col + ((row+1) >> 1);
              } else {
                r = IO.fuji_width - 1 + row - (col >> 1);
                c = row + ((col+1) >> 1);
              }
              if (r < S.height && c < S.width)
                imgdata.image[((r)>>IO.shrink)*S.iwidth+((c)>>IO.shrink)][FC(r,c)]
                  = imgdata.rawdata.raw_image[(row+S.top_margin)*S.raw_pitch/2+(col+S.left_margin)];
            }
          }
        }
        else {
          int row,col;
          for (row=0; row < S.height; row++)
            for (col=0; col < S.width; col++)
              imgdata.image[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][fcol(row,col)]
                = imgdata.rawdata.raw_image[(row+S.top_margin)*S.raw_pitch/2+(col+S.left_margin)];
        }
      }
    else // if(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY)
      {
        if(imgdata.rawdata.color4_image)
          {
            if(S.width*8 == S.raw_pitch)
              memmove(imgdata.image,imgdata.rawdata.color4_image,S.width*S.height*sizeof(*imgdata.image));
            else
              {
                for(int row = 0; row < S.height; row++)
                  memmove(&imgdata.image[row*S.width],
                          &imgdata.rawdata.color4_image[(row+S.top_margin)*S.raw_pitch/8+S.left_margin],
                          S.width*sizeof(*imgdata.image));
              }
          }
        else if(imgdata.rawdata.color3_image)
          {
            unsigned char *c3image = (unsigned char*) imgdata.rawdata.color3_image;
            for(int row = 0; row < S.height; row++)
              {
                ushort (*srcrow)[3] = (ushort (*)[3]) &c3image[(row+S.top_margin)*S.raw_pitch];
                ushort (*dstrow)[4] = (ushort (*)[4]) &imgdata.image[row*S.width];
                for(int col=0; col < S.width; col++)
                  {
                    for(int c=0; c< 3; c++)
                      dstrow[col][c] = srcrow[S.left_margin+col][c];
                    dstrow[col][3]=0;
                  }
              }
          }
        else
          {
            // legacy decoder, but no data?
            throw LIBRAW_EXCEPTION_DECODE_RAW;
          }
      }

    // Free PhaseOne separate copy allocated at function start
    if (is_phaseone_compressed())
      {
        phase_one_free_tempbuffer();
      }
    // hack - clear later flags!

    if (load_raw == &CLASS canon_600_load_raw && S.width < S.raw_width)
      {
        canon_600_correct();
      }

    imgdata.progress_flags
      = LIBRAW_PROGRESS_START|LIBRAW_PROGRESS_OPEN | LIBRAW_PROGRESS_RAW2_IMAGE
      |LIBRAW_PROGRESS_IDENTIFY|LIBRAW_PROGRESS_SIZE_ADJUST|LIBRAW_PROGRESS_LOAD_RAW;
    return 0;
  }
  catch ( LibRaw_exceptions err) {
    EXCEPTION_HANDLER(err);
  }
}