Writing image header data using jpeglib - c++

I want to write the header data of a JPEG image using jpeglib. Unfortunately, I am not exactly sure which header data I really do need. I am sure of:
- quantization table
- Huffman tables
- shared image info (I am not exactly sure which data this contains, somebody wrote about 5 unchangable bytes)
and I know that the usual header size should be 624 bytes.
My code looks like:
jpeg_mem_dest(&cinfo, &buffer, &bufferSize);
cinfo.image_width = imageWidth;
cinfo.image_height = imageHeight;
cinfo.input_components = inputComponents;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, false);
jpeg_write_tables(&cinfo);
jpeg_start_compress(&cinfo, false);
headerSize = bufferSize;
How to write only tables is taken from the jpeglib doc section "Abbreviated datastreams and multiple images".
Unfortunately, it writes only 574 bytes and when prepending the written header data to the image data without header it says "JPEG datastream contains no image" when trying to decompress it again.
Analysing an original file which uses a shared header I found the following markers:
markers found are:
FFD8 // Start Of Image
FFE0 // Application-specific
FFFE // Comment
FFDB // Define Quantization Table(s)
FFDB // Define Quantization Table(s)
FFC4 // Define Huffman Table(s)
FFC0 // Start Of Frame (Baseline DCT)
MIP maps (4 mip maps):
FFDA
FFD9
FFDA
FFD9
FFDA
FFD9
FFDA
FFD9
Descriptions are taken from
https://en.wikipedia.org/wiki/JPEG#Syntax_and_structure
From a comment in the original image I do even know the original JPEG compression lib:
Intel(R) JPEG Library, version 1,5,4,36
The point is I want to get the schema behind the format to write exactly the data which is required (apparently some essential image header information is missing otherwise it would at least find a JPEG image I guess).
In the reading process I always prepend the shared header to the image data of one single JPEG image.

Related

How do I read text chunks quicker with libpng?

With libpng, I’m trying to extract text chunks in a 44-megabyte PNG image (and preferably validate that the PNG data is not malformed (e. g. lacking IEND, etc.)). I could do that with png_read_png and png_get_text, but it took way too long for me, 0.47 seconds, which I’m pretty sure is because of the massive amount of the IDAT chunks the image has. How do I do this in a quicker manner?
I didn’t need the pixels, so I tried to make libpng ignore the IDAT chunks.
To have libpng ignore IDAT chunks, I tried:
png_read_info(p_png, p_png_information); png_read_image(p_png, nullptr); png_read_end(p_png, p_png_information); to skip IDAT chunks; crashed and failed.
png_set_keep_unknown_chunks to make libpng unknow about IDAT, and png_set_read_user_chunk_fn(p_png, nullptr, discard_an_unknown_chunk) (discard_an_unknown_chunk is a function that does return 1;) to discard unknown chunks; a weird CRC error occurred on the first IDAT chunk and failed.
And failed to do that.
Edit
Running as a Node.js C++ addon, mostly written in C++, on Windows 10, with i9-9900K CPU # 3.6 GHz and gigabytes of memory.
Read the image file on an SSD with fs.readFileSync, a Node.js method returning a Buffer, and tossed it to the libpng to process.
Yes, at first, I blamed libpng for the prolonged computation. Now I see there might be other reasons causing the delay. (If that’s the case, this question would be a bad one with an XY problem.) Thank you for your comments. I’ll check my code out again more thoroughly.
Edit 2
With every step for feeding the PNG data input to the C++ addon kept the same, I ended up manually picking and decoding text chunks only, with my C pointer magic and some C++ magic. And, the performance was impressive (0.0020829 seconds on processing), being almost immediate. Don’t know why and how though.
B:\__A2MSUB\image-processing-utility>npm run test
> image-processing-utility#1.0.0 test B:\__A2MSUB\image-processing-utility
> node tests/test.js
----- “read_png_text_chunks (manual decoding, not using libpng.)” -----
[
{
type: 'tEXt',
keyword: 'date:create',
language_tag: null,
translated_keyword: null,
content: '2020-12-13T22:01:22+09:00',
the_content_is_compressed: false
},
{
type: 'tEXt',
keyword: 'date:modify',
language_tag: null,
translated_keyword: null,
content: '2020-12-13T21:53:58+09:00',
the_content_is_compressed: false
}
]
----- “read_png_text_chunks (manual decoding, not using libpng.)” took 0.013713 seconds.
B:\__A2MSUB\image-processing-utility>
I had to do something similar, but where I wanted libpng to do all of the metadata chunk parsing (e.g. eXIf, gAMA, pHYs, zEXt, cHRM, etc. chunks). Some of these chunks can appear after the IDAT, which means the metadata can't be read with just png_read_info. (The only way to get to them would be to do a full decode of the image, which is expensive, and then call png_read_end.)
My solution was to create a synthetic PNG byte stream that is fed to libpng via the read callback set using png_set_read_fn. In that callback, I skip all IDAT chunks in the source PNG file, and when I get to an IEND chunk, I instead emit a zero-length IDAT chunk.
Now I call png_read_info: it parses all of the metadata in all of the chunks it sees, stopping at the first IDAT, which in my synthetic PNG stream is really the end of the source PNG image. Now I have all of the metadata and can query libpng for it via the png_get_xxx functions.
The read callback that creates the synthetic PNG stream is a little complicated due to it being called by libpng multiple times, each for small sections of the stream. I solved that using a simple state machine that processes the source PNG progressively, producing the synthetic PNG stream on-the-fly. You could avoid those complexities if you produce the synthetic PNG stream up-front in memory before calling png_read_info: without any real IDATs, your full synthetic PNG stream is bound to be small...
While I don't have benchmarks to share here, the final solution is fast because IDATs are skipped entirely and not decoded. (I use a file seek to skip each IDAT in the source PNG after reading the 32-bit chunk length.)
You can check that all the correct PNG chunks are in a file, in the correct order, and not repeated and with correct checksums using pngcheck. It is open source so you could look at how it works.
If you add the parameter -7, you can not only check the structure but also extract the text:
pngcheck -7 a.png
Output
File: a.png (60041572 bytes)
date:create:
2020-12-24T13:22:41+00:00
date:modify:
2020-12-24T13:22:41+00:00
OK: a.png (10000x1000, 48-bit RGB, non-interlaced, -0.1%).
I generated a 60MB PNG and the above check takes 0.067s on my MacBook Pro.

