Solved

Read a raster

Posted on 1998-10-30
23
371 Views
Last Modified: 2008-02-20
What must i do to access individual samples 8-bit packed stored in a raster???
0
Comment
Question by:Sol
  • 13
  • 10
23 Comments
 
LVL 22

Expert Comment

by:nietod
Comment Utility
What file format? what platform?
0
 

Author Comment

by:Sol
Comment Utility
I'm trying to read the individual samples of a TIFF RGBA image (red,green,blue,alpha). I've a function named TIFFReadRGBAImage that reads a TIFF and stores the result in a supplied raster.

What must i do to acces individual samples??

This is the code done:

in = TIFFOpen(m_ovl+".tif", "r");
   
TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &imageWidth);
if (in) {
      
            TIFFRGBAImage img;
            char emsg[1024];
            uint32* buf;

            if(TIFFRGBAImageBegin(&img,in,0,emsg)) {
                  
            buf = (uint32*)_TIFFmalloc(imageWidth*imageLength*SamplePerPixel);  //THE RASTER

            if (!buf)
                    goto OutOfDIBMemory;

            if (buf != NULL) {

                  if (TIFFRGBAImageGet(&img,buf,img.width,img.height)) {

                        // PROCESS RASTER DATA
                        // ¿¿WHAT MUST I DO HERE???

                  }
                  free (buf);
            }

            TIFFRGBAImageEnd(&img);
            
            }
      }


Thanks!!!

0
 

Author Comment

by:Sol
Comment Utility
Adjusted points to 70
0
 
LVL 22

Accepted Solution

by:
nietod earned 80 total points
Comment Utility
If by "raster" you mean an array of pixel values, then you just need to calculate the offset to the pixel value in the array.  Assuming that "samplePerPixel" is the number of bytes used to store a single pixel's value and DesiredRow and DesiredColumn are the row and column values fo the pixel you want, you would use

unsigned char *PixlDatPtr = (unisigned char *) Buf;  // Use char to make byte calculations work.
int Offset = ((DesiredRow*ImageWidth) + DesiredColumn) * SamplePerPixel;
PixDatPtr += Offset;  // Point to desired pixel.
0
 

Author Comment

by:Sol
Comment Utility
Hi!!

As your answer, PixDatPtr points to desired pixel. But what i want is get from this pixel the individual information, red,green,blue and alpha.

What must i do now that i’ve pointed to desired pixel???

The ideal code was a code that gives me four variables, red, blue,green and alpha that each one give me the value of that parameters from a specified pixel.

Thanks!!


0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
How you would extract that information would depend on how it is stored.  However, there is no universal raster format.  So I can't say how it is stored.  

If it is in 32 bit color, then there is a good chance that red will be in the low byte, green in the next and blue in the next and alpha in the high byte (RGBA).  But another common format switches red and blue, that would produce BGRA.  And of course their are other posibilities.  In addtion, what if it isn't 32 bit color?  In windows, there is a 16 bit format where the RGB values are 5 bits each, starting with red in the low 5 bits.  The high bit is not used in this format.  

If you know the format, then it is no big deal to extract the information with the & operator and the >> operator.  Do you know how to use those?
0
 

Author Comment

by:Sol
Comment Utility
Hi Nietod!!

Raster pixels are 8-bit packed red, green, blue and alpha samples. (RGBA format).

I don't know how to use the & and the >> operator to extract that information.

Would you explain me that??
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
Use the & operator to "mask" of the group of bits you want, then use the >> operator to shift them to the low byte (if needed), like

Assuming that an int is 32 bits, then you might have

unsigned int GetRed(unsigned int V)
{
   return V & 0x000000FF;
}
unsigned int GetGreen(unsigned int V)
{
   return (V & 0x0000FF00) >> 8;
}
unsigned int GetBlue(unsigned int V)
{
   return (V & 0x00FF0000) >> 16;
}
unsigned int GetAlpha(unsigned int V)
{
   return V  >> 24;  // no need to mask as other bytes are shifted out.
}

I hope that helps.
0
 

Author Comment

by:Sol
Comment Utility
The last question..

You have declarated V as a unsigned int, but i have a raster (buffer) declared as a unsigned long *, a image declared as TIFF* and the width and the height.

who is V???

As an example:

