crop image with opencv in c - c

I want to crop 1 pixel from all sides of image.
My code works well in some margins but does not work well in some margins (ex. widthleft=widthright=heightup=heightdown=1).
I should use C not C++.
IplImage* edgecuter_v3(unsigned int height, unsigned int width,
IplImage* p_in_img_grey) {
unsigned int widthleft, widthright, heightup, heightdown, heighteff;
unsigned int widtheff;
widthleft = 1;
widthright = 1;
heightup = 1;
heightdown = 1;
widtheff = width - widthleft - widthright;
heighteff = height - heightup - heightdown;
IplImage *p_out_img;
unsigned char *p_in_img_data;
p_in_img_data = (unsigned char *) p_in_img_grey->imageData;
unsigned char (*p_char_array_in)[width];
p_char_array_in = (unsigned char (*)[width]) p_in_img_data;
p_out_img = cvCreateImage(cvSize(widtheff, heighteff), IPL_DEPTH_8U, 1);
unsigned char *p_out_img_data;
p_out_img_data = (unsigned char *) p_out_img->imageData;
unsigned char (*p_char_array_out)[widtheff];
p_char_array_out = (unsigned char (*)[widtheff]) p_out_img_data;
unsigned int row_indx;
unsigned int col_indx;
for (row_indx = 0; row_indx < heighteff ; row_indx++) {
for (col_indx = 0; col_indx < widtheff; col_indx++) {
p_char_array_out[row_indx ][col_indx ] =
p_char_array_in[row_indx+heightup][col_indx+widthleft];
}
}
cvNamedWindow("one", CV_WINDOW_AUTOSIZE);
cvShowImage("one", p_out_img);
cvWaitKey(0);
return p_out_img;}
I sweep index with other methods and assignments like but not work.
p_char_array_out[row_indx ][col_indx ] =
p_char_array_in[row_indx+heightup][col_indx+widthleft];
thanks lot

I found the solution. maybe useful for others.
Acording to this link 32bit boundary "If the number of cols * pixel size isn't a multiple of 4 then each row if the image will be padded"
The right way for sweep is to use "widthStep" not "width" for considering pad
widthStep_r = p_in_img->widthStep;

Related

What's wrong with my PNG IDAT CHUNK datas?

