JPG vers tImage

Résolu
papyvore Messages postés 223 Date d'inscription samedi 15 novembre 2003 Statut Membre Dernière intervention 16 décembre 2021 - 29 nov. 2017 à 11:17
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 - 30 nov. 2017 à 19:42
Bonjour,
j'extrais des images jpg vers un timage en cherchant dans stream ou un memo , je charge dans timage les élément compris entre FF D8 ...FFD9
jusque là tout va bien.
mais je trouve des images qui contiennent elles même des images,structuré comme ça

Image principale FF D8
Image inter FFD8
FFD9
FFD9

Comme je fais une recherche entre FFD8 et FFD9 le premier D9 trouvé n'est pas le bon.
c'est sans doute un peu brouillon ,mais quelqu'un à une idée.
comment extraire ce qui est entre le premier D8 est le dernier D9 incluant tout ce qui est compris entre ces deux bornes.
merci.

4 réponses

Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
29 nov. 2017 à 14:37
Bonjour,

Un ordinateur calcule dans un système discret. Pour lui, il n'y a rien entre FFD8 et FFD9. Ta question est donc étrange.

Un peu de ton code ne pourrait que nous aider, je pense...
--
0
papyvore Messages postés 223 Date d'inscription samedi 15 novembre 2003 Statut Membre Dernière intervention 16 décembre 2021 15
29 nov. 2017 à 15:20
en effet je me suis mal exprimé .
une image jpg en hexa commence par FF D8 et se termine par FF D9
alors pour regarder ce qu'il ce passe je charge dans un memo un fichier contenant des images.
procedure TForm2.LoadFromFileToMem(const FileName: string);
var
ms: TMemoryStream;
begin
ms := TMemoryStream.Create;
ms.LoadFromFile(FileName);
Memo1.Lines.Text := StreamToHex(ms);
ms.Free;
end;

en suite je compte les images

NbImage := CompteImage('FFD8', Memo1.Text);

Function TForm2.CompteImage(Const SubStr: String; Const s: String): Integer;
Var
I: Integer;
begin
Result := 0;
I := 0;
Repeat
I := PosEx(SubStr, s, I + 1);
If I <> 0 Then
inc(Result);
Until I = 0;
End;

for I := 0 to NbImage - 1 do
begin
Memo2.Clear;
CopyString('FFD8', 'FFD9', Memo1, Memo2);
....
procedure TForm2.CopyString(mot1: string; mot2: string; memoIn: TMemo;
memoOut: TMemo);
var
CurseurDepart: Integer;
CurseurFin: Integer;
longueur_mot1: Integer;
longueurSelection: Integer;
maSelection: string;
memStream: TMemoryStream;
jpeg: TJPEGImage;
i : integer;
begin
longueur_mot1 := Length(mot1);
CurseurDepart := PosEx(mot1, memoIn.Text, 1) - 1;
CurseurFin := PosEx(mot2, memoIn.Text, CurseurDepart + longueur_mot1) - 1;
longueurSelection := (CurseurFin) - (CurseurDepart - 4);
memoIn.SelStart := CurseurDepart; // On positionne le curseur après le 1er mot
memoIn.SelLength := longueurSelection; // On sélectionne ...
maSelection := memoIn.SelText; // On récupère le texte sélectionné
maSelection := ExcludeChars(maSelection, #10);
memoOut.Lines.Add(maSelection);
memoIn.SelText := ''; // efface la sélection

try
memStream := TMemoryStream.Create;
jpeg := TJPEGImage.Create;
HexToStream(Memo2.Text, memStream);
memStream.Seek(0, soBeginning);
// memStream.Seek(Pos('FFD8', Memo2.Text), soBeginning);

jpeg.LoadFromStream(memStream);

Image1.Picture := nil;
Image1.Picture.Assign(jpeg);
Image1.Picture.SaveToFile(IntToStr(I) + '.jpg');
finally
jpeg.Free;
memStream.Free
end;

end;

voilà en gros et pas travaillé .c'est comme ça que j'ai vu qu'une miniature était dans un jpg.
ce que je cherche entre FFD8 le début d'un jpg et FFD9 la fin du jpg c'est l'image .
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
29 nov. 2017 à 16:53
Ce n'est pas la peine de passer par une chaîne.
A mon avis, tu t'y prends mal.

Regarde comme j'ai fait ici :
http://codes-sources.commentcamarche.net/source/38197-initiation-au-fichier-de-sauvegarde-binaire
0
papyvore Messages postés 223 Date d'inscription samedi 15 novembre 2003 Statut Membre Dernière intervention 16 décembre 2021 15 > Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019
29 nov. 2017 à 17:00
merci je regarde ça
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
Modifié le 30 nov. 2017 à 12:44
Salut à tous,
Ce n'est pas la peine de passer par une chaîne.
A mon avis, tu t'y prends mal.
euh ... oui et non ^^
oui il s'y prend certainement mal (trop compliqué)
et non passer par une chaine a des avantages mais il faut procéder autrement ;)
je vous poste ici un projet de démo:
UFindJpegMain.pas
unit UFindJpegMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, JPEG;

