libpng error invalid chunk type when loading png from memory - c++

I'm trying to load a PNG from a memory buffer so I can access the ImageData without having to save it as a file first.
The memory buffer contains a valid png-file, when using fwrite to save it as a file on disk I get the following image: https://dl.dropboxusercontent.com/u/13077624/test.png
This represents a depth Image received by a Kinect sensor, for those of you wondering.
This is the code that gives errors:
struct mem_encode
{
char *buffer;
png_uint_32 size;
png_uint_32 current_pos;
};
void handle_data(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
cout<<"Saving as file: "<<determinePathExtension(PNGFrame,"png");
FILE* fp=fopen("test.png","wb");
fwrite(data_,bytes_transferred,1,fp);
fclose(fp);
//get PNG file info struct (memory is allocated by libpng)
png_structp png_ptr = NULL;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
std::cerr << "ERROR: Couldn't initialize png read struct" << std::endl;
cin.get();
return; //Do your own error recovery/handling here
}
// get PNG image data info struct (memory is allocated by libpng)
png_infop info_ptr = NULL;
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
std::cerr << "ERROR: Couldn't initialize png info struct" << std::endl;
cin.get();
png_destroy_read_struct(&png_ptr, (png_infopp)0, (png_infopp)0);
return; //Do your own error recovery/handling here
}
struct mem_encode pngdata;
pngdata.buffer=data_;
pngdata.size=(png_uint_32)bytes_transferred;
pngdata.current_pos=0;
png_set_read_fn(png_ptr,&pngdata, ReadData);
//Start reading the png header
png_set_sig_bytes(png_ptr, 8);
png_read_info(png_ptr,info_ptr);
//... Program crashes here
}
else
{
cout<<error.message()<<" Bytes received: "<<bytes_transferred<<endl;
delete this;
}
}
static void ReadData(png_structp png_ptr, png_bytep outBytes,
png_size_t byteCountToRead){
struct mem_encode* p=(struct mem_encode*)png_get_io_ptr(png_ptr);
size_t nsize=p->size + byteCountToRead;
if(byteCountToRead>(p->size-p->current_pos)) png_error(png_ptr,"read error in read_data_memory (loadpng)");
/* copy new bytes */
memcpy(outBytes,p->buffer + p->size,byteCountToRead);
p->current_pos+=byteCountToRead;
}
Calling the method results in the program crashing with the following error:
libpng error: [00][00][00][00]: invalid chunk type
data_ represents the the databuffer storing the PNG-image and is a char *.
Any help would be appreciated.
Sources I used:
http://www.libpng.org/pub/png/libpng-1.0.3-manual.html
http://blog.hammerian.net/2009/reading-png-images-from-memory/
http://santosdev.blogspot.be/2012/08/loading-png-image-with-libpng-1512-or.html
http://www.piko3d.net/tutorials/libpng-tutorial-loading-png-files-from-streams/
Could this be caused by network bytes being translated badly?

