EXIF- Daten und GDIPlus



  • Ich habe folgendes Problem:

    1. ich lese eine JPG (TIF) Datei ein mit GDIPlus und speichere ds in ein
    TBitmap - Ist OK
    2. Ich Speicher das Bild (Aus dem TBitmap) in eine JPG (TIF) Datei
    mit GDIPlius - Ist auch noch (fast) OK
    3. Ich lese die EXIF- Daten aus einer 2. JPG Datei aus und übertrage diese
    in das neue Bild - JPG- Objekt in der GDIPlus.

    Hier liegt das Problem: scheinbar werden die EXIF Daten übertragen, die sind in der neuen Datei auch scheinbar enthalten.
    Aber einige Einträge werden beim nächsten Öffnen anders usgelesen.

    Speziell die Daten zu ICC- Farbprofilen gehen irgendwie kaputt.
    Kennt jemand den Effekt?
    Kann einer den Fehler lokalisieren im folgenden Code?

    // Diese Methode sucht die Class-ID eines Encoders (aus der MSDN Library)
    //
    int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
    {
       UINT  num = 0;          // number of image encoders
       UINT  size = 0;         // size of the image encoder array in bytes
    
       ImageCodecInfo *pImageCodecInfo = NULL;
    
       GetImageEncodersSize(&num, &size);
       if(size == 0)
          return -1;  // Failure
    
       pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
       if(pImageCodecInfo == NULL)
          return -1;  // Failure
    
       GetImageEncoders(num, size, pImageCodecInfo);
    
       for(UINT j = 0; j < num; ++j)
       {
          if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
          {
             *pClsid = pImageCodecInfo[j].Clsid;
             free(pImageCodecInfo);
             return j;  // Success
          }
       }
    
       free(pImageCodecInfo);
       return -1;  // Failure
    }
    //***********************************************************************
    
    //Datei Speichern als "AFile"
    //EXIF- Daten übertragen aus "AFiledataFrom
    // Alle Variablen zum Lese der zu übertragenden EXIF Daten haben im Namen "DataFrom"
    // Das zu speichernde Bitmap- Bild liegt in Variabele FBitmap vor
    void __fastcall TGDIPJPGImage::SaveToFile(AnsiString AFile,AnsiString AFileDataFrom)
    {
      GdiplusStartupInput gdiplusStartupInput;
      Gdiplus::ULONG_PTR gdiplusToken;
    
      UINT sizeDataFrom=0;
      UINT countDataFrom=0;
      Bitmap* bitmapDataFrom=NULL;
      PropertyItem* pPropBufferDataFrom=NULL;
    
      Bitmap* bitmap;
      CLSID  clsid;
      EncoderParameters encoderParameters;
      PropertyItem* propertyItem;
    
      GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    
    //"Alte" Erweiterte daten lesen  **************************
      bitmapDataFrom = new Bitmap((WideString)AFileDataFrom);
      bitmapDataFrom->GetPropertySize(&sizeDataFrom, &countDataFrom);
      // GetAllPropertyItems returns an array of PropertyItem objects.
      // Allocate a buffer large enough to receive that array.
      pPropBufferDataFrom =(PropertyItem*)malloc(sizeDataFrom);
      // Get the array of PropertyItem objects.
      bitmapDataFrom->GetAllPropertyItems(sizeDataFrom, countDataFrom, pPropBufferDataFrom);
      delete bitmapDataFrom;
    //"Alte" Erweiterte daten lesen ENDE **********************
    
      bitmap = new Bitmap(FBitmap->Handle,FBitmap->Palette);
    //  propertyItem = new PropertyItem;
    
      GetEncoderClsid(L"image/jpeg", &clsid);
    
    //"Alte" Erweiterte daten übernehmen **********************
      if (pPropBufferDataFrom!=NULL)
      {
        PropertyItem* propertyItem = new PropertyItem;
        for(UINT j = 0; j < countDataFrom; ++j)
        {
          pPropBufferDataFrom[j].type=pPropBufferDataFrom[j].type;
    
          propertyItem->id = pPropBufferDataFrom[j].id;
          propertyItem->length = pPropBufferDataFrom[j].length;
          propertyItem->type = pPropBufferDataFrom[j].type;
          propertyItem->value = pPropBufferDataFrom[j].value;
          bitmap->SetPropertyItem(propertyItem);
        }
    
        delete propertyItem;
        free(pPropBufferDataFrom);
      }
    //"Alte" Erweiterte daten übernehmen Ende *****************
    
      //EncoderQuality aus GDIPlus geht nicht!!! (???)
      //Ist in EXTGDIPLUS.H deklariert als: extern __EncoderQuality
      encoderParameters.Parameter[ 0 ].Guid = Gdiplus::_EncoderQuality;
      encoderParameters.Count = 1;
      encoderParameters.Parameter[ 0 ].Type = EncoderParameterValueTypeLong;
      encoderParameters.Parameter[ 0 ].NumberOfValues = 1;
      encoderParameters.Parameter[ 0 ].Value = &FJPGQuality;
      bitmap->Save((WideString)AFile, &clsid, &encoderParameters);
    
      delete bitmap;
      GdiplusShutdown(gdiplusToken);
    }
    

    Wie gesagt, das Speichern klappt ganz gut, viele EXIF- daten sind auch wieder lesbar.

    Aber einige Daten gehen kaputt - speziell vorhandene ICC- Farbprofile.
    Und genau die müssen erhalten bleiben

    Thx
    Frank




Anmelden zum Antworten