從ARM機上讀取JPG檔案程式碼

wzm10455發表於2013-05-19
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "public.h"
#include "fbdev.h"
#include "gdi.h"

#include "jpeglib.h"
#include "jerror.h"
static unsigned short RGB2LCD16BitsColor(HCANVAS hCanvas,St_RGB stColor)//給畫布設年色置
{
   St_Canvas *pstCanvas = hCanvas;
   unsigned int uiBitsPerPixel = 0;
   unsigned int uiRedLen = 0,uiGreenLen = 0,uiBlueLen = 0;
   unsigned int uiRedOff = 0,uiGreenOff = 0,uiBlueOff = 0;
   unsigned short usRed = 0,usGreen = 0,usBlue = 0;
   unsigned short us16BitsColor = 0;

   if(NULL == pstCanvas)
   {
      printf(DEBUG_ERROR"in file:%s:%d:Invalid Canvas!!!\n",__FILE__,__LINE__);
      return 0;
   }
   if(NULL == pstCanvas->hLCDDev)
   {
      printf(DEBUG_ERROR"in file:%s:%d:Invalid Canvas!!!\n",__FILE__,__LINE__);
      return 0;
   }

   uiBitsPerPixel = GetBitsPerPixel(pstCanvas->hLCDDev);

   if(uiBitsPerPixel != 16)
   {
      printf(DEBUG_ERROR"in file:%s:%d:Invalid BitsPerPixel:%d!!!\n",
              __FILE__,__LINE__,(int)uiBitsPerPixel);
      return 0;
   }
   uiRedLen = GetColorLength(pstCanvas->hLCDDev,E_RED);
   uiGreenLen = GetColorLength(pstCanvas->hLCDDev,E_GREEN);
   uiBlueLen = GetColorLength(pstCanvas->hLCDDev,E_BLUE);
   uiRedOff = GetColorOffset(pstCanvas->hLCDDev,E_RED);
   uiGreenOff = GetColorOffset(pstCanvas->hLCDDev,E_GREEN);
   uiBlueOff = GetColorOffset(pstCanvas->hLCDDev,E_BLUE);

   usRed = stColor.ucRed;
   usGreen = stColor.ucGreen;
   usBlue = stColor.ucBlue;

   us16BitsColor = ((usRed>>(8-uiRedLen)) << uiRedOff)
                   | ((usGreen>>(8-uiGreenLen)) << uiGreenOff)
                   | ((usBlue>>(8-uiBlueLen)) << uiBlueOff);
   return us16BitsColor;
}

void DrawAPoint(HCANVAS hCanvas,int x,int y,St_RGB stColor)
{
   St_Canvas *pstCanvas = hCanvas;
   unsigned int uiLCDWidth = 0;
   unsigned int uiLCDHeight = 0;
   unsigned short usColor16b = 0;
   unsigned short * pusStartBuf = NULL;

   if(NULL == pstCanvas)//畫布如果為空
   {
      printf(DEBUG_ERROR"in file:%s:%d:Invalid Canvas!!!\n",__FILE__,__LINE__);//標柱在哪裡出錯
      return;
   }
   if(NULL == pstCanvas->hLCDDev)//如果LED裝置不存在
   {
      printf(DEBUG_ERROR"in file:%s:%d:Invalid LCD Device!!!\n",__FILE__,__LINE__);
      return;
   }
   usColor16b = RGB2LCD16BitsColor(hCanvas,stColor);//設定16為顏色bit位
   uiLCDWidth = GetLCDWidth(pstCanvas->hLCDDev);//獲得裝置畫布的長度和高度
   uiLCDHeight = GetLCDHeight(pstCanvas->hLCDDev);

   if(x < 0 || x >= uiLCDWidth || y < 0 || y >= uiLCDHeight)//判斷要畫的點的位置是否在範圍之內
   {
      printf(DEBUG_WARNING"in file:%s:%d:Invalid value of point:(%d,%d)!!!\n",
              __FILE__,__LINE__,x,y);
      return;
   }
   pusStartBuf = (unsigned short *)pstCanvas->pvCanvasBuf;//找到起始位置
   *(pusStartBuf + uiLCDWidth * y + x) = usColor16b;//找到要畫的點的存放顏色的位置,然後賦值
   return;
}

