//////////////////////////////////////////////////////////////////////////////// // HistogramLog function by <dave> : dave(at)posortho(dot)com bool CxImage::HistogramLog() { if (!pDib) return false; //q(i,j) = 255/log(1 + |high|) * log(1 + |p(i,j)|); int x, y, i; RGBQUAD color; RGBQUAD yuvClr; unsigned int YVal, high = 1; // Find Highest Luminance Value in the Image if( head.biClrUsed == 0 ){ // No Palette for(y=0; y < head.biHeight; y++){ info.nProgress = (long)(50*y/head.biHeight); for(x=0; x < head.biWidth; x++){ color = GetPixelColor( x, y ); YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); if (YVal > high ) high = YVal; } } } else { // Palette for(i = 0; i < (int)head.biClrUsed; i++){ color = GetPaletteColor((BYTE)i); YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); if (YVal > high ) high = YVal; } } // Logarithm Operator double k = 255.0 / ::log( 1.0 + (double)high ); if( head.biClrUsed == 0 ){ for( y = 0; y < head.biHeight; y++ ){ info.nProgress = (long)(50+50*y/head.biHeight); for( x = 0; x < head.biWidth; x++ ){ color = GetPixelColor( x, y ); yuvClr = RGBtoYUV( color ); yuvClr.rgbRed = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) ); color = YUVtoRGB( yuvClr ); SetPixelColor( x, y, color ); } } } else { for(i = 0; i < (int)head.biClrUsed; i++){ color = GetPaletteColor( (BYTE)i ); yuvClr = RGBtoYUV( color ); yuvClr.rgbRed = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) ); color = YUVtoRGB( yuvClr ); SetPaletteColor( (BYTE)i, color ); } } return true; }
void compute_distortion(ImageParameters *p_Img, InputParameters *p_Inp, ImageData *imgData) { DistortionParams *p_Dist = p_Img->p_Dist; if (p_Inp->Verbose != 0) { select_img(p_Img, p_Inp, &p_Img->imgSRC, &p_Img->imgREF, imgData); find_snr (p_Img, p_Inp, &p_Img->imgREF, &p_Img->imgSRC, &p_Dist->metric[SSE], &p_Dist->metric[PSNR]); if (p_Inp->Distortion[SSIM] == 1) find_ssim (p_Img, p_Inp, &p_Img->imgREF, &p_Img->imgSRC, &p_Dist->metric[SSIM]); if (p_Inp->Distortion[MS_SSIM] == 1) find_ms_ssim(p_Img, p_Inp, &p_Img->imgREF, &p_Img->imgSRC, &p_Dist->metric[MS_SSIM]); // RGB Distortion if(p_Inp->DistortionYUVtoRGB == 1) { YUVtoRGB(p_Img, &p_Img->imgREF, &p_Img->imgRGB_ref); YUVtoRGB(p_Img, &p_Img->imgSRC, &p_Img->imgRGB_src); find_snr (p_Img, p_Inp, &p_Img->imgRGB_ref, &p_Img->imgRGB_src, &p_Dist->metric[SSE_RGB], &p_Dist->metric[PSNR_RGB]); if (p_Inp->Distortion[SSIM] == 1) find_ssim (p_Img, p_Inp, &p_Img->imgRGB_ref, &p_Img->imgRGB_src, &p_Dist->metric[SSIM_RGB]); if (p_Inp->Distortion[MS_SSIM] == 1) find_ms_ssim(p_Img, p_Inp, &p_Img->imgRGB_ref, &p_Img->imgRGB_src, &p_Dist->metric[MS_SSIM_RGB]); } } }
long CxImage::Histogram(long* red, long* green, long* blue, long* gray, long colorspace) { if (!pDib) return 0; RGBQUAD color; if (red) memset(red,0,256*sizeof(long)); if (green) memset(green,0,256*sizeof(long)); if (blue) memset(blue,0,256*sizeof(long)); if (gray) memset(gray,0,256*sizeof(long)); long xmin,xmax,ymin,ymax; if (pSelection){ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; } else { xmin = ymin = 0; xmax = head.biWidth; ymax=head.biHeight; } for(long y=ymin; y<ymax; y++){ for(long x=xmin; x<xmax; x++){ #if CXIMAGE_SUPPORT_SELECTION if (SelectionIsInside(x,y)) #endif //CXIMAGE_SUPPORT_SELECTION { switch (colorspace){ case 1: color = HSLtoRGB(GetPixelColor(x,y)); break; case 2: color = YUVtoRGB(GetPixelColor(x,y)); break; case 3: color = YIQtoRGB(GetPixelColor(x,y)); break; case 4: color = XYZtoRGB(GetPixelColor(x,y)); break; default: color = GetPixelColor(x,y); } if (red) red[color.rgbRed]++; if (green) green[color.rgbGreen]++; if (blue) blue[color.rgbBlue]++; if (gray) gray[(BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)]++; } } } long n=0; for (int i=0; i<256; i++){ if (red && red[i]>n) n=red[i]; if (green && green[i]>n) n=green[i]; if (blue && blue[i]>n) n=blue[i]; if (gray && gray[i]>n) n=gray[i]; } return n; }
/// ///Private methods /// void Worker::transformImages(int n,const RoboCompCameraBus::Format& format,RoboCompCameraBus::Image &image) { uint8_t *temp; RoboCompCameraBus::Format ftemp; ftemp.width = busparams.width; ftemp.height = busparams.height; ftemp.modeImage = format.modeImage; if(format.modeImage != RoboCompCameraBus::YUV422) { if(format.modeImage == RoboCompCameraBus::GRAY8) YUVtoGray(ftemp.width,ftemp.height,pSour,pDes,n); else { if(format.modeImage == RoboCompCameraBus::RGB888Packet) YUVtoRGB(ftemp.width,ftemp.height, pSour, pDes,n); else { if(format.modeImage == RoboCompCameraBus::RGB888Planar) YUVtoRGBPtr(ftemp.width,ftemp.height,pSour,pDes,n); } } for(int i=0;i<n;i++) { temp = pSour[i]; pSour[i] = pDes[i]; pDes[i] = temp; } } if (ftemp.width != format.width or ftemp.height != format.height) { resizeImage(ftemp,pSour,format,pDes,n); for(int i=0;i<n;i++) { temp = pSour[i]; pSour[i] = pDes[i]; pDes[i] = temp; } } for(int i=0;i<n;i++) { if(cameraParamsList[i].invertedH != false or cameraParamsList[i].invertedV != false) mirror(format,pSour[i],cameraParamsList[i].invertedH,cameraParamsList[i].invertedV); } int size = format.width*format.height; if (format.modeImage == RoboCompCameraBus::RGB888Packet or format.modeImage == RoboCompCameraBus::RGB888Planar) size *= 3; if (format.modeImage == RoboCompCameraBus::YUV422) size *= 2; image.timeStamp = reloj.elapsed(); image.frmt = format; image.frmt.size = size; }
void YUV::displayFrame() { char inputKey; prepareBufferRead(); YUVtoRGB(); cvShowImage("YUV", img); /* wait according to the frame rate */ inputKey = cvWaitKey(1.0 / (fps / tempSubSampl) * 1000); }
void ColorSpace::YUVtoRGB (CoImage* pIn, CoImage* pOut) { assert (pIn->GetType() == MAT_Tfloat); assert (pOut->GetType() == MAT_Tbyte); float* prY = pIn->m_matX.data.fl[0]; float* prU = pIn->m_matY.data.fl[0]; float* prV = pIn->m_matZ.data.fl[0]; BYTE* pbR = pOut->m_matX.data.ptr[0]; BYTE* pbG = pOut->m_matY.data.ptr[0]; BYTE* pbB = pOut->m_matZ.data.ptr[0]; for (int i = 0; i < pIn->GetHeight() * pIn->GetWidth(); i ++) { YUVtoRGB(prY[i], prU[i], prV[i], &pbR[i], &pbG[i], &pbB[i]); } }
void PhPictureTools::ConvertYV12toRGB(const unsigned char *yuvIn, unsigned char *rgbOut, int w, int h) { int yuv[3]; const unsigned char *op[3]; op[0] = yuvIn; op[1] = op[0] + w * h; op[2] = op[1] + w * h /4; for(int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { yuv[0] = *(op[0]++); if (x % 2 == 0 && y % 2 == 0) { yuv[2] = *(op[1]++); yuv[1] = *(op[2]++); } YUVtoRGB(yuv, rgbOut); rgbOut += 3; } } }
void YUV::YUVtoRGB() { unsigned char *imgBuffer; /* openCV image buffer */ int r, g, b, y, u, v; /* auxiliary variables */ /* The video is stored in YUV planar mode but OpenCv uses packed modes */ imgBuffer = (uchar*) img->imageData; /* YUV444: |yR*yC| yR*yC| yR*yC| */ for (unsigned int i = 0, j = 0; i < nRows * nCols; i++, j+=3) { /* Accessing to planar information */ y = yBuffer[i]; u = uBuffer[i]; v = vBuffer[i]; YUVtoRGB(y, u, v, r, g, b); // Fill the OpenCV buffer - packed mode: BGRBGR...BGR imgBuffer[j ] = b; imgBuffer[j + 1] = g; imgBuffer[j + 2] = r; } }
/** * HistogramStretch * \param method: 0 = luminance (default), 1 = linked channels , 2 = independent channels. * \param threshold: minimum percentage level in the histogram to recognize it as meaningful. Range: 0.0 to 1.0; default = 0; typical = 0.005 (0.5%); * \return true if everything is ok * \author [dave] and [nipper]; changes [DP] */ bool CxImage::HistogramStretch(long method, double threshold) { if (!pDib) return false; double dbScaler = 50.0/head.biHeight; long x,y; if ((head.biBitCount==8) && IsGrayScale()){ double p[256]; memset(p, 0, 256*sizeof(double)); for (y=0; y<head.biHeight; y++) { info.nProgress = (long)(y*dbScaler); if (info.nEscape) break; for (x=0; x<head.biWidth; x++) { p[BlindGetPixelIndex(x, y)]++; } } double maxh = 0; for (y=0; y<255; y++) if (maxh < p[y]) maxh = p[y]; threshold *= maxh; int minc = 0; while (minc<255 && p[minc]<=threshold) minc++; int maxc = 255; while (maxc>0 && p[maxc]<=threshold) maxc--; if (minc == 0 && maxc == 255) return true; if (minc >= maxc) return true; // calculate LUT BYTE lut[256]; for (x = 0; x <256; x++){ lut[x] = (BYTE)max(0,min(255,(255 * (x - minc) / (maxc - minc)))); } for (y=0; y<head.biHeight; y++) { if (info.nEscape) break; info.nProgress = (long)(50.0+y*dbScaler); for (x=0; x<head.biWidth; x++) { BlindSetPixelIndex(x, y, lut[BlindGetPixelIndex(x, y)]); } } } else { switch(method){ case 1: { // <nipper> double p[256]; memset(p, 0, 256*sizeof(double)); for (y=0; y<head.biHeight; y++) { info.nProgress = (long)(y*dbScaler); if (info.nEscape) break; for (x=0; x<head.biWidth; x++) { RGBQUAD color = BlindGetPixelColor(x, y); p[color.rgbRed]++; p[color.rgbBlue]++; p[color.rgbGreen]++; } } double maxh = 0; for (y=0; y<255; y++) if (maxh < p[y]) maxh = p[y]; threshold *= maxh; int minc = 0; while (minc<255 && p[minc]<=threshold) minc++; int maxc = 255; while (maxc>0 && p[maxc]<=threshold) maxc--; if (minc == 0 && maxc == 255) return true; if (minc >= maxc) return true; // calculate LUT BYTE lut[256]; for (x = 0; x <256; x++){ lut[x] = (BYTE)max(0,min(255,(255 * (x - minc) / (maxc - minc)))); } // normalize image for (y=0; y<head.biHeight; y++) { if (info.nEscape) break; info.nProgress = (long)(50.0+y*dbScaler); for (x=0; x<head.biWidth; x++) { RGBQUAD color = BlindGetPixelColor(x, y); color.rgbRed = lut[color.rgbRed]; color.rgbBlue = lut[color.rgbBlue]; color.rgbGreen = lut[color.rgbGreen]; BlindSetPixelColor(x, y, color); } } } break; case 2: { // <nipper> double pR[256]; memset(pR, 0, 256*sizeof(double)); double pG[256]; memset(pG, 0, 256*sizeof(double)); double pB[256]; memset(pB, 0, 256*sizeof(double)); for (y=0; y<head.biHeight; y++) { info.nProgress = (long)(y*dbScaler); if (info.nEscape) break; for (long x=0; x<head.biWidth; x++) { RGBQUAD color = BlindGetPixelColor(x, y); pR[color.rgbRed]++; pB[color.rgbBlue]++; pG[color.rgbGreen]++; } } double maxh = 0; for (y=0; y<255; y++) if (maxh < pR[y]) maxh = pR[y]; double threshold2 = threshold*maxh; int minR = 0; while (minR<255 && pR[minR]<=threshold2) minR++; int maxR = 255; while (maxR>0 && pR[maxR]<=threshold2) maxR--; maxh = 0; for (y=0; y<255; y++) if (maxh < pG[y]) maxh = pG[y]; threshold2 = threshold*maxh; int minG = 0; while (minG<255 && pG[minG]<=threshold2) minG++; int maxG = 255; while (maxG>0 && pG[maxG]<=threshold2) maxG--; maxh = 0; for (y=0; y<255; y++) if (maxh < pB[y]) maxh = pB[y]; threshold2 = threshold*maxh; int minB = 0; while (minB<255 && pB[minB]<=threshold2) minB++; int maxB = 255; while (maxB>0 && pB[maxB]<=threshold2) maxB--; if (minR == 0 && maxR == 255 && minG == 0 && maxG == 255 && minB == 0 && maxB == 255) return true; // calculate LUT BYTE lutR[256]; BYTE range = maxR - minR; if (range != 0) { for (x = 0; x <256; x++){ lutR[x] = (BYTE)max(0,min(255,(255 * (x - minR) / range))); } } else lutR[minR] = minR; BYTE lutG[256]; range = maxG - minG; if (range != 0) { for (x = 0; x <256; x++){ lutG[x] = (BYTE)max(0,min(255,(255 * (x - minG) / range))); } } else lutG[minG] = minG; BYTE lutB[256]; range = maxB - minB; if (range != 0) { for (x = 0; x <256; x++){ lutB[x] = (BYTE)max(0,min(255,(255 * (x - minB) / range))); } } else lutB[minB] = minB; // normalize image for (y=0; y<head.biHeight; y++) { info.nProgress = (long)(50.0+y*dbScaler); if (info.nEscape) break; for (x=0; x<head.biWidth; x++) { RGBQUAD color = BlindGetPixelColor(x, y); color.rgbRed = lutR[color.rgbRed]; color.rgbBlue = lutB[color.rgbBlue]; color.rgbGreen = lutG[color.rgbGreen]; BlindSetPixelColor(x, y, color); } } } break; default: { // <dave> double p[256]; memset(p, 0, 256*sizeof(double)); for (y=0; y<head.biHeight; y++) { info.nProgress = (long)(y*dbScaler); if (info.nEscape) break; for (x=0; x<head.biWidth; x++) { RGBQUAD color = BlindGetPixelColor(x, y); p[RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue)]++; } } double maxh = 0; for (y=0; y<255; y++) if (maxh < p[y]) maxh = p[y]; threshold *= maxh; int minc = 0; while (minc<255 && p[minc]<=threshold) minc++; int maxc = 255; while (maxc>0 && p[maxc]<=threshold) maxc--; if (minc == 0 && maxc == 255) return true; if (minc >= maxc) return true; // calculate LUT BYTE lut[256]; for (x = 0; x <256; x++){ lut[x] = (BYTE)max(0,min(255,(255 * (x - minc) / (maxc - minc)))); } for(y=0; y<head.biHeight; y++){ info.nProgress = (long)(50.0+y*dbScaler); if (info.nEscape) break; for(x=0; x<head.biWidth; x++){ RGBQUAD color = BlindGetPixelColor( x, y ); RGBQUAD yuvClr = RGBtoYUV(color); yuvClr.rgbRed = lut[yuvClr.rgbRed]; color = YUVtoRGB(yuvClr); BlindSetPixelColor( x, y, color ); } } } } } return true; }
//////////////////////////////////////////////////////////////////////////////// // HistogramRoot function by <dave> : dave(at)posortho(dot)com bool CxImage::HistogramRoot() { if (!pDib) return false; //q(i,j) = sqrt(|p(i,j)|); int x, y, i; RGBQUAD color; RGBQUAD yuvClr; double dtmp; unsigned int YVal, high = 1; // Find Highest Luminance Value in the Image if( head.biClrUsed == 0 ){ // No Palette for(y=0; y < head.biHeight; y++){ info.nProgress = (long)(50*y/head.biHeight); if (info.nEscape) break; for(x=0; x < head.biWidth; x++){ color = BlindGetPixelColor( x, y ); YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); if (YVal > high ) high = YVal; } } } else { // Palette for(i = 0; i < (int)head.biClrUsed; i++){ color = GetPaletteColor((BYTE)i); YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); if (YVal > high ) high = YVal; } } // Root Operator double k = 128.0 / ::log( 1.0 + (double)high ); if( head.biClrUsed == 0 ){ for( y = 0; y < head.biHeight; y++ ){ info.nProgress = (long)(50+50*y/head.biHeight); if (info.nEscape) break; for( x = 0; x < head.biWidth; x++ ){ color = BlindGetPixelColor( x, y ); yuvClr = RGBtoYUV( color ); dtmp = k * ::sqrt( (double)yuvClr.rgbRed ); if ( dtmp > 255.0 ) dtmp = 255.0; if ( dtmp < 0 ) dtmp = 0; yuvClr.rgbRed = (BYTE)dtmp; color = YUVtoRGB( yuvClr ); BlindSetPixelColor( x, y, color ); } } } else { for(i = 0; i < (int)head.biClrUsed; i++){ color = GetPaletteColor( (BYTE)i ); yuvClr = RGBtoYUV( color ); dtmp = k * ::sqrt( (double)yuvClr.rgbRed ); if ( dtmp > 255.0 ) dtmp = 255.0; if ( dtmp < 0 ) dtmp = 0; yuvClr.rgbRed = (BYTE)dtmp; color = YUVtoRGB( yuvClr ); SetPaletteColor( (BYTE)i, color ); } } return true; }
//////////////////////////////////////////////////////////////////////////////// // HistogramNormalize function by <dave> : dave(at)posortho(dot)com bool CxImage::HistogramNormalize() { if (!pDib) return false; int histogram[256]; int threshold_intensity, intense; int x, y, i; unsigned int normalize_map[256]; unsigned int high, low, YVal; RGBQUAD color; RGBQUAD yuvClr; memset( &histogram, 0, sizeof( int ) * 256 ); memset( &normalize_map, 0, sizeof( unsigned int ) * 256 ); // form histogram for(y=0; y < head.biHeight; y++){ info.nProgress = (long)(50*y/head.biHeight); if (info.nEscape) break; for(x=0; x < head.biWidth; x++){ color = BlindGetPixelColor( x, y ); YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); histogram[YVal]++; } } // find histogram boundaries by locating the 1 percent levels threshold_intensity = ( head.biWidth * head.biHeight) / 100; intense = 0; for( low = 0; low < 255; low++ ){ intense += histogram[low]; if( intense > threshold_intensity ) break; } intense = 0; for( high = 255; high != 0; high--){ intense += histogram[ high ]; if( intense > threshold_intensity ) break; } if ( low == high ){ // Unreasonable contrast; use zero threshold to determine boundaries. threshold_intensity = 0; intense = 0; for( low = 0; low < 255; low++){ intense += histogram[low]; if( intense > threshold_intensity ) break; } intense = 0; for( high = 255; high != 0; high-- ){ intense += histogram [high ]; if( intense > threshold_intensity ) break; } } if( low == high ) return false; // zero span bound // Stretch the histogram to create the normalized image mapping. for(i = 0; i <= 255; i++){ if ( i < (int) low ){ normalize_map[i] = 0; } else { if(i > (int) high) normalize_map[i] = 255; else normalize_map[i] = ( 255 - 1) * ( i - low) / ( high - low ); } } // Normalize if( head.biClrUsed == 0 ){ for( y = 0; y < head.biHeight; y++ ){ info.nProgress = (long)(50+50*y/head.biHeight); if (info.nEscape) break; for( x = 0; x < head.biWidth; x++ ){ color = BlindGetPixelColor( x, y ); yuvClr = RGBtoYUV( color ); yuvClr.rgbRed = (BYTE)normalize_map[yuvClr.rgbRed]; color = YUVtoRGB( yuvClr ); BlindSetPixelColor( x, y, color ); } } } else { for(i = 0; i < (int)head.biClrUsed; i++){ color = GetPaletteColor( (BYTE)i ); yuvClr = RGBtoYUV( color ); yuvClr.rgbRed = (BYTE)normalize_map[yuvClr.rgbRed]; color = YUVtoRGB( yuvClr ); SetPaletteColor( (BYTE)i, color ); } } return true; }
//////////////////////////////////////////////////////////////////////////////// // HistogramEqualize function by <dave> : dave(at)posortho(dot)com bool CxImage::HistogramEqualize() { if (!pDib) return false; int histogram[256]; int map[256]; int equalize_map[256]; int x, y, i, j; RGBQUAD color; RGBQUAD yuvClr; unsigned int YVal, high, low; memset( &histogram, 0, sizeof(int) * 256 ); memset( &map, 0, sizeof(int) * 256 ); memset( &equalize_map, 0, sizeof(int) * 256 ); // form histogram for(y=0; y < head.biHeight; y++){ info.nProgress = (long)(50*y/head.biHeight); if (info.nEscape) break; for(x=0; x < head.biWidth; x++){ color = BlindGetPixelColor( x, y ); YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); histogram[YVal]++; } } // integrate the histogram to get the equalization map. j = 0; for(i=0; i <= 255; i++){ j += histogram[i]; map[i] = j; } // equalize low = map[0]; high = map[255]; if (low == high) return false; for( i = 0; i <= 255; i++ ){ equalize_map[i] = (unsigned int)((((double)( map[i] - low ) ) * 255) / ( high - low ) ); } // stretch the histogram if(head.biClrUsed == 0){ // No Palette for( y = 0; y < head.biHeight; y++ ){ info.nProgress = (long)(50+50*y/head.biHeight); if (info.nEscape) break; for( x = 0; x < head.biWidth; x++ ){ color = BlindGetPixelColor( x, y ); yuvClr = RGBtoYUV(color); yuvClr.rgbRed = (BYTE)equalize_map[yuvClr.rgbRed]; color = YUVtoRGB(yuvClr); BlindSetPixelColor( x, y, color ); } } } else { // Palette for( i = 0; i < (int)head.biClrUsed; i++ ){ color = GetPaletteColor((BYTE)i); yuvClr = RGBtoYUV(color); yuvClr.rgbRed = (BYTE)equalize_map[yuvClr.rgbRed]; color = YUVtoRGB(yuvClr); SetPaletteColor( (BYTE)i, color ); } } return true; }
/** * HistogramStretch * \param method: 0 = luminance (default), 1 = linked channels , 2 = independent channels. * \return true if everything is ok * \author [dave] and [nipper] */ bool CxImage::HistogramStretch(long method) { if (!pDib) return false; if ((head.biBitCount==8) && IsGrayScale()){ // get min/max info BYTE minc = 255, maxc = 0; BYTE gray; long y; double dbScaler = 50.0/head.biHeight; for (y=0; y<head.biHeight; y++) { info.nProgress = (long)(y*dbScaler); for (long x=0; x<head.biWidth; x++) { gray = GetPixelIndex(x, y); if (gray < minc) minc = gray; if (gray > maxc) maxc = gray; } } if (minc == 0 && maxc == 255) return true; // calculate LUT BYTE lut[256]; BYTE range = maxc - minc; if (range != 0){ for (long x = minc; x <= maxc; x++){ lut[x] = (BYTE)(255 * (x - minc) / range); } } else lut[minc] = minc; for (y=0; y<head.biHeight; y++) { info.nProgress = (long)(50.0+y*dbScaler); for (long x=0; x<head.biWidth; x++) { SetPixelIndex(x, y, lut[GetPixelIndex(x, y)]); } } } else { switch(method){ case 1: { // <nipper> // get min/max info BYTE minc = 255, maxc = 0; RGBQUAD color; long y; for (y=0; y<head.biHeight; y++) { for (long x=0; x<head.biWidth; x++) { color = GetPixelColor(x, y); if (color.rgbRed < minc) minc = color.rgbRed; if (color.rgbBlue < minc) minc = color.rgbBlue; if (color.rgbGreen < minc) minc = color.rgbGreen; if (color.rgbRed > maxc) maxc = color.rgbRed; if (color.rgbBlue > maxc) maxc = color.rgbBlue; if (color.rgbGreen > maxc) maxc = color.rgbGreen; } } if (minc == 0 && maxc == 255) return true; // calculate LUT BYTE lut[256]; BYTE range = maxc - minc; if (range != 0){ for (long x = minc; x <= maxc; x++){ lut[x] = (BYTE)(255 * (x - minc) / range); } } else lut[minc] = minc; // normalize image double dbScaler = 100.0/head.biHeight; for (y=0; y<head.biHeight; y++) { info.nProgress = (long)(y*dbScaler); for (long x=0; x<head.biWidth; x++) { color = GetPixelColor(x, y); color.rgbRed = lut[color.rgbRed]; color.rgbBlue = lut[color.rgbBlue]; color.rgbGreen = lut[color.rgbGreen]; SetPixelColor(x, y, color); } } } break; case 2: { // <nipper> // get min/max info BYTE minR = 255, maxR = 0; BYTE minG = 255, maxG = 0; BYTE minB = 255, maxB = 0; RGBQUAD color; long y; for (y=0; y<head.biHeight; y++) { for (long x=0; x<head.biWidth; x++) { color = GetPixelColor(x, y); if (color.rgbRed < minR) minR = color.rgbRed; if (color.rgbBlue < minB) minB = color.rgbBlue; if (color.rgbGreen < minG) minG = color.rgbGreen; if (color.rgbRed > maxR) maxR = color.rgbRed; if (color.rgbBlue > maxB) maxB = color.rgbBlue; if (color.rgbGreen > maxG) maxG = color.rgbGreen; } } if (minR == 0 && maxR == 255 && minG == 0 && maxG == 255 && minB == 0 && maxB == 255) return true; // calculate LUT BYTE lutR[256]; BYTE range = maxR - minR; if (range != 0) { for (long x = minR; x <= maxR; x++){ lutR[x] = (BYTE)(255 * (x - minR) / range); } } else lutR[minR] = minR; BYTE lutG[256]; range = maxG - minG; if (range != 0) { for (long x = minG; x <= maxG; x++){ lutG[x] = (BYTE)(255 * (x - minG) / range); } } else lutG[minG] = minG; BYTE lutB[256]; range = maxB - minB; if (range != 0) { for (long x = minB; x <= maxB; x++){ lutB[x] = (BYTE)(255 * (x - minB) / range); } } else lutB[minB] = minB; // normalize image double dbScaler = 100.0/head.biHeight; for (y=0; y<head.biHeight; y++) { info.nProgress = (long)(y*dbScaler); for (long x=0; x<head.biWidth; x++) { color = GetPixelColor(x, y); color.rgbRed = lutR[color.rgbRed]; color.rgbBlue = lutB[color.rgbBlue]; color.rgbGreen = lutG[color.rgbGreen]; SetPixelColor(x, y, color); } } } break; default: { // <dave> // S = ( R - C ) ( B - A / D - C ) double alimit = 0.0; double blimit = 255.0; double lowerc = 255.0; double upperd = 0.0; double tmpGray; RGBQUAD color; RGBQUAD yuvClr; double stretcheds; if ( head.biClrUsed == 0 ){ long x, y, xmin, xmax, ymin, ymax; xmin = ymin = 0; xmax = head.biWidth; ymax = head.biHeight; for( y = ymin; y < ymax; y++ ){ info.nProgress = (long)(50*y/ymax); for( x = xmin; x < xmax; x++ ){ color = GetPixelColor( x, y ); tmpGray = RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); if ( tmpGray < lowerc ) lowerc = tmpGray; if ( tmpGray > upperd ) upperd = tmpGray; } } if (upperd==lowerc) return false; for( y = ymin; y < ymax; y++ ){ info.nProgress = (long)(50+50*y/ymax); for( x = xmin; x < xmax; x++ ){ color = GetPixelColor( x, y ); yuvClr = RGBtoYUV(color); // Stretch Luminance tmpGray = (double)yuvClr.rgbRed; stretcheds = (double)(tmpGray - lowerc) * ( (blimit - alimit) / (upperd - lowerc) ); // + alimit; if ( stretcheds < 0.0 ) stretcheds = 0.0; else if ( stretcheds > 255.0 ) stretcheds = 255.0; yuvClr.rgbRed = (BYTE)stretcheds; color = YUVtoRGB(yuvClr); SetPixelColor( x, y, color ); } } } else { DWORD j; for( j = 0; j < head.biClrUsed; j++ ){ color = GetPaletteColor( (BYTE)j ); tmpGray = RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); if ( tmpGray < lowerc ) lowerc = tmpGray; if ( tmpGray > upperd ) upperd = tmpGray; } if (upperd==lowerc) return false; for( j = 0; j < head.biClrUsed; j++ ){ color = GetPaletteColor( (BYTE)j ); yuvClr = RGBtoYUV( color ); // Stretch Luminance tmpGray = (double)yuvClr.rgbRed; stretcheds = (double)(tmpGray - lowerc) * ( (blimit - alimit) / (upperd - lowerc) ); // + alimit; if ( stretcheds < 0.0 ) stretcheds = 0.0; else if ( stretcheds > 255.0 ) stretcheds = 255.0; yuvClr.rgbRed = (BYTE)stretcheds; color = YUVtoRGB(yuvClr); SetPaletteColor( (BYTE)j, color ); } } } } } return true; }
BitmapStorage *BitmapIO_YUV::Load(BitmapInfo *fbi, Bitmap *map, BMMRES *status) { unsigned char *yuvbuf = NULL; BMM_Color_64 *rgbbuf = NULL; BitmapStorage *s = NULL; //-- Initialize Status Optimistically *status = BMMRES_SUCCESS; //-- Make sure nothing weird is going on if(openMode != BMM_NOT_OPEN) { *status = ProcessImageIOError(fbi,BMMRES_INTERNALERROR); return NULL; } //-- Update Bitmap Info *status = GetImageInfo(fbi); if (*status != BMMRES_SUCCESS) return(NULL); //-- Open YUV File ----------------------------------- File file(fbi->Name(), _T("rb")); inStream = file.stream; if (inStream == NULL) { *status = ProcessImageIOError(fbi); return NULL; } //-- Create Image Storage ---------------------------- s = BMMCreateStorage(map->Manager(),BMM_TRUE_32); if(!s) { *status = ProcessImageIOError(fbi,BMMRES_INTERNALERROR); return NULL; } //-- Allocate Image Storage -------------------------- if (s->Allocate(fbi,map->Manager(),BMM_OPEN_R)==0) { memory_error_out: *status = ProcessImageIOError(fbi,BMMRES_MEMORYERROR); goto bail_out; io_error_out: *status = ProcessImageIOError(fbi); bail_out: if (s) delete s; if (yuvbuf) free(yuvbuf); if (rgbbuf) free(rgbbuf); return NULL; } //-- Allocate Buffers -------------------------------- yuvbuf=(unsigned char *)malloc(fbi->Width()*2); rgbbuf=(BMM_Color_64 *)malloc(fbi->Width()*sizeof(BMM_Color_64)); if(!yuvbuf || !rgbbuf) goto memory_error_out; //-- Read Image INT_PTR pixels = fbi->Width() * fbi->Height(); int rows = 0; while (pixels) { pixels = fread(yuvbuf,2,fbi->Width(),inStream); if (pixels != fbi->Width() && pixels != 0) { goto io_error_out; } if (pixels) { YUVtoRGB(rgbbuf,yuvbuf,fbi->Width()); if (s->PutPixels(0,rows,fbi->Width(),rgbbuf)!=1) goto io_error_out; rows++; if (rows>fbi->Height()) break; } //-- Progress Report if (fbi->GetUpdateWindow()) SendMessage(fbi->GetUpdateWindow(),BMM_PROGRESS,rows,fbi->Height()); } if (yuvbuf) free(yuvbuf); if (rgbbuf) free(rgbbuf); //-- Set the storage's BitmapInfo s->bi.CopyImageInfo(fbi); return s; }