type
  Tfrm_FindJpegMain = class(TForm)
    img_Full: TImage;
    btn_LoadJpeg: TButton;
    OpenDialog1: TOpenDialog;
    img_Thumb: TImage;
    lbl_Full: TLabel;
    lbl_Thumb: TLabel;
    ckb_ViewFullImg: TCheckBox;
    ScrollBox1: TScrollBox;
    procedure btn_LoadJpegClick(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

var
  frm_FindJpegMain        : Tfrm_FindJpegMain;

implementation

{$R *.dfm}
uses StrUtils;

const // constante pour début d'image Jpeg
  STR_JPEG_BEGIN: string = #$FF + #$D8 + #$FF;

type
  // Record pour stocker les positions de l'image et de sa miniature
  TImgPos = packed record
    ImgStart: Int64;
    MinStart: Int64;
  end;

// recherche les positions de l'image et de sa miniature

function GetImagesPos(const aStrImg: string): TImgPos;
begin
  ZeroMemory(@Result, SizeOf(Result));
  with Result do begin
    // Début de l'image
    ImgStart := Pos(STR_JPEG_BEGIN, aStrImg);
    // Début de la miniature
    MinStart := PosEx(STR_JPEG_BEGIN, aStrImg, ImgStart + 1);
  end;
end;


procedure Tfrm_FindJpegMain.btn_LoadJpegClick(Sender: TObject);
var
  StrImg       : string;
  MS           : TMemoryStream;
  JPG          : TJPEGImage;
  ImgPos       : TImgPos;
begin
  if OpenDialog1.Execute then
  begin
    MS := TMemoryStream.Create;
    // Charge l'image par un MemoryStream
    with MS do try
      LoadFromFile(OpenDialog1.FileName);
      // on place le tout dans une chaine
      // pas besoin de gerer la mémoire
      // et on peut faire des recherches avec Pos & PosEx ou autres routines
      SetLength(StrImg, Size);
      MoveMemory(@StrImg[1], Memory, Size);

      ImgPos := GetImagesPos(StrImg);
      with ImgPos do begin
      // si une miniature existe
        if MinStart <> 0 then begin
        // on positionne le Stream au début de la miniature
          MS.Position := Pred(MinStart);
          // puis on charge le résultat dans un TImage
          if (img_Thumb.Picture.Graphic is TJPEGImage) then
            TJPEGImage(img_Thumb.Picture.Graphic).LoadFromStream(MS)
          else
          begin
            JPG := TJPEGImage.Create;
            try
              JPG.LoadFromStream(MS);
              img_Thumb.Picture.Assign(JPG);
            finally
              JPG.Free;
            end;
          end;
          lbl_Thumb.Caption := Format('Miniature size %d x %d',
            [img_Thumb.Picture.Graphic.Width,
              img_Thumb.Picture.Graphic.Height]);
        end;

        // et on recommence avec l'image entière si pas de miniature
        if (ImgStart <> 0) and ((MinStart = 0) or ckb_ViewFullImg.Checked) then begin
          MS.Position := Pred(ImgStart);
          if (img_Full.Picture.Graphic is TJPEGImage) then
            TJPEGImage(img_Full.Picture.Graphic).LoadFromStream(MS)
          else
          begin
            JPG := TJPEGImage.Create;
            try
              JPG.LoadFromStream(MS);
              img_Full.Picture.Assign(JPG);
            finally
              JPG.Free;
            end;
          end;
          lbl_Full.Caption := Format('Image size %d x %d',
            [img_Full.Picture.Graphic.Width, img_Full.Picture.Graphic.Height]);
        end;
      end;
    finally
      Free;
    end;
  end;
end;

end.
UFindJpegMain.dfm
object frm_FindJpegMain: Tfrm_FindJpegMain
  Left = 204
  Top = 124
  Width = 957
  Height = 596
  Caption = 'Jpeg Miniature D'#233'mo'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  DesignSize = (
    941
    558)
  PixelsPerInch = 96
  TextHeight = 13
  object img_Thumb: TImage
    Left = 144
    Top = 24
    Width = 225
    Height = 113
    Proportional = True
  end
  object lbl_Full: TLabel
    Left = 16
    Top = 136
    Width = 32
    Height = 13
    Caption = 'lbl_Full'
  end
  object lbl_Thumb: TLabel
    Left = 144
    Top = 8
    Width = 49
    Height = 13
    Caption = 'lbl_Thumb'
  end
  object btn_LoadJpeg: TButton
    Left = 8
    Top = 24
    Width = 75
    Height = 25
    Caption = 'Load Jpeg'
    TabOrder = 0
    OnClick = btn_LoadJpegClick
  end
  object ckb_ViewFullImg: TCheckBox
    Left = 16
    Top = 80
    Width = 97
    Height = 17
    Caption = 'View full image'
    Checked = True
    State = cbChecked
    TabOrder = 1
  end
  object ScrollBox1: TScrollBox
    Left = 16
    Top = 152
    Width = 901
    Height = 385
    Anchors = [akLeft, akTop, akRight, akBottom]
    TabOrder = 2
    object img_Full: TImage
      Left = 0
      Top = 0
      Width = 161
      Height = 113
      AutoSize = True
    end
  end
  object OpenDialog1: TOpenDialog
    Filter = 'Image jpg|*.jpg;*.jpeg'
    Left = 8
    Top = 48
  end
