/*************************************************************************** dxr3colormanager.c - description ------------------- begin : Tue Oct 22 2002 copyright : (C) 2002 by Stefan Schluenss email : vdr@schluenss.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** * Background: * Each encoded pixel in the SPU could have one of the values 0,1,2,3. * * These values Pixelvalue Maps to index 0 --> 4 --> * The SPU data definition allows highlighting of rectangular areas. They * * are defined by a starting and ending row. Whithin these rows one could * * define a starting column for using a new color palette mapping. This * * mapping will be used til the end of the line or up to the next column * * defintion. * Look at the picture below: * Row Col=5 Col=16 n-2 ............................... n-1 ............................... n .....-------------------------- <- Highligh region starts here .....| 6,3,1,2 | 0,2,8,9 .....| 6,3,1,2 | 0,2,8,9 .....| 6,3,1,2 | 0,2,8,9 n+4 .....-------------------------- <- Highligh region ends here n+5 ............................... n+6 ............................... In the above example one region (from n to n+4) is defined with two * highlight sections - one from column 5 up to 15 and the second from 16 * til the end of the line. **/ #include #include "dxr3colormanager.h" #include #include #include // ================================== //! constructor cColorManager::cColorManager() { NrOfRegions = -1; for(int i = 0; i < MAX_NO_OF_REGIONS; i++) hlr[i] = NULL; } // ================================== cColorManager::~cColorManager() { for (int i = 0; i < NrOfRegions; i++) { if (hlr[i]) { delete(hlr[i]); } } } // ================================== // Opens a new highlight region void cColorManager::OpenRegion(int y) { // Calling method (cColorManager::EncodeColors) // already checks MAX_NO_OF_REGIONS curRegion = new yRegion(); curRegion->Y1 = y; NrOfRegions++; hlr[NrOfRegions] = curRegion; NewSection(0); //there's always at least a section } // ================================== // Closes the spu-highlight region void cColorManager::CloseRegion(int y) { curRegion->Y2 = y; } // ================================== void cColorManager::EncodeColors(int width, int height, unsigned char* map, unsigned char* dmap) { unsigned char color; unsigned char oldcolor = 0xFF; unsigned char ColorIndex; int mapoffset = 0; OpenRegion(0); for (int y = 0; y < height; ++y) { oldcolor = 0xFF; FirstSection(); for(int x = 0; x < width; ++x) { if (x > curSection->X2) { oldcolor = 0xFF; NextSection(); } color = map[mapoffset + x]; if (color == oldcolor) dmap[mapoffset + x] = ColorIndex; else { // try to map the color in the current region if (AddColor(x, y, color, ColorIndex)) { // store as the highlight region index dmap[mapoffset + x] = ColorIndex; } else { CloseRegion(y - 1); if (NrOfRegions <= MAX_NO_OF_REGIONS - 1) { // retry with another region OpenRegion(y); x = -1; oldcolor = 0xFF; } else { esyslog("dxr3: colormanager: too many regions (%d)" " - giving up", NrOfRegions); return; } } } } mapoffset += width; } // close the last highlight region CloseRegion(height); //#define colordebug #ifdef colordebug { FILE *fp; fp = fopen("OSD.dump","w+"); u_char *pippo = dmap; u_char *pippo2 = map; int curregion = 0; int cursection = 0; for (int dumpy = 0; dumpy < height; dumpy++) { if(curregion < NrOfRegions) { if(hlr[curregion]->Y1 == dumpy) { fprintf(fp, "%i", hlr[curregion]->N); for (int sec = 0; sec < hlr[curregion]->N; sec++) fprintf(fp, ",%i", hlr[curregion]->Section[sec]->X1); for (int dumpx = 0; dumpx < width; dumpx++) fprintf(fp, "="); fprintf(fp, "\n"); curregion++; } } cursection = 0; for (int dumpx = 0; dumpx < width; dumpx++) { if (curregion < NrOfRegions) { if (cursection < hlr[curregion]->N) { if (hlr[curregion]->Section[cursection]->X1 == dumpx) { fprintf(fp, "|"); cursection++; } } } fprintf(fp, "%01X", *pippo2 & 0xF); pippo2++; } fprintf(fp, "\n"); cursection = 0; for (int dumpx = 0; dumpx < width; dumpx++) { if(curregion < NrOfRegions) { if (cursection < hlr[curregion]->N) { if (hlr[curregion]->Section[cursection]->X1 == dumpx) { fprintf(fp, "|"); cursection++; } } } fprintf(fp, "%01X", *pippo & 0xF); pippo++; } fprintf(fp, "\n"); } fclose(fp); printf("**** dumped\n"); } #endif } // ================================== unsigned char cColorManager::AddColor(int x, int y, unsigned char color, unsigned char &ColorIndex) { if (!curSection->HasColor(color, ColorIndex)) { // this color is new for this section if (curSection->AllColorsUsed(curRegion->Y1==y)) { // no more free colors if (y != curRegion->Y1) { // terminate region return(0); } NewSection(x); } // and add new color ColorIndex = curSection->AddColor(color); } return(1); } // ================================== void cColorManager::FirstSection(void) { curSectionIndex = 0; curSection = curRegion->Section[0]; } // ================================== void cColorManager::NextSection(void) { curSectionIndex++; if (curSectionIndex < curRegion->N) curSection=curRegion->Section[curSectionIndex]; // it shouldn't happen else esyslog("dxr3: colormanager: ran out of sections"); } // ================================== // convert into SPU - hope is correct description unsigned char* cColorManager::GetSpuData(int& len) { if (NrOfRegions >= 0) { int ptr = 0; spudata[ptr++] = 0x07; // CHG_COLCON command spudata[ptr++] = 0x00; // total size of parameter area spudata[ptr++] = 0x00; // will be filled later for(int i = 0; i <= NrOfRegions;i++) { spudata[ptr++] = (hlr[i]->Y1 >> 8) & 0x0f; spudata[ptr++] = (hlr[i]->Y1 & 0xff); spudata[ptr++] = (((hlr[i]->N) & 0x0f) << 4) | ((hlr[i]->Y2 >> 8) & 0x0f); spudata[ptr++] = (hlr[i]->Y2 & 0xff); for(int c = 0; c < hlr[i]->N; c++) { spudata[ptr++] = hlr[i]->Section[c]->X1 >> 8; spudata[ptr++] = hlr[i]->Section[c]->X1 & 0xff; spudata[ptr++] = (hlr[i]->Section[c]->Colors[3] << 4) | (hlr[i]->Section[c]->Colors[2] & 0x0F); spudata[ptr++] = (hlr[i]->Section[c]->Colors[1] << 4) | (hlr[i]->Section[c]->Colors[0] & 0x0F); spudata[ptr++] = (hlr[i]->Section[c]->Opac[3] << 4) | hlr[i]->Section[c]->Opac[2]; spudata[ptr++] = (hlr[i]->Section[c]->Opac[1] << 4) | hlr[i]->Section[c]->Opac[0]; } } spudata[ptr++] = 0x0f; // termination of parameter block spudata[ptr++] = 0xff; spudata[ptr++] = 0xff; spudata[ptr++] = 0xff; int size = ptr - 1; spudata[1] = size >> 8; spudata[2] = size & 0xff; len = ptr; } else { len = 0; } #if OSD_SPU_CM_DUMP FILE *fp; fp = fopen("CM.dump", "a+"); fprintf(fp, "len:%03d ", len); for (int i = 0; i < len; i++) fprintf(fp, "%02X", *(spudata + i)); fprintf(fp, "\n"); fclose(fp); #endif return(spudata); } // ================================== void cColorManager::NewSection(int x) { int N = curRegion->N; if (N >= MAX_NO_OF_SECTIONS - 1) { esyslog("dxr3: colormanager: bummer, too many sections (%d)," " reusing last one", N); return; // reuse last section, not optimal but there's no other way out } curSection = new xSection(x); curRegion->Section[N] = curSection; if (N > 0) curRegion->Section[N-1]->X2 = x - 1; (curRegion->N)++; curSectionIndex = N; } // ================================== xSection::xSection(int x) { X1 = x; X2 = 32767; NrOfColors = 0; for (int i = 0; i < 4; i++) { Opac[i] = 0xFF; Colors[i] = 0; } } // ================================== unsigned char xSection::AddColor(unsigned int color) { unsigned char ColorIndex = 0; if (NrOfColors <= 3) { Colors[NrOfColors] = color; Opac[NrOfColors] = color >> 4; ColorIndex = NrOfColors; NrOfColors++; } return(ColorIndex); } // ================================== bool xSection::HasColor(unsigned int color, unsigned char &ColorIndex) { for(int i = 0; i < NrOfColors; i++) { if (Colors[i] == color) { ColorIndex = i; return (true); } } return(false); } // Local variables: // mode: c++ // c-file-style: "stroustrup" // c-file-offsets: ((inline-open . 0)) // indent-tabs-mode: t // End: