how to use collect-view in Cooja in my own application - contiki

i have a question about collect-view. Can collect-view be used in other applications? i simulate some applications by cooja, and want to collect information about network,such as network map,ETX and so on. how can i use collect-view to collect information about my own applications?
thanks!

In the apps/collect-view or in your application you can add your own information to be sent by collect by redefining collect_view_arch_read_sensors, check for example how it is done for the Z1 mote in the collect-view-z1.c:
#include "collect-view.h"
#include "cc2420.h"
#include "dev/leds.h"
#include "dev/i2cmaster.h"
#include "dev/tmp102.h"
#include "collect-view-z1.h"
/*---------------------------------------------------------------------------*/
static uint16_t
get_temp()
{
/* XXX Fix me: check /examples/z1/test-tmp102.c for correct conversion */
return (uint16_t)tmp102_read_temp_raw();
}
/*---------------------------------------------------------------------------*/
void
collect_view_arch_read_sensors(struct collect_view_data_msg *msg)
{
static int initialized = 0;
if(!initialized) {
tmp102_init();
initialized = 1;
}
msg->sensors[BATTERY_VOLTAGE_SENSOR] = 0;
msg->sensors[BATTERY_INDICATOR] = 0;
msg->sensors[LIGHT1_SENSOR] = 0;
msg->sensors[LIGHT2_SENSOR] = 0;
msg->sensors[TEMP_SENSOR] = get_temp();
msg->sensors[HUMIDITY_SENSOR] = 0;
}
Notice that collect_view_arch_read_sensors(msg); is called by collect-view.c when you call collect_view_construct_message(...) from your application. This is how it is done in the examples/ipv6/rpl-collect/udp-sender.c example:
/* Collect structure */
struct {
uint8_t seqno;
uint8_t for_alignment;
struct collect_view_data_msg msg;
} msg;
/* Create the collect structure */
collect_view_construct_message(&msg.msg, &parent,
parent_etx, rtmetric,
num_neighbors, beacon_interval);
/* Send over UDP */
uip_udp_packet_sendto(client_conn, &msg, sizeof(msg),
&server_ipaddr, UIP_HTONS(UDP_SERVER_PORT));

When contiki calls the Call back function, for example the recv() function in rime-protocol, The sink node should use printf() to print out the sensor data. This output then will be read by Collect View GUI per-line.
take a look at
tools/collect-view/src/org/contikios/contiki/collect/CollectServer.java
The handleIncomingData() called by serialData(), then checks if it's a sensor data or not in SensorData.parseSensorData().
It will ignore if empty, incorrect format, comment, or annotation
sensor data will be displayed in Collect View GUI if meets some condition. for example, the data length calculated match with datalen implisit on its sensor data.

Related

Writing to the serial monitor on the Sparkfun ESP8266 Thing

Below is my current code:
#include <Wire.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "836addccd2ee4f05b96f0f3ad831249e"; // ***Type in your Blynk Token
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "_Fast&Furious";// ***your wifi name
char pass[] = "Mclaren2018";// ***and password
const int MOTION_PIN = 4; // Pin connected to motion detector
WidgetLCD lcd(V1);
void setup()
{
Serial.begin(115200);
Blynk.begin(auth, ssid, pass);
pinMode(MOTION_PIN, INPUT_PULLUP);
Serial.println("SETUP");
}
void loop()
{
Blynk.run();
int proximity = digitalRead(MOTION_PIN);
if (proximity == LOW) // If the sensor's output goes low, motion is detected
{
Blynk.virtualWrite(5,1023);
lcd.clear();
lcd.print(0,0,"Motion detected");
Serial.println("Motion detected!");
}
else
{
Blynk.virtualWrite(5,0);
lcd.clear();
lcd.print(0,0,"Motion NOT detected");
Serial.println("Motion NOT detected!");
}
}
I am currently trying to simily write some text to the serial console. But when I upload my code it will just write a string of k's to the console. What am I doing wrong to produce such a strange output?
This is a link to the tutorial I have been following: http://designinformaticslab.github.io/productdesign_tutorial/2017/01/24/motion_sensor.html
Any help would be much appreciated!
It all looks good to me, are you sure you have the baud rate set correctly on the serial monitor? I would write a new program real quick that ONLY does serial output and get that working (this simplifies the problem to solve, and makes it more obvious if it is something like serial port speed), then go back to your more complete program and it should work.

