This is one of the "I am new and my code takes six years to run; I also like jelly"-type posts, but I really need help. The code shown below is a *very* simple method of compacting animations (a bit like RLE). It was designed more as a test than anything else, but it would certainly help alot if I could increase the speed.
bool MASICi9::CreateDGR(String file,short frames,String output,bool prepend)
{
ofstream loge("DGREncode.txt") // log file
if (prepend){TBuffA->LoadFromFile(file + "0000.bmp");}
else{TBuffA->LoadFromFile(file + "0.bmp");} //Load the source bitmap into a Graphics::TBitmap object.
i2 = TBuffA->Height;
i1 = TBuffA->Width;
h = i1*i2;
w = h*frames;
loge << "DGR Encoder (1.6) -- MASICi9" << endl << "Writing DGR V.2 (adv)" << endl << "Pixels per image = " << h << endl << "Total number of pixels = " << w << endl;
x = h;
output += ".dgr"; //add extention to name of output file
ofstream out(output.c_str(),ios::binary); //open an output file stream
loge << "Writing header....";
out.put(''D''); //signature and version
out.put(''G'');
out.put(''R'');
out.put(''2'');
out.write((char *)(&frames),2); //frames
out.write((char *)(&i1),4); //width
out.write((char *)(&i2),4); //height
loge << "done: " << frames << " frames, " << i1 << " width " << i2 << " height." << endl << "Writing first frame....";
h = 0;
for (int bc = 0; bc<i2; bc++)
{
for (int ac = 0; ac<i1; ac++)
{
T = TBuffA->Canvas->Pixels[ac][bc]; //store the 32 bit pixel data from the bitmap canvas in a TColor object.
out.write((char *)(&T),sizeof(T)); //write the TColor object to the file
h++; //log data
}
}
w = 4*h;
loge << "done: " << w << " bytes, forming " << h << " pixels." << endl;
s = 9+w;
for (int i = 1; i<=frames; i++) //for frames 2->n
{
loge << "Writing frame " << i+1 << ".....";
//read the source frame, and the previous frame (TBuffA is the previous, TBuffG is the current frame).
if (prepend)
{
if (i < 10)
{
TBuffA->LoadFromFile(file+ "000" + String(i-1)+".bmp");
TBuffG->LoadFromFile(file+ "000" + String(i)+".bmp");
}
else if (i < 100)
{
if (i == 10){TBuffA->LoadFromFile(file+ "000" + String(i-1)+".bmp");}
else {TBuffA->LoadFromFile(file+ "00" + String(i-1)+".bmp");}
TBuffG->LoadFromFile(file+ "00" + String(i)+".bmp");
}
else if (i < 1000)
{
if (i == 100){TBuffA->LoadFromFile(file+ "00" + String(i-1)+".bmp");}
else {TBuffA->LoadFromFile(file+ "0" + String(i-1)+".bmp");}
TBuffG->LoadFromFile(file+ "0" + String(i)+".bmp");
}
}
else
{
TBuffA->LoadFromFile(file+String(i-1)+".bmp");
TBuffG->LoadFromFile(file+String(i)+".bmp");
}
h = 0;
w = 0;
m = 0;
if (TBuffG->Height == i2 && TBuffG->Width == i1)
{
i3 = 0;
s4 = 0;
for (int bc = 0; bc<i2; bc++)
{
for (int ac = 0; ac<i1; ac++)
{
m++;
FG = TBuffA->Canvas->Pixels[ac][bc]; //save pixels as a TColor
BG = TBuffG->Canvas->Pixels[ac][bc];
if (FG == BG) //if they are the same, increment the counter, and discard the pixels
{
i3++;
w++;
}
if (FG != BG) //otherwise.....
{
if (i3 != 0) //if the counter is greater than zero, write the number of skipped pixels (includes a signature "//").
{
out.put(''/'');
out.put(''/'');
out.write((char *)(&i3),sizeof(i3));
i3 = 0;
s4++;
}
out.write((char *)(&BG),sizeof(BG)); //write the new pixel
h++;
}
}
}
if (i3 != 0)
{
out.put(''/'');
out.put(''/'');
out.write((char *)(&i3),sizeof(i3)); //write the number of skipped pixels at the end of the current frame (if any)
s4++;
}
}
else
{
return false;
}
loge << "done: " << m << " pixels, " << h << " were unique, and " << w << " were copies -- " << (h*4) + (6*s4) << " bytes." << endl;
x += h;
s += (h*4) + (6*s4);
}
loge << "DGR Encoding complete." << endl << "DGR Size: " << s << " bytes." << endl << "Source bitmap size: " << (i1*i2*frames*4)+(54*frames) << " bytes.";
out.close();
loge.close(); //close the file streams
return true;
}
I said it was pretty basic, but it does what I want. The pixels (although really 24 bit) seem to include a padding block to align them to the 32 bit memory thingie.... though that top level byte seems critical (removal results in bad stuff happening....).
and now the decoder..... this is where the problem is. If any more than about 15,000 pixels change in a single frame, everthing gets horrifically jerky.
bool MASICi9::DrawDGR(String file,int x,int y,TCanvas* surface)
{
ifstream in(file.c_str(),ios::binary); //open file
if (in.get() == ''D'') //check signature
{
if (in.get() == ''G'')
{
if (in.get() == ''R'')
{
test = false; //set default version
c1 = in.get();
if (c1 == ''2'')//check actual version
{test = true;}
//the next lines read the header, frames, width and height
if (!test)
{
in.read((char *)(&s4),2);
in.read((char *)(&s1),2);
in.read((char *)(&s2),2);
i1 = s1;
i2 = s2;
}
else
{
in.read((char *)(&s4),2);
in.read((char *)(&i1),sizeof(i1));
in.read((char *)(&i2),sizeof(i2));
}
TBuffG->Height = i2; //set bitmap height
TBuffG->Width = i1; //set bitmap width
for (int bc = 0; bc<i2; bc++)
{
for (int ac = 0; ac<i1; ac++)
{
in.read((char *)(&FG),sizeof(FG)); //read the pixel from the file;
TBuffG->Canvas->Pixels[ac][bc] = FG; //store pixel to temporary bitmap
}
}
surface->Draw(x,y,TBuffG); //draw bitmap to window
for (int i = 1; i<=s4; i++) //read compressed frames
{
i3 = 0;
m = 0;
for (int bc = 0; bc<i2; bc++)
{
for (int ac = 0; ac<i1; ac++)
{
if (i3 == 0) //if skipped pixel counter is zero
{
if (in.peek()==''/'') //search for skip signature
{
in.get();
if (in.peek()==''/'')
{
in.get();
if (test){in.read((char *)(&i3),sizeof(i3));} //read 4 bytes of skipped pixels if version 2
else{in.read((char *)(&s3),sizeof(s3));i3=s3;} //read 2 bytes if version 1
bc--;
}
else
{
c1 = ''/'';
c2 = in.get();
c3 = in.get();
c4 = in.get();
FG = (c1<<24) + (c2<<16) + (c3<<8) + c4;
TBuffG->Canvas->Pixels[ac][bc] = FG; //on mistake (ie: pixel has a value of "/" in it -- untested, never actually happened), form a pixel from known data and store to canvas.
}
}
else
{
in.read((char *)(&FG),sizeof(FG)); //if no signature found, read a pixel and store to canvas.
TBuffG->Canvas->Pixels[ac][bc] = FG;
}
}
else
{
i3--; //if skipped pixels > 0, count down.
}
}
}
App->ProcessMessages(); //check the windows message pump
if (!DGRPlayOK) //if told to stop playing, exit
{return false;}
surface->Draw(x,y,TBuffG); //draw frame to canvas
}
}
}
}
in.close(); //close file stream
return true;
}
Please help -- as a newbie programmer there are probably millions of ways to optimise that I can''t see.
If you''ve looked at this and thought "freaky code" or somesuch, it''s because I''m using Borland C++ Builder 5, which handles all the DCs and thingies. Probably a mixed blessing, since my code has to go through even more layes of processing, but it suits my needs (apart from speed).
--Cirian