I think you forgot to read the PNG signature bytes. Use
if (png_sig_cmp(data, 0, 8)
png_error(png_ptr, "it's not a PNG file");
Then your
png_set_sig_bytes(png_ptr,8);
lets libpng know you have already read the signature.
Or, you could use png_set_sig_bytes(png_ptr, 0); and
let libpng do the checking for you.

Are you sure your ReadData function is correct? Why do you start memcpy from the address p->buffer + p->size - isn't it the end of the buffer? And what does nsize do?

Related

SDL only making beeping noises instead of the actual audio file

I recently managed to get past the errors of using SDL for sound.
Now that it's running and I'm not running into errors, my program is only playing beeping noises instead of the file I've provided.
I want the program to play the .wav file I'm passing to the SDL_LoadWAV.
I've tried with two different .wav files of different length and size, and checked the header files to find comments and tips on what format is required for the SDL to play the .wav file, haven't gotten anywhere with either of it.
The myAudioCallback function is responsible for handling the SDL callback.
void myAudioCallback(void* userdata, Uint8* stream, int len)
{
AudioData* audio = (AudioData*)userdata;
if (audio->length == 0)
return;
Uint32 length = (Uint32)len;
length = (length > audio->length ? audio->length : length); // if length is more than the audio length, then set length to be the audio.length, if not, set it to be the length passed to the function
std::cout << "Audio Length " << audio->length << std::endl;
std::cout << "Audio Position " << audio->position << std::endl;
SDL_memcpy(stream, audio->position, length); // audio callback is called by SDL, this ensures that the stream and data that is sent, is copied over to our struct, so we can use it and manipulate it
audio->position += length;
audio->length -= length;
}
My loadAudio function is responsible for loading the audio file and saving information about the audio file to the various variables I've declared in the .h (see further down for my .h)
void mainEngineCW4::loadAudio() // this function is for the sole purpose of loading the .wav file
{
SDL_Init(SDL_INIT_AUDIO); // loads the SDL to initialise audio
char* audioFile = "backgroundmusic.wav"; // a char pointer for the file path
// LoadWAV loads the wav file, and by putting it in an if statement like this, we can simutaneously check if the result is null, meaning an error occured while loading it.
if (SDL_LoadWAV(audioFile, &wavSpec, &wavStart, &wavLength) == NULL)
std::cerr << "Error: file could not be loaded as an audio file." << std::endl;
else
std::cout << audioFile << " loaded" << std::endl;
}
The playAudio function is responsible for loading the audio device and playing the audio through the Audio device
void mainEngineCW4::playAudio() // this function is for loading an audio device, and playing the audio through that device
{
audio.position = wavStart; // define where we start in the audio file
audio.length = wavLength; // define the length of the audio file
wavSpec.callback = myAudioCallback; // the callback variable needs a function that its going to run to be able to call back the audio that is played. assigning the function name to the variable allows it to call that function when needed
wavSpec.userdata = &audio; // the userdata is the audio itself
audioDevice = SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, SDL_AUDIO_ALLOW_ANY_CHANGE); // opens the audio device, also having it play the audio information found at memory address for wavspec
if (audioDevice == 0) {
std::cerr << SDL_GetError() << std::endl;
return; }
SDL_PauseAudioDevice(audioDevice, 0); // mildly confused by why they decided to call the function for starting to play audio for "PauseAudioDevice" but yeah. this plays audio.
}
Here's my .h. I've defined myAudioCallback outside of the class, since SDL doesn't like the additional hidden parameter of a member function
struct AudioData
{
Uint8* position;
Uint32 length;
};
void myAudioCallback(void* userdata, Uint8* stream, int len);
class mainEngineCW4 :
public BaseEngine
{
public:
void loadAudio();
void playAudio();
void endAudio();
private:
// variables and pointers for audio information
AudioData audio;
SDL_AudioSpec wavSpec;
SDL_AudioDeviceID audioDevice;
Uint8* wavStart;
Uint32 wavLength;
};
I've removed the other functions and variables that are irrelevant to the issue I'm having
My problem is that I want my program to play the audio file I pass in, not just beeping noises.
Any help is greatly appreciated
EDIT: I realised I'm crap at providing info and explanation to things, so I edited in more information, explanation and the header file. If there is anything else I can provide, please let me know
With the help of a friend, I managed to fix the issue.
It seems like SDL didn't like it when I passed
SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, SDL_AUDIO_ALLOW_ANY_CHANGE);
so instead, I passed
SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, 0);
instead. This made the file play nicely, as well as having additional variables for the length and position of the audio file.
Another issue I ran into even after I got the file playing, was that the beeping was still playing with the audio file. I wasn't able to fix this directly myself, instead, when I cleaned the solution the day after, the beeping was gone, and the only thing playing was the audio file.
I've attached the code that works below.
In addition to the struct I created in the .h
struct AudioData
{
Uint8* position;
Uint32 length;
};
Defining the audio_position and audio_length as a global variable also helped in copying over information in the audio callback function.
static Uint8* audio_position;
static Uint32 audio_length;
void myAudioCallback(void* userdata, Uint8* stream, int len)
{
if (audio_length == 0)
return;
len = (len > audio_length ? audio_length : len); // if length is more than the audio length, then set length to be the audio.length, if not, set it to be the length passed to the function
SDL_memcpy(stream, audio_position, len); // audio callback is called by SDL, this ensures that the stream and data that is sent, is copied over to our struct, so we can use it and manipulate it
audio_position += len;
audio_length -= len;
}
For the load audio, I made sure that I actually load all the information that would be considered "loading", including storing the AudioSpec callback function, and setting the length and position of the audio file.
void mainEngineCW4::loadAudio() // this function is for the sole purpose of loading the .wav file
{
if (SDL_Init(SDL_INIT_AUDIO) < 0 || audioPlaying == true) // loads the SDL to initialise audio
return;
char* filePath = "backgroundmusic.wav"; // a char pointer for the file path
// LoadWAV loads the wav file, and by putting it in an if statement like this, we can simutaneously check if the result is null, meaning an error occured while loading it.
if (SDL_LoadWAV(filePath, &desiredSpec, &wavStart, &wavLength) == NULL)
std::cerr << "Error: file could not be loaded as an audio file." << std::endl;
else
std::cout << filePath << " loaded" << std::endl;
desiredSpec.callback = myAudioCallback; // the callback variable needs a function that its going to run to be able to call back the audio that is played. assigning the function name to the variable allows it to call that function when needed
desiredSpec.userdata = &audioInfo; // the userdata is the audio itself
audio_position = wavStart; // define where we start in the audio file
audio_length = wavLength; // define the length of the audio file
}
I also added a boolean to the class, so that when this returns true, it means that the audio has already been playing or has already been loaded, as to ensure SDL won't play the same thing simultaneously.
void mainEngineCW4::playAudio() // this function is for loading an audio device, and playing the audio through that device
{
if (audioPlaying == true)
return;
audioDevice = SDL_OpenAudioDevice(NULL, 0, &desiredSpec, NULL, 0); // opens the audio device, also having it play the audio information found at memory address for wavspec
if (audioDevice == 0)
{
std::cerr << SDL_GetError() << std::endl;
return;
}
SDL_PauseAudioDevice(audioDevice, 0); // mildly confused by why they decided to call the function for starting to play audio for "PauseAudioDevice" but yeah. this plays audio.
audioPlaying = true;
}
void mainEngineCW4::endAudio()
{
SDL_CloseAudioDevice(audioDevice);
SDL_FreeWAV(wavStart);
audioPlaying = false;
}

