CImg - how to convert interleaved raw data? - cimg

I just started using CImg libraries and I would like to test it with raw data, but I am experiencing big problems to figure out why I cannot obtain correct results.
My RGB24 raw file format is RGB interleaved (RGBRGBRGB ...) while CImg stores data as explained here.
The (last) test code I wrote is this, where I collect all the possible 4! = 24 combination for permute_axes method
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifdef cimg_display
#undef cimg_display
#define cimg_display 0
#endif
#include "CImg.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdint>
#include <cstdlib>
#include <thread>
#include <vector>
#include <array>
#include <cmath>
#include <unistd.h>
#include <sys/file.h>
#include <fcntl.h>
using namespace std;
using namespace cimg_library;
#define MODE_700 (mode_t) S_IRWXU // 00700
#define MODE_400 (mode_t) S_IRUSR // 00400
#define MODE_200 (mode_t) S_IWUSR // 00200
#define MODE_100 (mode_t) S_IXUSR // 00100
#define MODE_070 (mode_t) S_IRWXG // 00070
#define MODE_040 (mode_t) S_IRGRP // 00040
#define MODE_020 (mode_t) S_IWGRP // 00020
#define MODE_010 (mode_t) S_IXGRP // 00010
#define MODE_007 (mode_t) S_IRWXO // 00007
#define MODE_004 (mode_t) S_IROTH // 00004
#define MODE_002 (mode_t) S_IWOTH // 00002
#define MODE_001 (mode_t) S_IXOTH // 00001
#define MODE_777 (mode_t) MODE_700 | MODE_070 | MODE_007
int main(int argc, const char *argv[])
{
//uint8_t buffer[960 * 1280 * 3];
CImg <uint8_t> image(960, 1280, 1, 3);
// CImg <float> gaussk(7,7,3);
uint8_t buffer[960 * 1280 * 3] = {0};
float var = 1.5*1.5;
// int32_t xtmp;
// int32_t ytmp;
int32_t fd = -1;
stringstream sstr;
cout << "image size is: " << unsigned(image.size()) << endl;
printf("opening %s\n", argv[1]);
fd = open(argv[1], O_RDONLY);
if(fd == -1)
{
perror("open: ");
return -1;
}
cout << "Reading..." << endl;
// read(fd, image.data(), image.size());
read(fd, buffer, sizeof(buffer));
close(fd);
fd = -1;
for(uint8_t i = 0; i < 24; i++)
{
sstr << "blurred_" << unsigned(i) << ".raw";
image.assign(buffer, 960, 1280, 1, 3);
switch(i)
{
case 0:
image.permute_axes("xyzc");
break;
case 1:
image.permute_axes("xycz");
break;
case 2:
image.permute_axes("xzyc");
break;
case 3:
image.permute_axes("xzcy");
break;
case 4:
image.permute_axes("xcyz");
break;
case 5:
image.permute_axes("xczy");
break;
case 6:
image.permute_axes("yxzc");
break;
case 7:
image.permute_axes("yxcz");
break;
case 8:
image.permute_axes("yzxc");
break;
case 9:
image.permute_axes("yzcx");
break;
case 10:
image.permute_axes("ycxz");
break;
case 11:
image.permute_axes("yczx");
break;
case 12:
image.permute_axes("zxyc");
break;
case 13:
image.permute_axes("zxcy");
break;
case 14:
image.permute_axes("zyxc");
break;
case 15:
image.permute_axes("zycx");
break;
case 16:
image.permute_axes("zcxy");
break;
case 17:
image.permute_axes("zcyx");
break;
case 18:
image.permute_axes("cxyz");
break;
case 19:
image.permute_axes("cxzy");
break;
case 20:
image.permute_axes("cyxz");
break;
case 21:
image.permute_axes("cyzx");
break;
case 22:
image.permute_axes("czxy");
break;
case 23:
image.permute_axes("czyx");
break;
}
image.blur(2.5);
// image.save("blurred.bmp");
cout << "Writing " << sstr.str() << endl;
fd = open(sstr.str().c_str(), O_RDWR | O_CREAT, MODE_777);
write(fd, image.data(), image.size());
close(fd);
sstr.str("");
}
return 0;
}
But the output blurred frame is wrong, most of the times in grayscale.
According to the header file CImg.h this conversion should be possible, and it's what I understand also after reading this blog post.
Before I start to write my own function to try to fix this problem, what is the correct way to deal with raw file and to make such a conversion with CImg ?