..
if (TIFFReadRGBAImage(tif,w,h,raster,0)) {

GetAlpha(//WHAT MUST I PUT HERE???);

// I have de TIFF image in the raster 8-bit packed .

}
free (buf);
}

Thanks nietod!!

0
 

Author Comment

by:Sol
Comment Utility
Adjusted points to 75
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>>You have declarated V as a unsigned int, but i have a raster (buffer) declared as a
>>     unsigned long *, a image declared as TIFF* and the width and the height.
You can use unsigned int or unsigned long or whatever, just so yoou know that the value is 32 bits.

That is a parameter that you pass to a function.  The function takes a 32 bit pixel color and extracts one of the color components.

Assuming that raster is an array of 32 bit pixel values, then to get the alpha value fo the first pixel you could do

if (TIFFReadRGBAImage(tif,w,h,raster,0)) {
    int Alpha;
     Alpha = GetAlpha(raster[0]);
}

Note you have to combine the two things we have mentioned.  You need to dot he calculation using the image's dimensions to get a pointer to (or offset to) the data of the desired pixel, then given that 32 bit value, you can use the code I showed you to extract the color information.  Depending on what your goals, you might not want to actually use the functions I showed you, you might want to use their code in-line and a loop or something.
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 

Author Comment

by:Sol
Comment Utility
This is the last question, i promise!! ;-D

I’ve writte this to try the code:

if (TIFFReadRGBAImage(in,imageWidth,imageLength,buf,0)) {

.
            Offset = ((y*imageWidth)+x)*SamplePerPixel;
            Alpha=buf[Offset] >> 24;
            Red=buf[Offset] & 0x000000FF;
            Green=(buf[Offset] & 0x0000FF00) >> 8;
            Blue=(buf[Offset] & 0x00FF0000) >> 16;
.

with x from 0 to imageWidth and y from 0 to imageLenght....

Is correct to put the offset there?? (buf[Offset])???

As you mentioned, i can do this:

unsigned char *PixlDatPtr = (unisigned char *) Buf; // Use char to make byte calculations work.
int Offset = ((DesiredRow*ImageWidth) + DesiredColumn) * SamplePerPixel;
PixDatPtr += Offset; // Point to desired pixel.

Then i have PixDatPtr pointing to desired pixel, but, what must i do to apply the GetRed, GetGreen, etc...function??

You have helped me very much. Thanks.

0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
If buf is an array of 32 bit values (for example, long) and if you use the [] operator, then you do not want to use the SamplePerPixel value in your calculations  The [] operator takes into account the fact that each entry in the array is 3 butes (we are assuming that SamplePerPixel is 4).  So in that case, you would do

Offset = (y*imageWidth)+x
Alpha=buf[Offset] >> 24;

You only need to use the SamplePerPixel if you are dealing with images that have different color formats (Like say 8 bit and 16 bit color as well).  In those cases you would make the array a byte (unsigned char) array and then calculate offset into the array using the SamplePerPixel value as well.
0
 

Author Comment

by:Sol
Comment Utility
 If buf is an array of 32 bit values (for example, long)

Buff, as the instructions of libtiff (library of TIFF image) says, is an array of width times height 32-bit entries.

  and if you use the [] operator, then you do not want to use the SamplePerPixel value in your calculations The [] operator takes into account the fact that each entry in the array is 3 bytes (we are assuming that SamplePerPixel is 4). So in that case, you would do

Offset = (y*imageWidth)+x
Alpha=buf[Offset] >> 24;

Only notice that when i was trying the code, I was looking for the pixels which have an alpha different of 255, then this succeded:

....
x = 1943, y = 889, Alpha = 160, Red = 2, Green = 0, Blue = 0
First-chance exception in X_Sheet.exe: 0xC0000005: Access Violation.

Do you know what does it mean??? I’ve readed a wrong position???

I don’t understand it, because the image is 2381 width and 889 height...


0
 

Author Comment

by:Sol
Comment Utility
Adjusted points to 80
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>>.First-chance exception in X_Sheet.exe: 0xC0000005: Access Violation.

>>     Do you know what does it mean??? I’ve readed a wrong position???
It means you've tried to access an invalid memory address.  Probably bacause your pointer calculations were wrong and you were calculating an offset that is past the end of the array.

>>     I don’t understand it, because the image is 2381 width and 889 height
If you are write about those figures, then the image will be over 8 meg.  Are you sure that is correct?  Did you allocate space for 8 meg of pixel data?

Sorry I didn't get back sooner.  We are having trouble connecting to EE.  I may not be able to repond again for a while.  (Out of curiousity, are you having any problems with Experts Exhange?)
0
 

Author Comment

by:Sol
Comment Utility
>> It means you've tried to access an invalid memory address.  >> Probably bacause your pointer calculations were wrong and you >> were calculating an offset that is past the end of the array.

Yes, but i've token the height and the width of the image from fields of TIFF image file. Look at this (libtiff library):

An image is organized as a rectangular array of pixels. The dimensions of this array are stored in the following fields:

ImageLength
The number of rows (sometimes described as scanlines) in the image.

ImageWidth
The number of columns in the image, i.e., the number of pixels per scanline.

Then, my buffer is defined like this:

buf = (uint32*)_TIFFmalloc(imageWidth*imageLength*SamplePerPixel);

As you see, i don't know what is wrong now....

On the other hand, yes, i've been having little problems to contact with Experts-Exchange, but not serious problems...

I'll be waiting for you!! ;-DD

THANKS NIETOD!!
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
Can you post the code that causes the error. i.e the code that calculates the offset and uses it.
0
 

Author Comment

by:Sol
Comment Utility
Here you have the part of the code where the offset is calculated and used to take the samples...

.

if (in) {
      
      // Here i get the information of the TIFF file.

      TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &imageWidth);
      TIFFGetField(in, TIFFTAG_IMAGELENGTH, &imageLength);  
      
      // I declare de buffer.            
      buf = (uint32*)_TIFFmalloc(imageWidth*imageLength*SamplePerPixel);

      if (!buf)
            goto OutOfDIBMemory;

      if (buf != NULL) {
      
            if (TIFFReadRGBAImage(in,imageWidth,imageLength,buf,0)) {
                                    
                  for (a=0;a<=imageWidth;a++) {
                                    
                        for (b=0;b<=imageLength;b++) {

                              Offset = ((b*imageWidth)+a);
                              Alpha=buf[Offset] >> 24;
                              Red=buf[Offset] & 0x000000FF;
                              Green=(buf[Offset] & 0x0000FF00) >> 8;
                              Blue=(buf[Offset] & 0x00FF0000) >> 16;
                        }
                  }
            }
                  
            _TIFFfree (buf);
      }

TIFFClose(in);
}
      