void FillRect(HCANVAS hCanvas,int x,int y,int w,int h,St_RGB stColor)
{
   St_Canvas *pstCanvas = hCanvas;
   unsigned int uiLCDWidth = 0;
   unsigned int uiLCDHeight = 0;
   unsigned short usColor16b = 0;
   unsigned short * pusStartBuf = NULL;
   unsigned short * pusRowData = NULL;
   int i = 0;
   unsigned int uiNumOfPixelPerHLine = 0;
   unsigned int uiNumOfPixelPerVLine = 0;

   if(NULL == pstCanvas)
   {
      printf(DEBUG_ERROR"in file:%s:%d:Invalid Canvas!!!\n",__FILE__,__LINE__);
      return;
   }
   if(NULL == pstCanvas->hLCDDev)
   {
      printf(DEBUG_ERROR"in file:%s:%d:Invalid LCD Device!!!\n",__FILE__,__LINE__);
      return;
   }
   usColor16b = RGB2LCD16BitsColor(hCanvas,stColor);
   uiLCDWidth = GetLCDWidth(pstCanvas->hLCDDev);
   uiLCDHeight = GetLCDHeight(pstCanvas->hLCDDev);

   if(x < 0 || x >= uiLCDWidth
      || y < 0 || y >= uiLCDHeight
      || w <= 0 || h <= 0)
   {
      printf(DEBUG_WARNING"in file:%s:%d:Invalid value of point:(%d,%d),w=%d,h=%d!!!\n",
              __FILE__,__LINE__,x,y,w,h);
      return;
   }
   uiNumOfPixelPerHLine = MIN(uiLCDWidth-x,w);
   pusRowData = (unsigned short *)malloc(uiNumOfPixelPerHLine*sizeof(unsigned short));
   if(NULL == pusRowData)
   {
      printf(DEBUG_WARNING"in file:%s:%d:Malloc failed!!!\n",__FILE__,__LINE__);
      return;
   }
   for(i = 0;i < uiNumOfPixelPerHLine;i++)
   {
      pusRowData[i] = usColor16b;
   }
   uiNumOfPixelPerVLine = MIN(uiLCDHeight-y,h);
   pusStartBuf = (unsigned short *)pstCanvas->pvCanvasBuf;
   for(i = 0;i < uiNumOfPixelPerVLine;i++)
   {
      memcpy(pusStartBuf + (y+i)*uiLCDWidth + x,
              pusRowData,
              uiNumOfPixelPerHLine*sizeof(unsigned short));
   }
   free(pusRowData);
   return;
}



