Swapping Jpeg RGB Channels (RGB->BGR) - image

I have a Jpeg RGB single-scan clip (with Adobe App14 marker, and R, G, B components all interleaved in the same scan). I am wondering if there is way to edit the Jpeg clip header (or append other headers like EXIF) so that decoders can interpret the R channel as B and vice versa without changing the rest of the bitstream?
I had tried swapping the ordering of "Scan component selectors" in the scan header, and the decoder (Windows Photo Viewer in this case) successfully displayed Red as Blue and Blue as Red afterwards. However, the ITU-T.81 Jpeg specification specifically said that "Csj:Scan component selector: Each Csj shall match one of the Ci values specified in the frame header, and the ordering in the scan header shall follow the ordering in the frame header." So I guess changing the Scan component selector ordering is not a valid option unless there is any updated specification saying that this is no longer the restriction.
Does anyone know other ways to swap the RGB channels by either appending some sort of app data or modifying Jpeg frame or scan headers without touching the scan data at all?
Thank you for your inputs.

If you have the image in raw format you can modify the exif CFA using exiftool. The array may vary depending on the sensor and format.
For swapping dng files, you can use the following
exiftool.exe -subifd:cfapattern2="2 1 1 0" file.dng
Where
0 = Red,
1 = Green,
2 = Blue,
If your desperate you could always consider converting your Jpg to Raw and then back again

Related

Is png rgba data changed by a browser when displayed?