TIFFClose(in);
NotACorrectTIFF:
      OutOfDIBMemory:
          TiffOpenError:
            if (in)
                  TIFFClose(in);
return;

0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
You are going a little too far past the end of the raster data array.  each of your loops execute 1 time to many.  The end at "<=",  but should end only at "<"
0
 

Author Comment

by:Sol
Comment Utility
Adjusted points to 85
0
 

Author Comment

by:Sol
Comment Utility
Congratulations nietod!!

You've done it!! :-O ;-D

i've changed the end at "<" and know the code compile!

Only one thing...I don't understand why i can't get the (2138,883) pixel if the image is 2138,883....The only thing i know sure is that if a put "<=" i only can get the image from (0,0) to (1938,883), and know i can get from (0,0) to (2137,882)  But it doesn't matter...

It's been a pleasure to meet you... THANKS!!

Whenever you have a problem in telecommunications (i'm Telecommunications Superior Engineer
In Polytechnic University of Catalonia,Barcelona,Spain) or whatever, i'll try to help you..sure!!

Whatever you need, I can be reached at:

fjimenez@arquired.es
alfede@gps.tsc.upc.es

BYE!!

0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>>Only one thing...I don't understand why i can't get the (2138,883)
>> pixel if the image is 2138,883....The only thing i know sure is that
>> if a put "<=" i only can get the image from (0,0) to (1938,883), and
>> know i can get from (0,0) to (2137,882)  But it doesn't matter...
Its not a problem.  You are now gettign the whole image (right to the very end), before yoiu were going past the end.  Remember the C++ arrays are numbers from 0, so if you have an array with 10 entries you acccess them in a for loop using

for (int i =0; i<10; ++i)
    array[i];
This access the 10 entries from 0 to 9.  If you had a "i <= 10"  it would access an 11th entry and would (probably) crash.  That is what you had been doing.  You were accessing one extra pixel on each row (starting each row 1 pixel later than the previous one) and accessing one whole extra row as well, thus you were calculating offets past the end of the pixel data and causing a crash.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now