void DrawText(HCANVAS hCanvas,
              const unsigned char *pucFontData,
              int wFont,int hFont,
              int x,int y,
              St_RGB stColor)//x,y代表著起始座標
{
     int i,j;
      St_Canvas *pstCanvas = hCanvas;
         unsigned int uiLCDWidth = 0;
         unsigned int uiLCDHeight = 0;
         unsigned short usColor16b = 0;
         unsigned short * pusStartBuf = NULL;

         if(NULL == pstCanvas)//畫布如果為空
         {
            printf(DEBUG_ERROR"in file:%s:%d:Invalid Canvas!!!\n",__FILE__,__LINE__);//標柱在哪裡出錯
            return;
         }
         if(NULL == pstCanvas->hLCDDev)//如果LED裝置不存在
         {
            printf(DEBUG_ERROR"in file:%s:%d:Invalid LCD Device!!!\n",__FILE__,__LINE__);
            return;
         }
         usColor16b = RGB2LCD16BitsColor(hCanvas,stColor);//設定16為顏色bit位
         uiLCDWidth = GetLCDWidth(pstCanvas->hLCDDev);//獲得裝置畫布的長度和高度
         uiLCDHeight = GetLCDHeight(pstCanvas->hLCDDev);

         if(x < 0 || x >= uiLCDWidth || y < 0 || y >= uiLCDHeight)//判斷要畫的點的位置是否在範圍之內
         {
            printf(DEBUG_WARNING"in file:%s:%d:Invalid value of point:(%d,%d)!!!\n",
                    __FILE__,__LINE__,x,y);
            return;
         }
     pusStartBuf = (unsigned short *)pstCanvas->pvCanvasBuf;//找到起始位置

         for(i=0;i<3*24;i=i+3)
         {
             //每三個是一行是否要圖顏色位的標誌
             //0-》0 1 2 3 4 5 6 7
          // pucFontData[i]
             for(j=0;j<8;j++)
             {
                 if(pucFontData[i] &(unsigned char)(((unsigned char)0x01)<<j))
                 {
                     DrawAPoint(hCanvas,x+j,y+i/3,stColor);
                 }
             }
        //pucFontData[i+1]
             //1-》8 9 10 11 12 13 14 15
             for(j=0;j<8;j++)
             {
                 if(pucFontData[i+1] &(unsigned char)(((unsigned char)0x01)<<j))
                 {
                     DrawAPoint(hCanvas,x+j+8,y+i/3,stColor);
                 }
             }
           //pucFontData[i+2]
             //2-》16 17 18 19 20 21 22 23
             for(j=0;j<8;j++)
             {
                 if(pucFontData[i+2] &(unsigned char)(((unsigned char)0x01)<<j))
                 {
                     DrawAPoint(hCanvas,x+j+16,y+i/3,stColor);
                 }
             }
         }
     //如將十六進位制數轉換成二進位制數,只要將每一位十六進位制數用四位相應的二進位制數表示,即可完成轉換
    return;
}
void DrawBmp(HCANVAS hCanvas,
             const char * pstrBMPFileName,
             int wBMP,int hBMP,
             int x,int y)
{
    St_Canvas *pstCanvas = hCanvas;
   int i,j;
   FILE *pfBMP=NULL;
   int iRGBDataoffset=0;
   unsigned char * pucLineData=NULL;
   St_RGB stColor={0};
   unsigned int uiLCDWidth = 0;
   unsigned int uiLCDHeight = 0;
  // unsigned short usColor16b = 0;
  // unsigned short * pusStartBuf = NULL;

   if(NULL == pstCanvas)//畫布如果為空
       {
             printf(DEBUG_ERROR"in file:%s:%d:Invalid Canvas!!!\n",__FILE__,__LINE__);//標柱在哪裡出錯
             return;
        }

   if(NULL==pstrBMPFileName)
   {
       printf(DEBUG_ERROR"in file:%s:%d:Invalid BMP File Name!!!\n",__FILE__,__LINE__);//標柱在哪裡出錯
                    return;
   }
   if(NULL == pstCanvas->hLCDDev)//如果LED裝置不存在
        {
             printf(DEBUG_ERROR"in file:%s:%d:Invalid LCD Device!!!\n",__FILE__,__LINE__);
             return;
          }
         // usColor16b = RGB2LCD16BitsColor(hCanvas,stColor);//設定16為顏色bit位
          uiLCDWidth = GetLCDWidth(pstCanvas->hLCDDev);//獲得裝置畫布的長度和高度
          uiLCDHeight = GetLCDHeight(pstCanvas->hLCDDev);

   if(x < 0 || x >= uiLCDWidth || y < 0 || y >= uiLCDHeight)//判斷要畫的點的位置是否在範圍之內
          {
             printf(DEBUG_WARNING"in file:%s:%d:Invalid value of point:(%d,%d)!!!\n",
                     __FILE__,__LINE__,x,y);
             return;
          }
     //pusStartBuf = (unsigned short *)pstCanvas->pvCanvasBuf;//找到起始位置
   pucLineData=(unsigned char *)malloc(wBMP*3);

   if(NULL == pucLineData)
     {
        printf(DEBUG_ERROR"in file:%s:%d:Malloc failed!!!\n",
                __FILE__,__LINE__);
        return;
     }

   pfBMP=fopen(pstrBMPFileName,"rb");
   if(NULL == pfBMP)
    {
       printf(DEBUG_ERROR"in file:%s:%d:Can't open BMP File:%s!!!\n",
               __FILE__,__LINE__,pstrBMPFileName);
       return;
    }

   fseek(pfBMP,10,SEEK_SET);
   fread(&iRGBDataoffset,4,1,pfBMP);
   fseek(pfBMP,iRGBDataoffset,SEEK_SET);

   for(i=0;i<hBMP;i++)
   {
          fread(pucLineData,1,wBMP*3,pfBMP);
          for(j = 0;j < wBMP;j++)
          {
             stColor.ucBlue = pucLineData[j*3];
             stColor.ucGreen = pucLineData[j*3+1];
             stColor.ucRed = pucLineData[j*3+2];
             DrawAPoint(hCanvas,x+j,y+hBMP-1-i,stColor);
          }
   }

   free(pucLineData);
   pucLineData=NULL;
   fclose(pfBMP);
   pfBMP=NULL;
   return;

}