end
FindJpeg.dpr
program FindJpeg;

uses
  Forms,
  UFindJpegMain in 'UFindJpegMain.pas' {frm_FindJpegMain};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(Tfrm_FindJpegMain, frm_FindJpegMain);
  Application.Run;
end.


n'ayant pas plus de précisions sur la structure interne de tes fichiers cette exemple te donne une très bonne base de départ.

ps: vous constaterez qu'il n'est pas utile de fixer la fin des données de l'image ($FFD9) l'unité JPEG sait retrouver la taille réelle des données à afficher uniquement avec l'adresse de début de l'image.

Cordialement
     
@+ Cirec la belle voix de mon filleul
0
papyvore Messages postés 223 Date d'inscription samedi 15 novembre 2003 Statut Membre Dernière intervention 16 décembre 2021 15
30 nov. 2017 à 14:32
salut
oui merci c'est ce don j'avais besoin et GetImagesPos va m'aider.
je tournais au tour avec PosEx(STR_JPEG_BEGIN, aStrImg, ImgStart + 1); j'oubliais simplement +1 ,c'est pour ça que j'avais toujours la même valeur et puis avec "mon usine a gaz" ...... ta solution nettement plus pro que la mienne .!!!
néanmoins , j'ai du modifer
STR_JPEG_BEGIN: string = #$FF + #$D8 + #$FF;
en
STR_JPEG_BEGIN: string = #$D8FF;
sinon ça marchait pas.??
merci.
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
30 nov. 2017 à 15:40
néanmoins , j'ai du modifer
STR_JPEG_BEGIN: string = #$FF + #$D8 + #$FF;
en
STR_JPEG_BEGIN: string = #$D8FF;
sinon ça marchait pas.??


je suppose que tu n'utilises pas la même méthode que moi pour mettre le stream dans une chaine de caractères du coup les octets sont inversés.

au passage avec quelle version de Delphi tu travailles ?
0
papyvore Messages postés 223 Date d'inscription samedi 15 novembre 2003 Statut Membre Dernière intervention 16 décembre 2021 15 > Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022
30 nov. 2017 à 17:23
je l'ai testé avec xe8
mais chez moi j'ai d7 ,je viens de tester c'est ta version qui marche
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
30 nov. 2017 à 19:42
... c'est bien ce que je craignais, la faute à l'unicode :p

mais la correction est simple
Il suffit de passer tous les string en AnsiString (3 en tout)
 ...
uses StrUtils;
const // contante pour début d'image Jpeg
  STR_JPEG_BEGIN: AnsiString = #$FF + #$D8 + #$FF; // ********* ici *********
 ... 
// recherche les positions de l'image et de sa miniature
function GetImagesPos(const aStrImg: AnsiString): TImgPos;// ********* ici *********
 ...
procedure Tfrm_FindJpegMain.btn_LoadJpegClick(Sender: TObject);
var
  StrImg       : AnsiString;  // ********* et ici *********
 ...

et le code fonctionne de D7 à Tokyo 10.2 sans autre modification

Cordialement,
0
Rejoignez-nous