arduino programming: not enough memory message

I am new to arduino programming (Arduino Pro Mini 3.3v version), i have some code like below. I am connecting 9DOF, OLED screen and a BLE breakout to arduino pro mini.
I already went through some of the memory optimization tips, but i still have some issue. Even with the following code, i only have 9 bytes left for dynamic memory. If i enable BTLEserial.begin();, it will kill the memory. Please any suggestions will be appreciated.
#include <Wire.h>
#include <SPI.h>
#include <SparkFunLSM9DS1.h>
#include "Adafruit_BLE_UART.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
LSM9DS1 imu;
#define LSM9DS1_M 0x1E // Would be 0x1C if SDO_M is LOW
#define LSM9DS1_AG 0x6B // Would be 0x6A if SDO_AG is LOW
#define ADAFRUITBLE_REQ 10
#define ADAFRUITBLE_RDY 2
#define ADAFRUITBLE_RST 9
Adafruit_BLE_UART BTLEserial = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);
void setup(void) {
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC, 0x3D); // initialize with the I2C addr 0x3D (for the 128x64)
display.display();
delay(2000);
display.clearDisplay();
display.drawPixel(10, 10, WHITE);
display.display();
delay(2000);
display.clearDisplay();
imu.settings.device.commInterface = IMU_MODE_I2C;
imu.settings.device.mAddress = LSM9DS1_M;
imu.settings.device.agAddress = LSM9DS1_AG;
if (!imu.begin())
{
while (1)
;
}
// BTLEserial.begin(); - if i uncomment this code, i will get a not enough memory error.
}
aci_evt_opcode_t laststatus = ACI_EVT_DISCONNECTED;
void loop() {
displayAllDOF();
}
void displayAllDOF(){
display.setTextSize(1);
display.setTextColor(WHITE);
imu.readGyro();
display.setCursor(0,0);
display.print("G:");
display.print(imu.calcGyro(imu.gx));
display.print(", ");
display.print(imu.calcGyro(imu.gy));
display.print(", ");
display.print(imu.calcGyro(imu.gz));
display.println(" ");
imu.readAccel();
display.print("A:");
display.print(imu.calcAccel(imu.ax));
display.print(", ");
display.print(imu.calcAccel(imu.ay));
display.print(", ");
display.print(imu.calcAccel(imu.az));
display.println(" ");
imu.readMag();
display.print("M:");
display.print(imu.calcMag(imu.mx));
display.print(", ");
display.print(imu.calcMag(imu.my));
display.print(", ");
display.print(imu.calcMag(imu.mz));
display.println(" ");
display.display();
display.clearDisplay();
}
To start, you'll need to figure out where your RAM is going - How much does each library take? Do you really need to run them all at the same time? You know that you can run the display library, and the IMU code in your current setup - Can you implement something that only enables the IMU code, pulls data, then disables it? And the same with the display and BTLE code? That way each library is only consuming RAM when it's needed, and frees it once it's operation is finished
Update 1
An example of what I mentioned above. I do not know if all the libraries implement the .end() function. They may have a similar method you can use.
// Simple data storage for the .gx and .gy values
typedef struct {
float x, y;
} GyroData_t;
GyroData_t getImuData() {
GyroData_t data;
// Create the IMU class, gather data from it, and then destroy it
LSM9DS1 *imu = new LSM9DS1();
imu->begin();
imu->readGyro();
data.x = imu.gx;
data.y = imu.gy;
imu->end();
// This will reclaim the RAM that was used by the IMU - We no longer need it
delete imu;
return data;
}
void displayAllDOF() {
// Gather the IMU data
GyroData_t data = getImuData();
// Create the display object, and print the data we received
Adafruit_SSD1306 *display = new Adafruit_SSD1306(OLED_RESET);
display->print(...);
....
display->end();
// Reclaim the display RAM used
delete display;
// Do any bluetooth operations now
doBluetoothStuff();
}
void doBluetoothStuff() {
Adafruit_BLE_UART *BTLEserial = new Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);
BTLESerial->begin();
...
BTLESerial->end();
delete BTLESerial;
}

Creating topology with routers in ns-3

