I have created a custom double point-type for storing the point position in the PCD file. I required the double data type since my points are in global coordinates and have very large values (of order 10^6 to 10^7) and require good precision. Since the values are large and the default FLOAT32 precision is limited, there is considerable data approximation which is also visible during visualization.
I created this PCD by transforming the raw pointcloud with the initial global reference coordinate from GPS in the data bag that I have. I am using a 15 point precision.
I created a separate script for visualizing this custom point-type PCD. But by visually comparing, I cannot see any considerable difference between the FLOAT32 and double data-type PCD's.
Raw_float_pcd_visualization
Transformed_float_pcd_visualization
Transformed_double_pcd_visualization
You can see that the transformed_double and transformed_float PCD's are quite similar and approximated. While the raw_float PCD is quite good as compared to these two.
I am attaching the PCD files for reference:
raw_float
transformed_float
transformed_double
I think that I am skipping some things while loading the pointcloud and there are some more changes that need to be done in order to visualize the points with double point precision.
I used "pcl_viewer" from pcl_tools for visualizing FLOAT type PCD's.
Code for visualizaing custom DOUBLE point-structure PCD:
#define PCL_NO_PRECOMPILE
#include <iostream>
// #include "double_viz/pcl_double.h"
#include <pcl-1.7/pcl/common/common.h>
#include <pcl-1.7/pcl/io/pcd_io.h>
#include <pcl-1.7/pcl/visualization/pcl_visualizer.h>
#include <pcl-1.7/pcl/console/parse.h>
#include <pcl-1.7/pcl/point_cloud.h>
#include <pcl-1.7/pcl/point_types.h>
namespace pcl
{
#define PCL_ADD_UNION_POINT4D_DOUBLE \
union EIGEN_ALIGN16 { \
double data[4]; \
struct { \
double x; \
double y; \
double z; \
}; \
};
struct _PointXYZDouble
{
PCL_ADD_UNION_POINT4D_DOUBLE; // This adds the members x,y,z which can also be accessed using the point (which is float[4])
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
struct EIGEN_ALIGN16 PointXYZDouble : public _PointXYZDouble
{
inline PointXYZDouble (const _PointXYZDouble &p)
{
x = p.x; y = p.y; z = p.z; data[3] = 1.0;
}
inline PointXYZDouble ()
{
x = y = z = 0.0;
data[3] = 1.0;
}
inline PointXYZDouble (double _x, double _y, double _z)
{
x = _x; y = _y; z = _z;
data[3] = 1.0;
}
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
}
POINT_CLOUD_REGISTER_POINT_STRUCT (pcl::_PointXYZDouble,
(double, x, x)
(double, y, y)
(double, z, z)
)
POINT_CLOUD_REGISTER_POINT_WRAPPER(pcl::PointXYZDouble, pcl::_PointXYZDouble)
// This function displays the help
void
showHelp(char * program_name)
{
std::cout << std::endl;
std::cout << "Usage: " << program_name << " cloud_filename.[pcd]" << std::endl;
std::cout << "-h: Show this help." << std::endl;
}
// This is the main function
int
main (int argc, char** argv)
{
// Show help
if (pcl::console::find_switch (argc, argv, "-h") || pcl::console::find_switch (argc, argv, "--help"))
{
showHelp (argv[0]);
return 0;
}
// Fetch point cloud filename in arguments | Works with PCD
std::vector<int> filenames;
if (filenames.size () != 1)
{
filenames = pcl::console::parse_file_extension_argument (argc, argv, ".pcd");
if (filenames.size () != 1)
{
showHelp (argv[0]);
return -1;
}
}
// Load file | Works with PCD and PLY files
pcl::PointCloud<pcl::PointXYZDouble>::Ptr source_cloud (new pcl::PointCloud<pcl::PointXYZDouble> ());
if (pcl::io::loadPCDFile (argv[filenames[0]], *source_cloud) < 0)
{
std::cout << "Error loading point cloud " << argv[filenames[0]] << std::endl << std::endl;
showHelp (argv[0]);
return -1;
}
// Visualization
// printf( "\nPoint cloud colors : white = original point cloud\n"
// " red = transformed point cloud\n");
pcl::visualization::PCLVisualizer viewer ("Visualize double PCL");
// Define R,G,B colors for the point cloud
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZDouble> source_cloud_color_handler (source_cloud, 100, 100, 100);
// We add the point cloud to the viewer and pass the color handler
viewer.addPointCloud (source_cloud, source_cloud_color_handler, "original_cloud");
viewer.addCoordinateSystem (1.0, "cloud", 0);
viewer.setBackgroundColor(0.05, 0.05, 0.05, 0); // Setting background to a dark grey
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 1, "original_cloud");
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "original_cloud");
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, 1, "original_cloud");
//viewer.setPosition(800, 400); // Setting visualiser window position
while (!viewer.wasStopped ()) // Display the visualiser until 'q' key is pressed
{
viewer.spinOnce ();
}
return 0;
}
In the raw_float file, the size field has been defined as 4 bytes each: SIZE 4 4 4 4,
to be read as double it should be SIZE 8 8 8 8.
With your current implementation each field is being read as Float32
By default, printf() seems to align strings to the right.
printf("%10s %20s %20s\n", "col1", "col2", "col3");
/* col1 col2 col3 */
I can also align text to the left like this:
printf("%-10s %-20s %-20s", "col1", "col2", "col3");
Is there a quick way to center text? Or do I have to write a function that turns a string like test into (space)(space)test(space)(space) if the text width for that column is 8?
printf by itself can't do the trick, but you could play with the "indirect" width, which specifies the width by reading it from an argument. Lets' try this (ok, not perfect)
void f(char *s)
{
printf("---%*s%*s---\n",10+strlen(s)/2,s,10-strlen(s)/2,"");
}
int main(int argc, char **argv)
{
f("uno");
f("quattro");
return 0;
}
#GiuseppeGuerrini's was helpful, by suggesting how to use print format specifiers and dividing the whitespace. Unfortunately, it can truncate text.
The following solves the problem of truncation (assuming the field specified is actually large enough to hold the text).
void centerText(char *text, int fieldWidth) {
int padlen = (fieldWidth - strlen(text)) / 2;
printf("%*s%s%*s\n", padLen, "", text, padlen, "");
}
There is no printf() format specifier to centre text.
You will need to write your own function or locate a library which provides the functionality that you're looking for.
You may try write own function for this problem.
/**
* Returns a sting "str" centered in string of a length width "new_length".
* Padding is done using the specified fill character "placeholder".
*/
char *
str_center(char str[], unsigned int new_length, char placeholder)
{
size_t str_length = strlen(str);
// if a new length is less or equal length of the original string, returns the original string
if (new_length <= str_length)
return str;
char *buffer;
unsigned int i, total_rest_length;
buffer = malloc(sizeof(char) * new_length);
// length of a wrapper of the original string
total_rest_length = new_length - str_length;
// write a prefix to buffer
i = 0;
while (i < (total_rest_length / 2)) {
buffer[i] = placeholder;
++i;
}
buffer[i + 1] = '\0';
// write the original string
strcat(buffer, str);
// write a postfix to the buffer
i += str_length;
while (i < new_length) {
buffer[i] = placeholder;
++i;
}
buffer[i + 1] = '\0';
return buffer;
}
Results:
puts(str_center("A", 0, '-')); // A
puts(str_center("A", 1, '-')); // A
puts(str_center("A", 10, '-')); // ----A-----
puts(str_center("text", 10, '*')); // ***text***
puts(str_center("The C programming language", 26, '!')); // The C programming language
puts(str_center("The C programming language", 27, '!')); // The C programming language!
puts(str_center("The C programming language", 28, '!')); // !The C programming language!
puts(str_center("The C programming language", 29, '!')); // !The C programming language!!
puts(str_center("The C programming language", 30, '!')); // !!The C programming language!!
puts(str_center("The C programming language", 31, '!')); // !!The C programming language!!!
Ill drop my 2 cents after dealing with similar issue of trying to center a table headers in a row with printf.
The following macros will need to be printed before/after the text and will align regardless of the length of the text itself.
Notice that if we have odd length strings, we will not align as should(because the normal devision will result in missing space).
Therefor a round up is needed, and I think this is the elegant way to solve that issue:
#define CALC_CENTER_POSITION_PREV(WIDTH, STR) (((WIDTH + ((int)strlen(STR))) % 2) \
? ((WIDTH + ((int)strlen(STR)) + 1)/2) : ((WIDTH + ((int)strlen(STR)))/2))
#define CALC_CENTER_POSITION_POST(WIDTH, STR) (((WIDTH - ((int)strlen(STR))) % 2) \
? ((WIDTH - ((int)strlen(STR)) - 1)/2) : ((WIDTH - ((int)strlen(STR)))/2))
Usage example:
printf("%*s%*s" , CALC_CENTER_POSITION_PREV(MY_COLUMN_WIDTH, "Header")
, "Header"
, CALC_CENTER_POSITION_POST(MY_COLUMN_WIDTH, "Header"), "");
There are two solutions, the first is similar to the above, by placing macros in printf, and the second is a custom macro, which calculates the length of the formatted string in advance through snprintf, and then calls the printf function to output.
#include <stdio.h>
#include <string.h>
#define LEFT(str, w) \
({int m = w + strlen(str); m % 2 ? (m + 1) / 2 : m / 2;})
#define RIGHT(str, w) \
({ int m = w - strlen(str); m % 2 ? (m - 1) / 2 : m / 2; })
#define STR_CENTER(str, width) \
LEFT(str, width), str, RIGHT(str, width), ""
#define PRINTF_CENTER(width, start, fmt, end, ...) ({ \
int n = snprintf(NULL, 0, fmt, __VA_ARGS__); \
int m = width - n; \
int left = m % 2 ? (m + 1) / 2 : m / 2; \
int right = m % 2 ? (m - 1) / 2 : m / 2; \
printf(start "%*s" fmt "%*s" end, left, "", \
__VA_ARGS__, right, ""); \
})
#define MYFORMAT_CENTER(width, fmt, ...) \
PRINTF_CENTER(40, "[", fmt , "]\n", __VA_ARGS__)
int main(int argc, char const *argv[])
{
printf("%*s%*s\n\n", STR_CENTER("--- Hello World ---", 40));
printf("[%*s%*s]\n", STR_CENTER("I am okay today", 40));
MYFORMAT_CENTER(40, "%d, e is %f", 1, 2.71828);
MYFORMAT_CENTER(40, "%d, pi is %f", 2, 3.1415926);
MYFORMAT_CENTER(40, "%s %d.", "This is such a long string that it exceeds the given size:", 40);
return 0;
}
Output:
--- Hello World ---
[ I am okay today ]
[ 1, e is 2.718280 ]
[ 2, pi is 3.141593 ]
[ This is such a long string that it exceeds the given size: 40. ]
Yes, you will either have to write your own function that returns " test " etc, e.g.
printf("%s %s %s", center("col1", 10), center("col2", 20), center("col3", 20));
Or you have a center_print function, something like the following:
void center_print(const char *s, int width)
{
int length = strlen(s);
int i;
for (i=0; i<=(width-length)/2; i++) {
fputs(" ", stdout);
}
fputs(s, stdout);
i += length;
for (; i<=width; i++) {
fputs(" ", stdout);
}
}
A more compact version of PADYMKO's function above (which still leaks memory):
char *str_center(char str[], unsigned int new_length, char placeholder)
{
size_t str_length = strlen(str);
char *buffer;
/*------------------------------------------------------------------
* If a new length is less or equal length of the original string,
* returns the original string
*------------------------------------------------------------------*/
if (new_length <= str_length)
{
return(str);
}
buffer = malloc(sizeof(char) * (new_length + 1));
memset(buffer, placeholder, new_length);
buffer[new_length] = '\0';
bcopy(str, buffer + (( new_length - str_length) / 2), str_length);
return(buffer);
}
This sets the whole of newly allocated buffer to the padding character, null terminates that, and then drops the string to be centred into the middle of the buffer - no loops, or keeping track of where to copy to..
If you want to be able to use a printf() format string for that and you accept to be limited to the GNU clib, you can extend printf() with your own conversion specifier for centering a string with. Add the conversion specifier with register_printf_function().
See here for the documentation: https://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html
The other answers already provide you with a solution on how to manually print a string in the center, which you still need when using your own conversion specifier.
You can use either of the following two options:
char name[] = "Name1";
//Option One
printf("%*s", 40+strlen(name)/2, name, 40-strlen(name)/2, "");
puts("");//skip one line
//Option two
printf("%*s", 40+strlen("Name2")/2, "Name2", 40-strlen("Name2")/2, "");
The output is:
Name1(center)
Name2(center)
I am trying to follow the sample code on encoding in the ffmpeg document and successfully build a application to encode and generate a mp4 file but I face the following problems:
1) I am using the H263 for encoding but I can only set the width and height of the AVCodecContext to 176x144, for other case (like 720x480 or 640x480) it will return fail.
2) I can't play the output mp4 file by using the default Android player, isn't it support H263 mp4 file? p.s. I can play it by using other player
3) Is there any sample code on encoding other video frame to make a new video (which mean decode the video and encode it back in different quality setting, also i would like to modify the frame content)?
Here is my code, thanks!
JNIEXPORT jint JNICALL Java_com_ffmpeg_encoder_FFEncoder_nativeEncoder(JNIEnv* env, jobject thiz, jstring filename){
LOGI("nativeEncoder()");
avcodec_register_all();
avcodec_init();
av_register_all();
AVCodec *codec;
AVCodecContext *codecCtx;
int i;
int out_size;
int size;
int x;
int y;
int output_buffer_size;
FILE *file;
AVFrame *picture;
uint8_t *output_buffer;
uint8_t *picture_buffer;
/* Manual Variables */
int l;
int fps = 30;
int videoLength = 5;
/* find the H263 video encoder */
codec = avcodec_find_encoder(CODEC_ID_H263);
if (!codec) {
LOGI("avcodec_find_encoder() run fail.");
}
codecCtx = avcodec_alloc_context();
picture = avcodec_alloc_frame();
/* put sample parameters */
codecCtx->bit_rate = 400000;
/* resolution must be a multiple of two */
codecCtx->width = 176;
codecCtx->height = 144;
/* frames per second */
codecCtx->time_base = (AVRational){1,fps};
codecCtx->pix_fmt = PIX_FMT_YUV420P;
codecCtx->codec_id = CODEC_ID_H263;
codecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
/* open it */
if (avcodec_open(codecCtx, codec) < 0) {
LOGI("avcodec_open() run fail.");
}
const char* mfileName = (*env)->GetStringUTFChars(env, filename, 0);
file = fopen(mfileName, "wb");
if (!file) {
LOGI("fopen() run fail.");
}
(*env)->ReleaseStringUTFChars(env, filename, mfileName);
/* alloc image and output buffer */
output_buffer_size = 100000;
output_buffer = malloc(output_buffer_size);
size = codecCtx->width * codecCtx->height;
picture_buffer = malloc((size * 3) / 2); /* size for YUV 420 */
picture->data[0] = picture_buffer;
picture->data[1] = picture->data[0] + size;
picture->data[2] = picture->data[1] + size / 4;
picture->linesize[0] = codecCtx->width;
picture->linesize[1] = codecCtx->width / 2;
picture->linesize[2] = codecCtx->width / 2;
for(l=0;l<videoLength;l++){
//encode 1 second of video
for(i=0;i<fps;i++) {
//prepare a dummy image YCbCr
//Y
for(y=0;y<codecCtx->height;y++) {
for(x=0;x<codecCtx->width;x++) {
picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3;
}
}
//Cb and Cr
for(y=0;y<codecCtx->height/2;y++) {
for(x=0;x<codecCtx->width/2;x++) {
picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2;
picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5;
}
}
//encode the image
out_size = avcodec_encode_video(codecCtx, output_buffer, output_buffer_size, picture);
fwrite(output_buffer, 1, out_size, file);
}
//get the delayed frames
for(; out_size; i++) {
out_size = avcodec_encode_video(codecCtx, output_buffer, output_buffer_size, NULL);
fwrite(output_buffer, 1, out_size, file);
}
}
//add sequence end code to have a real mpeg file
output_buffer[0] = 0x00;
output_buffer[1] = 0x00;
output_buffer[2] = 0x01;
output_buffer[3] = 0xb7;
fwrite(output_buffer, 1, 4, file);
fclose(file);
free(picture_buffer);
free(output_buffer);
avcodec_close(codecCtx);
av_free(codecCtx);
av_free(picture);
LOGI("finish");
return 0; }
H263 accepts only certain resolutions:
128 x 96
176 x 144
352 x 288
704 x 576
1408 x 1152
It will fail with anything else.
The code supplied in the question (I used it myself at first) seems to only generate a very rudimentary, if any, container format.
I found that this example, http://cekirdek.pardus.org.tr/~ismail/ffmpeg-docs/output-example_8c-source.html, worked much better as it creates a real container for the video and audio streams. My video is now displayable on the Android device.