QT error with copy file function

I wrote a QT code to copy the whole content from sourcefile to destfile. With small-size files, it runs successfully, but with large-size files (for example, a video with 700MB of size), after process of copy, the destfile only had 2Kb of size.
This is the code of Copy routine, which does the copying process:
void Copy(QString destfile, QString sourcefile)
{
qint64 bufSize = 100*1024*1024;//100 MB
char *buf = new char [bufSize];
//qint64 dataSize;
QFile sfile(sourcefile), dfile(destfile);
if (!sfile.open(QIODevice::ReadOnly) || !dfile.open(QIODevice::WriteOnly))
{
qDebug() << "Error";
return;
}
while (!sfile.atEnd())
{
sfile.read(buf, bufSize);
dfile.write(buf);
}
sfile.close();
dfile.close();
qDebug() << "OK";
}
dfile.write(buf); will write a null terminated string to your file, not the entire array. You want to do :
dfile.write(buf, bufSize);
^^^^
Notes:
You probably want to check the returned value of this call to test how many bytes were actually written. Same for sfile.read(buf, bufSize);, test how many bytes were read (it could be less than bufSize).
Something like :
while (!sfile.atEnd())
{
qint64 bytesRead = sfile.read(buf, bufSize);
if(dfile.write(buf, bytesRead) < 0)
// error ...
}
Also, buf could be allocated on the stack, no new is needed here.

