1

I'm working on a Quartz Composer plug-in with OpenCV and I have this issue with still images (only) converted to gray via cvCvtColor. I'm working on 2.4 but I had the same issue with 2.3 :

Everything is OK for webcam images, and - strange, isn't it ? - for direct jpeg pictures from the iPhone. But with other images I have this distortion trouble.

When I scale the original picture, it correct the trouble, but it's not a really good way to resolve the trouble.

Here is the original image and on the right the image with the height scaled by 1.226 (???) :

enter image description here

Does anyone ever have this trouble. I was wondering if it wasn't my way to convert the input image in IplImage, but my code seems to be correct as I found other programs using the same way...

Could it be a trouble of number of channels in output ?

Thank you.

EDIT :

Here is the code of the method.

- (void) createWithInputImage: (id<QCPlugInInputImageSource>) image {

IplImage *r = NULL;
if (image != nil) {
    // NSLog(@"Carasuelo OpenCV - width: %f", [image imageBounds].size.width);
    CvSize size = cvSize([image imageBounds].size.width, [image imageBounds].size.height);
    const char *colorModel;
    const char *channelSeq;
    int depth;
    int channels;
    if ([image bufferPixelFormat] == QCPlugInPixelFormatARGB8) {
        depth = IPL_DEPTH_8U;
        channels = 4;
        colorModel = (char *)"RGBA";
        channelSeq = (char *)"ARGB";

    } else if ([image bufferPixelFormat] == QCPlugInPixelFormatBGRA8) {
        depth = IPL_DEPTH_8U;
        channels = 4;
        colorModel = (char *)"RGBA";
        channelSeq = (char *)"BGRA";

        // QUARTZ COMPOSER IMAGES ARE ALWAYS BGRA8 -> 8U

    } else if ([image bufferPixelFormat] == QCPlugInPixelFormatRGBAf) {
        depth = IPL_DEPTH_32F;
        channels = 4;
        colorModel = (char *)"RGBA";
        channelSeq = (char *)"RGBA";

    } else if ([image bufferPixelFormat] == QCPlugInPixelFormatI8) {
        depth = IPL_DEPTH_8U;
        channels = 1;
        colorModel = (char *)"GREY";
        channelSeq = (char *)"GREY";

    } else if ([image bufferPixelFormat] == QCPlugInPixelFormatIf) {
        depth = IPL_DEPTH_32F;
        channels = 1;
        colorModel = (char *)"GREY";
        channelSeq = (char *)"GREY";

    } else {
        NSLog(@"Format d'image non supporté: %@", [image bufferPixelFormat]);
    }


    r = cvCreateImage(size, depth, channels);

    r->imageData = (char *)[image bufferBaseAddress];

    strcpy(r->colorModel, colorModel);
    strcpy(r->channelSeq, channelSeq);
}

[self setImageCV:r];

}

Thank you !

Benoît Lahoz
  • 1,270
  • 1
  • 18
  • 43

1 Answers1

0

[image bytesPerRow] returns the number of bytes in a row of pixels, which may not be the same as [image imageBounds].size.width * bytesPerPixel (for processor addressing efficiency, padding is added so that each row begins on a multiple of 16).

So, instead of r->imageData = (char *)[image bufferBaseAddress]; try something like this:

unsigned long qcImageHeight = [image imageBounds].size.height;
unsigned long qcImageBytesPerRow = [image bytesPerRow];
char * qcImageData = (char *)[image imageBufferBaseAddress];
for(unsigned long y = 0; y < height; ++y)
    memcpy((char *)r->imageData + y * r->widthStep, qcImageData + y * qcImageBytesPerRow, r->widthStep);
smokris
  • 11,740
  • 2
  • 39
  • 59
  • Thank you @smokris ! Unfortunately, I have an error in XCode on the line : memcpy(r->imageData + y * r->widthStep, qcImageData + y * qcImageBytesPerRow, r->widthStep); **arithmetic on a pointer to void** I know there must be an obvious solution but well... DO I have to cast it ? To what type ? – Benoît Lahoz Feb 09 '13 at 10:24
  • Thx, and sorry : (char *) was in my initial function too... But, well... it doesn't work and I have the same issue with your method... :-/ – Benoît Lahoz Feb 10 '13 at 00:37
  • Darn. I'm not sure, then. – smokris Feb 10 '13 at 00:58