int LibRaw::raw2image(void)
{

    CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);

    try {
        raw2image_start();

        if (is_phaseone_compressed())
          {
			  phase_one_allocate_tempbuffer();
			  phase_one_subtract_black((ushort*)imgdata.rawdata.raw_alloc,imgdata.rawdata.raw_image);
	          phase_one_correct();
          }

        // 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(decoder_info.decoder_flags & LIBRAW_DECODER_FLATFIELD)
            {
              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);
    }
}