So you have interleaved data and want it non-interleaved to be able to let CImg functions work with it.
So why didn't you just do exactly what the blog post you referenced advised under IMPORTANT
CImg result(dataPointer, spectrum, width, height, depth, false);
result.permute_axes("yzcx");
for your code that would be
image.assign(buffer, 3, 960, 1280, 1); // note the 3 being first
image.permute_axes("yzcx");
image.blur(2.5);
// image.save("blurred.bmp");
//now convert back to interleaved
image.permute_axes("cxyz");
fd = open(sstr.str().c_str(), O_RDWR | O_CREAT, MODE_777);
write(fd, image.data(), image.size());

Related

I'm converting ints to chars and trying to send them from a C client to a Python server on another computer. Getting 'send: Bad address'

On one computer with the client (written in C) I get the error send: Bad address when I try to send chars to another computer with a server written in Python. But the address is NOT bad.
If instead of chars I just send a written string, "A string written like this" I can send it just fine to the server and see it print with no problems. So, I don't think there is really a problem with an address.
I have also tried converting the int to a string. I get error when compiling cannot convert string to char. I have tried variations and I can only compile with the client written as it is below.
The client (in C)
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#define ADDR "192.168.0.112"
#define PORT "12003"
void sendall(int socket, char *bytes, int length)
{
int n = 0, total = 0;
while (total < length) {
n = send(socket, bytes + total, total-length, 0);
if (n == -1) {
perror("send");
exit(1);
}
total += n;
}
}
void thesock(char *ADDRf, char *PORTf, char *RAZZstr)
{
struct addrinfo hints = {0}, *addr = NULL;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int status = getaddrinfo(ADDRf, PORTf, &hints, &addr);
if (status != 0) {
std::cerr << "Error message";
exit(1);
}
int sock = -1;
struct addrinfo *p = NULL;
for (p = addr; p != NULL; p = addr->ai_next) {
sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sock == -1) {
continue;
}
if (connect(sock, p->ai_addr, p->ai_addrlen) != -1) {
break;
}
close(sock);
}
if (p == NULL) {
fprintf(stderr, "connect(), socket()\n");
exit(1);
}
sendall(sock, RAZZstr, 12);
close(sock);
}
int main()
{
int someInt = 321;
char strss[12];
sprintf(strss, "%d", someInt);
thesock(ADDR, PORT, strss);
return 0;
}
This last part of the code above is where the chars, or string is entered. It's this part of the code where you can replace strss in thesock with a string written in the strss position "just like this" and it will send to the server on the other computer written in Python. Though, when compiling I do get warnings ISO C++ forbids converting a string constant to ‘char*’.
The server (In Python)
import os
import sys
import socket
s=socket.socket()
host='192.168.0.112'
port=12003
s.bind((host,port))
s.listen(11)
while True:
c, addr=s.accept()
content=c.recv(29).decode('utf-8')
print(content)
This server decodes utf-8. I don't know if I have the option for a different 'decode' here. I don't think Python has 'chars'.
TL;DR: this is unrelated to "address" in terms of IP address but it is about invalid access to a local memory access.
int n = 0, total = 0;
while (total < length) {
n = send(socket, bytes + total, total-length, 0);
total - length is a negative number, i.e. 0-12 = -12 in your case. The third argument of send is of type size_t, i.e. an unsigned integer. The negative number (-12) thus gets cast into an unsigned integer, resulting in a huge unsigned integer.
This causes send to access memory far outside the allocated memory for bytes, hence EFAULT "Bad address".

how to combine ADRESH and ADRESL on 12 bit ADC

MICRO: PIC18LF47K42
compiler: XC8
application: MPLABX
I am trying to combine the values in of 12 bit ADC. They go into ADRESH and ADRESL. My ADC is set up for right-justify which does formating as so:
ADRESH:(----MSB,x,x,x) ADRESL: (X,X,X,X,X,X,X,LSB)
From inspecting the value in my result register i can tell i dont have a great resolution. Im pretty sure its becasue of how im combining ADRESH and ADRESL. How could i do this?
#include "myIncludes.h"
volatile unsigned char ZCDSoftwareFlag = 0;
volatile unsigned char switchValue = 0;
void main(void)
{
portInit();
triac = 0;
unsigned char result;
adcInit();
while(1)
{
__delay_us(4);
ADCON0bits.GO = 1; //Start conversion
while (ADCON0bits.GO); //Wait for conversion done
result = ADRESH;
result = result << 8;
result = result |ADRESL;
}
}
And heres the ADC init function
void adcInit(void)
{
ADCON0bits.FM = 1; //right-justify
ADCON0bits.CS = 1; //ADCRC Clock
ADPCH = 0x00; //RA0 is Analog channel
ADCON0bits.ON = 1; //Turn ADC On
ADCON0bits.GO = 1; //Start conversion
}
You try to put an 12Bit result in an 8 Bit variable. Switch it to 16Bit.
uint16_t result;
Then you can combine the values:
result = ADRESH;
result = result << 8;
result = result |ADRESL;

How to resolve File not availabe

This is the code I am using for the encryption but it generate an error
"CCKeyDerivationPBKDF is unavailable" in AESKeyForPassword method though it is declare before implementation. How to Resolve it.
#ifndef _CC_PBKDF_H_
#define _CC_PBKDF_H_
#include <sys/types.h>
#include <sys/param.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include <Availability.h>
#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonHMAC.h>
#ifdef __cplusplus
extern "C" {
#endif
enum {
kCCPBKDF2 = 2,
};
typedef uint32_t CCPBKDFAlgorithm;
enum {
kCCPRFHmacAlgSHA1 = 1,
kCCPRFHmacAlgSHA224 = 2,
kCCPRFHmacAlgSHA256 = 3,
kCCPRFHmacAlgSHA384 = 4,
kCCPRFHmacAlgSHA512 = 5,
};
typedef uint32_t CCPseudoRandomAlgorithm;
/*
#function CCKeyDerivationPBKDF
#abstract Derive a key from a text password/passphrase
#param algorithm Currently only PBKDF2 is available via kCCPBKDF2
#param password The text password used as input to the derivation
function. The actual octets present in this string
will be used with no additional processing. It's
extremely important that the same encoding and
normalization be used each time this routine is
called if the same key is expected to be derived.
#param passwordLen The length of the text password in bytes.
#param salt The salt byte values used as input to the derivation
function.
#param saltLen The length of the salt in bytes.
#param prf The Pseudo Random Algorithm to use for the derivation
iterations.
#param rounds The number of rounds of the Pseudo Random Algorithm
to use.
#param derivedKey The resulting derived key produced by the function.
The space for this must be provided by the caller.
#param derivedKeyLen The expected length of the derived key in bytes.
#discussion The following values are used to designate the PRF:
* kCCPRFHmacAlgSHA1
* kCCPRFHmacAlgSHA224
* kCCPRFHmacAlgSHA256
* kCCPRFHmacAlgSHA384
* kCCPRFHmacAlgSHA512
#result kCCParamError can result from bad values for the password, salt,
and unwrapped key pointers as well as a bad value for the prf function.
*/
int CCKeyDerivationPBKDF( CCPBKDFAlgorithm algorithm, const char *password, size_t passwordLen,
const uint8_t *salt, size_t saltLen,
CCPseudoRandomAlgorithm prf, uint rounds,
uint8_t *derivedKey, size_t derivedKeyLen)
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
/*
* All lengths are in bytes - not bits.
*/
/*
#function CCCalibratePBKDF
#abstract Determine the number of PRF rounds to use for a specific delay on
the current platform.
#param algorithm Currently only PBKDF2 is available via kCCPBKDF2
#param passwordLen The length of the text password in bytes.
#param saltLen The length of the salt in bytes.
#param prf The Pseudo Random Algorithm to use for the derivation
iterations.
#param derivedKeyLen The expected length of the derived key in bytes.
#param msec The targetted duration we want to achieve for a key
derivation with these parameters.
#result the number of iterations to use for the desired processing time.
*/
uint CCCalibratePBKDF(CCPBKDFAlgorithm algorithm, size_t passwordLen, size_t saltLen,
CCPseudoRandomAlgorithm prf, size_t derivedKeyLen, uint32_t msec)
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
#ifdef __cplusplus
}
#endif
#endif /* _CC_PBKDF_H_ */
#import "AESEncryption.h"
#import <CommonCrypto/CommonCryptor.h>
//#import <CommonCrypto/CommonKeyDerivation.h>
//#import <CommonKeyDerivation.h>
#implementation AESEncryption
NSString * const
kRNCryptManagerErrorDomain = #"net.robnapier.RNCryptManager";
const CCAlgorithm kAlgorithm = kCCAlgorithmAES128;
const NSUInteger kAlgorithmKeySize = kCCKeySizeAES128;
const NSUInteger kAlgorithmBlockSize = kCCBlockSizeAES128;
const NSUInteger kAlgorithmIVSize = kCCBlockSizeAES128;
const NSUInteger kPBKDFSaltSize = 8;
const NSUInteger kPBKDFRounds = 1000;//0; // ~80ms on an iPhone 4
// ===================
+ (NSData *)encryptedDataForData:(NSData *)data
password:(NSString *)password
iv:(NSData **)iv
salt:(NSData **)salt
error:(NSError **)error {
NSAssert(iv, #"IV must not be NULL");
NSAssert(salt, #"salt must not be NULL");
*iv = [self randomDataOfLength:kAlgorithmIVSize];
*salt = [self randomDataOfLength:kPBKDFSaltSize];
NSData *key = [self AESKeyForPassword:password salt:*salt];
size_t outLength;
NSMutableData *
cipherData = [NSMutableData dataWithLength:data.length +
kAlgorithmBlockSize];
CCCryptorStatus
result = CCCrypt(kCCEncrypt, // operation
kAlgorithm, // Algorithm
kCCOptionPKCS7Padding, // options
key.bytes, // key
key.length, // keylength
(*iv).bytes,// iv
data.bytes, // dataIn
data.length, // dataInLength,
cipherData.mutableBytes, // dataOut
cipherData.length, // dataOutAvailable
&outLength); // dataOutMoved
if (result == kCCSuccess) {
cipherData.length = outLength;
}
else {
if (error) {
*error = [NSError errorWithDomain:kRNCryptManagerErrorDomain
code:result
userInfo:nil];
}
return nil;
}
return cipherData;
}
// ===================
+ (NSData *)randomDataOfLength:(size_t)length {
NSMutableData *data = [NSMutableData dataWithLength:length];
int result = SecRandomCopyBytes(kSecRandomDefault, length,data.mutableBytes);
NSLog(#"%d",result);
NSAssert1(result == 0, #"Unable to generate random bytes: %d", errno);
//NSAssert( #"Unable to generate random bytes: %d", errno);
return data;
}
// ===================
// Replace this with a 10,000 hash calls if you don't have CCKeyDerivationPBKDF
+ (NSData *)AESKeyForPassword:(NSString *)password
salt:(NSData *)salt {
NSMutableData *
derivedKey = [NSMutableData dataWithLength:kAlgorithmKeySize];
int result = CCKeyDerivationPBKDF(kCCPBKDF2, // algorithm
password.UTF8String, // password
password.length, // passwordLength
salt.bytes, // salt
salt.length, // saltLen
kCCPRFHmacAlgSHA1, // PRF
kPBKDFRounds, // rounds
derivedKey.mutableBytes, // derivedKey
derivedKey.length); // derivedKeyLen
NSLog(#"%d",result);
// Do not log password here
NSAssert1(result == kCCSuccess,#"Unable to create AES key for password: %d", result);
//NSAssert(#"Unable to create AES key for password: %d", result);
return derivedKey;
}
#end
The code placed above implementation is of CommonCrypto/CommonKeyDerivation.h which was not found be me xcode and hence I put code directly at the top.
Try to comment out this lines:
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
I think they limit the method to a particular Operating System and this is exactly what you don't need.
But I cannot guarantee if further issues may appear. I'm trying to achieve the same.
You have merely declared 2 prototypes for CCKeyDerivationPBKDF and CCCalibratePBKDF. Either put the full code for the functions at this place or declare them as extern and have them in a seperate module or library.

Use iconv API in C

I try to convert a sjis string to utf-8 using the iconv API. I compiled it already succesfully, but the output isn't what I expected.
My code:
void convertUtf8ToSjis(char* utf8, char* sjis){
iconv_t icd;
int index = 0;
char *p_src, *p_dst;
size_t n_src, n_dst;
icd = iconv_open("Shift_JIS", "UTF-8");
int c;
p_src = utf8;
p_dst = sjis;
n_src = strlen(utf8);
n_dst = 32; // my sjis string size
iconv(icd, &p_src, &n_src, &p_dst, &n_dst);
iconv_close(icd);
}
I got only random numbers. Any ideas?
Edit:
My input is
char utf8[] = "\xe4\xba\x9c"; //亜
And output should be:
0x88 0x9F
But is in fact:
0x30 0x00 0x00 0x31 0x00 ...
I was unable to duplicate the problem. The only thing I can suggest is to be careful about your allocations.
Code:
#include <iconv.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void convertUtf8ToSjis(char* utf8, char* sjis){
...
}
int main(int argc, char *argv[])
{
char utf8[] = "\xe4\xba\x9c";
char *sjis;
sjis = malloc(32);
convertUtf8ToSjis(utf8, sjis);
int i;
for (i = 0; sjis[i]; i++)
{
printf("%02x\n", (unsigned char)sjis[i]);
}
free(sjis);
}
Output:
$ gcc t.c
$ ./a.out
88
9f

If I have two instances of Glib::IOChannel, they block until both written. What is the correct way to do this?

I have modified the example found here to use two io channels. None of the callbacks seem to be called before I have written to both channels. After that they are called individually when writing to the fifos. Am I forgetting something?
Start the test program in one shell window.
Write echo "abc" > testfifo1 in second shell window. -> nothing happens.
Write echo "def" > testfifo2 in a third shell window. -> now I get "abc" and "def"
Write to one of the fifos. This is immediately served.
Edit:
The solution, as hinted by Gormley below, was the lack of nonblock.
read_fd1 = open("testfifo1", O_RDONLY | O_NONBLOCK);
...
read_fd2 = open("testfifo2", O_RDONLY | O_NONBLOCK);
This change to the code below made it respond immediately.
The code:
#include <gtkmm/main.h>
#include <fcntl.h>
#include <iostream>
int read_fd1, read_fd2;
Glib::RefPtr<Glib::IOChannel> iochannel1, iochannel2;
// Usage: "echo "Hello" > testfifo<1|2>", quit with "Q"
bool MyCallback1(Glib::IOCondition io_condition)
{
Glib::ustring buf;
iochannel1->read_line(buf);
std::cout << "io 1: " << buf;
if (buf == "Q\n")
Gtk::Main::quit();
return true;
}
bool MyCallback2(Glib::IOCondition io_condition)
{
Glib::ustring buf;
iochannel2->read_line(buf);
std::cout << "io 2: " << buf;
if (buf == "Q\n")
Gtk::Main::quit();
return true;
}
int main(int argc, char *argv[])
{
// the usual Gtk::Main object
Gtk::Main app(argc, argv);
if (access("testfifo1", F_OK) == -1)
{
if (mkfifo("testfifo1", 0666) != 0)
return -1;
}
if (access("testfifo2", F_OK) == -1)
{
if (mkfifo("testfifo2", 0666) != 0)
return -1;
}
read_fd1 = open("testfifo1", O_RDONLY);
if (read_fd1 == -1)
return -1;
read_fd2 = open("testfifo2", O_RDONLY);
if (read_fd2 == -1)
return -1;
Glib::signal_io().connect(sigc::ptr_fun(MyCallback1), read_fd1, Glib::IO_IN);
Glib::signal_io().connect(sigc::ptr_fun(MyCallback2), read_fd2, Glib::IO_IN);
iochannel1 = Glib::IOChannel::create_from_fd(read_fd1);
iochannel2 = Glib::IOChannel::create_from_fd(read_fd2);
app.run();
if (unlink("testfifo1"))
std::cerr << "error removing fifo 1" << std::endl;
if (unlink("testfifo2"))
std::cerr << "error removing fifo 2" << std::endl;
return 0;
}
These two statements block the program from getting into the main loop until both fifos
are open for write. fifos block until both sides are connected
iochannel1 = Glib::IOChannel::create_from_fd(read_fd1);
iochannel2 = Glib::IOChannel::create_from_fd(read_fd2);