Pass unsigned char * by reference - objective-c

HI! I create a function to get a grayscale version of an image, but i have problem trying to pass by reference the destination of the bit(s) generated by this function:
void grayscale (const unsigned char *source, unsigned char **dest, int data_size) {
for (int i=0; i < data_size; i= i+4) {
int gray = (source[i] + source[i+1] + source[i+2]) / 3;
gray = 255 - (int)cos(source[i])*255;
*dest[i] = (char)gray;
*dest[i + 1] = (char)gray;
*dest[i + 2] = (char)gray; //HERE AN ERROR
*dest[i + 3] = (char)255;
}
}
I call this function with:
grayscale(source, &destination, width*height*4 );
Is there something wrong with pointers ?
(i'm working on objective C and i obtain a EXC_BAD_ACCESS).
Thank you

It's not clear why you're using an additional level of indirection for dest, since *dest is not being modified but most likely you need to do the following - change:
*dest[i] = (char)source[i];
*dest[i + 1] = (char)gray;
*dest[i + 2] = (char)gray;
*dest[i + 3] = (char)255;
to:
(*dest)[i] = (char)source[i];
(*dest)[i + 1] = (char)gray;
(*dest)[i + 2] = (char)gray;
(*dest)[i + 3] = (char)255;
The reason for this is operator precedence/associativity.
Also it's hard to tell without seeing the calling code, but I'm guessing you may need to change:
(*dest)[i] = (char)source[i];
to:
(*dest)[i] = (char)source[i / 4];
if you're trying to do something like convert a single plane image to RGBA.

Your call is fine, you have an illegal memory access. Debug your indices and check the size of the array your passing in, also check that it is still in scope. Most likely i+2 is out of bounds.

Related

How to pass a pointer argument to a function without knowing the size to be allocated for that pointer

I know this question is very noob. I am trying to understand how the pointer thing works. I studied basics of C but still did not understand this.
Given this piece of function:
+ (void)nv21ToRgbWithWidth:(unsigned int)width height:(unsigned int)height yuyv:(unsigned char *)yuyv rgb:(unsigned char *)rgb
{
const int nv_start = width * height ;
UInt32 i, j, index = 0, rgb_index = 0;
UInt8 y, u, v;
int r, g, b, nv_index = 0;
for(i = 0; i < height ; i++)
{
for(j = 0; j < width; j ++){
//nv_index = (rgb_index / 2 - width / 2 * ((i + 1) / 2)) * 2;
nv_index = i / 2 * width + j - j % 2;
y = yuyv[rgb_index];
u = yuyv[nv_start + nv_index ];
v = yuyv[nv_start + nv_index + 1];
r = y + (140 * (v-128))/100; //r
g = y - (34 * (u-128))/100 - (71 * (v-128))/100; //g
b = y + (177 * (u-128))/100; //b
if(r > 255) r = 255;
if(g > 255) g = 255;
if(b > 255) b = 255;
if(r < 0) r = 0;
if(g < 0) g = 0;
if(b < 0) b = 0;
index = rgb_index % width + (height - i - 1) * width;
rgb[index * 3+0] = b;
rgb[index * 3+1] = g;
rgb[index * 3+2] = r;
rgb_index++;
}
}
}
How am I suppose to know how the unsigned char * for rgb should be initialized before passing in to the function?
I tried calling the function like this:
unsigned char *rgb = NULL;
[MyClass nv21ToRgbWithWidth:imageWidth height:imageHeight yuyv:yuyvValues rgb:rgb];
But the the program crashes on this line:
rgb[index * 3+0] = b;
I see rgb was initialized with NULL, so you can't assign values. So, I thought of initializing an array and pass it to pointer rgb like this:
unsigned char rgbArr[10000];
unsigned char *rgb = rgbArr;
but the function still crashes. I really don't know how should I pass the rgb parameter in this function. Please help me understand this.
The expected size in bytes seems to be at least height*width*3; it might be that allocating such an array as a local variable (as you do with unsigned char rgbArr[10000]) exceeds a stack limit; The program likely crashes in such a case. I'd try to use the heap instead:
unsigned char* rgb = malloc(imageHeight*imageWidth*3);
[MyClass nv21ToRgbWithWidth:imageWidth height:imageHeight yuyv:yuyvValues rgb:rgb];
...
free(rgb);
That is what the malloc(), calloc(), realloc() and free() functions are for. Don't forget to use the free() function to prevent memory leaks... I hope that helps.

Define a function in MATLAB

I wrote down a code to calculate the integral ParEa in terms of a function J as follows:
Laa = 0.01;
ja = 1;
De = 0.001;
J = #(Oma) ja.* Oma .*exp(-Oma/Laa);
ParEaa = #(Oma) pi.^(-1).*J./(Oma.*(Oma + De));
IParEaa = integral(ParEaa, 0, inf)
But it gives the errors:
Undefined function or method 'integral' for input arguments of
type 'function_handle'.
Error in ==> sample at 9
IParEaa = integral(ParEaa, 0, inf)
I want to calculate the integral without substituting the explicit expression of J into ParEa? How should I do it?
I think you're mixing up the symbolic and numeric integration.
I cannot check with Matlab but I would suggest the following:
For numerical simulation:
J = #(Oma) ja.* Oma .*exp(-Oma/Laa);
ParEaa = #(Oma,J) pi.^(-1).*J./(Oma.*(Oma + De));
IParEaa = integral(ParEaa, 0, inf)
For the symbolic integration:
syms oma
expr = pi^(-1)*(ja*Oma*exp(-Oma/Laa))/(Oma*(Oma + De));
int(expr,oma,0,inf)
I hope it works,
Michael

Script interface for the Fit image Palette introduced in GMS 2.3?

The Fit Image Palette is quite nice and powerful. Is there a script interface that we can access it directly?
There is a script interface, and the example script below will get you started. However, the script interface is not officially supported. It might therefore be buggy or likely to change in future GMS versions.
For GMS 2.3 the following script works:
// create the input image:
Image input := NewImage("formula test", 2, 100)
input = 500.5 - icol*11.1 + icol*icol*0.11
// add some random noise:
input += (random()-0.5)*sqrt(abs(input))
// create image with error data (not required)
Image errors := input.ImageClone()
errors = tert(input > 1, sqrt(input), 1)
// setup fit:
Image pars := NewImage("pars", 2, 3)
Image parsToFit := NewImage("pars to fit", 2, 3)
pars = 10; // starting values
parsToFit = 1;
Number chiSqr = 1e6
Number conv_cond = 0.00001
Result("\n starting pars = {")
Number xSize = pars.ImageGetDimensionSize(0)
Number i = 0
for (i = 0; i < xSize; i++)
{
Result(GetPixel(pars, i, 0))
if (i < (xSize-1)) Result(", ")
}
Result("}")
// fit:
String formulaStr = "p0 + p1*x + p2*x**2"
Number ok = FitFormula(formulaStr, input, errors, pars, parsToFit, chiSqr, conv_cond)
Result("\n results pars = {")
for (i = 0; i < xSize; i++)
{
Result(GetPixel(pars, i, 0))
if (i < (xSize-1)) Result(", ")
}
Result("}")
Result(", chiSqr ="+ chiSqr)
// plot results of fit:
Image plot := PlotFormula(formulaStr, input, pars)
// compare the plot and original data:
Image compare := NewImage("Compare Fit", 2, 100, 3)
compare[icol, 0] = input // original data
compare[icol, 1] = plot // fit function
compare[icol, 2] = input - plot // residuals
ImageDocument linePlotDoc = CreateImageDocument("Test Fitting")
ImageDisplay linePlotDsp = linePlotDoc.ImageDocumentAddImageDisplay(compare, 3)
linePlotDoc.ImageDocumentShow()

Is there any PDF command, that scales rectangle coordinates?

I have an application, that extracts text and rectangles from pdf files for further analysis. I use ItextSharp for extraction, and everything worked smoothly, until I stumbled upon a document, which has some strange table cell rectangles. The values in the drawing commands, that I retrieve, seem 10 times larger, than actual dimensions of the latter rectangles.
Just an example :
2577 831.676 385.996 3.99609 re
At the same time, when viewing the document all rectangles seem to correctly fit in the bounds of document pages. My guess is that there should be some scaling command, telling, that these values should be scaled down. Is the assumption right, or how is it possible, that such large rectangles are rendered so, that they stay inside the bounds of a page ?
The pdf document is behind this link : https://www.dropbox.com/s/gyvon0dwk6a9cj0/prEVS_ISO_11620_KOM_et.pdf?dl=0
The code, that handles extraction of dimensions from PRStream is as follows :
private static List<PdfRect> GetRectsAndLinesFromStream(PRStream stream)
{
var streamBytes = PdfReader.GetStreamBytes(stream);
var tokenizer = new PRTokeniser(new RandomAccessFileOrArray(streamBytes));
List<string> newBuf = new List<string>();
List<PdfRect> rects = new List<PdfRect>();
List<string> allTokens = new List<string>();
float[,] ctm = null;
List<float[,]> ctms = new List<float[,]>();
//if current ctm has not yet been added to list
bool pendingCtm = false;
//format definition for string-> float conversion
var format = new System.Globalization.NumberFormatInfo();
format.NegativeSign = "-";
while (tokenizer.NextToken())
{
//Add them to our master buffer
newBuf.Add(tokenizer.StringValue);
if (
tokenizer.TokenType == PRTokeniser.TokType.OTHER && newBuf[newBuf.Count - 1] == "re"
)
{
float startPointX = (float)double.Parse(newBuf[newBuf.Count - 5], format);
float startPointY = (float)double.Parse(newBuf[newBuf.Count - 4], format);
float width = (float)double.Parse(newBuf[newBuf.Count - 3], format);
float height = (float)double.Parse(newBuf[newBuf.Count - 2], format);
float endPointX = startPointX + width;
float endPointY = startPointY + height;
//if transformation is defined, correct coordinates
if (ctm!=null)
{
//extract parameters
float a = ctm[0, 0];
float b = ctm[0, 1];
float c = ctm[1, 0];
float d = ctm[1, 1];
float e = ctm[2, 0];
float f = ctm[2, 1];
//reverse transformation to get x and y from x' and y'
startPointX = (startPointX - startPointY * c - e) / a;
startPointY = (startPointY - startPointX * b - f) / d;
endPointX = (endPointX - endPointY * c - e) / a;
endPointY = (endPointY - endPointX * b - f) / d;
}
rects.Add(new PdfRect(startPointX, startPointY , endPointX , endPointY ));
}
//store current ctm
else if (tokenizer.TokenType == PRTokeniser.TokType.OTHER && newBuf[newBuf.Count - 1] == "q")
{
if (ctm != null)
{
ctms.Add(ctm);
pendingCtm = false;
}
}
//fetch last ctm and remove it from list
else if (tokenizer.TokenType == PRTokeniser.TokType.OTHER && newBuf[newBuf.Count - 1] == "Q")
{
if (ctms.Count > 0)
{
ctm = ctms[ctms.Count - 1];
ctms.RemoveAt(ctms.Count -1 );
}
}
else if (tokenizer.TokenType == PRTokeniser.TokType.OTHER && newBuf[newBuf.Count - 1] == "cm")
{
// x' = x*a + y*c + e ; y' = x*b + y*d + f
float a = (float)double.Parse(newBuf[newBuf.Count - 7], format);
float b = (float)double.Parse(newBuf[newBuf.Count - 6], format);
float c = (float)double.Parse(newBuf[newBuf.Count - 5], format);
float d = (float)double.Parse(newBuf[newBuf.Count - 4], format);
float e = (float)double.Parse(newBuf[newBuf.Count - 3], format);
float f = (float)double.Parse(newBuf[newBuf.Count - 2], format);
float[,] tempCtm = ctm;
ctm = new float[3, 3] {
{a,b,0},
{c,d,0},
{e,f,1}
};
//multiply matrices to form 1 transformation matrix
if (pendingCtm && tempCtm != null)
{
float[,] resultantCtm;
if (!TryMultiplyMatrix(tempCtm, ctm, out resultantCtm))
{
throw new InvalidOperationException("Invalid transform matrix");
}
ctm = resultantCtm;
}
//current CTM has not yet been saved to stack
pendingCtm = true;
}
return rects;
}
The command you are looking for is cm. Did you read The ABC of PDF with iText? The book isn't finished yet, but you can already download the first five chapters.
This is a screen shot of the table that shows the cm operator:
This is an example of 5 shapes that are created in the exact same way, using identical syntax:
They are added at different positions, even in a different size and shape, because of the change in the graphics state: the coordinate system was changed, and the shapes are rendered in that altered coordinate system.

C language. Logic error: The left operand of '-' is a garbage value

I have the following code, but in this line of code I have warning x[i] = (rhs[i] - x[i - 1]) / b;, compiler is telling me that rhs[i] is a garbage value. Why it's happend? And how to remove this warning?
double* getFirstControlPoints(double* rhs, const int n) {
double *x;
x = (double*)malloc(n * sizeof(double));
double *tmp; // Temp workspace.
tmp = (double*)malloc(n * sizeof(double));
double b = 2.0;
x[0] = rhs[0] / b;
for (int i = 1; i < n; i++) // Decomposition and forward substitution.
{
tmp[i] = 1 / b;
b = (i < n - 1 ? 4.0 : 3.5) - tmp[i];
x[i] = (rhs[i] - x[i - 1]) / b; //The left operand of '-' is a garbage value
}
for (int i = 1; i < n; i++) {
x[n - i - 1] -= tmp[n - i] * x[n - i]; // Backsubstitution.
}
free(tmp);
return x;
}
All compiler warnings and calling getFirstControlPoints you may see on screenshots.
You need a check to make sure you have at least 4 points in the points array because this loop (line 333):
for (NSInteger i = 1 ; i < n - 1 ; ++i) {
// initialisation stuff
}
will not execute at all for n = 0, 1, 2.
Assume that points has 3 objects in it, At line 311 you set n to the count - 1 i.e. n == 2
Then the loop condition is i < 2 - 1 i.e. i < 1.
I think you need the loop condition to be i < n
if points.count is 0 or 1 you are facing some problems, because then, n is -1 or 0, and you access rhs[n-1]; and you malloc n* bytes;
maybe that can be the problem. that you put some rangechecks int o the code?