Write exif data to jpeg stream

I try to insert some EXIF Data in a JPEG stream. I am using libexif for that.
The libexif example shows how to open a file -> add the data -> and then save the file. What I have is a pointer (void * JPEGPointer) to a JPEG stream. So I want to just add the from libexif generated data to this pointer for sending it via FTP. Not saving to a file. The following code is basically the example from libexif with some not working memcpy() attempts from myself. The JPG File is corrupted after the memcpy so i can not open it with any Software. I think i am copying the exif to the wrong position. I can not use any aditional library unfortunately.
// Set the image options
exif_data_set_option(exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
exif_data_set_data_type(exif, EXIF_DATA_TYPE_COMPRESSED);
exif_data_set_byte_order(exif, FILE_BYTE_ORDER);
// Create the mandatory EXIF fields with default data
exif_data_fix(exif);
/* Create a EXIF_TAG_USER_COMMENT tag. This one must be handled
* differently because that tag isn't automatically created and
* allocated by exif_data_fix(), nor can it be created using
* exif_entry_initialize() so it must be explicitly allocated here.
*/
entry = createTag(exif, EXIF_IFD_EXIF, EXIF_TAG_USER_COMMENT,
sizeof(ASCII_COMMENT) + sizeof(FILE_COMMENT) - 2);
/* Write the special header needed for a comment tag */
memcpy(entry->data, ASCII_COMMENT, sizeof(ASCII_COMMENT)-1);
/* Write the actual comment text, without the trailing NUL character */
memcpy(entry->data+8, FILE_COMMENT, sizeof(FILE_COMMENT)-1);
/* createTag() happens to set the format and components correctly for
* EXIF_TAG_USER_COMMENT, so there is nothing more to do. */
/* Get a pointer to the EXIF data block we just created */
exif_data_save_data(exif, &exif_data, &exif_data_len);
assert(exif_data != NULL);
//copy exif data to my JPEGPointer...not working like that
memcpy(JPEGPointer+ exif_data_len * sizeof(uint8_t), JPEGPointer, sizeof(JPEGPointer)+exif_data_len);
free(exif_data);
exif_data_unref(exif);
Any ideas how to put that EXIF data to the correct position in the JPEG data?

LibRaw and OpenCV

I use a Canon EOS 1200D.
This camera creates JPEG files with a resolution of 5184 x 3456.
The camera creates also CR2 files.
I use LibRaw to open this file.
LibRaw processor;
processor.open_file("test1.CR2");
If i debug my program i can see:
processor.imgdata.sizes.raw_height = 3516
processor.imgdata.sizes.raw_width = 5344
processor.imgdata.sizes.height = 3465
processor.imgdata.sizes.width = 5202
processor.imgdata.sizes.top_margin = 51
processor.imgdata.sizes.left_margin = 142
processor.imgdata.sizes.iheight = 3465
processor.imgdata.sizes.iwidth = 5202
1/ Why the resolution of 5184 x 3456 does not appear?
I see also four objects in:
processor.tiff_ifd like this:
[0] {t_width=5184 t_height=3456 bps=8 ...}
[1] {t_width=160 t_height=120 bps=8 ...}
[2] {t_width=668 t_height=432 bps=16 ...}
[3] {t_width=5344 t_height=3516 bps=14 ...}
2/ What does these four objects?
3/ I do not understand what the statement:
processor.unpack();
do.
Does it convert from RGBG format to RGB format?
Now, i would like create an cv::Mat with the resolution of 5184 x 3456 and without losing accuracy.
4/ So how i can convert my CR2 file to a cv::Mat with format CV_16UC3?
From several CR2 files, i would like create a new image wich is the average.
5/ So, when i have a cv::Mat with format CV_16UC3, how i can save it in a file without losing accuracy?
Thank you.
EDIT
Ok, so I have to use:
processor.imgdata.params.output_bps = 16;
processor.open_file("test1.CR2");
processor.unpack();
processor.dcraw_process();
libraw_processed_image_t* output = processor.dcraw_make_mem_image();
But how i can specify to use the JPEG resolution?
I think it is with:
processor.imgdata.params.cropbox
but how specify the JPEG resolution without hard coding?
Please refer to LibRAW documentation.
LibRAW uses all information stored in the raw file. In-camera and many commercial converters apply some cropping for various reasons. (see discussion here http://www.libraw.org/node/2117).
Raw files frequently contain several images: apart from raw data itself, there in normally one or more small preview images (thumbnails).
unpack method only unpacks data from raw file format without any demosaic. It is still the same raw data. To get RGB data, please refer to "Postprocessing" section in the documentation, particularly dcraw_process

Stitch many images in one using Libtiff

I want to copy many images in one big image in different positions and then save it to .tif, but I don't want to store them in memory all at once, so I need to define tiff file stored on disk, and then write my images one by one.
I'm using Libtiff. The problem that I can't see method that can write pixels to some address with displacement like
RGB* p= init_pointer+dy*width+dx
Is there any solution? (Maybe I should create just binary file and write header by my own, but it's a hard way, maybe libtiff can make it easier?)
So if I rephrase my question: how to obtain raw pointer to tiff data stored on disk for write pixel data?
For example I can create file on disk and write header by hand, and then write my images with offset using raw pointer, something like:
FILE* f = _tfopen(fileName, _T("wb"));
uint64 fileSize = headerSize + (uint64)im.Width() * im.Height() * (grayscale ? 1 : 3);
// Allocate file space
if( _fseeki64(f, fileSize - 1, SEEK_SET) == 0 &&
fputc(0, f) != EOF )
{
_fseeki64(f, 0, SEEK_SET);
// Write header
//write img using pointer with offset
int64 posPixels = headerSize + (rc.top - rcClip.top) * width + (rc.left - rcClip.left);
Once more time: I need to write many images into one image of tiff format like this http://upload.wikimedia.org/wikipedia/commons/a/a0/Rochester_NY.jpg and I must avoid creation of large image in RAM, so I need to write images one by one to file(only one image in RAM in the same time) and I trying to do this using libtiff.
Or another simple example: I have main image M(10000,10000) and I have some image m1(200,200) and I need to write image m1 to M at location (200,300)

Saving output frame as an image file CUDA decoder

I am trying to save the decoded image file back as a BMP image using the code in CUDA Decoder project.
if (g_bReadback && g_ReadbackSID)
{
CUresult result = cuMemcpyDtoHAsync(g_bFrameData[active_field], pDecodedFrame[active_field], (nDecodedPitch * nHeight * 3 / 2), g_ReadbackSID);
long padded_size = (nWidth * nHeight * 3 );
CString output_file;
output_file.Format(_T("image/sample_45.BMP"));
SaveBMP(g_bFrameData[active_field],nWidth,nHeight,padded_size,output_file );
if (result != CUDA_SUCCESS)
{
printf("cuMemAllocHost returned %d\n", (int)result);
}
}
But the saved image looks like this
Can anybody help me out here what am i doing wrong .. Thank you.
After investigating further, there were several modifications I made to your approach.
pDecodedFrame is actually in some non-RGB format, I think it is NV12 format which I believe is a particular YUV variant.
pDecodedFrame gets converted to an RGB format on the GPU using a particular CUDA kernel
the target buffer for this conversion will either be a surface provided by OpenGL if g_bUseInterop is specified, or else an ordinary region allocated by the driver API version of cudaMalloc if interop is not specified.
The target buffer mentioned above is pInteropFrame (even in the non-interop case). So to make an example for you, for simplicity I chose to only use the non-interop case, because it's much easier to grab the RGB buffer (pInteropFrame) in that case.
The method here copies pInteropFrame back to the host, after it has been populated with the appropriate RGB image by cudaPostProcessFrame. There is also a routine to save the image as a bitmap file. All of my modifications are delineated with comments that include RMC so search for that if you want to find all the changes/additions I made.
To use, drop this file in the cudaDecodeGL project as a replacement for the videoDecodeGL.cpp source file. Then rebuild the project. Then run the executable normally to display the video. To capture a specific frame, run the executable with the nointerop command-line switch, eg. cudaDecodGL nointerop and the video will not display, but the decode operation and frame capture will take place, and the frame will be saved in a framecap.bmp file. If you want to change the specific frame number that is captured, modify the g_FrameCapSelect = 37; variable to some other number besides 37, and recompile.
Here is the replacement for videoDecodeGL.cpp I used pastebin because SO has a limit on the number of characters that can be entered in a question body.
Note that my approach is independent of whether readback is specified. I would recommend not using readback for this sequence.