32-битные данные с плавающей точкой с прямым порядком байтов в CGImage - PullRequest
3 голосов
/ 06 декабря 2011

Я пытаюсь написать приложение, которое читает изображение FITS. FITS расшифровывается как «Гибкий транспортный формат изображения», и это формат, который в первую очередь используется для хранения научных данных, связанных с астрофизикой, и, во-вторых, он используется большинством астрономов-любителей, которые фотографируют небо с помощью CCD-камеры. Таким образом, файл FITS содержит изображения, но они также могут содержать таблицы и другие виды данных. Поскольку я новичок в Objectiv-C и программировании какао (я начинаю этот проект год назад, но так как я занят, я почти не касаюсь его в течение одного года!), Я начал пытаться создать библиотеку, которая позволит мне преобразовывать содержимое изображения файла в NSImageRep. Двоичные данные изображения FITS могут быть 8 бит / пиксель, 16 бит / пиксель, 32 бит / пиксель, целое число без знака или 32 бит / пиксель, 64 бит / пиксель с плавающей запятой, все в формате Big Endian.

Мне удается получить представление изображения для изображения FITS в оттенках серого в 16-битном / пиксельном, 32-битном / пиксельном целом числе без знака, но я получаю очень странное поведение, когда ищу 32-битную / пиксельную плавающую точку (и проблема стоит RGB 32 бит / пиксель с плавающей запятой). До сих пор я не тестировал целочисленные данные 8 бит / пиксель и изображение RGB на основе целочисленных данных 16 бит / пиксель и 32 бит / пиксель, потому что я еще не нашел файл примера в Интернете.

Ниже приведен мой код для создания файла формы изображения в оттенках серого:

-(void) ConstructImgGreyScale
{
CGBitmapInfo     bitmapInfo;
int bytesPerRow;

switch ([self BITPIX])   // BITPIX : Number bits/pixel. Information extracted from the FITS header
{
    case 8:
        bytesPerRow=sizeof(int8_t);
        bitmapInfo = kCGImageAlphaNone ;
        break;
    case 16:
        bytesPerRow=sizeof(int16_t);
        bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrder16Big;
        break;
    case 32:
        bytesPerRow=sizeof(int32_t);
        bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrder32Big;
        break;
    case 64:
        bytesPerRow=sizeof(int64_t);
        bitmapInfo = kCGImageAlphaNone;
        break;
    case -32:
        bytesPerRow=sizeof(Float32);
        bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrder32Big  | kCGBitmapFloatComponents;
    case -64:
        bytesPerRow=sizeof(Float64);
        bitmapInfo = kCGImageAlphaNone  | kCGBitmapFloatComponents;
        break;
    default:
        NSLog(@"Unknown pixel bit size");
        return;
}
[self setBitsPerSample:abs([self BITPIX])];

[self setColorSpaceName:NSCalibratedWhiteColorSpace];

[self setPixelsWide:[self NAXESofAxis:0]]; // <- Size of the X axis. Extracted from FITS header
[self setPixelsHigh:[self NAXESofAxis:1]]; // <- Size of the Y axis. Extracted from FITS header

[self setSize:  NSMakeSize( 2*[self pixelsWide], 2*[self pixelsHigh])];

[self setAlpha: NO];
[self setOpaque:NO];

CGDataProviderRef provider=CGDataProviderCreateWithCFData ((CFDataRef) Img);

CGFloat Scale[2]={0,28};
image = CGImageCreate ([self pixelsWide],
                       [self pixelsHigh],
                       [self bitsPerSample],
                       [self bitsPerSample],
                       [self pixelsWide]*bytesPerRow,
                       [[NSColorSpace deviceGrayColorSpace] CGColorSpace],
                       bitmapInfo,
                       provider,
                       NULL,
                       NO,
                       kCGRenderingIntentDefault
                       );

CGDataProviderRelease(provider);
return;
}  

и вот снимок результата для данных с плавающей запятой 32 / бит / пикс: Изображение NASA HST !

Изображение кажется смещенным влево, но что более раздражает, так это то, что я получаю два представления одного и того же изображения (верхняя и нижняя часть кадра) в одном кадре.

А для какого-то другого файла поведение более странное: Звездное поле 1 , (Для другой ссылки, как комментарий, как новый пользователь, я не могу иметь более двух ссылок в этом тексте. Как и я не могу поставить непосредственно изображение.)

Все три изображения звездного поля представляют собой одинаковое содержимое файла. Я получаю правильное представление изображения в нижней части кадра (звезды слишком сильно насыщены, но я еще не играл с кодировкой). Но в верхней части каждый раз, когда я открываю один и тот же файл, я получаю различное представление изображения. Похоже, что каждый раз, когда я открываю этот файл, он не использует одну и ту же последовательность байтов для создания представления изображения (по крайней мере, для верхней части).

Кроме того, я не знаю, содержит ли изображение, дублированное снизу, половину данных а верхняя - вторая половина, или, если это просто копия данных.

Когда я конвертирую содержимое моих Данных в примитивный формат (удобочитаемое число), число совместимо с тем, что должно быть в пикселе, в хорошей позиции. Это позволяет мне думать, что проблема не в данных, а в том, как CGImage интерпретирует данные, т. Е. Я ошибаюсь где-то в аргументе, который я передаю функции CGImageCreate.

В случае, если RGB подходит для данных изображения, я получаю в конце 18 изображение в свой кадр. 6 копий каждого изображения R, G и B. Все в оттенках серого. Обратите внимание, что в случае изображения RGB мой код отличается.

Что я делаю не так?

1 Ответ

1 голос
/ 08 декабря 2011

Хорошо, я наконец-то нашел решение моей проблемы, касающейся дублирования изображения.И это была очень глупая ошибка, и я не горжусь тем, что не нашел ее раньше.

В коде я забываю break в case -32.Тем не менее остается вопрос о смене картины.Я не вижу сдвига при открытии 32-битного целочисленного изображения, но оно появляется в данных с 32-битной плавающей запятой.

Кто-нибудь имеет представление о том, откуда этот сдвиг может возникнуть в моем коде?Это связано с тем, как я создаю образ?Или, возможно, это связано с тем, как я рисую изображение?

Ниже приведен фрагмент кода, который я использую для рисования изображения.Поскольку изображение сначала было перевернуто, я немного изменил координаты.

- (bool)draw {
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
if (!context || !image) {
    return NO;
}
NSSize size = [self size];

CGContextTranslateCTM(context, 0, size.height);
CGContextScaleCTM(context, 1, -1);

CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), image);
return YES;
}
...