int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)
{

    if(!stream)
        return ENOENT;
    if(!stream->valid())
        return LIBRAW_IO_ERROR;
    recycle();

    try {
        ID.input = stream;
        SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN);

        if (O.use_camera_matrix < 0)
            O.use_camera_matrix = O.use_camera_wb;

        identify();
#if 0
        size_t bytes = ID.input->size()-libraw_internal_data.unpacker_data.data_offset;
        float bpp = float(bytes)/float(S.raw_width)/float(S.raw_height);
        float bpp2 = float(bytes)/float(S.width)/float(S.height);
        printf("RawSize: %dx%d data offset: %d data size:%d bpp: %g bpp2: %g\n",S.raw_width,S.raw_height,libraw_internal_data.unpacker_data.data_offset,bytes,bpp,bpp2);
        if(!strcasecmp(imgdata.idata.make,"Hasselblad") && bpp == 6.0f)
          {
            load_raw = &LibRaw::hasselblad_full_load_raw;
            S.width = S.raw_width;
            S.height = S.raw_height;
            P1.filters = 0;
            P1.colors=3;
            P1.raw_count=1;
            C.maximum=0xffff;
            printf("3 channel hassy found\n");
          }
#endif
        if(C.profile_length)
            {
                if(C.profile) free(C.profile);
                C.profile = malloc(C.profile_length);
                merror(C.profile,"LibRaw::open_file()");
                ID.input->seek(ID.profile_offset,SEEK_SET);
                ID.input->read(C.profile,C.profile_length,1);
            }
        
        SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY);
    }
    catch ( LibRaw_exceptions err) {
        EXCEPTION_HANDLER(err);
    }
    catch (std::exception ee) {
        EXCEPTION_HANDLER(LIBRAW_EXCEPTION_IO_CORRUPT);
    }

    if(P1.raw_count < 1) 
        return LIBRAW_FILE_UNSUPPORTED;

    
    write_fun = &LibRaw::write_ppm_tiff;
    
    if (load_raw == &LibRaw::kodak_ycbcr_load_raw) 
        {
            S.height += S.height & 1;
            S.width  += S.width  & 1;
        }
	libraw_decoder_info_t dinfo;
	get_decoder_info(&dinfo);
	if(dinfo.decoder_flags & LIBRAW_DECODER_LEGACY)
	{
		// Adjust sizes according to image buffer size
		S.raw_width = S.width;
		S.left_margin = 0;
		S.raw_height = S.height;
		S.top_margin = 0;
	}

    IO.shrink = P1.filters && (O.half_size ||
	((O.threshold || O.aber[0] != 1 || O.aber[2] != 1) ));

    S.iheight = (S.height + IO.shrink) >> IO.shrink;
    S.iwidth  = (S.width  + IO.shrink) >> IO.shrink;

    if(imgdata.idata.filters == 303979333U)
     {
    	//printf("BL=%d [%d,%d,%d,%d]\n",C.black,C.cblack[0],C.cblack[1],C.cblack[2],C.cblack[3]);
		C.black = C.cblack[0];
		C.cblack[0]=C.cblack[1]=C.cblack[2]=C.cblack[3]=0;
		imgdata.idata.filters = 2;	
     }
	// X20
	if(imgdata.idata.filters == 0x5bb8445b)
	{
		C.black = 257;
		C.cblack[0]=C.cblack[1]=C.cblack[2]=C.cblack[3]=0;
		imgdata.idata.filters = 2;	
		S.width = 4030;
		S.height = 3010;
		S.top_margin = 2;
		S.left_margin = 2;
	}
	// X100S
	if(imgdata.idata.filters == 0x5145bb84)
	{
		C.black = 1024;
		C.cblack[0]=C.cblack[1]=C.cblack[2]=C.cblack[3]=0;
		S.left_margin = 2;
		S.top_margin = 1;
		S.width = 4934;
		S.height = 3290;
		imgdata.idata.filters = 2;
	}

    // Save color,sizes and internal data into raw_image fields
    memmove(&imgdata.rawdata.color,&imgdata.color,sizeof(imgdata.color));
    memmove(&imgdata.rawdata.sizes,&imgdata.sizes,sizeof(imgdata.sizes));
    memmove(&imgdata.rawdata.iparams,&imgdata.idata,sizeof(imgdata.idata));
    memmove(&imgdata.rawdata.ioparams,&libraw_internal_data.internal_output_params,sizeof(libraw_internal_data.internal_output_params));
    
    SET_PROC_FLAG(LIBRAW_PROGRESS_SIZE_ADJUST);


    return LIBRAW_SUCCESS;
}