I have a JPEG in memory as a char* and a bytesize, if I save it to disk with a .jpg extension it's a perfect JPEG file. The thing is, I don't want to save it unless it's a minimum width/height. I got it into memory using a socket recv() call. What should I do ?
1) What do you mean by "unless it's a minimum width/height"?
2) JPEG's are manipulated in memory by the requisite JPEG C/C++ libraries and code. Are you using a JPEG library? You certainly would not want to do this yourself without using a library of some type (IJG, Intel, etc.).
1) Exactly that, I don't want to write it to disk unless the width or height is a minimum of (say) 512 pixels.
I'm not using a library because I planned on just writing the block of memory to disk. Now that I need to probe the dimensions I guess I need a library.
I was going to use GDI+ but in order to create an Image from memory it has to be an IStream and that looks like a pain. Can I easily create a JPEG object from a memory block using those libraries you mentioned ?
I'm not using a library because I planned on just writing the block of memory to disk.
Unless you know what you're doing, you don't want to mess around with an image format such as JPEG with home-made code. Leave that to the authors of these libraries to handle those details -- they spent years on it.
Originally Posted by endemoniada
I was going to use GDI+ but in order to create an Image from memory it has to be an IStream and that looks like a pain. Can I easily create a JPEG object from a memory block using those libraries you mentioned ?
I don't know what GDI+ does internally, but if it converts the JPEG to a DIB or some compatible bitmap structure, manipulates it, and then writes it back from the compatible format to JPEG, that is not the same as manipulating the JPEG directly in memory.
The IJG library is one of the industry standard libraries to manipulate JPEG files, so I would expect you can do anything with it in terms of memory blocks. Why not read the documentation and look at the sample files?
I was going to use GDI+ but in order to create an Image from memory it has to be an IStream and that looks like a pain. Can I easily create a JPEG object from a memory block using those libraries you mentioned ?
What pain? You create stream, copy your bytes there, rewind it to the beginning, and that's it.
JPEG files consist of a series of component structures with each structure beginning with a 2 byte marker. The image dimensions are stored in the "Start Of Frame" structure. The first byte of a marker is always 0xFF. The second byte specifies the type of component structure. Some markers are stand alone while others are followed by additional bytes. If a component structure is more than just the marker, the two bytes immediately following the marker specify the size of the structure including the structure size bytes, but not the marker bytes. The 2 byte size, as well as the 2 byte image dimensions, are stored in big-endian format, that is, the first byte is more significant than the second.
To find the image dimensions, the JPEG file is scanned from the beginning. Component structures are skipped until the Start Of Frame structure is found. There is only one Start Of Frame structure per image, however, images can contain thumbnails images that are nested within application specific structures. This prohibits the file from simply being scanned for a Start Of Frame marker. There are 13 different Start Of Frame markers, but the image dimensions are stored the same way for all of them. JPEG files may also contain padding bytes before any of the markers. These padding bytes have the value of 0xFF.
In the following code segment, Data is a pointer to the file's array of bytes and Size is the number of bytes in the file.
Code:
int Width;
int Height;
int Index;
unsigned char Marker;
int StructureSize;
Width = 0;
Height = 0;
Index = 0;
while (Index < Size)
{
if (Data[Index] == 0xFF)
{
// Get the component structure marker.
Index = Index + 1;
do
{
if (Index < Size)
{
Marker = Data[Index];
Index = Index + 1;
}
else
{
Marker = 0xFF;
}
} while ((Marker == 0xFF) && (Index < Size));
// Determine the componsent structure size.
if (((Marker >= 0xD0) && (Marker <= 0xD9)) || (Marker == 0x01))
{
StructureSize = 0;
}
else if (Index < (Size - 1))
{
StructureSize = (Data[Index] << 8) | Data[Index + 1];
}
else
{
StructureSize = 1;
}
// Check if the marker is for the Start Of Frame component structure.
if (((Marker & 0xF0) == 0xC0) && (Marker != 0xC4) && (Marker != 0xC8) && (Marker != 0xCC) && (Index < (Size - 6)))
{
Height = (Data[Index + 3] << 8) | Data[Index + 4];
Width = (Data[Index + 5] << 8) | Data[Index + 6];
Index = Size;
}
Index = Index + StructureSize;
} // end if (Data[Index] == 0xFF)
else
{
Index = Size;
}
} // end while (Index < Size)
Bookmarks