void DrawJPG(HCANVAS hCanvas,
             const char * pstrJPGFileName,
             int x,int y)
{
   St_Canvas *pstCanvas = hCanvas;
   unsigned int uiLCDWidth = 0;
   unsigned int uiLCDHeight = 0;
   int i = 0;
   FILE * pfJPG = NULL;

   JSAMPARRAY ppucRowData = NULL;
   St_RGB stColor = {0};
   struct jpeg_decompress_struct jinfo;
   struct jpeg_error_mgr jerr;
   unsigned int row_stride = 0;
   unsigned long uiRealWidth = 0;
   unsigned long uiRealHeight = 0;

   if(NULL == pstCanvas)
   {
      printf(DEBUG_ERROR"in file:%s:%d:Invalid Canvas!!!\n",__FILE__,__LINE__);
      return;
   }
   if(NULL == pstCanvas->hLCDDev)
   {
      printf(DEBUG_ERROR"in file:%s:%d:Invalid LCD Device!!!\n",__FILE__,__LINE__);
      return;
   }
   if(NULL == pstrJPGFileName)
   {
      printf(DEBUG_ERROR"in file:%s:%d:Invalid BMP File Name!!!\n",
              __FILE__,__LINE__);
      return;
   }
   uiLCDWidth = GetLCDWidth(pstCanvas->hLCDDev);
   uiLCDHeight = GetLCDHeight(pstCanvas->hLCDDev);
   if(x < 0 || x >= uiLCDWidth
      || y < 0 || y >= uiLCDHeight)
   {
      printf(DEBUG_WARNING"in file:%s:%d:Invalid value of point:(%d,%d)!!!\n",
              __FILE__,__LINE__,x,y);
      return;
   }

   /*Bind error handler*/
   jinfo.err = jpeg_std_error(&jerr);
   /*init jpeg decompress object*/
   jpeg_create_decompress(&jinfo);
   /*Bind jpg data object*/
   pfJPG = fopen(pstrJPGFileName,"rb");
   if(NULL == pfJPG)
   {
      printf(DEBUG_WARNING"in file:%s:%d:Open file:%s failed!!!\n",
              __FILE__,__LINE__,pstrJPGFileName);
      jpeg_destroy_decompress(&jinfo);
      return;
   }
   jpeg_stdio_src(&jinfo, pfJPG);
   //jpeg_mem_src(&jinfo,mem,insize);//decompress from mem

   /*Read JPG header*/
   jpeg_read_header(&jinfo, TRUE);
   printf(DEBUG_INFO"Scale Num = %d\n",jinfo.scale_num);
   printf(DEBUG_INFO"Scale Denom = %d\n",jinfo.scale_denom);
   printf(DEBUG_INFO"Out Color Space = %d\n",jinfo.out_color_space);
   //JCS_RGB = 2;

   /*Start decompressing*/
   jpeg_start_decompress(&jinfo);
   /*Only get decompress arguments*/
   //jpeg_calc_output_dimensions(&jinfo);
   printf(DEBUG_INFO"Output Width = %d\n",jinfo.output_width);
   printf(DEBUG_INFO"Output Height = %d\n",jinfo.output_height);
   //Color Channel
   printf(DEBUG_INFO"Output Components = %d\n",jinfo.output_components);

   /*Alloc buffer memory for row data*/
   row_stride = jinfo.output_width * jinfo.output_components;
   ppucRowData = (*jinfo.mem->alloc_sarray)((j_common_ptr) &jinfo, JPOOL_IMAGE, row_stride, 1);

   /*Read Data by ScanLine*/
   uiRealWidth = MIN(uiLCDWidth-x,jinfo.output_width);
   uiRealHeight = MIN(uiLCDHeight-y,jinfo.output_height);
   while (jinfo.output_scanline < uiRealHeight) //jinfo.output_height
   {
      int line = 0;
      jpeg_read_scanlines(&jinfo, ppucRowData, 1);
      //output_scanline start from 0,but after scanline it will add 1
      line=jinfo.output_scanline-1;
      for(i=0;i < uiRealWidth;i++) //jinfo.output_width
      {//put pixel into framebuffer
         stColor.ucRed = ppucRowData[0][i*3];
         stColor.ucGreen = ppucRowData[0][i*3+1];
         stColor.ucBlue = ppucRowData[0][i*3+2];
         DrawAPoint(hCanvas,x + i, y + line, stColor);
      }
   }//end while

   /*Finish Decompress*/
   jpeg_finish_decompress(&jinfo);

   /*Destroy Decompress Object*/
   jpeg_destroy_decompress(&jinfo);
   fclose(pfJPG);
}