I am trying to create a very simple topology containing a server and client connected via a router. The following code I got through a GUI. I am trying to run it but it throws me a long error I am new to ns-3, so kindly bear with me.
#include "ns3/simulator-module.h"
#include "ns3/node-module.h"
#include "ns3/core-module.h"
#include "ns3/common-module.h"
#include "ns3/global-route-manager.h"
#include "ns3/helper-module.h"
#include "ns3/bridge-module.h"
using namespace ns3;
int main(int argc, char *argv[])
{
CommandLine cmd;
cmd.Parse (argc, argv);
/* Configuration. */
/* Build nodes. */
NodeContainer term_0;
term_0.Create (1);
NodeContainer term_1;
term_1.Create (1);
NodeContainer router_0;
router_0.Create (1);
/* Build link. */
CsmaHelper csma_hub_0;
csma_hub_0.SetChannelAttribute ("DataRate", DataRateValue (100000000));
csma_hub_0.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (10000)));
CsmaHelper csma_hub_1;
csma_hub_1.SetChannelAttribute ("DataRate", DataRateValue (100000000));
csma_hub_1.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (10000)));
/* Build link net device container. */
NodeContainer all_hub_0;
all_hub_0.Add (router_0);
all_hub_0.Add (term_0);
NetDeviceContainer ndc_hub_0 = csma_hub_0.Install (all_hub_0);
NodeContainer all_hub_1;
all_hub_1.Add (router_0);
all_hub_1.Add (term_1);
NetDeviceContainer ndc_hub_1 = csma_hub_1.Install (all_hub_1);
/* Install the IP stack. */
InternetStackHelper internetStackH;
internetStackH.Install (term_0);
internetStackH.Install (term_1);
internetStackH.Install (router_0);
/* IP assign. */
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.0.0.0", "255.255.255.0");
Ipv4InterfaceContainer iface_ndc_hub_0 = ipv4.Assign (ndc_hub_0);
ipv4.SetBase ("10.0.1.0", "255.255.255.0");
Ipv4InterfaceContainer iface_ndc_hub_1 = ipv4.Assign (ndc_hub_1);
/* Generate Route. */
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
/* Generate Application. */
uint16_t port_udpEcho_0 = 9;
UdpEchoServerHelper server_udpEcho_0 (port_udpEcho_0);
ApplicationContainer apps_udpEcho_0 = server_udpEcho_0.Install (term_1.Get(0));
apps_udpEcho_0.Start (Seconds (0.0));
apps_udpEcho_0.Stop (Seconds (2.0));
Time interPacketInterval_udpEcho_0 = Seconds (1.0);
UdpEchoClientHelper client_udpEcho_0 (iface_ndc_hub_1.GetAddress(1), 9);
client_udpEcho_0.SetAttribute ("MaxPackets", UintegerValue (1));
client_udpEcho_0.SetAttribute ("Interval", TimeValue (interPacketInterval_udpEcho_0));
client_udpEcho_0.SetAttribute ("PacketSize", UintegerValue (1024));
apps_udpEcho_0 = client_udpEcho_0.Install (term_0.Get (0));
apps_udpEcho_0.Start (Seconds (0.1));
apps_udpEcho_0.Stop (Seconds (2.0));
/* Simulation. */
/* Pcap output. */
/* Stop the simulation after x seconds. */
uint32_t stopTime = 3;
Simulator::Stop (Seconds (stopTime));
/* Start and clean simulation. */
Simulator::Run ();
Simulator::Destroy ();
}
If you are new, you should start your program by looking the examples already provided by ns-3. Like this: https://www.nsnam.org/doxygen/simple-routing-ping6_8cc_source.html. Looking the network topology, it is what you want.
Trying to run your code, I had to change a lot of headers to make it compile (maybe different versions, given the time - or your GUI is outdated). Remove yours and put these:
#include "ns3/core-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/csma-helper.h"
And finally, you'd printed nothing, so I am not sure of what you were trying to do. As you are using, UdpEchoClientHelper and UdpEchoServerHelper, I would recommend to enable their logs. You can do this with these two lines:
/* Configuration. */
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
I am new too and I do not know what you are trying to do. So I will stop my answer here. Good luck.

Why is RB interrupt routine running twice?