i'm trying for learning purpose to create manually a png file from with OpenGL
All other CHUNKS are okk (IHDR, pHY, IEND).
firstly, I read pixels by Opengl :
int s_width = glutGet(GLUT_SCREEN_WIDTH), s_height = glutGet(GLUT_SCREEN_HEIGHT);
int pixelArraySize = s_width*s_height*_glColorChannels;
unsigned char *pixelsArrayInfo = (unsigned char*)malloc(pixelArraySize);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, (unsigned short)s_width, (unsigned short)s_height, GL_RGB, GL_UNSIGNED_BYTE, pixelsArrayInfo);
then, I created a function of generating scanlines like this:
"each scanline is an array of RGB values in one screen line preceded by '0' "
unsigned char *generateScanlines(unsigned char *pixels, int s_width, int s_height)
{
int eachScanlineLength = 1 + s_width*3;
unsigned char *finalOutput = (unsigned char*)malloc(s_height*eachScanlineLength);
for(int i=0; i<s_height; i++){
finalOutput[i*eachScanlineLength] = 0;
copyElement(finalOutput, pixels, i*eachScanlineLength, (i+1)*eachScanlineLength, i*eachScanlineLength+1);
}
return finalOutput;
}
void copyElement(unsigned char *dest, unsigned char *src, int src_debut, int src_fin, int dest_debut)
{
for(int i=src_debut, j=dest_debut; i<src_fin; i++, j++){
dest[j] = src[i];
}
}
unsigned char *deflateDatas(unsigned char *pixels, int s_width, int s_height, int *deflatedDataLength)
{
unsigned char *deflated = (unsigned char*)malloc(compressBound(s_height*(1 + s_width*3)));
unsigned char *scanlines = invertArray(generateScanlines(pixels, s_width, s_height), s_height*(1 + s_width*3));
z_stream defstream;
defstream.zalloc = Z_NULL;
defstream.zfree = Z_NULL;
defstream.opaque = Z_NULL;
defstream.avail_in = (uInt)(s_height*(1 + s_width*3));
defstream.next_in = (Bytef *)scanlines;
defstream.avail_out = (uInt)(compressBound(s_height*(1 + s_width*3)));
defstream.next_out = (Bytef *)deflated;
deflateInit(&defstream, 0);
deflate(&defstream, Z_FINISH);
deflateEnd(&defstream);
*deflatedDataLength = compressBound(s_height*(1 + s_width*3));
return deflated;
}
then, it seem it work, but when I test it my OpenGL program I get this :
[small png output][1]
also, i created a basic bmp File and it work perfectly
i try to find if it's any error, maybe it's in scanlines generation or misunderstanding with the PNG file format.
the invertArray() code :
unsigned char *invertArray(unsigned char *myArray, int arrayEnd)
{ unsigned char *invertedtableau = (unsigned char*)malloc(arrayEnd*sizeof(unsigned char));
for(int i=0 ; i<=arrayEnd ; i++)
{ invertedtableau[i] = myArray[arrayEnd-i];
}
return invertedtableau; }
SOLUTION
I found where the error comes from, accordind to Mark Adler, the scanlines gemeration method was, wrong.
Also, file was inverted because Opengl is only compatible with bottom left gormat, but png is a top left format, then we need to invert the pixel buffer before generating scanlines(ehat i tried with invertArray() method).
The last error was that the calling of deflate method and storing the deflated length was also wrong.
the whole deflating code :
// generating scanline function
unsigned char *generateScanlines(unsigned char *pixels, int s_width, int s_height, int colorChannel)
{
int eachScanlineLength = 1 + s_width * colorChannel, i = 1, j = 0; // one scanline length
unsigned char *scanlines = (unsigned char *)malloc(s_height * eachScanlineLength); // memory allocation for the scanline output
memset(scanlines, 0, s_height * eachScanlineLength * sizeof(char)); // we set all the output values to 0
// then we copy pixels elements in the output, skipping the fisrt output values, that should ever be 0
for (i = 1, j = 0; i < s_height && j < s_height; i++, j++)
memcpy(scanlines + 1 + (i - 1) * eachScanlineLength, pixels + j * (eachScanlineLength - 1), eachScanlineLength - 1);
memcpy(scanlines + 1 + (i - 1) * eachScanlineLength, pixels + j * (eachScanlineLength - 1), eachScanlineLength - 1);
return scanlines;
}
// deflating IDAT CHUNK data algorithm
unsigned char *deflateDatas(unsigned char *pixels, int s_width, int s_height, int colorChannel, int *deflatedLen)
{
unsigned long inLen = s_height * (1 + s_width * colorChannel), tmpLen = 0; // input len of scanlines datas
unsigned char *scanlines = generateScanlines(pixels, s_width, s_height, colorChannel); // generating scanlines from the pixels
unsigned char *deflatedDatas = NULL; // setting up the deflated datas output
int result = 0;
// initialising zlib
z_stream defstream;
defstream.zalloc = Z_NULL;
defstream.zfree = Z_NULL;
defstream.opaque = Z_NULL;
defstream.avail_in = inLen;
defstream.next_in = (Bytef *)scanlines;
defstream.avail_out = 0;
defstream.next_out = (Bytef *)deflatedDatas;
if ((result = deflateInit(&defstream, Z_DEFAULT_COMPRESSION)) == Z_OK)
{
// calculate the actual length and update zlib structure
unsigned long estimateLen = deflateBound(&defstream, inLen);
deflatedDatas = (unsigned char *)malloc(estimateLen);
if (deflatedDatas != NULL)
{
// updation zlib configuration
defstream.avail_out = (uInt)estimateLen;
defstream.next_out = (Bytef *)deflatedDatas;
// do the compression
deflate(&defstream, Z_FINISH);
tmpLen = (unsigned char *)defstream.next_out - deflatedDatas;
}
}
deflateEnd(&defstream); // end of deflating algorithm
*deflatedLen = tmpLen; // copying the defalted data length to the IDAT->length
free(scanlines);
return deflatedDatas;
}
the bottom left to top left pixelbuffer flipping code :
void flipPixels(unsigned char *pixelsArray, int s_width, int s_heigth, int colorChannel)
{
int totalLength = s_width * s_heigth * colorChannel;
int oneLineLength = s_width * colorChannel;
unsigned char *tmp = (unsigned char *)malloc(totalLength * sizeof(unsigned char));
memcpy(tmp, pixelsArray, totalLength);
for (int i = 0; i < s_heigth; i++)
memcpy(pixelsArray + oneLineLength * i, tmp + totalLength - oneLineLength * (i + 1), oneLineLength);
free(tmp);
}
[1]:
https://i.stack.imgur.com/5khCg.png
We don't see all the relevant code, but first, you seem to be deliberately corrupting your image data by reversing the bytes. Don't do that. Remove the call to invertArray().
Second, you are not returning the size of the compressed data. You are returning the upper-bound estimate of that.
Use deflateBound() (after calling deflateInit()), not compressBound(). Call deflateBound() once (instead of three times) and save the answer in unsigned long bound. Return the size of the compressed data, which is bound - defstream.avail_out.
Lastly, you are not compressing! The second argument to deflateInit() should be Z_DEFAULT_COMPRESSION or something else other than 0, which means no compression.
Your example has an incorrect CRC for the IDAT chunk, so there's something else wrong in the code you don't show for constructing that chunk.
Even if I undo the invertArray() (which itself has another error), what I get is still messed-up image that appears to have a byte deleted on each row.
We can't help you unless you provide all of your code. There are many errors, and you don't know where they are.