int GetFileSize(char * path)
{
    FILE *fp;
    int length;
    fp=fopen(path,"rb");
    if(fp==NULL)
      printf("file not found!\n");
   else
   {    //把檔案的位置指標移到檔案尾
       fseek(fp,0L,SEEK_END);
         //獲取檔案長度;
       length=ftell(fp);
       printf("The length is %1d  bytes\n",length);
       fclose(fp);
   }
    return length+1;
}

void DrawJPGFromMem(HCANVAS hCanvas,
             const unsigned char * pucJPGData,//第二個引數是指記憶體首地址
             int x,int y,unsigned long ulLenOfJPGData)
{
    St_Canvas *pstCanvas=hCanvas;
    unsigned int uiLCDWidth=0;
    unsigned int uiLCDHeight=0;
    int i=0;

    JSAMPARRAY ppucRowData=NULL;
    St_RGB stColor={0};
    struct jpeg_decompress_struct jinfo;
    struct jpeg_error_mgr jerr;
    unsigned int row_stride=0;
    unsigned long uiRealWidth=0;
    unsigned long uiRealHeight=0;

    if(NULL==pstCanvas)
    {
        printf(DEBUG_ERROR"in file :%s:%d:Invalid Canvas!!!\n",__FILE__,__LINE__);
        return;
    }
    if(NULL==pstCanvas->hLCDDev)
    {
        printf(DEBUG_ERROR"in file:%s:%d:Invalid hLCDDev!!!\n ",__FILE__,__LINE__);
        return;
    }
    uiLCDWidth=GetLCDWidth(pstCanvas->hLCDDev);
    uiLCDHeight=GetLCDHeight(pstCanvas->hLCDDev);

    if(x<0||x>=uiLCDWidth||y<0||y>=uiLCDHeight)
    {
        printf(DEBUG_WARNING"in file:%s:%d:Invalid value of point(%d,%d)!!!\n",__FILE__,__LINE__,x,y);
        return;
    }

    //繫結錯誤
    jinfo.err=jpeg_std_error(&jerr);
    //建立壓縮物件
    jpeg_create_decompress(&jinfo);


    jpeg_mem_src(&jinfo,pucJPGData,ulLenOfJPGData);

    jpeg_read_header(&jinfo,TRUE);
    printf(DEBUG_INFO"Scale Num = %d\n",jinfo.scale_num);
    printf(DEBUG_INFO"Scale Denom = %d\n",jinfo.scale_denom);
   printf(DEBUG_INFO"Out Color Space = %d\n",jinfo.out_color_space);

   jpeg_start_decompress(&jinfo);

   printf(DEBUG_INFO"Output Width = %d\n",jinfo.output_width);
   printf(DEBUG_INFO"Output Height = %d\n",jinfo.output_height);
     //Color Channel
   printf(DEBUG_INFO"Output Components = %d\n",jinfo.output_components);

   row_stride=jinfo.output_width*jinfo.output_height;
   ppucRowData=(*jinfo.mem->alloc_sarray)((j_common_ptr)&jinfo,JPOOL_IMAGE,row_stride,1);

   uiRealWidth = MIN(uiLCDWidth-x,jinfo.output_width);
   uiRealHeight = MIN(uiLCDHeight-y,jinfo.output_height);
   while(jinfo.output_scanline<uiRealHeight)
   {
       int line=0;
       jpeg_read_scanlines(&jinfo,ppucRowData,1);

       line=jinfo.output_scanline-1;

       for(i=0;i < uiRealWidth;i++) //jinfo.output_width
       {//put pixel into framebuffer
              stColor.ucRed = ppucRowData[0][i*3];//每個畫素的顏色要用三個位元組表示
              stColor.ucGreen = ppucRowData[0][i*3+1];
              stColor.ucBlue = ppucRowData[0][i*3+2];
              DrawAPoint(hCanvas,x + i, y + line, stColor);
          }
   }

   /*Finish Decompress*/
   jpeg_finish_decompress(&jinfo);

   /*Destroy Decompress Object*/
   jpeg_destroy_decompress(&jinfo);


   return;
}

相關文章