I have a 2-pixel PNG image with the following rgba:
image.setAt(0, 0, { red:255, green:10, blue:10, alpha:100 });
image.setAt(1, 0, { red:255, green:255, blue:55, alpha:255 });
image.setAt(0, 1, { red:90, green:10, blue:65, alpha:250 });
image.setAt(1, 1, { red:60, green:255, blue:0, alpha:14 });
(using node's pngjs-image module)
When the image is loaded by the browser (firefox) and copied to canvas to test the rgba data, the following is returned:
255 7 7 100
255 255 55 255
89 9 64 250
54 255 0 14
It seems like only Alpha channel values are preserved while pixel colors are arbitrarily changed.
What's going on?
(using Firefox 41 on Linux)
EDIT
From intro on pngtoy nodejs module I have found the following:
Low-level implementation of PNG file parser/reader/decoder using
JavaScript on client size.
Why this when browsers support PNG already?
The browser will simply load and convert any PNG type into RGBA
bitmaps. It will also apply ICC and gamma correction to the image
resulting in different values than in the original bitmap.
However, I thought that PNG itself should have ICC and Gamma correction chunks so that the browser applies them. Does the browser make such image manipulation to any png file even without ICC/gamma chunk inside the file?
Firefox converts images with alpha to pre-multiplied alpha for internal use. If your workflow is recovering the image from Firefox' internal image buffer, there will be loss of precision when reversing the pre-multipled alpha. In the extreme, pixels with alpha equal to zero will be returned as transparent black, regardless of the underlying color in the original PNG. This effect doesn't depend upon whether color management chunks are present or not.
Note that this doesn't happen when you click on a PNG image and "save as..."; in this case the original PNG is returned.
Firefox may also modify the internal image (depending upon the setting of gfs.color_management.mode in "about:config") when color management chunks (iCCP, sRGB, gAMA, and/or cHRM) are present, but that does not seem to be the case for this particular question. Again, "save as..." will return the original pixels and the color management chunks unchanged.

How do I import a png file in Postscript with Ghostscript?

I'm trying to place a png image on a postscript document for conversion to a pdf file using Ghostscript (v 9.15) ps2pdf. I've found that the following code works nicely with a jpg file, but I need to import png files instead. It looks like i must need a different filter, but I can't find one that works. Does anyone have a solution?
239 % number of pixels in the horizontal axis
67 % number of pixels in the vertical axis
8 % bits per color channel (1, 2, 4, or 8)
[239 0 0 -67 0 67] % transform array... maps unit square to pixel [ w 0 0 -h 0 h ]
(My_Logo.jpg) (r) file % see page 587 and page 77 for more details
/DCTDecode filter % see page 589
false % pull channels from separate sources
3 % 3 color channels (RGB)
colorimage % see page 544 and page 288 for more detail
PostScript doesn't support PNG directly, it does support JPEG which is why your code above works.
If you want to read image data from a PNG file you will need to open the file, strip the header, then read each chunk individually parsing the data from it. It might be easiest to write the bitmap data to an intermediate file, but its perfectly possible to write a stream decoder to supply the data as required for a procedural image data source.
Fortunately PostScript (level 3 for certain, most versions of level 2) does support Flate, so you don't have to write the decompression code in PostScript, you can use the filter directly.
You will need to specify a colour space, depending on whether the PNG uses a palette or not.
PostScript is a programming language, so this is all possible, it will take an experienced PostScript programmer a couple of days to write and debug it I should think.
NOTE! PostScript does not support transparency, so you cannot apply alpha channels from PNG files at all.

gray levels are changed after using imsave function

I used these codes to produce an RGB image with gray levels between 50 and 170.
a='C:\Users\sepideh\Desktop\IP_abadpour\S45C-113050518040.jpg';
b=imread(a);
b=b+50;
b(b>170)=170;
and you'll see when I call functions max and min, it is proved that the gray levels are between 50 and 170.
max(max(max(b)))
ans =
170
min(min(min(b)))
ans =
50
then I used imshow and imsave functions to save the image with the name "50to170"
c=imshow(b);
d=imsave(c);
Now I read the written image in this way:
a='C:\Users\sepideh\Desktop\IP_abadpour\50to170.jpg';
b=imread(a);
This time when I call max and min functions,I see:
max(max(max(b)))
ans =
235
min(min(min(b)))
ans =
16
I mean it seems that gray levels have been changed after using imshow and imsave functions!
Why does it happen?
Is it because of the format (.jpg) that I'm using when employing imsave function?
Instead of using imsave, use imwrite
b=imread(a);
b=b+50;
b(b>170)=170;
imwrite(b,'50to170.png','png')
Notice that I am saving it as a png file instead of a jpg to prevent compression. Bitmap also saves it without compression.
This method is a more direct way to save raw image matrices than using imshow and imsave.
If you want the same functionality of imsave (selecting where the file goes) check out "uiputfile" to get file name and location.
I tested it.
1.First of all you can't use imsave(b) because the function imsave expects its first input argument to be a valid handle to a single graphics object.So first you should show the image in form c=imshow(b) and then use c as an input for function imsave.
2.If you want to save the image without showing it first use function "imwrite" and pass b as the first input argument to it.
Note that if you don't want gray levels be changed after saving, you should use 'bmp' as the save format not 'jpg'.
Because 'jpg' does not support indexed images and "imwrite" converts indexed images to RGB before writing data to JPEG files so the gray levels might be changed.It's not related to the contrast stretching when showing the image in matlab.It's related to the format used to save the image.

Can I edit the thumbnail image inside JFIF files?

Can I edit the thumbnail image inside JPG/JFIF files?
If this is possible--how so (using what utility)?
The end result needs to be that the thumbnail image "can" be a wholly different image than the jpeg.
Thank you much,
Michael
Typically, thumbnails are uncompressed RGB data. You locate the marker, see where the thumbnail's width/height are marked, then modify the byte stream following it. the stream is of length width*height*3 bytes.
If it's indexed, you'd have to overwrite the palette and the index entries. Just look for the APP0 marker, start modifying it.
A compliant EXIF thumbnail image must fit in the 64K APP1 marker and is usually compressed as JPEG (unlike what #Karthik says). The thumbnail image is independent of the main image and can easily be changed since it is inside a marker segment that doesn't affect the main image. The JPEG marker segments are basically a linked list of independent binary blobs with 2-byte identifiers (e.g. FFE1 in this case) and 2-byte lengths. You can swap out one for another and you won't "break" the file. There is no checksum or other mechanism that verifies the entire file data integrity. I'm not familiar with libraries to edit this information, but you can do it in a small amount of code that only has to parse the marker blobs type and length without knowing their contents. You can also do it the "quick and dirty" way by ensuring that your new thumbnail is no larger than the original and then you can just write it in it's place without moving the other parts of the file around. The marker length is not checked against its contents, so unused space is ignored.

How to display JPEG image on microcontroller LCD?

I am recently developing some firmware on the STM3210E development board which has an ARM cortex M3 processor. It has been interfaced to a 240x320 LCD. After going through the demo firmware, I realised that images are encoded in 32 bit variables (correct me if I am wrong) stored in array as shown below.
uint32_t STM32Banner[50] = {0x6461EB7A, 0x646443BC, 0x64669BFE, 0x6468F440, 0x646B4C82,
0x646DA4C4, 0x646FFD06, 0x64725548, 0x6474AD8A, 0x647705CC,
0x64795E0E, 0x647BB650, 0x647E0E92, 0x648066D4, 0x6482BF16,
0x64851758, 0x64876F9A, 0x6489C7DC, 0x648C201E, 0x648E7860,
0x6490D0A2, 0x649328E4, 0x64958126, 0x6497D968, 0x649A31AA,
0x649C89EC, 0x649EE22E, 0x64A13A70, 0x64A392B2, 0x64A5EAF4,
0x64A84336, 0x64AA9B78, 0x64ACF3BA, 0x64AF4BFC, 0x64B1A43E,
0x64B3FC80, 0x64B654C2, 0x64B8AD04, 0x64BB0546, 0x64BD5D88,
0x64BFB5CA, 0x64C20E0C, 0x64C4664E, 0x64C6BE90, 0x64C916D2,
0x64CB6F14, 0x64CDC756, 0x64D01F98, 0x64D277DA, 0x64D4D01C}
Could you please explain me how to convert a JPEG/PNG/BMP image to this format (RGB565) ?
You have two choices:
Write your own set of decoders.
Use available free decoders
The first solution is only really viable for BMP (and perhaps GIF), which is quite a simple format compared to PNG and JPEG. Even so, writing a BMP decoder that handles all different versions and specialties of BMP gracefully takes quite a bit of work (I have tried it). Hacking together something that can extract the image data from the most common BMP formats is quite easy though.
The second solution is probably the way to go for the other formats. Most open-source decoders are available under LGPL or similar, so licensing shouldn't really be a problem. For JPEG images use libJPEG, for PNG use libPNG and for GIF use giflib.
Most of the decoders do not support decoding to RGB565 so you will have to write a converter to convert from RGB888 to RGB565.
use a program like GIMP to convert to an uncompressed bmp (what you normally get when you save-as bmp).
A bmp has something like a 54 byte header then it goes into the data. Each line is pixels either 3 bytes (RGB) or four bytes (RGBX) per pixel. The width is aligned on a 4 byte boundary so if you have three bytes per and multiply that by the width in pixels if that is not a multiple of four (say 3 bits wide * 3 = 9 as a simple example) then there will be some padding. You know from opening the file in gimp how wide it is, you probably want to use gimp to adjust the image to match your lcd screen anyway. The first bytes of data after the header are the pixel in the lower left corner of the image, you might need to flip the image in the y axis, or just start off this way and see what happens.
Knowing the size of your image, (from opening it with gimp), you can do a little math to see if the size of the file matches with what I am saying, if it is dramatically smaller then there is some compression going on and you need to save again and change the settings for the bmp.
Once you have this figured out then write a simple program to extract the pixels from the bmp and save them in the format you desire. Even better read the code and docs and understand how to program the lcd and you can get from raw pixels to the lcd without having to to through their specific format/code.

Resources