BlinkenArea - GitList
Repositories
Blog
Wiki
BlinkenLib
Code
Commits
Branches
Tags
Search
Tree:
962674e
Branches
Tags
master
v0.1
v0.2
v0.3
v0.3.1
v0.4
v0.4.1
v0.5
v0.5.1
v0.5.2
v0.5.3
v0.5.4
v0.5.5
v0.6.0
v0.6.1
v0.6.2
v0.6.3
v0.6.4
v0.6.5
v0.6.6
v0.6.7
v0.6.8
v0.6.9
v0.7.0
v0.7.1
v0.7.10
v0.7.2
v0.7.3
v0.7.4
v0.7.5
v0.7.6
v0.7.7
v0.7.8
v0.7.9
v0.8.0
v0.8.1
BlinkenLib
BlinkenFrame.c
BlinkenLib v.0.1.1 (2005-01-23)
Christian Heimke
commited
962674e
at 2011-07-15 09:00:54
BlinkenFrame.c
Blame
History
Raw
/* BlinkenLib * version 0.1 date 2004-11-25 * Copyright (C) 2004: Stefan Schuermans <1stein@schuermans.info> * Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html * a blinkenarea.org project * powered by eventphone.de */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "BlinkenConstants.h" #include "BlinkenFrame.h" #include "Tools.h" struct sBlinkenFrame { int height; int width; int channels; int maxval; int duration; unsigned char * * * pppData; }; stBlinkenFrame * BlinkenFrameNew( int height, int width, int channels, int maxval, int duration ) { stBlinkenFrame * pFrame; if( height < BlinkenHeightMin ) height = BlinkenHeightMin; if( height > BlinkenHeightMax ) height = BlinkenHeightMax; if( width < BlinkenWidthMin ) width = BlinkenWidthMin; if( width > BlinkenWidthMax ) width = BlinkenWidthMax; if( channels < BlinkenChannelsMin ) channels = BlinkenChannelsMin; if( channels > BlinkenChannelsMax ) channels = BlinkenMaxvalMax; if( maxval < BlinkenMaxvalMin ) maxval = BlinkenMaxvalMin; if( maxval > BlinkenMaxvalMax ) maxval = BlinkenMaxvalMax; if( duration < BlinkenDurationMin ) duration = BlinkenDurationMin; if( duration > BlinkenDurationMax ) duration = BlinkenDurationMax; pFrame = (stBlinkenFrame *)malloc( sizeof( stBlinkenFrame ) ); if( pFrame == NULL ) return NULL; pFrame->height = height; pFrame->width = width; pFrame->channels = channels; pFrame->maxval = maxval; pFrame->duration = duration; pFrame->pppData = (unsigned char * * *)malloc3D( height, width, channels, sizeof( unsigned char ) ); if( pFrame->pppData == NULL ) { free( pFrame ); return NULL; } return pFrame; } stBlinkenFrame * BlinkenFrameClone( stBlinkenFrame * pSrcFrame ) { int y, x, c; stBlinkenFrame * pFrame; if( pSrcFrame == NULL ) return NULL; pFrame = BlinkenFrameNew( pSrcFrame->height, pSrcFrame->width, pSrcFrame->channels, pSrcFrame->maxval, pSrcFrame->duration ); if( pFrame == NULL ) return NULL; for( y = 0; y < pFrame->height; y++ ) for( x = 0; x < pFrame->width; x++ ) for( c = 0; c < pFrame->channels; c++ ) pFrame->pppData[y][x][c] = pSrcFrame->pppData[y][x][c]; return pFrame; } void BlinkenFrameFree( stBlinkenFrame * pFrame ) { if( pFrame == NULL ) return; free( pFrame->pppData ); free( pFrame ); } void BlinkenFrameClear( stBlinkenFrame * pFrame ) { int y, x, c; if( pFrame == NULL ) return; for( y = 0; y < pFrame->height; y++ ) for( x = 0; x < pFrame->width; x++ ) for( c = 0; c < pFrame->channels; c++ ) pFrame->pppData[y][x][c] = 0; } int BlinkenFrameGetHeight( stBlinkenFrame * pFrame ) { if( pFrame == NULL ) return 0; return pFrame->height; } int BlinkenFrameGetWidth( stBlinkenFrame * pFrame ) { if( pFrame == NULL ) return 0; return pFrame->width; } int BlinkenFrameGetChannels( stBlinkenFrame * pFrame ) { if( pFrame == NULL ) return 0; return pFrame->channels; } int BlinkenFrameGetMaxval( stBlinkenFrame * pFrame ) { if( pFrame == NULL ) return 0; return pFrame->maxval; } int BlinkenFrameGetDuration( stBlinkenFrame * pFrame ) { if( pFrame == NULL ) return 0; return pFrame->duration; } void BlinkenFrameSetDuration( stBlinkenFrame * pFrame, int duration ) { if( pFrame == NULL ) return; if( duration < BlinkenDurationMin ) duration = BlinkenDurationMin; if( duration > BlinkenDurationMax ) duration = BlinkenDurationMax; pFrame->duration = duration; } unsigned char BlinkenFrameGetPixel( stBlinkenFrame * pFrame, int y, int x, int c ) { if( pFrame == NULL || y < 0 || y >= pFrame->height || x < 0 || x >= pFrame->width || c < 0 || c >= pFrame->channels ) return 0; return pFrame->pppData[y][x][c]; } void BlinkenFrameSetPixel( stBlinkenFrame * pFrame, int y, int x, int c, unsigned char val ) { if( pFrame == NULL || y < 0 || y >= pFrame->height || x < 0 || x >= pFrame->width || c < 0 || c >= pFrame->channels ) return; if( val > pFrame->maxval ) val = pFrame->maxval; pFrame->pppData[y][x][c] = val; } unsigned long BlinkenFrameGetColor( stBlinkenFrame * pFrame, int y, int x ) { if( pFrame == NULL || y < 0 || y >= pFrame->height || x < 0 || x >= pFrame->width ) return 0; if( pFrame->channels == 1 ) return (((unsigned long)pFrame->pppData[y][x][0] * 255 + pFrame->maxval / 2) / pFrame->maxval) << 16 | (((unsigned long)pFrame->pppData[y][x][0] * 255 + pFrame->maxval / 2) / pFrame->maxval) << 8 | (((unsigned long)pFrame->pppData[y][x][0] * 255 + pFrame->maxval / 2) / pFrame->maxval); if( pFrame->channels == 2 ) return (((unsigned long)pFrame->pppData[y][x][0] * 255 + pFrame->maxval / 2) / pFrame->maxval) << 16 | (((unsigned long)pFrame->pppData[y][x][1] * 255 + pFrame->maxval / 2) / pFrame->maxval) << 8; return (((unsigned long)pFrame->pppData[y][x][0] * 255 + pFrame->maxval / 2) / pFrame->maxval) << 16 | (((unsigned long)pFrame->pppData[y][x][1] * 255 + pFrame->maxval / 2) / pFrame->maxval) << 8 | (((unsigned long)pFrame->pppData[y][x][2] * 255 + pFrame->maxval / 2) / pFrame->maxval); } void BlinkenFrameSetColor( stBlinkenFrame * pFrame, int y, int x, unsigned long color ) { int alpha, alpha_, c; if( pFrame == NULL || y < 0 || y >= pFrame->height || x < 0 || x >= pFrame->width ) return; alpha = (color >> 24) & 0xFF; alpha_ = 255 - alpha; if( pFrame->channels >= 1 ) pFrame->pppData[y][x][0] = (unsigned char)(( ((((color >> 16) & 0xFF) * pFrame->maxval + 127) / 255) * alpha + (unsigned long)pFrame->pppData[y][x][0] * alpha_ ) / 255); if( pFrame->channels >= 2 ) pFrame->pppData[y][x][1] = (unsigned char)(( ((((color >> 8) & 0xFF) * pFrame->maxval + 127) / 255) * alpha + (unsigned long)pFrame->pppData[y][x][1] * alpha_ ) / 255); if( pFrame->channels >= 3 ) pFrame->pppData[y][x][2] = (unsigned char)(( (((color & 0xFF) * pFrame->maxval + 127) / 255) * alpha + (unsigned long)pFrame->pppData[y][x][2] * alpha_ ) / 255); for( c = 3; c < pFrame->channels; c++ ) pFrame->pppData[y][x][c] = (unsigned char)(( 0 + (unsigned long)pFrame->pppData[y][x][c] * alpha_ ) / 255); } void BlinkenFrameResize( stBlinkenFrame * pFrame, int height, int width, int channels, int maxval ) { unsigned char * * * pppData; int y, x, c; int emptyY, emptyX, skipY, skipX, rangeY, rangeX; unsigned long val, div; if( pFrame == NULL ) return; if( height < BlinkenHeightMin ) height = BlinkenHeightMin; if( height > BlinkenHeightMax ) height = BlinkenHeightMax; if( width < BlinkenWidthMin ) width = BlinkenWidthMin; if( width > BlinkenWidthMax ) width = BlinkenWidthMax; if( channels < BlinkenChannelsMin ) channels = BlinkenChannelsMin; if( channels > BlinkenChannelsMax ) channels = BlinkenMaxvalMax; if( maxval < BlinkenMaxvalMin ) maxval = BlinkenMaxvalMin; if( maxval > BlinkenMaxvalMax ) maxval = BlinkenMaxvalMax; if( height == pFrame->height && width == pFrame->width && channels == pFrame->channels && maxval == pFrame->maxval ) return; //allocate new data array pppData = (unsigned char * * *)malloc3D( height, width, channels, sizeof( unsigned char ) ); if( pppData == NULL ) return; for( y = 0; y < height; y++ ) for( x = 0; x < width; x++ ) for( c = 0; c < channels; c++ ) pppData[y][x][c] = 0; //get number of pixels to skip / to leave empty in X and Y direction if( height > pFrame->height ) { emptyY = (height - pFrame->height) / 2; skipY = 0; rangeY = pFrame->height; } else { emptyY = 0; skipY = (pFrame->height - height) / 2; rangeY = height; } if( width > pFrame->width ) { emptyX = (width - pFrame->width) / 2; skipX = 0; rangeX = pFrame->width; } else { emptyX = 0; skipX = (pFrame->width - width) / 2; rangeX = width; } //resize frame with help of calculated parameters for( y = 0; y < rangeY; y++ ) { for( x = 0; x < rangeX; x++ ) { if( channels >= pFrame->channels ) //add channels: copy last channel into new channels { for( c = 0; c < pFrame->channels; c++ ) pppData[emptyY + y][emptyX + x][c] = (unsigned char)(((unsigned long)pFrame->pppData[skipY + y][skipX + x][c] * maxval + pFrame->maxval / 2) / pFrame->maxval); for( ; c < channels; c++ ) pppData[emptyY + y][emptyX + x][c] = pppData[emptyY + y][emptyX + x][pFrame->channels - 1]; } else //remove channels: merge leftover channels with last kept channel { val = 0; for( c = 0; c < channels - 1; c++ ) pppData[emptyY + y][emptyX + x][c] = (unsigned char)(((unsigned long)pFrame->pppData[skipY + y][skipX + x][c] * maxval + pFrame->maxval / 2) / pFrame->maxval); for( c = channels - 1; c < pFrame->channels; c++ ) val += (unsigned long)pFrame->pppData[skipY + y][skipX + x][c]; div = pFrame->maxval * (pFrame->channels - channels + 1); pppData[emptyY + y][emptyX + x][channels - 1] = (unsigned char)((val * maxval + div / 2) / div); } } } pFrame->height = height; pFrame->width = width; pFrame->channels = channels; pFrame->maxval = maxval; free( pFrame->pppData ); pFrame->pppData = pppData; } void BlinkenFrameScale( stBlinkenFrame * pFrame, int height, int width ) { unsigned char * * * pppData; double scaleHor, scaleVer, ox, oy, ox1, oy1, val; int c, nx, ny, x, y, oxi, oyi, ox1i, oy1i; if( pFrame == NULL ) return; if( height < BlinkenHeightMin ) height = BlinkenHeightMin; if( height > BlinkenHeightMax ) height = BlinkenHeightMax; if( width < BlinkenWidthMin ) width = BlinkenWidthMin; if( width > BlinkenWidthMax ) width = BlinkenWidthMax; if( height == pFrame->height && width == pFrame->width ) return; scaleHor = (double)width / (double)pFrame->width; scaleVer = (double)height / (double)pFrame->height; //allocate new data array pppData = (unsigned char * * *)malloc3D( height, width, pFrame->channels, sizeof( unsigned char ) ); if( pppData == NULL ) return; //scale every channel for( c = 0; c < pFrame->channels; c++ ) { for( ny = 0; ny < height; ny++ ) { for( nx = 0; nx < width; nx++ ) { oy = (double)ny / scaleVer; //sub-pixel exact range in old picture ox = (double)nx / scaleHor; oy1 = (double)(ny + 1) / scaleVer - 0.000001; ox1 = (double)(nx + 1) / scaleHor - 0.000001; if( oy < 0 || ox < 0 || oy1 >= pFrame->height || ox1 >= pFrame->width) //out of old picture pppData[ny][nx][c] = 0; else { oyi = (int)oy; oxi = (int)ox; oy1i = (int)oy1; ox1i = (int)ox1; if( oyi == oy1i ) { if( oxi == ox1i) //one source pixel { val = (double)pFrame->pppData[oyi][oxi][c]; } else //one line of source pixels { val = (double)pFrame->pppData[oyi][oxi][c] * (1 - ox + oxi) + (double)pFrame->pppData[oyi][ox1i][c] * (ox1 - ox1i); for( x = oxi + 1; x < ox1i; x++ ) val += (double)pFrame->pppData[oyi][x][c]; val /= ox1 - ox; } } else //one column of source pixels { if( oxi == ox1i ) { val = (double)pFrame->pppData[oyi][oxi][c] * (1 - oy + oyi) + (double)pFrame->pppData[oy1i][oxi][c] * (oy1 - oy1i); for( y = oyi + 1; y < oy1i; y++ ) val += (double)pFrame->pppData[y][oxi][c]; val /= oy1 - oy; } else //rectangle of source pixels { val = (double)pFrame->pppData[oyi][oxi][c] * (1 - oy + oyi) * (1 - ox + oxi) + (double)pFrame->pppData[oyi][ox1i][c] * (1 - oy + oyi) * (ox1 - ox1i) + (double)pFrame->pppData[oy1i][oxi][c] * (oy1 - oy1i) * (1 - ox + oxi) + (double)pFrame->pppData[oy1i][ox1i][c] * (oy1 - oy1i) * (ox1 - ox1i); for( y = oyi + 1; y < oy1i; y++ ) { val += (double)pFrame->pppData[y][oxi][c] * (1 - ox + oxi) + (double)pFrame->pppData[y][ox1i][c] * (ox1 - ox1i); } for( x = oxi + 1; x < ox1i; x++ ) { val += (double)pFrame->pppData[oyi][x][c] * (1 - oy + oyi) + (double)pFrame->pppData[oy1i][x][c] * (oy1 - oy1i); } for( y = oyi + 1; y < oy1i; y++ ) for( x = oxi + 1; x < ox1i; x++ ) val += (double)pFrame->pppData[y][x][c]; val /= (oy1 - oy) * (ox1 - ox); } } pppData[ny][nx][c] = (unsigned char)(val + 0.5); } } //for( nx ... } //for( ny ... } //for( c ... pFrame->height = height; pFrame->width = width; free( pFrame->pppData ); pFrame->pppData = pppData; } char * BlinkenFrameToString( stBlinkenFrame * pFrame ) { int size, y, x, c; char * str, * ptr; unsigned long val; if( pFrame == NULL ) return NULL; size = pFrame->height * (pFrame->width + 1) + 32; str = (char *)malloc( size ); if( str == NULL ) return NULL; ptr = str; for( y = 0; y < pFrame->height; y++ ) { for( x = 0; x < pFrame->width; x++ ) { val = 0; for( val = 0, c = 0; c < pFrame->channels; c++ ) val += pFrame->pppData[y][x][c]; val = val * 7 / pFrame->maxval / pFrame->channels; *ptr = " -+*%#&@"[val]; ptr++; } *ptr = '\n'; ptr++; } sprintf( ptr, "%u ms\n", pFrame->duration ); return str; }