I have some code below that has a slight bug that I don't know how to fix. Essentially what is happening is my high ISR is running twice after the the flag is set. It only runs twice and is consistent. The subroutine should run only once because the flag is set when the input on RB changes, and the routine runs twice after one change to RB's input. The testing was conducted in MPLAB v8.6 using the workbook feature.
#include <p18f4550.h>
#include <stdio.h>
void init(void)
{
RCONbits.IPEN =1; //allows priority
INTCONbits.GIE = 1; //allows interrupts
INTCONbits.PEIE = 1; //allows peripheral interrupts
INTCONbits.RBIF = 0; //sets flag to not on
INTCONbits.RBIE = 1; //enables RB interrupts
INTCON2bits.RBPU = 1; //enable pull up resistors
INTCON2bits.RBIP = 1; //RB interrupts is high priority
PORTB = 0x00;
TRISBbits.RB7 = 1; //enable RB7 as an input so we can throw interrupts when it changes.
}
#pragma code
#pragma interrupt high_isr
void high_isr(void)
{
if(INTCONbits.RBIF == 1)
{
INTCONbits.RBIF = 0;
//stuff
}
}
#pragma code
#pragma code high_isr_entry = 0x08
void high_isr_entry(void)
{_asm goto high_isr _endasm}
void main(void)
{
init();
while(1);
}
The RB7 interrupt flag is set based on a compare of the last latched value and the current state of the pin. In the datasheet it says "The pins are compared with the old value latched on the last read of PORTB. The 'mismatch' outputs of RB7:RB4 are ORed together to generate the RB Port Change Interrupt with Flag bit."
To clear the mismatch condition the datasheet goes on to say "Any read or write of PORTB (except with the
MOVFF (ANY), PORTB instruction). This will end the mismatch condition."
You then wait one Tcy (execute a nop instruction) and then clear the flag. This is documented on page 116 of the datasheet.
So the simplest fix in this scenario is in the interrupt routine declare a dummy variable and set it to RB7 like this:
#pragma interrupt high_isr
void high_isr(void)
{
unsigned short dummy;
if(INTCONbits.RBIF == 1)
{
dummy = PORTBbits.RB7; // Perform read before clearing flag
Nop();
INTCONbits.RBIF = 0;
// rest of your routine here
// ...

Changing DCT coefficients

I decided to use libjpeg as the main library working with jpeg files.
I've read libjpg.txt file. And I was pleased that library allows DCT coefficients reading/writing in a convenient way. Since writing an own decoder will take a long time.
My work is related to the lossless embedding. Currently I need to read DCT coefficients from a file then modify some of them and write changed coefficients in the same file.
Well, I found jpeg_write_coefficients() function. And I naively thought that I could apply it to a decompression object (struct jpeg_decompress_struct). But it does not work and requires a compression object.
I can't believe that such the powerful library is not able to do this.
I think that most likely I'm missing something. Although I tried to be attentive.
Perhaps the writing coefficients can be done more sophisticated way.
But I don't know how to.
I will be very glad if you propose your ideas.
You can ue jpeg_write_coefficients to write your changed DCT.
The following information is avaliable in libjpeg.txt
To write the contents of a JPEG file as DCT coefficients, you must provide
the DCT coefficients stored in virtual block arrays. You can either pass
block arrays read from an input JPEG file by jpeg_read_coefficients(), or
allocate virtual arrays from the JPEG compression object and fill them
yourself. In either case, jpeg_write_coefficients() is substituted for
jpeg_start_compress() and jpeg_write_scanlines(). Thus the sequence is
* Create compression object
* Set all compression parameters as necessary
* Request virtual arrays if needed
* jpeg_write_coefficients()
* jpeg_finish_compress()
* Destroy or re-use compression object
jpeg_write_coefficients() is passed a pointer to an array of virtual block
array descriptors; the number of arrays is equal to cinfo.num_components.
The virtual arrays need only have been requested, not realized, before
jpeg_write_coefficients() is called. A side-effect of
jpeg_write_coefficients() is to realize any virtual arrays that have been
requested from the compression object's memory manager. Thus, when obtaining
the virtual arrays from the compression object, you should fill the arrays
after calling jpeg_write_coefficients(). The data is actually written out
when you call jpeg_finish_compress(); jpeg_write_coefficients() only writes
the file header.
When writing raw DCT coefficients, it is crucial that the JPEG quantization
tables and sampling factors match the way the data was encoded, or the
resulting file will be invalid. For transcoding from an existing JPEG file,
we recommend using jpeg_copy_critical_parameters(). This routine initializes
all the compression parameters to default values (like jpeg_set_defaults()),
then copies the critical information from a source decompression object.
The decompression object should have just been used to read the entire
JPEG input file --- that is, it should be awaiting jpeg_finish_decompress().
jpeg_write_coefficients() marks all tables stored in the compression object
as needing to be written to the output file (thus, it acts like
jpeg_start_compress(cinfo, TRUE)). This is for safety's sake, to avoid
emitting abbreviated JPEG files by accident. If you really want to emit an
abbreviated JPEG file, call jpeg_suppress_tables(), or set the tables'
individual sent_table flags, between calling jpeg_write_coefficients() and
jpeg_finish_compress().
So to change a single dct, you can use the following simple code:
To access any dct coeff, you need to change four index, cx, bx, by, bi.
In my code, I used blockptr_one[bi]++; to increase one dct Coeff
#include <stdio.h>
#include <jpeglib.h>
#include <stdlib.h>
#include <iostream>
#include <string>
int write_jpeg_file(std::string outname,jpeg_decompress_struct in_cinfo, jvirt_barray_ptr *coeffs_array ){
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE * infile;
if ((infile = fopen(outname.c_str(), "wb")) == NULL) {
fprintf(stderr, "can't open %s\n", outname.c_str());
return 0;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, infile);
j_compress_ptr cinfo_ptr = &cinfo;
jpeg_copy_critical_parameters((j_decompress_ptr)&in_cinfo,cinfo_ptr);
jpeg_write_coefficients(cinfo_ptr, coeffs_array);
jpeg_finish_compress( &cinfo );
jpeg_destroy_compress( &cinfo );
fclose( infile );
return 1;
}
int read_jpeg_file( std::string filename, std::string outname )
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE * infile;
if ((infile = fopen(filename.c_str(), "rb")) == NULL) {
fprintf(stderr, "can't open %s\n", filename.c_str());
return 0;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
(void) jpeg_read_header(&cinfo, TRUE);
jvirt_barray_ptr *coeffs_array = jpeg_read_coefficients(&cinfo);
//change one dct:
int ci = 0; // between 0 and number of image component
int by = 0; // between 0 and compptr_one->height_in_blocks
int bx = 0; // between 0 and compptr_one->width_in_blocks
int bi = 0; // between 0 and 64 (8x8)
JBLOCKARRAY buffer_one;
JCOEFPTR blockptr_one;
jpeg_component_info* compptr_one;
compptr_one = cinfo.comp_info + ci;
buffer_one = (cinfo.mem->access_virt_barray)((j_common_ptr)&cinfo, coeffs_array[ci], by, (JDIMENSION)1, FALSE);
blockptr_one = buffer_one[0][bx];
blockptr_one[bi]++;
write_jpeg_file(outname, cinfo, coeffs_array);
jpeg_finish_decompress( &cinfo );
jpeg_destroy_decompress( &cinfo );
fclose( infile );
return 1;
}
int main()
{
std::string infilename = "you_image.jpg", outfilename = "out_image.jpg";
/* Try opening a jpeg*/
if( read_jpeg_file( infilename, outfilename ) > 0 )
{
std::cout << "It's Okay..." << std::endl;
}
else return -1;
return 0;
}
You should really take a look at transupp.h and sources for jpegtran that comes with the library.
Anyway, here is my dirty code with comments, assembled partially from jpegtran. It lets you manipulate DCT coefficients one by one.
#include "jpeglib.h" /* Common decls for cjpeg/djpeg applications */
#include "transupp.h" /* Support routines for jpegtran */
struct jpeg_decompress_struct srcinfo;
struct jpeg_compress_struct dstinfo;
struct jpeg_error_mgr jsrcerr, jdsterr;
static jpeg_transform_info transformoption; /* image transformation options */
transformoption.transform = JXFORM_NONE;
transformoption.trim = FALSE;
transformoption.force_grayscale = FALSE;
jvirt_barray_ptr * src_coef_arrays;
jvirt_barray_ptr * dst_coef_arrays;
/* Initialize the JPEG decompression object with default error handling. */
srcinfo.err = jpeg_std_error(&jsrcerr);
jpeg_create_decompress(&srcinfo);
/* Initialize the JPEG compression object with default error handling. */
dstinfo.err = jpeg_std_error(&jdsterr);
jpeg_create_compress(&dstinfo);
FILE *fp;
if((fp = fopen(filePath], "rb")) == NULL) {
//Throw an error
} else {
//Continue
}
/* Specify data source for decompression */
jpeg_stdio_src(&srcinfo, fp);
/* Enable saving of extra markers that we want to copy */
jcopy_markers_setup(&srcinfo, JCOPYOPT_ALL);
/* Read file header */
(void) jpeg_read_header(&srcinfo, TRUE);
jtransform_request_workspace(&srcinfo, &transformoption);
src_coef_arrays = jpeg_read_coefficients(&srcinfo);
jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
/* Do your DCT shenanigans here on src_coef_arrays like this (I've moved it into a separate function): */
moveDCTAround(&srcinfo, &dstinfo, 0, src_coef_arrays);
/* ..when done with DCT, do this: */
dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo, src_coef_arrays, &transformoption);
fclose(fp);
//And write everything back
fp = fopen(filePath, "wb");
/* Specify data destination for compression */
jpeg_stdio_dest(&dstinfo, fp);
/* Start compressor (note no image data is actually written here) */
jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
/* Copy to the output file any extra markers that we want to preserve */
jcopy_markers_execute(&srcinfo, &dstinfo, JCOPYOPT_ALL);
jpeg_finish_compress(&dstinfo);
jpeg_destroy_compress(&dstinfo);
(void) jpeg_finish_decompress(&srcinfo);
jpeg_destroy_decompress(&srcinfo);
fclose(fp);
And the function itself:
void moveDCTAround (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays)
{
size_t block_row_size;
JBLOCKARRAY coef_buffers[MAX_COMPONENTS];
JBLOCKARRAY row_ptrs[MAX_COMPONENTS];
//Allocate DCT array buffers
for (JDIMENSION compnum=0; compnum<srcinfo->num_components; compnum++)
{
coef_buffers[compnum] = (dstinfo->mem->alloc_barray)((j_common_ptr) dstinfo, JPOOL_IMAGE, srcinfo->comp_info[compnum].width_in_blocks,
srcinfo->comp_info[compnum].height_in_blocks);
}
//For each component,
for (JDIMENSION compnum=0; compnum<srcinfo->num_components; compnum++)
{
block_row_size = (size_t) sizeof(JCOEF)*DCTSIZE2*srcinfo->comp_info[compnum].width_in_blocks;
//...iterate over rows,
for (JDIMENSION rownum=0; rownum<srcinfo->comp_info[compnum].height_in_blocks; rownum++)
{
row_ptrs[compnum] = ((dstinfo)->mem->access_virt_barray)((j_common_ptr) &dstinfo, src_coef_arrays[compnum], rownum, (JDIMENSION) 1, FALSE);
//...and for each block in a row,
for (JDIMENSION blocknum=0; blocknum<srcinfo->comp_info[compnum].width_in_blocks; blocknum++)
//...iterate over DCT coefficients
for (JDIMENSION i=0; i<DCTSIZE2; i++)
{
//Manipulate your DCT coefficients here. For instance, the code here inverts the image.
coef_buffers[compnum][rownum][blocknum][i] = -row_ptrs[compnum][0][blocknum][i];
}
}
}
//Save the changes
//For each component,
for (JDIMENSION compnum=0; compnum<srcinfo->num_components; compnum++)
{
block_row_size = (size_t) sizeof(JCOEF)*DCTSIZE2 * srcinfo->comp_info[compnum].width_in_blocks;
//...iterate over rows
for (JDIMENSION rownum=0; rownum < srcinfo->comp_info[compnum].height_in_blocks; rownum++)
{
//Copy the whole rows
row_ptrs[compnum] = (dstinfo->mem->access_virt_barray)((j_common_ptr) dstinfo, src_coef_arrays[compnum], rownum, (JDIMENSION) 1, TRUE);
memcpy(row_ptrs[compnum][0][0], coef_buffers[compnum][rownum][0], block_row_size);
}
}

Resources