I have a big binary file with lots of files stored inside it. I'm trying to copy the data of a PCX image from the file and write it to a new file which I can then open in an image editor.
After obtaining the specs for the header of a PCX file I think that I've located the image in the big binary file. My problem is that I cannot figure out how many bytes I'm supposed to read after the header. I read about decoding PCX files, but I don't want to decode anything. I want to read the encoded image data and write that to a seperate file so the image editor can open in.
Here is the header. I've included the values of the image as I guess they can be used to determine the "end-of-file" for the image data.
struct PcxHeader
{
BYTE Identifier; // PCX Id Number (Always 0x0A) // 10
BYTE Version; // Version Number // 5
BYTE Encoding; // Encoding Format // 1
BYTE BitsPerPixel; // Bits per Pixel // 8
WORD XStart; // Left of image // 0
WORD YStart; // Top of Image // 0
WORD XEnd; // Right of Image // 319
WORD YEnd; // Bottom of image // 199
WORD HorzRes; // Horizontal Resolution // 320
WORD VertRes; // Vertical Resolution // 200
BYTE Palette[48]; // 16-Color EGA Palette
BYTE Reserved1; // Reserved (Always 0)
BYTE NumBitPlanes; // Number of Bit Planes // 1
WORD BytesPerLine; // Bytes per Scan-line // 320
WORD PaletteType; // Palette Type // 0
WORD HorzScreenSize; // Horizontal Screen Size // 0
WORD VertScreenSize; // Vertical Screen Size // 0
BYTE Reserved2[54]; // Reserved (Always 0)
};
There are three components to the PCX file format:
128-byte header (though less are actually used, it is 128 bytes long)
variable-length image data
optional 256 color palette (though improper PCX files exist with palette sizes other than 256 colors).
From the Wikipedia artice:
Due to the PCX compression scheme the only way to find the actual length of the image data is to read and process it. This effort is made difficult because the format allows for the compressed data to run beyond the image dimensions, often padding it to the next 8 or 16 line boundary.
In general, then, it sound like you'll have to do a "deep process" of the image data to find the complete PCX file embedded within your larger binary file.
Without knowing much about the PCX file format, I can take a best guess at this:
bytesAfterHeader = header.BytesPerLine * header.VertRes;
Related
I realized it is bad for me to neglect this thought, because I haven't read anything about number of channels and bits per sample in this light. My reason is that I'm not sure how the samples of 2-channel 8-bit PCM files will look like.
Is it 1 sample = 1 channel? or 1 sample = 4 bits (left) + 4 bits (right)
Context:
I am writing a program that reads WAV files, and it occurred to me that if I come across 8-bit PCM WAV files, and my code reads this way (see below), then my program is unable to properly read multi-channel 8-bit PCM WAV files.
// read actual audio data after obtaining
// the headers
// audioData is a vector of vectors (1 vector per channel)
uint32_t temp;
while( !feof(wavFile) ) {
for(uint16_t i = 0; i < numChannels; i++) {
temp = 0;
fread(&temp,sizeof(uint8_t),1,wavFile);
audioData.at(i).push_back(temp);
}
}
The structure, which typically describes format of WAV audio data, is described in MSDN here: WAVEFORMATEX structure:
"sample" for PCM audio is a block of data, which includes all channels
nBlockAlign value is size, in bytes, of such block corresponding to sample
samples go at specific fixed rate, defined by nSamplesPerSec value
each sample block consists of nChannels values, each one of wBitsPerSample
That is, two channel file with 8 bits per sample has nSamplesPerSec pairs for each second of audio data, each pair includes two 8-bit values for every channel of the two.
(here is an example of where this structure exists in the WAV file - though this is a more complicated case with 24-bits/sample, but you should get the idea).
Is there a way to calculate the Maximum size that could take any image compressed with PNG ?
I need to know, that (for example) a PNG of a resolution of 350x350 (px), can't be larger than "X" KB. (and for a constant quality compression, like 90)
the "X" value is the one I'm looking for. Or in math expression
350px * 350px * (90q) < X KB
I'm not quite familiar with the PNG compression algorithm, but there is probably a max value for a specific resolution ?
P.S. : the PNG has no alpha is this case.
From the PNG format here:
The maximum case happens when the data is incompressible
(for example, if the image resolution is 1x1,
or if the image is larger but contains random incompressible data).
That would make the maximum size:
8 // PNG signature bytes
+ 25 // IHDR chunk (Image Header)
+ 12 // IDAT chunk (assuming only one IDAT chunk)
+ height // in pixels
* (
1 // filter byte for each row
+ (
width // in pixels
* 3 // Red, blue, green color samples
* 2 // 16 bits per color sample
)
)
+ 6 // zlib compression overhead
+ 2 // deflate overhead
+ 12 // IEND chunk
Compression "quality" doesn't enter into this.
Most applications will probably separate the IDAT chunk into smaller chunks, typically 8 kbytes each, so in the case of a 350x350 image there would be 44 IDAT chunks, so add 43*12 for IDAT chunk overhead.
As a check, a 1x1 16-bit RGB image can be written as a 72-byte PNG, and a 1x1 8-bit grayscale image is 67 bytes.
If the image is interlaced, or has any ancillary chunks, or has an alpha channel, it will naturally be bigger.
I was trying to load BMP picture into memory and save the RGB array into a file(my own format 3d model with texture data).I made the programming to convert OBJ and its texture data into a m2d file. But when I loaded the file in actual in my m2d loader it showed me green continuous lines on the picture.
I opened the BMP file in hex editor, found two 00s as culprit(occurred many times).
Any hint how should I take these 00s out of my RGB array?
Any hint or tip will be appreciated.
Each horizontal row in a BMP must be a multiple of 4 bytes long.
If the pixel data does not take up a multiple of 4 bytes, then 0x00 bytes are added at the end of the row. For a 24-bpp image, the number of bytes per row is (imageWidth*3 + 3) & ~3. The number of padding bytes is ((imageWidth*3 + 3) & ~3) - (imageWidth*3).
I am fairly new to image processing using Visual C++, I am in search of a way that reads black and white TIFF files and writes the image as an array hex values representing 0 or 1, then get the location information of either 0 (black) or 1 (white).
After a bit of research on Google and an article here https://www.ibm.com/developerworks/linux/library/l-libtiff/#resources I have the following trivial questions, please do point me to relevant articles, there are so many that I couldn’t wrap my heads around them, meanwhile I will keep on searching and reading.
Is it possible to extract pixel location information from TIFF using LIBTIFF?
Again being new to all image formats, I couldn't help to think that an image is made up of a 2D array of hex values , is the bitmap format more appropriate? Thinking in that way makes me wonder if I can just write the location of “white” or “black” mapped from its height onto a 2D array. I want the location of either “black” or “white”, is that possible? I don’t really want an array of 0s and 1s that represents the image, not sure if I even need them.
TIFF Example of a 4 by 2 BW image:
black white
white black
black black
white white
Output to something like ptLocArray[imageHeight][imageWidth] under a function named mappingNonPrint()
2 1
4 4
or under a function named mappingPrint()
1 2
3 3
With LIBTIFF, in what direction/ways does it read TIFF files?
Ideally I would like TIFF file to be read vertically from top to bottom, then shifts to the next column, then start again from top to bottom. But my gut tells me that's a fairy tale, being very new to image processing, I like to know how TIFF is read for example a single strip ones.
Additional info
I think I should add why I want the pixel location. I am trying to make a cylindrical roll printer, using a optical rotary encoder providing a location feedback The height of the document represents the circumference of the roll surface, the width of the document represent the number of revolutions.
The following is a grossly untested logic of my ENC_reg(), pretty much unrelated to the image processing part, but this may help readers to see what I am trying to do with the processed array of a tiff image. i is indexed from 0 to imageHeight, however, each element may be an arbitrary number ranging from 0 to imageHeight, could be 112, 354 etc that corresponds to whatever the location that contains black in the tiff image. j is indexed from 0 to imageWidth, and each element there is also starting 0 to imageWidth. For example, ptLocArray[1][2] means the first location that has a black pixel in column 2, the value stored there could be 231. the 231st pixel counting from the top of column 2.
I realized that the array[imageHeight][] should be instead array[maxnum_blackPixelPerColumn], but I don't know how to count the number of 1s, or 0s per column....because I don't know how to convert the 1s and 0s in the right order as I mentioned earlier..
void ENC_reg()
{
if(inputPort_ENC_reg == true) // true if received an encoder signal
{
ENC_regTemp ++; // increment ENC register temp value by one each time the port registers a signal
if(ENC_regTemp == ptLocArray[i][j])
{
Rollprint(); // print it
i++; // increment by one to the next height location that indicates a "black", meaning print
if (ENC_regTemp == imageHeight)
{
// Check if end of column reached, end of a revolution
j++; // jump to next column of the image (starting next revolution)
i = 0; // reset i index to 0, to the top of the next column
ENC_regTemp = 0; // reset encoder register temp to 0 for the new revolution
};
};
ENC_reg(); // recall itself;
};
}
As I read your example, you want two arrays for each column of the image, one to contain the numbers of rows with a black pixel in that column, the other with indices of rows with a white pixel. Right so far?
This is certainly possible, but would require huge amounts of memory. Even uncompressed, a single pixel of a grayscale image will take one byte of memory. You can even use bit packing and cram 8 pixels into a byte. On the other hand, unless you restrict yourself to images with no more than 255 rows, you'll have multiple bytes to represent each column index. And you'd need extra logic to mark the end of the column.
My point is: try working with the “array of 0s and 1s” as this should be both easier to accomplish, less demanding in terms of memory, and more efficient to run.
I'm trying to understand building a bmp based on raw data in c++ and I have a few questions.
My bmp can be black and white so I figured that the in the bit per pixel field I should go with 1. However in a lot of guides I see the padding field adds the number of bits to keep 32 bit alignment, meaning my bmp will be the same file size as a 24 bit per pixel bmp.
Is this understanding correct or in some way is the 1 bit per pixel smaller than 24, 32 etc?
Thanks
Monochrome bitmaps are aligned too, but they will not take as much space as 24/32-bpp ones.
A row of 5-pixel wide 24-bit bitmap will take 16 bytes: 5*3=15 for pixels, and 1 byte of padding.
A row of 5-pixel wide 32-bit bitmap will take 20 bytes: 5*4=20 for pixels, no need for padding.
A row of 5-pixel wide monochrome bitmap will take 4 bytes: 1 byte for pixels (it is not possible to use less than a byte, so whole byte is taken but 3 of its 8 bits are not used), and 3 bytes of padding.
So, monochrome bitmap will of course be smaller than 24-bit one.
The answer is already given above (that bitmap rows are aligned/padded to 32-bit boundary), however if you want more information, you might want to read DIBs and Their Uses, the "DIB Header" section - it explains in detail.
Every scanline is DWORD-aligned. The scanline is buffered to alignment; the buffering is not necessarily 0.
The scanlines are stored upside down, with the first scan (scan 0) in memory being the bottommost scan in the image. (See Figure 1.) This is another artifact of Presentation Manager compatibility. GDI automatically inverts the image during the Set and Get operations. Figure 1. (Embedded image showing memory and screen representations.)