Resizing a the dimensions of a pixel pgm image in C

What i am trying to do i resize the a regular pgm image,by a factor of 3--100X100 becomes 33X33,i am using pointer array to store the original image and the resized image, the original image will be 10000 long and the resized image will be 1089 long, I am trying to do get the every 3rd element in the width dimension and skipping two width rows(as height also needs to be reduced),I keep getting a weird blurry image when I write it in a pgm output,i get there might be a little difference as we are rounding height and width,this is just a bit of the code.
enter code here
int k,l,m;
image =(unsigned char*) malloc((width*height) * sizeof(unsigned char));
int thumbHeight=round(height/3);
int thumbWidth =round(width/3);
resizedImage =(unsigned char*) malloc(((resizedWidth*resizedHeight)) * sizeof(unsigned char));
for(l=0;l<resizedHeight;l++){
for(k=0;k<resizedWidth;k++){
*resizedImage= *image;
image++;
image++;
}
//skipping two lines
for (m=0;m<width*2;m++){
image++;
}
}
maybe:
unsigned char *resize(const unsigned char *source, unsigned char *dest, size_t origx, size_t origy, size_t destx)
{
double ratio = (double)destx / origx;
double stepx = (double)origx / destx;
double stepy = (double)origy / (origy * ratio);
for(size_t y = 0; y < origy * ratio; y++)
{
for(size_t x = 0; x < destx; x++)
{
dest[y * destx + x] = source[(ssize_t)((y * stepy) * origx + x * stepx)];
}
}
return dest;
}
But I did not run this so it may be buggy.

C - Write access violation