Muxing AVPackets into mp4 file

I am developing a tool which receives a h.264 live stream from the network (the sender is a hardware encoder), buffers the last x-minutes and creates a video file of the last x-minutes if triggered.
My tool is able to receive the live stream and also to buffer AVPackets the with boost::serialization. Furthermore I am able to load the buffered AVPackets.
But when I try to create/mux a video file (mp4) with the loaded AVPackets there occurs an error in the mp4-file or mp4-header.
I am able to create a mp4-file and also to write Packets to the file with av_interleaved_write_frame(). The mp4-file has also a plausible size. So it seams that the AVPackets were written to the file.
But when I try to open the mp4-file with a player like vlc, the video doesn't play. The player provides an error like: the header isn't correct and doesn't play any frame. But I write the header with the writeHeader() function to the AVFormatContext.
I guess that the reason is that the AVFormatContext isn't correctly initialized but with the example of ffmpeg/libav (muxing-examples) I can't solve the problem.
Has any one a solution (example code) or an other example how to correctly initialize the AVFormatContext?
Thanks for your help.
Olgen
avcodec_init();
avcodec_register_all();
av_register_all();
av_log_set_level(AV_LOG_DEBUG);
char *outputFilename = "/tmp/output.mp4";
// define AVOutputFormat
AVOutputFormat *outputFormat = NULL;
outputFormat = av_guess_format("mp4", NULL, NULL);
if (!outputFormat) {
fprintf(stderr, "Could not find suitable output format\n");
return 1;
}
// define AVFormatContext
AVFormatContext *formatContext = NULL;
// lallocate the output media context
std::cout << "alloc" << std::endl;
formatContext = avformat_alloc_context();
// avformat_alloc_output_context(&formatContext, outputFormat, NULL, NULL);
if (!formatContext) {
fprintf(stderr, "Memory error\n");
return 1;
}
std::cout << "stream" << std::endl;
AVStream * video_st = av_new_stream(formatContext, 0);
AVCodec * codec = NULL;
avcodec_get_context_defaults3(video_st->codec, codec);
video_st->codec->coder_type = AVMEDIA_TYPE_VIDEO;
video_st->codec->flags = fc->streams[0]->codec->flags;
video_st->codec->sample_aspect_ratio = fc->streams[0]->codec->sample_aspect_ratio;
video_st->disposition = fc->streams[0]->disposition;
video_st->codec->codec_tag = fc->streams[0]->codec->codec_tag;
video_st->codec->bits_per_raw_sample = fc->streams[0]->codec->bits_per_raw_sample;
video_st->codec->chroma_sample_location = fc->streams[0]->codec->chroma_sample_location;
video_st->codec->codec_id = fc->streams[0]->codec->codec_id;
video_st->codec->codec_tag = fc->streams[0]->codec->codec_tag;
video_st->codec->time_base = fc->streams[0]->codec->time_base;
video_st->codec->extradata = fc->streams[0]->codec->extradata;
video_st->codec->extradata_size = fc->streams[0]->codec->extradata_size;
video_st->codec->pix_fmt = fc->streams[0]->codec->pix_fmt;
video_st->codec->width = fc->streams[0]->codec->width;
video_st->codec->height = fc->streams[0]->codec->height;
video_st->codec->sample_aspect_ratio = fc->streams[0]->codec->sample_aspect_ratio;
std::cout << "file" << std::endl;
avio_open(&formatContext->pb, outputFilename, AVIO_FLAG_WRITE);
std::cout << "header" << std::endl;
avformat_write_header(formatContext, NULL);
// av_write_header(formatContext);
// loop to write AVPackets with av_write_frame
The programm crashes after the avformat_write_header(formatContext, NULL) with a memory error. I also tried avformat_alloc_output_context() instead of avformat_alloc_output_context2() but both functions don't work. So I used avformat_alloc_context() (see above)
I think there is an alloction problem but why I can't use avformat_alloc_output_context2 or avformat_alloc_output_context. Could somebody figure out my problem here?
This is a general scheme shows how to mux video file from an existing packets
AVOutputFormat * outFmt = av_guess_format("mp4", NULL, NULL);
AVFormatContext *outFmtCtx = NULL;
avformat_alloc_output_context2(&outFmtCtx, outFmt, NULL, NULL);
AVStream * outStrm = av_new_stream(outFmtCtx, 0);
AVCodec * codec = NULL;
avcodec_get_context_defaults3(outStrm->codec, codec);
outStrm->codec->coder_type = AVMEDIA_TYPE_VIDEO;
///....
/// set some required value, such as
/// outStrm->codec->flags
/// outStrm->codec->sample_aspect_ratio
/// outStrm->disposition
/// outStrm->codec->codec_tag
/// outStrm->codec->bits_per_raw_sample
/// outStrm->codec->chroma_sample_location
/// outStrm->codec->codec_id
/// outStrm->codec->codec_tag
/// outStrm->codec->time_base
/// outStrm->codec->extradata
/// outStrm->codec->extradata_size
/// outStrm->codec->pix_fmt
/// outStrm->codec->width
/// outStrm->codec->height
/// outStrm->codec->sample_aspect_ratio
/// see ffmpeg.c for details
avio_open(&outFmtCtx->pb, outputFileName, AVIO_FLAG_WRITE);
avformat_write_header(outFmtCtx, NULL);
for (...)
{
av_write_frame(outFmtCtx, &pkt);
}
av_write_trailer(outFmtCtx);
avio_close(outFmtCtx->pb);
avformat_free_context(outFmtCtx);
For troubleshooting, it is useful to set detailed logging: av_log_set_level(AV_LOG_DEBUG);
This might not be the case, but avformat_write_header function should be used for writing header instead of function pointer in AVOutputFormat.write_header

