Announcement

Collapse
No announcement yet.

Powerpointdateien autom. "komprimieren"

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Powerpointdateien autom. "komprimieren"

    Hallo,

    wir erstellen mit Delphi automatisierte Powerpoint Präsentationen.
    Händisch kann man in jeder MS Office Applikation beim Speichern unter Extras die enthaltenen Bilder im Dokument komprimieren.
    Dadurch reduziert sich die Dateigröße der ppt's um bis zu 80 Prozent!

    Leider gelang es uns bisher nicht, einen Weg zu finden, diese Komprimierung per Programmcode anzusprechen.
    Die MS Office-SDKs schweigen sich - wie die VBA-Hilfe und der Objektexplorer aus. Auch der Office-Makrorekorder speichert diesen Dialog unter Speichern unter\Extras\Bilder komprimieren\ nicht mit ?!?

    Da die erzeugten Dateien "unkomprimiert" viel zu groß sind, die Anwender ihre Bilder nicht eigenständig in JPG's konvertieren und Zippen nicht in Frage kommt, komme ich an dieser Stelle nicht weiter.

    Es gibt bereits fertige Tools wie NPX, die die Größe von ppt's reduzieren. Allerdings muß man
    die Dateien einzeln von Hand auswählen etc.
    Trotzdem muß es doch irgendwie möglich sein?

    Danke im voraus
    Lutz

  • #2
    Hallo Lutz,

    eine Möglichkeit, die "Komprimierung" auf anderem Weg hinzukriegen, ist, Bilder in die Zwischenablage zu kopieren und per

    <PRE>
    newshape := shapes.PasteSpecial(ppPasteJPG);
    </PRE>

    wieder in die Folie einzufügen. Dabei findet offenbar eine Umwandlung ins JPG-Format, ein Herunterskalieren auf die dargestellte Größe und ein Wegschneiden ausgeblendeter Bildbereiche statt.

    So weit, so gut. Aber die Arbeit beginnt damit erst: Beim Wiedereinfügen in die Folie gehen Transparenz-Effekte verloren, animierte GIFs spielen nicht mehr, Gruppen müssen rekursiv aufgelöst und wieder zusammengefügt werden, und Animationseffekte sind weg. Gerade der letzte Punkte macht mir zur Zeit so zu schaffen, dass ich das Projekt einstweilen zur Seite gelegt habe...

    Wenn Du's hingekriegt, publiziere bitte hier die Lösung ;-)

    Gruß, Werne

    Comment


    • #3
      Hallo Werner,

      wenn man Shapes(n).AnimationSettings.Animate auf True prüft und bei positivem Result die
      einzelnen Werte für:
      * Shapes(n).AnimationSettings.AfterEffect;
      * Shapes(n).AnimationSettings.EntryEffect;
      * Shapes(n).AnimationSettings.AnimationOrder;
      * usw. prüft und diese - wenn vorhanden - nach dem PasteSpecial(ppPasteJPG) wieder zuweist ... sollte es doch eigentlich funzen!?

      Natürlich ist sicher noch etwas mehr Feinarbeit nötig, um die Position (Top, Left) und die anderen Pictureeigenschaften/-effekte zu übertragen. Deine Lösung ist sicher ein guter Ansatz. Die animierten Gif's müssen eigentlich nicht komprimiert werden. Möglicherweise hilft es hier, die Shapesize zu ermitteln und nur Picture > 70 KB zu verarbeiten?!

      Besten Gruss, Joche

      Comment


      • #4
        Hallo Jochen,

        danke für die Motivationsspritze, mich mit diesem Projekt nochmals zu befassen.

        Das mit den AnimationSettings hatte ich, genauso wie von Dir vorgeschlagen, schon eingebaut, aber trotzdem haben die Animationen einiger unserer Präsentationen hinterhin nicht mehr richtig funktioniert. Der Grund: Microsoft hat ab PPT2002 die Animationen komplett neu aufgebaut (Slide.TimeLine, Timeline.MainSequence, Effect etc.). Ich habe es bisher noch nicht geschafft, eine Shape in einer Sequence gegen eine andere (nämlich das zurückkopierte, komprimierte Bild) auszutauschen. Der folgende Code erzeugt ein "Zugriff verweigert":

        <PRE>
        procedure ReplaceShapeInSequence(oldshape,newshape,sequence: OLEVariant);
        var
        effect : OLEVariant;
        i : integer;
        begin
        for i:=1 to sequence.Count do begin
        effect := sequence.Item(i);
        if AnsiCompareText(VarToStr(effect.shape.Name), VarToStr(oldshape.Name))=0
        then begin
        effect.shape := newshape; // Zugriff verweigert!!!
        end;
        end;
        end;
        </PRE>

        Weiß jemand Rat? Eine Alternative wäre, den Effekt in der Sequenz neu zu erzeugen und alle Eigenschaften 1:1 zu transferieren; aber wegen der Komplexität der Strukuren erscheint mir das recht mühsam und fehlerträchtig...

        Wegen der animierten Gifs ist das eigentliche Problem, dass PPT keine Möglichkeit gibt, das Graphikformat abzufragen. Auch die Größe einer shape in KB kann nicht abgefragt werder (bei Bildern geht's indirekt über die Pixeldimensionen). Eine Anfrage in Microsoft's Powerpoint- und in Borland's OLEAutomation-Newsgroups zu diesen Themen hat mir keine Lösung gebracht. Aber vielleicht schafft's ja das Entwickler-Forum.

        Gruß, Werne

        Comment


        • #5
          Hi Werner,

          .. klingt ja alles nach einer echten Challenge :-)
          Ich installiere mir am Wochenende mal die
          Office-Developer Version. Möglicherweise
          findet man dann mehr Infos, als in der
          normalen Version.
          Ich werde das Ganze einmal genauer prüfen und mit verschiedenen PPT-Dateien und verschiedenen Compilern ausprobieren.

          Gruss, Joche

          Comment


          • #6
            Hi Werner,

            ich beschäftige mich - wie vorher geschrieben -
            mit der MS Office-Developer Version.

            Vorab habe ich spasseshalber mal versucht, die
            Grösse der einzelenen Shapes zu ermitteln, wenn
            es sich um msoPicture handelt..
            Klappte ganz gut über den Ochsenweg:
            - eine unsichtbare PictureBox plazieren;
            - dessen AutoSize auf True stellen;
            - Clipboardgrafik in die PictureBox kopieren;
            - PictureBox-image als File speichern;
            - Filegrösse bestimmen;
            - File löschen

            ... jedenfalls erhält man so genauere Werte als mit Shape- Width & Height.
            Es gibt sicher einen besseren Weg - mal schaun,
            was das MSOD-SDK "sagt".
            MS scheint die Funktionen in eine DLL namens:
            OISAPP.DLL imlementiert zu haben. In dieser DLL
            findet man einen Verweis auf eine "CompressPicsDialog....."-Funktion.
            Im vollgespamten Web fand ich nichts zu dieser DLL oder dem Compress-Dialog?!?

            Gruss, Joche

            Comment


            • #7
              Hallo Jochen,

              ist ja super, was Du da alles rauskriegst! Das mit der PictureBox (damit meinst Du ein TImage?) ist eine gute Idee. Bleibt beim Umweg über die Zwischenablage und die Picturebox eigentlich das Graphikformat erhalten? Wenn ja, dann könnte man auch den Header der temporär erzeugten Datei analysien und rauskriegen, ob ein animiertes GIF-Bild vorliegt. Das wäre ein entscheidender Vorteil gegenüber meiner eigenen Routine, die Bildpixel zu ermitteln, was nicht erkennt, ob das Bild z.B. als JPG/GIF/PNG komprimiert in der Powerpoint-Folie vorliegt:

              <PRE>
              procedure OriginalPictureSize(shape:OLEVariant; var width,height:integer);
              var
              sh : OLEVariant;
              begin
              if shape.Type=msoPicture then begin
              sh := shape.Duplicate;
              ResetPictureProperties(sh);
              width := PointsToPixels(sh.Width);
              height := PointsToPixels(sh.Height);
              sh.Delete;
              end else begin
              width := -1;
              height := -1;
              end;
              end;
              </PRE>

              Dies benötigt noch folgende Hilfroutinen:

              <PRE>
              function PixelsPerInch:integer;
              var
              DC: HDC;
              begin
              DC := GetDC(0);
              try
              Result := GetDeviceCaps(DC, LOGPIXELSY);
              finally
              ReleaseDC(0,DC);
              end;
              end;

              <BR>

              function PointsToPixels(Points:double): Integer;
              begin
              Result := Trunc((Points / 72) * PixelsPerInch);
              end;

              <BR>

              procedure ResetPictureProperties(shape:OLEVariant);
              // aus: http://www.mvps.org/skp/ppt00044.htm#2
              begin
              if shape.Type=msoPicture then begin
              shape.LockAspectRatio := false;
              shape.ScaleWidth(1, true, msoScaleFromTopLeft);
              shape.ScaleHeight(1, true, msoScaleFromTopLeft);
              shape.LockAspectRatio := true;
              shape.PictureFormat.ColorType := msoPictureAutomatic;
              shape.PictureFormat.Brightness := 0.5;
              shape.PictureFormat.Contrast := 0.5;
              end;
              end;
              </PRE>

              Gruß, Werne

              Comment


              • #8
                Hi Werner,

                jo, TImage >> sorry für den MS-Office Slang :-)
                Ich denke, das Ursprungsformat bekommt man
                nicht mehr hin. Das Clipboard wandelt das Shape
                in ein Metafileformat.
                Aber die Grösse des Shapes lässt sich auf diese
                Tour recht gut ermitteln.

                Ich bin langsam zu der Überzeugung gekommen, dass es sinnvoll ist, für jedes Slide alle
                Shapes uns deren Eigenschaften in ein Array zu kopieren und nach ZOrder zu sortieren.
                Ich spiele noch ein wenig mit diversen PPTs und steige tiefer ein.

                by the way: MS berücksichtigt beim Compress keine kleineren Grafiken und Gif-Picture.
                Hier müsste es reichen, alle Picture-Shapes >= 500 KB zu verarbeiten.
                Gruss, Joche

                Comment


                • #9
                  Hallo Jochen,

                  bist Du an dem Thema noch dran?

                  Ich habe jetzt mal dieselbe Graphik-Datei in verschiedene Formate umgewandelt (bmp, gif, jpg, png), in Powerpoint eingefügt und nach dem von Dir beschriebenen Verfahren aus der PPT-Folie wieder in eigene Dateien extrahiert:

                  <PRE>
                  procedure TForm2.ExtractPic(shape:OLEVariant);
                  var
                  fn : string;
                  pic : TPicture;
                  begin
                  if shape.Type=msoPicture then begin
                  pic := TPicture.Create;
                  try
                  shape.Copy;
                  fn := ExtractFilePath(FFileName) + shape.Name + '.dat';
                  pic.Assign(Clipboard);
                  pic.SaveToFile(fn);
                  Statusbar1.SimpleText := fn;
                  finally
                  pic.Free;
                  end;
                  end;
                  end;
                  </PRE>

                  Die entstandenen Dateien habe ich mir dann mit meinem Hex-Editor angeschaut und dabei gefunden, dass im Extract der jpg-Datei die Original-Datei 1:1 enthalten ist. Leider werden die anderen Formate nicht erkannt. Hast Du eine Ahnung was da passiert?

                  Gruß, Werne

                  Comment

                  Working...
                  X