I have an error at the last line, in nullString, a function setting all the string to '\0' with a simple for()
void function ( unsigned char inputArray[], size_t inputSize )
{
size_t cellSize;
if (inputSize <= 256)
cellSize = 1;
else
cellSize = ceil(inputSize / 2 / 256) + 1;
// Sub Box
unsigned char subBox[255];
for (size_t line = 0; line < 255; line++)
subBox[line] = 0;
generate_SubBox(subBox, key);
// Sub Box
// Sub Box reverse
unsigned char subBox_Inverse[255];
for (size_t line = 0; line < 255; line++)
subBox_Inverse[line] = 0;
generate_SubBox_Inverse(subBox_Inverse, subBox, key);
// Sub Box reverse
unsigned char* inputArray2 = NULL;
inputArray2 = malloc(sizeof(unsigned char)* inputSize / 2);
verifyMalloc(inputArray2);
nullString(inputArray2, inputSize / 2);
unsigned char string_temp[3] = { 0 };
size_t w = 0;
for (size_t i = 0; i < inputSize / 2; i++)
{
string_temp[0] = inputArray[w];
string_temp[1] = inputArray[w + 1];
inputArray2[i] = strtoll(string_temp, NULL, 16);
w += 2;
}
}
I tried neutralizing line per line all instructions coming before nullString() by commenting them but it doesn't change anything.
If I neutralize nullString, the error comes after, at
inputArray2[i] = strtoll(...)
Hope you've got the answer :)
Thanks in advance !
EDIT:
Here is nullString:
void nullString(unsigned char input[], size_t length)
{
for (size_t x = 0; x < length; x++)
input[x] = '\0';
}
I commented all the instructions before nullString, the error is still there.
I also verified variables and they all look like good
EDIT 2:
verifyMalloc:
void verifyMalloc(int* pointer)
{
if (pointer == NULL)
{
perror("Erreur");
Sleep(15000);
exit(0);
}
}
Everything we're seeing is seriously hinting at you forgetting to #include <stdlib.h> (and ignoring the warnings resulting from that).
This is what might happens when you use malloc() without including stdlib.h in the same file:
the compiler consider the malloc() function to be declared implicitly, which means it is assuming that it's return types is int (instead of *void).
This might work when sizeof (int) is the same as sizeof (*void). But when int is 32-bits while pointers are 64-bits then the address returned by malloc() might lose half of it's bits and point to an invalid address.
Try using
void bzero(void *s, size_t n); or
void *memset(void *s, int c, size_t n);
instead of your nullString() and for()something[x]=0 loops.
Then, this does not make all of the array zeroed:
unsigned char string_temp[3] = { 0 };
This makes
string[0] = 0;
string[1] = god_knows;
string[2] = god_knows_not;
so either - unsigned char string_temp[3] = {0,0,0};
or bzero(string_temp,3);
Consequently, when you do this:
string_temp[0] = inputArray[w];
string_temp[1] = inputArray[w + 1];
inputArray2[i] = strtoll(string_temp, NULL, 16);
strtoll() will be guessing when to stop. No guarantee this would be at string_temp[2].
Then, this should be enough:
unsigned char* inputArray2 = malloc(sizeof(unsigned char) * inputSize / 2);
inputArray2 will be NULL if malloc failed, or a valid pointer if it succeeded.
You may want to check your inputSize / this_and_that arithmetics. Does it really deliver what you expect? You might be surprised by division result of integer operands.
This also looks suspicious:
inputArray2[i] = strtoll(string_temp, NULL, 16);
strtoll returns longlong integer but your inputArray2 is of unsigned char type. So you are trying to store 8 bytes (sizeof longlong = 8) and you reserved place only for one (sizeof char = 1)
Redeclare your inputArray2 as long long
long long *inputArray2 = malloc(sizeof(long long) * inputSize /2 );
And try this with memset():
size_t size = sizeof(long long) * inputSize/2;
//Do you really need long long? You are storing max three digits. uint_8 will be enough
long long* inputArray2 = malloc(size);
memset(inputArray2, 0, size);

Find JPG/JPEG image height and width using C