How do I get the DC coefficient from a jpg using the jpg library?

I am new to this stuff, but I need to get the dc-coefficient from a jpeg using the jpeg library?
I was told as a hint that the corresponding function is in jdhuff.c, but I can't find it. I tried to find a decent article about the jpg library where I can get this, but no success so far.
So I hope you guys can help me a bit and point me to either some documentation or have a hint.
So, here is what I know:
A jpg picture consists of 8x8 Blocks. That are 64 Pixels. 63 of it are named AC and 1 is named DC. Thats the coefficient. The position is at array[0][0].
But how do I exactly read that with the jpg library? I am using C++.
edit:
This is what I have so far:
read_jpeg::read_jpeg( const std::string& filename )
{
FILE* fp = NULL; // File-Pointer
jpeg_decompress_struct cinfo; // jpeg decompression parameters
JSAMPARRAY buffer; // Output row-buffer
int row_stride = 0; // physical row width
my_error_mgr jerr; // Custom Error Manager
// Set Error Manager
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
// Handle longjump
if (setjmp(jerr.setjmp_buffer)) {
// JPEG has signaled an error. Clean up and throw an exception.
jpeg_destroy_decompress(&cinfo);
fclose(fp);
throw std::runtime_error("Error: jpeg has reported an error.");
}
// Open the file
if ( (fp = fopen(filename.c_str(), "rb")) == NULL )
{
std::stringstream ss;
ss << "Error: Cannot read '" << filename.c_str() << "' from the specified location!";
throw std::runtime_error(ss.str());
}
// Initialize jpeg decompression
jpeg_create_decompress(&cinfo);
// Show jpeg where to read the data
jpeg_stdio_src(&cinfo, fp);
// Read the header
jpeg_read_header(&cinfo, TRUE);
// Decompress the file
jpeg_start_decompress(&cinfo);
// JSAMPLEs per row in output buffer
row_stride = cinfo.output_width * cinfo.output_components;
// Make a one-row-high sample array
buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
// Read image using jpgs counter
while (cinfo.output_scanline < cinfo.output_height)
{
// Read the image
jpeg_read_scanlines(&cinfo, buffer, 1);
}
// Finish the decompress
jpeg_finish_decompress(&cinfo);
// Release memory
jpeg_destroy_decompress(&cinfo);
// Close the file
fclose(fp);
}
This is not possible using the standard API. With libjpeg API the closest you can get is raw pixel data of Y/Cb/Cr channels.
To get coefficients' data you'd need to hack the decode_mcu function (or its callers) to save the data decoded there.

