Add FITS to thumbnailer

This commit is contained in:
2025-03-06 09:34:45 -08:00
parent 05b0aa9a2f
commit c05fc36ee3
5 changed files with 195 additions and 77 deletions
+177 -65
View File
@@ -1,12 +1,80 @@
#include "libxisf.h"
#include <thumbcache.h>
#include "../rawimage.h"
#include <fitsio2.h>
bool OpenGLES = false;
void RawImageToHTBITMAP(std::shared_ptr<RawImage> &rawImage, HBITMAP *hbmp, UINT thumbSize)
{
rawImage->calcStats();
if(rawImage->imageStats().m_median[0] < rawImage->norm() * 0.2f)
{
//OutputDebugStringA("Stretch image");
MTFParam params = rawImage->calcMTFParams();
rawImage->applySTF(params);
}
UINT w = rawImage->width();
UINT h = rawImage->height();
UINT cw = thumbSize;
UINT ch = thumbSize;
if (w > h)
ch = h * thumbSize / w;
else
cw = w * thumbSize / h;
rawImage->resize(cw, ch);
rawImage->convertToType(RawImage::UINT8);
BITMAPINFO bmi = {};
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = cw;
bmi.bmiHeader.biHeight = -static_cast<LONG>(ch);
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
UINT lw = cw * 4;
BYTE *pBits;
HBITMAP bmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, reinterpret_cast<void **>(&pBits), NULL, 0);
const unsigned char *p = (const unsigned char*)rawImage->data();
const unsigned short *ps = (const unsigned short*)rawImage->data();
if(rawImage->channels() == 1)
{
for(UINT y = 0; y < ch; y++)
{
for(UINT x = 0; x < cw; x++)
{
pBits[(y * lw) + x * 4 + 0] = p[y * cw + x];
pBits[(y * lw) + x * 4 + 1] = p[y * cw + x];
pBits[(y * lw) + x * 4 + 2] = p[y * cw + x];
pBits[(y * lw) + x * 4 + 3] = 255;
}
}
}
else
{
for(UINT y = 0; y < ch; y++)
{
for(UINT x = 0; x < cw; x++)
{
pBits[(y * lw) + x * 4 + 0] = p[y * cw * 4 + x * 4 + 2];
pBits[(y * lw) + x * 4 + 1] = p[y * cw * 4 + x * 4 + 1];
pBits[(y * lw) + x * 4 + 2] = p[y * cw * 4 + x * 4 + 0];
pBits[(y * lw) + x * 4 + 3] = 255;
}
}
}
*hbmp = bmp;
}
bool loadXISF(const LibXISF::ByteArray &data, HBITMAP *hbmp, UINT thumbSize)
{
OutputDebugStringA("TENMON");
try
{
LibXISF::XISFReader xisf;
@@ -25,11 +93,8 @@ bool loadXISF(const LibXISF::ByteArray &data, HBITMAP *hbmp, UINT thumbSize)
default: break;
}
LibXISF::Image tmpImage = xisfImage;
tmpImage.convertPixelStorageTo(LibXISF::Image::Planar);
UINT w = tmpImage.width();
UINT h = tmpImage.height();
std::shared_ptr<RawImage> rawImage;
if(tmpImage.colorSpace() == LibXISF::Image::ColorSpace::Gray)
@@ -42,75 +107,122 @@ bool loadXISF(const LibXISF::ByteArray &data, HBITMAP *hbmp, UINT thumbSize)
rawImage = RawImage::fromPlanar(tmpImage.imageData(), tmpImage.width(), tmpImage.height(), tmpImage.channelCount(), type);
}
rawImage->calcStats();
if(rawImage->imageStats().m_median[0] < rawImage->norm() * 0.2f)
{
OutputDebugStringA("Stretch image");
MTFParam params = rawImage->calcMTFParams();
rawImage->applySTF(params);
}
RawImageToHTBITMAP(rawImage, hbmp, thumbSize);
UINT cw = thumbSize;
UINT ch = thumbSize;
if (w > h)
ch = h * thumbSize / w;
else
cw = w * thumbSize / h;
rawImage->resize(cw, ch);
rawImage->convertToType(RawImage::UINT8);
BITMAPINFO bmi = {};
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = cw;
bmi.bmiHeader.biHeight = -static_cast<LONG>(ch);
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
UINT lw = cw * 4;
BYTE *pBits;
HBITMAP bmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, reinterpret_cast<void **>(&pBits), NULL, 0);
const unsigned char *p = (const unsigned char*)rawImage->data();
const unsigned short *ps = (const unsigned short*)rawImage->data();
if(tmpImage.channelCount() == 1)
{
for(UINT y = 0; y < ch; y++)
{
for(UINT x = 0; x < cw; x++)
{
pBits[(y * lw) + x * 4 + 0] = p[y * cw + x];
pBits[(y * lw) + x * 4 + 1] = p[y * cw + x];
pBits[(y * lw) + x * 4 + 2] = p[y * cw + x];
pBits[(y * lw) + x * 4 + 3] = 255;
}
}
}
else
{
for(UINT y = 0; y < ch; y++)
{
for(UINT x = 0; x < cw; x++)
{
pBits[(y * lw) + x * 4 + 0] = p[y * cw * 4 + x * 4 + 2];
pBits[(y * lw) + x * 4 + 1] = p[y * cw * 4 + x * 4 + 1];
pBits[(y * lw) + x * 4 + 2] = p[y * cw * 4 + x * 4 + 0];
pBits[(y * lw) + x * 4 + 3] = 255;
}
}
}
*hbmp = bmp;
return true;
}
catch (LibXISF::Error &err)
{
char text[1024];
sprintf(text, "Failed to open XISF image %s", err.what());
sprintf_s(text, 1000, "Failed to open XISF image %s", err.what());
OutputDebugStringA(text);
return false;
}
return false;
}
bool loadFITS(const LibXISF::ByteArray &data, HBITMAP *hbmp, UINT thumbSize)
{
fitsfile *file;
int status = 0;
int type = -1;
int num = 0;
long naxes[3] = {0};
auto checkError = [&status]()
{
char err[100];
char text[1000];
fits_get_errstatus(status, err);
sprintf_s(text, 1000, "Failed to load FITS file %s", err);
OutputDebugStringA(text);
return false;
};
const void *dataPtr = data.data();
size_t size = data.size();
fits_open_memfile(&file, "file.fits", READONLY, (void**)&dataPtr, &size, 0, nullptr, &status);
if(status)return checkError();
fits_get_num_hdus(file, &num, &status);
if(status)return checkError();
int imgtype;
int naxis;
for(int i=1; i <= num; i++)
{
fits_movabs_hdu(file, i, IMAGE_HDU, &status);if(status)return checkError();
fits_get_hdu_type(file, &type, &status);if(status)return checkError();
fits_get_img_param(file, 3, &imgtype, &naxis, naxes, &status);if(status)return checkError();
fits_get_img_equivtype(file, &imgtype, &status);if(status)return checkError();
if(type == IMAGE_HDU && naxis >= 2 && naxis <= 3 && status == 0)
{
RawImage::DataType type;
int fitstype;
long fpixel[3] = {1,1,1};
switch(imgtype)
{
case BYTE_IMG:
type = RawImage::UINT8;
fitstype = TBYTE;
break;
case SHORT_IMG:
type = RawImage::UINT16;
fitstype = TSHORT;
break;
case USHORT_IMG:
type = RawImage::UINT16;
fitstype = TUSHORT;
break;
case ULONG_IMG:
type = RawImage::UINT32;
fitstype = TUINT;
break;
case FLOAT_IMG:
type = RawImage::FLOAT32;
fitstype = TFLOAT;
break;
case DOUBLE_IMG:
type = RawImage::FLOAT64;
fitstype = TDOUBLE;
break;
default:
return false;
break;
}
size_t size = naxes[0]*naxes[1];
size_t w = naxes[0];
size_t h = naxes[1];
RawImage img(w, h, naxis == 2 ? 1 : naxes[2], type);
uint8_t *data = static_cast<uint8_t*>(img.data());
for (int i=1; i==1 || i<=naxes[2]; i++)
{
fpixel[2] = i;
fits_read_pix(file, fitstype, fpixel, size, NULL, data + img.size() * RawImage::typeSize(type) * (i-1), NULL, &status);
if(status)return checkError();
}
if(fitstype == TSHORT)
{
uint16_t *s = static_cast<uint16_t*>(img.data());
size_t size = img.size() * img.channels();
for(size_t i=0; i<size; i++)
s[i] -= INT16_MIN;
}
std::shared_ptr<RawImage> image;
if(img.channels() == 1)
image = std::make_shared<RawImage>(std::move(img));
else
image = RawImage::fromPlanar(img);
RawImageToHTBITMAP(image, hbmp, thumbSize);
return true;
}
}
return false;
}