I am trying to find the height and width of jpg/jpeg image in c language.
I have seen some lines of code
iPos = iPos + 5;
*ipHeight = ucpImageBuffer[iPos]<<8|ucpImageBuffer[iPos+1];
*ipWidth = ucpImageBuffer[iPos+2]<<8|ucpImageBuffer[iPos+3];
printf("\nW x H = %d x %d\n\n",*ipWidth,*ipHeight);
I find some lines of code as shown above but I don't know what should be in ucpImageBuffer?
And i also don't know from where I have to start?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
int iHeight=0, iWidth=0, iPos, i;
char *cpFileName = "/images/image1.jpg";
FILE *fp = fopen(cpFileName,"rb");
fseek(fp,0,SEEK_END);
long len = ftell(fp);
fseek(fp,0,SEEK_SET);
unsigned char *ucpImageBuffer = (unsigned char*) malloc (len+1);
fread(ucpImageBuffer,1,len,fp);
fclose(fp);
printf("\n\nBuffer size %ld", len);
/*Extract start of frame marker(FFCO) of width and hight and get the position*/
for(i=0;i<len;i++)
{
if((ucpImageBuffer[i]==0xFF) && (ucpImageBuffer[i+1]==0xC0) )
{
iPos=i;
break;
}
}
/*Moving to the particular byte position and assign byte value to pointer variable*/
iPos = iPos + 5;
iHeight = ucpImageBuffer[iPos]<<8|ucpImageBuffer[iPos+1];
iWidth = ucpImageBuffer[iPos+2]<<8|ucpImageBuffer[iPos+3];
printf("\nWxH = %dx%d\n\n", iWidth, iHeight);
free(ucpImageBuffer);
}

Access violation reading location location 0x1D5C4C2F

This function is throwing an access violation when reading raw pixel values and I can't figure out why.
Can consider this as the only part of my code running, I've run this solo with the same result.
string filenames[]={"firstclick.raw", "secondclick.raw","thirdclick.raw","fourthclick.raw","fifthclick.raw","sixthclick.raw","seventhclick.raw","eighthclick.raw"};
FILE *file;
int height= 750, width = 453, bbp=3;
unsigned char ****images;
images = (unsigned char ****)malloc(sizeof(unsigned char ***)*8);
for(int j = 0; j<8; j++){
images[j] = (unsigned char ***)malloc(sizeof(unsigned char**)*height);
for(int i = 0; i<height; i++){
images[j][i]= (unsigned char **)malloc(sizeof(unsigned char*)*width);
for(int k = 0; k<bbp; k++)
images[j][i][k]= (unsigned char *)malloc(sizeof(unsigned char)*bbp);
}
}
for (int i = 0; i<8; i++){
if (!(file=fopen(filenames[i].c_str(),"rb"))){
cout << "Cannot open file: "<<filenames[i].c_str() <<endl;
exit(1);
}
fread(images[i], sizeof(unsigned char), height*width*bbp, file);
fclose(file);
}
The problem here is you've allocated each element of your array as a separate array (somewhere else in memory, whose location is kept as a pointer). But when you read in, you assume that it's a single contiguous block. You will overwrite all those pointers, and overflow the buffer to boot.
If you want images to be a set of discrete blocks of memory, allocate like this:
unsigned char ** images;
int i;
images = malloc( sizeof(unsigned char *) * 8 );
for( i = 0; i < 8; i++ ) {
images[i] = malloc( width * height * bpp );
}
Note that sizeof(unsigned char) is defined by the standard to always be 1. You don't need to multiply by sizeof(unsigned char) all the time.
Now, to get a pixel address in an image, you need to multiply out (usually row-major):
unsigned char * pixel = images[i] + (y * width + x) * bpp;
unsigned char r = pixel[0];
unsigned char g = pixel[1];
unsigned char b = pixel[2];
when you allocate the memory blocks in different locations in memory an fread on that structure will not work.
instead allocate one big block then set the pointers to point inside the block, that way you can use fread on it.

Resources