Debug Assertion Failed

Using Visual Studio 2010, C++.
Programming level: beginner.
I have a code from a book Windows Game Programming Gurus and up until now have managed all problems i have stumbled upon.
But this i don't know what it is.
Here is a screenshot of an error:
That is one nice 8-bit image...
Now, it says File: f:\dd...
In my case f: drive is empty cd-rom...
This is the line where i think error is happening:
_lseek(file_handle, -((int) (bitmap->bitmapinfoheader.biSizeImage)), SEEK_END);
What is this thing?
The f:\dd directory is where the source code of the "C Runtime Library" (CRT) was located, when it was built. Since Microsoft built that, it doesn't correspond to your F: drive.
Anyway, the CRT detected that one of the file handles is wrong. You passed it to the CRT, so you should check why it's wrong. If you press Retry, you'll be put in the debugger. There you can see which of your functions put in the wrong file handle.
It won't tell you why the handle is wrong, though. A common reason is that you tried to open a file, and forgot to check if it succeeded. You only get a file handle if the file name is valid, and you're allowed to read that file.
The assertion happens in the C library. It makes sure you pass valid argument to the lseek() function.
You probably did not check for errors after doing open() or creat() on the file.
Looks like your file_handle is wrong. Are you sure the opening of your image succeeded ?
Full function code which uses C++ ifstream instead of low-level IO functions.
Jonathan and i tried to make _lseek work only to conclude that it doesn't work...
Don't know if that is entirely true, maybe there is some way it works correctly.
If you (the reader) know, feel free to message me.
The function now works, although main program displays image wrongly, but that is beside matter of this question, _lseek thing is solved :)
int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
{
int file_handle = 0; // the file handle
int index = 0; // looping index
int bitmapWidth = 0;
int bitmapHeight = 0;
int bitmapSize = 0;
UCHAR *temp_buffer = NULL; // used to convert 24 bit images to 16 bit
streampos pos_cur;
ifstream bitmapFile = ifstream ();
bitmapFile.open (filename, ifstream::in);
if (! bitmapFile.is_open ())
{
printError ("Error: OpenFile function failure. ");
// abort
return(0);
}
// load the bitmap file header:
//_lread(file_handle, &(bitmap->bitmapfileheader), sizeof(BITMAPFILEHEADER));
bitmapFile.read ((char *) &(bitmap->bitmapfileheader), sizeof (BITMAPFILEHEADER));
// test if this is a bitmap file
if (bitmap->bitmapfileheader.bfType != BITMAP_ID)
{
// close the file
//_lclose(file_handle);
bitmapFile.close ();
printError ("error: wrong bitmap type");
cout << "error: wrong bitmap type" << endl;
// return error
return(0);
} // end if
// now we know this is a bitmap, so read in all the sections.
if (bitmap->bitmapinfoheader.biSizeImage == 0)
printError ("error: biSizeImage equals 0");
// now the bitmap infoheader:
//_lread(file_handle, &bitmap->bitmapinfoheader, sizeof(BITMAPINFOHEADER));
bitmapFile.seekg (sizeof (BITMAPFILEHEADER), ios::beg);
pos_cur = bitmapFile.tellg (); // save current stream position
bitmapFile.read ((char *) &(bitmap->bitmapinfoheader), sizeof (BITMAPINFOHEADER));
//cout << bitmap->bitmapinfoheader.biBitCount << endl;
// now load the color palette if there is one
if (bitmap->bitmapinfoheader.biBitCount == 8)
{
//_lread(file_handle, &bitmap->palette, MAX_COLORS_PALETTE * sizeof(PALETTEENTRY));
// not tested:
bitmapFile.read ((char *) &(bitmap->palette), MAX_COLORS_PALETTE * sizeof(PALETTEENTRY));
// now set all the flags in the palette correctly and fix the reversed
// BGR RGBQUAD data format
for (index = 0; index < MAX_COLORS_PALETTE; index++)
{
// reverse the red and green fields
int temp_color = bitmap->palette[index].peRed;
bitmap->palette[index].peRed = bitmap->palette[index].peBlue;
bitmap->palette[index].peBlue = temp_color;
// always set the flags word to this
bitmap->palette[index].peFlags = PC_NOCOLLAPSE;
} // end for index
} // end if
bitmapWidth = bitmap->bitmapinfoheader.biWidth * (bitmap->bitmapinfoheader.biBitCount / 8);
bitmapHeight = bitmap->bitmapinfoheader.biHeight;
bitmapSize = bitmapWidth * bitmapHeight;
// finally the image data itself:
//_lseek(file_handle, -((int) (bitmap->bitmapinfoheader.biSizeImage)), SEEK_END);
bitmapFile.seekg (-((int) bitmapSize), ios::end);
//bitmapFile.seekg (sizeof (BITMAPINFOHEADER) + sizeof (BITMAPFILEHEADER) + MAX_COLORS_PALETTE * sizeof(PALETTEENTRY), ios::beg);
// now read in the image, if the image is 8 or 16 bit then simply read it
// but if its 24 bit then read it into a temporary area and then convert
// it to a 16 bit image
if (bitmap->bitmapinfoheader.biBitCount == 8 ||
bitmap->bitmapinfoheader.biBitCount == 16 ||
bitmap->bitmapinfoheader.biBitCount == 24)
{
// delete the last image if there was one
if (bitmap->buffer)
free(bitmap->buffer);
// allocate the memory for the image
//if (!(bitmap->buffer = (UCHAR *) malloc (bitmap->bitmapinfoheader.biSizeImage))) // error: biSizeImage == 0 !
if (!(bitmap->buffer = (UCHAR *) malloc (bitmapSize)))
{
// close the file
//_lclose(file_handle);
bitmapFile.close ();
// return error
return(0);
} // end if
// now read it in
//_lread(file_handle, bitmap->buffer, bitmap->bitmapinfoheader.biSizeImage);
bitmapFile.read ((char *) (bitmap->buffer), bitmapSize);
} // end if
else
{
// serious problem
return(0);
} // end else
// close the file
//_lclose(file_handle);
bitmapFile.close ();
// flip the bitmap
Flip_Bitmap(bitmap->buffer,
bitmap->bitmapinfoheader.biWidth * (bitmap->bitmapinfoheader.biBitCount / 8),
bitmap->bitmapinfoheader.biHeight);
//cout << "biSizeImage: " << bitmap->bitmapinfoheader.biSizeImage << endl;
//cout << (bitmap->bitmapinfoheader.biWidth * (bitmap->bitmapinfoheader.biBitCount / 8)) * bitmap->bitmapinfoheader.biHeight << endl;
// return success
return(1);
} // end Load_Bitmap_File
///////////////////////////////////////////////////////////
Current full source code:
http://pastebin.com/QQ6fMD7P
Expiration date is set to never.
Thanks to all people contributing to this question!
lseek crashes with the debug assertion failed error because it is a 16bit function. I found this out by looking at a chart of 16bit and 32bit functions on the microsoft website.
Solution is to use _llseek. _llseek is a 32bit function and can run on 64bit computers.
You do not need to change any parameters from _lseek to use _llseek.
_lseek(file_handle, -((int) (bitmap->bitmapinfoheader.biSizeImage)), SEEK_END);
becomes
_llseek(file_handle, -((int) (bitmap->bitmapinfoheader.biSizeImage)), SEEK_END);