在DNG-SDK基礎上寫DNG(RAW to DNG)

       通過以前文章的配置編譯通過的環境基礎上寫自己的DNG方法,推薦很給力的網址,https://forums.adobe.com/message/2127126?tstart=0,其中的一些參數根據自己的相機配置一下即可寫出DNG圖片,希望對大家能夠提供幫助。至此雖然DNG寫出來了,但對DNG整體結構和一些細節概念還是不知道,希望大家有好的文章貼一下。

網址內容:

SubIFD1 tags not updating

此問題已回答

 

 

Hey,

 

I'm currently developing code to write raw camera image data to dng files (I'm doing some processing in between so I'm not using the DNG Converter exe). I have not been able to find any tutorial on the dng sdk, so my code is based partly on the dng_validate code and partly on incomplete code provided by others.

 

Anyway, my problem is that the dngs are not being written correctly. When I run dng_validate on the created dng, I get the following: "Error: Missing or invalid SamplesPerPixel (SubIFD 1)". However, when I set the SamplesPerPixel tag in SubIFD 1, the change is not reflected in the output of dng_validate when run on the created dng. Similarly, when I set the PhotometricInterpretation tag to CFA (32803), the output of dng_validate still shows it as being set to LinearRaw. My question is are there other SubIFD 1 tags that can have the effect of overwriting the above tags?

 

Thanks,

 

aubrey

 

 

正確答案 作者: Vojtech Tryhuk 在 2009-7-14 上午5:36

>Warning: Neither AsShotNeutral nor AsShotWhiteXY included
I use SetCameraNeutral as shown in the previously posted code. Value for this tag has to be extracted from makernote and therefore a code for its extraction differs between cameras and manufacturers.

 

>Secondly, I am not clear on how to assign raw image data to the sdk class objects.
This is how I do it

 

    AutoPtr<dng_image> image(new dng_simple_image(bounds, planes, pixelType, memalloc));
    dng_pixel_buffer srcBuffer;
    srcBuffer.fPlane = 0;
    srcBuffer.fPlanes= planes;
    srcBuffer.fColStep = planes;
    srcBuffer.fRowStep = width*planes;
    srcBuffer.fPixelType  = pixelType;
    srcBuffer.fPixelSize  = TagTypeSize(pixelType);
    srcBuffer.fArea     = bounds;
    uint32 srcBufferSize = srcBuffer.fPixelSize *
                srcBuffer.fRowStep *
                height;

 

    AutoPtr<dng_memory_block> srcData (host.Allocate (srcBufferSize));
    srcBuffer.fData = srcData->Buffer ();


    for(int y=0;y<height;y++)
    {
        unsigned __int16* pData=srcBuffer.DirtyPixel_uint16(y,0,0);
        // copy line from source buffer to pData
    }
    image->Put(srcBuffer);

查看上下文中的回答

