99 lines
2.9 KiB
C
99 lines
2.9 KiB
C
#include "image_proc.h"
|
|||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include <windows.h>
|
||
|
|
|
||
|
|
int ExtractGray(const uint8_t *srcPixels, int w, int h, int bpp, GrayImage *outImg){
|
||
|
|
if(!srcPixels || w<=0 || h<=0) return 0;
|
||
|
|
int srcBytesPerPixel = bpp / 8;
|
||
|
|
int srcStride = ((w * srcBytesPerPixel + 3) / 4) * 4;
|
||
|
|
outImg->width = w;
|
||
|
|
outImg->height = h;
|
||
|
|
outImg->stride = w;
|
||
|
|
size_t total = (size_t)w * h;
|
||
|
|
outImg->data = (uint8_t*)malloc(total);
|
||
|
|
if(!outImg->data) return 0;
|
||
|
|
outImg->rows = (uint8_t**)malloc(sizeof(uint8_t*) * h);
|
||
|
|
if(!outImg->rows){
|
||
|
|
free(outImg->data);
|
||
|
|
outImg->data = NULL;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
for(int y=0; y<h; ++y){
|
||
|
|
outImg->rows[y] = outImg->data + (size_t)y * w;
|
||
|
|
}
|
||
|
|
|
||
|
|
for(int y=0; y<h; ++y){
|
||
|
|
const uint8_t *srcLine = srcPixels + (size_t)(h - 1 - y) * srcStride;
|
||
|
|
uint8_t *dstLine = outImg->rows[y];
|
||
|
|
if(bpp == 8){
|
||
|
|
memcpy(dstLine, srcLine, (size_t)w);
|
||
|
|
} else if(bpp == 24 || bpp == 32){
|
||
|
|
for(int x=0; x<w; ++x){
|
||
|
|
const uint8_t *p = srcLine + x * srcBytesPerPixel;
|
||
|
|
uint8_t B = p[0], G = p[1], R = p[2];
|
||
|
|
uint8_t Y = (uint8_t)((R*77 + G*150 + B*29) >> 8);
|
||
|
|
dstLine[x] = Y;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
free(outImg->rows); free(outImg->data);
|
||
|
|
memset(outImg,0,sizeof(*outImg));
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
void FreeGray(GrayImage *img){
|
||
|
|
if(!img) return;
|
||
|
|
free(img->rows);
|
||
|
|
free(img->data);
|
||
|
|
memset(img,0,sizeof(*img));
|
||
|
|
}
|
||
|
|
|
||
|
|
int Build8BitDIB(const GrayImage *img, BITMAPINFO **outBMI, uint8_t **outPixels){
|
||
|
|
if(!img || !img->data) return 0;
|
||
|
|
int w = img->width;
|
||
|
|
int h = img->height;
|
||
|
|
int bpp = 8;
|
||
|
|
int dstStride = ((w * (bpp/8) + 3)/4)*4;
|
||
|
|
size_t pixelBytes = (size_t)dstStride * h;
|
||
|
|
|
||
|
|
size_t bmiSize = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
|
||
|
|
BITMAPINFO *bmi = (BITMAPINFO*)calloc(1, bmiSize);
|
||
|
|
if(!bmi) return 0;
|
||
|
|
|
||
|
|
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||
|
|
bmi->bmiHeader.biWidth = w;
|
||
|
|
bmi->bmiHeader.biHeight = h;
|
||
|
|
bmi->bmiHeader.biPlanes = 1;
|
||
|
|
bmi->bmiHeader.biBitCount = 8;
|
||
|
|
bmi->bmiHeader.biCompression = BI_RGB;
|
||
|
|
bmi->bmiHeader.biSizeImage = (DWORD)pixelBytes;
|
||
|
|
bmi->bmiHeader.biClrUsed = 256;
|
||
|
|
|
||
|
|
for(int i=0;i<256;i++){
|
||
|
|
bmi->bmiColors[i].rgbBlue = (BYTE)i;
|
||
|
|
bmi->bmiColors[i].rgbGreen = (BYTE)i;
|
||
|
|
bmi->bmiColors[i].rgbRed = (BYTE)i;
|
||
|
|
bmi->bmiColors[i].rgbReserved = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint8_t *pixels = (uint8_t*)malloc(pixelBytes);
|
||
|
|
if(!pixels){
|
||
|
|
free(bmi);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
for(int y=0; y<h; ++y){
|
||
|
|
uint8_t *dstLine = pixels + (size_t)(h - 1 - y) * dstStride;
|
||
|
|
const uint8_t *srcLine = img->rows[y];
|
||
|
|
memcpy(dstLine, srcLine, (size_t)w);
|
||
|
|
if(dstStride > w){
|
||
|
|
memset(dstLine + w, 0, dstStride - w);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
*outBMI = bmi;
|
||
|
|
*outPixels = pixels;
|
||
|
|
return 1;
|
||
|
|
}
|