ScanLine für unterschiedliche Farbtiefen
-
Danke, für eure Tips. Habe gerade im Petzold nachgeschaut und gemerkt, daß wohl ein bisschen Einarbeitung notwendig ist. Naja, man lernt dazu...
-
Ich habe das hier mal ausgegraben und folgendes versucht
Graphics::TBitmap *pBitmap = new Graphics::TBitmap; pBitmap->LoadFromFile("datei1.bmp"); ofstream ofstr("datei2.bmp"); PRGBTriple DstLine; for (int y = 0; y < pBitmap->Height; y++) { DstLine=(PRGBTriple)pBitmap->ScanLine[y]; for (int x = 0; x < pBitmap->Width; x++) { ofstr << DstLine[x].rgbtRed; ofstr << DstLine[x].rgbtGreen; ofstr << DstLine[x].rgbtBlue; } } ofstr.flush(); delete pBitmap;Die zweite Datei "datei2.bmp" ist nach speichern fast genauso groß wie die erste.
Das neue Bitmap kann nicht gelesen werden.
Wie bekomme ich das sohin, das eine echte Bitmap entsteht,
ohne SaveToFile oder so
-
Google mal nach Dateiformat/ bmp !!!
Wenn Du nur die RGB- Werte in eine Datei schreibst, kommt nix g'scheits bei rum.
Da fehlt der gesamte Header ...
-
Leider gibts kein pBitmap->Header oder so.
-
Was hast Du gegen 'SaveToFile' ??? Damit ist Dir alles abgenommen.
Sonst schau mal in WinAPI- Forum. Du kannst Header selber erstellen. Aber wozu?
Oder zielst du auf Deinen anderen Thread - Text 6 Bild?
dann sch Dich mal schlau mit SaveToStream! Damit kannste Bilder + Texte + WasWasI in EINE Datei schreiben.
-
Ich möchte mehrere bmp´s in einer Datei speichern, und zusätzlich noch ander Stringdaten.
Beim Auslesen der gesamten Datei einsteht dan ein vector<stuktur> mit Bitmaps und Bildbeschreibungen.
Aber mit TStreams kann ich immer nur überschreiben.
Ich hab noch nicht herausgefunden, wie ich Stück für Stück Daten anhängen kann.
-
Dann Mach das mit Stream!
Du musst Dir nur ein eigenes 'Formar' ausdenken - oser googeln, ob's sowas gibt.
Ich mach das So:
0. Stream öffnen (Leer, Pointer auf Anfang)
1. Kennung in Stream, wieviel Bytes kommen plus 'Text' für Formatkennung
2. Daten (genau die Menge) in den Stream schreiben (SaveToStream)
3. wiederholen 1. und 2. bis alle Daten drin sind
4. Stream schliessen.
VoliaBeim lesen musst Du nur :
0. Stream öfnnen
1. Kennung lesen
2. Daten passend dazu lesen
3. wiederholen, bis Stream leer ist.
4. Stream schliessenBei BMPs geht das noch einfacher.
Aber so kannst Du verschiedene Daten speichern. Ich mach das mit ner Dia- Show-Datei, die enthält bmp, JPG oder GIF ...Beim Lesen hts ds Problem, dass jpgs nach lesen den Stream ans Ende setzen!!!
Dazu kopiere ich die Bytes in einen MemStream und lass daraus lesen.
-
Was meinst Du mit Kennung?
Size?
Wie füllst Du das Stream weiter auf mit CopyFrom oder Read?
-
OK Ich habs
TMemoryStream *stre1 = new TMemoryStream(); stre1->LoadFromFile("bits/buchlogo1.bmp"); TMemoryStream *stre2 = new TMemoryStream(); stre2->LoadFromFile("bits/buchlogo2.bmp"); TMemoryStream *stre3 = new TMemoryStream(); int s1 = stre1->Size; int s2 = stre2->Size; stre3->Position = 0; stre3->Size = stre1->Size + stre2->Size; stre1->SaveToStream(stre3); stre3->Position = s1; stre2->SaveToStream(stre3); stre3->SaveToFile("__1.bmp"); delete stre1; delete stre2; delete stre3;Hab den ganzen Tag damit verbracht
Danke Dir
-
So hatte ich das zwar nicht gemeint, aber wenns geht.
Ich Lade die Bilder (nacheinander ) in ein TPicture - da ist egal, welches Format - und schreibe die mit extra Daten in eine Datei.
Ich mach EINEN Stream auf (FileStream)
Ich schreibe ein paar BINAERDATEN in den Stream:
- Datenmenge - Groese der Bilddaten + ein paar extra bytes
- die extra bytes sind z.b: Bildtyp (JPEG,GIF ...)Dann mit SaveToStream das Picture in den Stream
Dann das ganze widerholt mit dem naechsten Bild.
Am Ende Stream schliessen.
Z.B. so:
I1, I2 und I3 sind TImage- Objekte im Formular. In alle drei ist irgendein Bild geladen!
Die Bilder können GIF, JPEG oder BMPs sein.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Fuer jpeg muss natuerlich jpeg.h includiert sein
Fuer GIF hab ich GIFIMAGE im System!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!void __fastcall TForm1::M_Save_1_2Click(TObject *Sender) { ShortString ClassName; unsigned char ClassNameSize; long Size; TFileStream *FS=new TFileStream("D:\\M_Test.SHP",fmCreate); TMemoryStream *MS=new TMemoryStream(); ClassName=I1->Picture->Graphic->ClassName(); ClassNameSize=ClassName[0]; I1->Picture->Graphic->SaveToStream(MS); Size=MS->Size; FS->Write(&Size,sizeof(Size)); FS->Write(&ClassName,ClassNameSize+1); FS->CopyFrom(MS,0);//Size); MS->Size=0; ClassName=I2->Picture->Graphic->ClassName(); ClassNameSize=ClassName[0]; I2->Picture->Graphic->SaveToStream(MS); Size=MS->Size; FS->Write(&Size,sizeof(Size)); FS->Write(&ClassName,ClassNameSize+1); FS->CopyFrom(MS,0);//Size); MS->Size=0; ClassName=I3->Picture->Graphic->ClassName(); ClassNameSize=ClassName[0]; I3->Picture->Graphic->SaveToStream(MS); Size=MS->Size; FS->Write(&Size,sizeof(Size)); FS->Write(&ClassName,ClassNameSize+1); FS->CopyFrom(MS,0);//Size); delete MS; delete FS; } //--------------------------------------------------------------------------- void __fastcall TForm1::M_LoadClick(TObject *Sender) { Graphics::TBitmap *BM; TJPEGImage *JPG; TGIFImage *GIF; AnsiString ClassName; unsigned char ClassNameSize; char ClassNameChar[256]; long Size; TFileStream *FS=new TFileStream("D:\\M_Test.SHP",fmOpenRead ); TMemoryStream *MS=new TMemoryStream(); FS->Read(&Size,sizeof(Size)); FS->Read(&ClassNameSize,sizeof(ClassNameSize)); FS->Read(ClassNameChar,ClassNameSize); ClassNameChar[ClassNameSize]=0; ClassName=AnsiString(ClassNameChar); MS->CopyFrom(FS,Size); MS->Position=0; if (ClassName.AnsiCompareIC("TBitmap")==0) { BM=new Graphics::TBitmap(); I3->Picture->Assign(BM); delete BM; } if (ClassName.AnsiCompareIC("TJPEGImage")==0) { JPG=new TJPEGImage(); I3->Picture->Assign(JPG); delete JPG; } if (ClassName.AnsiCompareIC("TGIFImage")==0) { GIF=new TGIFImage(); I3->Picture->Assign(GIF); delete GIF; } I3->Picture->Graphic->LoadFromStream(MS); MS->Size=0; FS->Read(&Size,sizeof(Size)); FS->Read(&ClassNameSize,sizeof(ClassNameSize)); FS->Read(ClassNameChar,ClassNameSize); ClassNameChar[ClassNameSize]=0; ClassName=AnsiString(ClassNameChar); MS->CopyFrom(FS,Size); MS->Position=0; if (ClassName.AnsiCompareIC("TBitmap")==0) { BM=new Graphics::TBitmap(); I1->Picture->Assign(BM); delete BM; } if (ClassName.AnsiCompareIC("TJPEGImage")==0) { JPG=new TJPEGImage(); I1->Picture->Assign(JPG); delete JPG; } if (ClassName.AnsiCompareIC("TGIFImage")==0) { GIF=new TGIFImage(); I1->Picture->Assign(GIF); delete GIF; } I1->Picture->Graphic->LoadFromStream(MS); MS->Size=0; FS->Read(&Size,sizeof(Size)); FS->Read(&ClassNameSize,sizeof(ClassNameSize)); FS->Read(ClassNameChar,ClassNameSize); ClassNameChar[ClassNameSize]=0; ClassName=AnsiString(ClassNameChar); MS->CopyFrom(FS,Size); MS->Position=0; if (ClassName.AnsiCompareIC("TBitmap")==0) { BM=new Graphics::TBitmap(); I2->Picture->Assign(BM); delete BM; } if (ClassName.AnsiCompareIC("TJPEGImage")==0) { JPG=new TJPEGImage(); I2->Picture->Assign(JPG); delete JPG; } if (ClassName.AnsiCompareIC("TGIFImage")==0) { GIF=new TGIFImage(); I2->Picture->Assign(GIF); delete GIF; } I2->Picture->Graphic->LoadFromStream(MS); MS->Size=0; delete MS; delete FS; }In der Datei stehen dann nacheinander:
Menge der folgenden Bild- Bytes
Laenge des Kennstrings
Kennstring
Bytes des BildesMenge folgende ....
Genau andersrum kann das ausgelesen werden!
Du kannst auch ganz andere Daten einmischen - mit geeigneter Kennung + Size- Angabe!
-
Es is supereinfach
Erst Text und paar bitmaps speichern
TMemoryStream *stre1 = new TMemoryStream(); TStrings *lt = new TStringList; TMemoryStream *stre2 = new TMemoryStream(); stre2->Position = 0; lt->Text = "Hier sin meine ganzen texteABJETZTFOLGTALLESANDERE"; stre2->Size = lt->Count + stre2->Size; lt->SaveToStream(stre2); stre1->LoadFromFile("bits/linus.bmp"); stre2->Size = stre1->Size + stre2->Size; stre1->SaveToStream(stre2); stre1->LoadFromFile("bits/buchlogo2.bmp"); stre2->Size = stre1->Size + stre2->Size; stre1->SaveToStream(stre2); stre2->SaveToFile("__1.mydc"); delete stre1; delete stre2; delete lt;Datei wider laden
TStrings *nlst = new TStringList; nlst->LoadFromFile("__1.mydc"); //Vor stringposition ABJETZTFOLGTALLESANDERE //sind meine ganzen strings und zuweisungen gespeichert int pos = nlst->Text.Pos("ABJETZTFOLGTALLESANDERE"); AnsiString as = nlst->Text.SubString(1, pos-1); delete nlst; ShowMessage(as); //AnsiString as verarbeiten //danach nur noch bmp für bmp laden TMemoryStream *stre3 = new TMemoryStream(); stre3->LoadFromFile("__1.mydc"); stre3->Position = pos+24;//die 24 entspricht der size die für //ABJETZTFOLGTALLESANDERE //hochgezählt wird while(pos < stre3->Size){ Image1->Picture->Bitmap->LoadFromStream(stre3); //eigentlich werden die bitmaps aber woanders abgespeichert pos = stre3->Position; } delete stre3;
-
Hi,
evtl. wäre es besser das I1, I2 und I3 vorher in ein Array zu packen. Dann kann man das schon mit einer for Schleife regeln und es wird kürzer (keine Wiederholungen) und variabler.MfG
Alexander Sulfrian
-
Die Funktion wird wohl in einer schleife aufgerufen, nehme ich an.
Oder eher doch nich
-
Das war nur in Beispiel!
Sollte nur das Speichern mehrerer Bilder zeigenWar zu faul eine Schleife zu machen!