此內容已被標記爲最終。  顯示 4 條回覆

  • 1. Re: SubIFD1 tags not updating 

     

    Vojtech Tryhuk 2009-7-7 上午12:43 (回覆 duxy_d

    Here's an excerpt from my code which performs raw to dng conversion, I hope it helps a bit:

     

            dng_memory_allocator memalloc(gDefaultDNGMemoryAllocator);

     

            dng_host host(&memalloc,NULL);
            dng_negative *negative=host.Make_dng_negative();

     

            dng_rect    bounds(0,0,height,width);
            uint32        planes=rawdata.channels>1?rawdata.channels:1;
            uint32        pixelType=ttShort;
            uint32        bitsPerSample=rawdata.bitsPerSample;
            uint32        pixelRange=1<<bitsPerSample;

     

            AutoPtr<dng_image> image(new dng_simple_image(bounds, planes, pixelType, memalloc));

     

            // allocate source buffer and copy image data to this buffer, put to image...


            negative->SetStage1Image(image);
            host.SetSaveDNGVersion (dngVersion_SaveDefault);
           
            // for bayer
            negative->SetColorKeys(colorKeyRed,colorKeyGreen,colorKeyBlue);
            negative->SetBayerMosaic(phase);
            negative->SetColorChannels(3);

     

            negative->SetWhiteLevel(rawdata.nWhite); // or negative->SetWhiteLevel(pixelRange-1);
            negative->SetBlackLevel(0);
            negative->SetBaselineExposure(rawdata.fBaselineExposure);
            if (rawdata.fBaselineNoise!=0)
                negative->SetBaselineNoise(rawdata.fBaselineNoise);
            // setbaselinesharpness, setgreensplit...
            // for nikon d1x negative->SetDefaultScale

     

            negative->SetDefaultCropSize(width,height);


            if (sraw)         // for sraw set analog balance
            {
                dng_vector_3 v(rawdata.fAnalogBalance[0],rawdata.fAnalogBalance[1],rawdata.fAnalogBalance[2]);
                negative->SetAnalogBalance(v);
                dng_vector_3 vn(1.0,1.0,1.0);
                negative->SetCameraNeutral(vn);
            }
            else     // ordinary raw
            {
                dng_vector_3 v(1.0,1.0,1.0);
                negative->SetAnalogBalance(v);
                dng_vector_3 cn(rawdata.fCameraNeutral[0],rawdata.fCameraNeutral[1],rawdata.fCameraNeutral[2]);
                negative->SetCameraNeutral((const dng_vector) cn);
            }

     

            // now i go through a table of cameras and create a profile
            AutoPtr<dng_camera_profile> camprofile (new dng_camera_profile ());
            dng_matrix_3by3 m(1,0.0000,0.0000,
                0.0000,1,0.0000,
                0.0000,0.0000,1);
                camprofile->SetName(szUniqueName);
                negative->SetModelName(szUniqueName);
                negative->SetBlackLevel(CameraTable[i].black); // if not known from raw file
                // setquadblacks
                negative->SetWhiteLevel(CameraTable[i].maximum);// if not known from raw file
                // init matrix m from cameratable
                // SetBaselineExposure, SetBaselineNoise


            camprofile->SetColorMatrix1((dng_matrix) m);
            camprofile->SetCalibrationIlluminant1(21);
            negative->AddProfile(camprofile);

     

            // setlinearization if lin.table is available


            // negative->SetActiveArea, SetDefaultCropOrigin, SetDefaultCropSize

     

            // set exif
            dng_orientation orient;
            orient.SetTIFF(rawdata.orientation);
            negative->SetBaseOrientation(orient);

     

            // for raw files with tiff header i use this code for exif
                if (bTiffHeader)
                {
                    std::string szName;
                    wcs2str(pNEFSCB->wcsPath,szName);
                    dng_file_stream stream(szName.c_str());
                    dng_info info;
                    info.Parse (host, stream);
                    info.PostParse (host);

     

        #define COPYEXIFTAG(tagName)    pExif->##tagName=info.fExif->##tagName;
        #define COPYEXIFTAGARR(tagName, cnt)    for(int c=0;c<cnt;c++) { pExif->##tagName[c]=info.fExif->##tagName[c]; }
                    COPYEXIFTAG(fImageDescription);
                    COPYEXIFTAG(fMake);
                    COPYEXIFTAG(fModel);
                    COPYEXIFTAG(fSoftware);
                    COPYEXIFTAG(fArtist);
                    ....

     

            // load xmp...


            negative->SynchronizeMetadata();

     

            dng_image_preview thumbnail;

     

            {
                host.SetNeedsImage(true);
                host.SetForPreview(true);
                host.SetMinimumSize(bJpegPreview?1024:256);
                host.SetPreferredSize(bJpegPreview?1024:256);
                if (!bJpegPreview)
                    host.SetMaximumSize(256);
                host.ValidateSizes ();
                uint32 gMathDataType = ttShort;
                int32 gMosaicPlane = 1;
                negative->BuildStage2Image (host,
                    gMathDataType);


                negative->BuildStage3Image (host,
                   gMosaicPlane);

     

                dng_timer timer ("Build thumbnail time");

     

                dng_render render (host, *negative);

     

                render.SetFinalSpace (negative->IsMonochrome () ? dng_space_GrayGamma22::Get ()
                    : dng_space_sRGB       ::Get ());

     

                render.SetFinalPixelType (ttByte);
                render.SetMaximumSize (256);
                thumbnail.fImage.Reset (render.Render ());

     

                // large preview
                if (bJpegPreview)
                    pJPGPreview=CreateJpegPreview(host,negative);   
            }

     

            dng_preview_list pl;
            if (NULL!=pJPGPreview)
            {
                pl.Append(AutoPtr<dng_preview>(pJPGPreview));
                pJPGPreview=NULL;
            }
            dng_image_writer writer;
            dng_file_stream filestream(szDNGFileName.c_str(), true);
            writer.WriteDNG(host,
                            filestream,
                            *negative,
                            thumbnail,
                            bCompressed?ccJPEG:ccUncompressed,
                            pl.Count()==0?NULL:&pl);

     

     

     

     

    1 位用戶發現它有用
  • 2. Re: SubIFD1 tags not updating 

     

    duxy_d 2009-7-14 上午2:58 (回覆 Vojtech Tryhuk

    Vojtech, thanks for the post and the code. It helped to solve the problem I was having with the PhotometricInterpretation tag (I was using inconsistent

    number of colour planes).

     

    However, although I can now generate dng files from raw files, the output dng files have constant intensity across the entire image (the input image doesn't). I think there are two possible problems with my code.

     

    Firstly, when I run dng_validate on the output dng, it is clear of errors but produces one warning: "Warning: Neither AsShotNeutral nor AsShotWhiteXY included (legal but not recommended)". What parameter/function should I use from the dng sdk to set either of these tags? I cannot find any mention of them in the sdk reference manual.

     

    Secondly, I am not clear on how to assign raw image data to the sdk class objects. I am putting the raw data onto a dng_memory_stream, and associating this stream with a dng_memory_block through a dng_memory_allocator. I've checked that this stream contains the correct data. Then, when I crate a dng_image, the dng_image object points to this same memory location. The dng_host also points to this memory location, and therefore the dng_negative that is formed from this dng_host points to the same memory location. In order to write the data to file, I create another dng_memory_stream using a different dng_memory_allocator, and write to this stream using the dng_image_writer::WriteDNG() function, with the dng_host and dng_negative objects as parameters. Finally I write the dng data from memory to the output file. I've checked the data on the output stream and it is not correct.

     

    An outline of the key stages of my code is included below. It is broadly similar to the code Vojtech provided in his reply. Is the outlined approach correct? Somwhere in the code the raw pixel data is being altered, but I can't figure out where, and I'm wondering is it something high-level that I'm doing wrong.

     

    Can anyone address either of these two problems? Any help would be much appreciated - I haven't been able to find any tutorial on the dng sdk so for some parts of code I've had to resort to trial and error

     

    Thanks,

     

    aubrey

     


    /*****************************************/

     


    void Correct::SaveDNG() {

     

      // raw_data is 1D array of raw pixel values

     

      // Create stream with associated memory and place raw data in it
      dng_memory_allocator memalloc(gDefaultDNGMemoryAllocator);
      dng_memory_stream stream(memalloc);
      stream.Put(raw_data, mImg->imgdata.sizes.height*mImg->imgdata.sizes.width*sizeof(unsigned short));

     

      // Create host
      dng_host host(&memalloc,NULL);
      host.SetPreferredSize(0);
      host.SetMinimumSize(100);
      host.SetMaximumSize(1000);
      host.ValidateSizes();
      host.SetKeepStage1(true);
      host.SetKeepDNGPrivate(true);

     

      // Create image and bind to memory containing raw data
      AutoPtr<dng_image> image(new dng_simple_image(dng_rect(mImg->imgdata.sizes.height, mImg->imgdata.sizes.width), 1, ttShort, 1<<16, memalloc));

     

      // Define camera profile
      AutoPtr<dng_camera_profile> camprofile(new dng_camera_profile);
      // ... set params here

     

      // Define IFD 0 and bind to host
      dng_ifd ifd0;
      // ... set params here
      ifd0.ReadImage(host, stream, *image.Get());

     

      // Define IFD 1 and bind to host
      dng_ifd ifd1;
      // ... set params here
      ifd1.ReadImage(host, stream, *image.Get());

     

      // Create negative, add camera profile, build images for each stage and update metadata
      dng_negative *negative(host.Make_dng_negative());
      // ... set params here
      negative->AddProfile(camprofile);
      negative->SetStage1Image(image);
      negative->BuildStage2Image(host);
      negative->BuildStage3Image(host, 1);
      negative->SynchronizeMetadata();
      negative->RebuildIPTC();

     

      // Define exif and bind to negative
      dng_exif* exif;
      // ... set params here
      exif = negative->GetExif();

     

      // Create image preview
      dng_image_preview thumbnail;
      // ... render etc.

     

      // Write all dng data to memory stream
      dng_image_writer writer;
      dng_memory_stream filestream(gDefaultDNGMemoryAllocator);
      writer.WriteDNG(host, filestream, *negative, thumbnail, ifd1.fCompression);

     

      // Write data in stream to file
      wxFile dng_file(filename.c_str(), wxFile::write);
      static const size_t BlockSize = 1024*64;
      size_t mem_stream_size = filestream.Length();
      std::vector<char> block_buffer(BlockSize);
      filestream.SetReadPosition(0);
      for (size_t p = 0; p < mem_stream_size; p += BlockSize)
      {
        size_t cur_clock_size = mem_stream_size-p;
        if (cur_clock_size > BlockSize) cur_clock_size = BlockSize;
          if (cur_clock_size == 0) break;
          filestream.Get(&block_buffer.front(), cur_clock_size);
          dng_file.Write(&block_buffer.front(), cur_clock_size);
      }
      dng_file.Close();
    }

  • 正確答案3. Re: SubIFD1 tags not updating 

     

    Vojtech Tryhuk 2009-7-14 上午5:36 (回覆 duxy_d

    >Warning: Neither AsShotNeutral nor AsShotWhiteXY included
    I use SetCameraNeutral as shown in the previously posted code. Value for this tag has to be extracted from makernote and therefore a code for its extraction differs between cameras and manufacturers.

     

    >Secondly, I am not clear on how to assign raw image data to the sdk class objects.
    This is how I do it

     

        AutoPtr<dng_image> image(new dng_simple_image(bounds, planes, pixelType, memalloc));
        dng_pixel_buffer srcBuffer;
        srcBuffer.fPlane = 0;
        srcBuffer.fPlanes= planes;
        srcBuffer.fColStep = planes;
        srcBuffer.fRowStep = width*planes;
        srcBuffer.fPixelType  = pixelType;
        srcBuffer.fPixelSize  = TagTypeSize(pixelType);
        srcBuffer.fArea     = bounds;
        uint32 srcBufferSize = srcBuffer.fPixelSize *
                    srcBuffer.fRowStep *
                    height;

     

        AutoPtr<dng_memory_block> srcData (host.Allocate (srcBufferSize));
        srcBuffer.fData = srcData->Buffer ();


        for(int y=0;y<height;y++)
        {
            unsigned __int16* pData=srcBuffer.DirtyPixel_uint16(y,0,0);
            // copy line from source buffer to pData
        }
        image->Put(srcBuffer);

  • 4. Re: SubIFD1 tags not updating 

     

    duxy_d 2009-7-23 上午4:26 (回覆 Vojtech Tryhuk

    Hey Vojtech, your code solved both my problems, thanks!

     

    I was using a dng_matrix instead of a dng_matrix_3 to set the AsShotNeutral, that was why it wasn't being assigned correctly.

     

    And I used your code to push the pixel data into the image object, which  worked perfectly.

     

    aubrey

發佈了45 篇原創文章 · 獲贊 22 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章