Advertisement
Guest User

Untitled

a guest
Apr 10th, 2018
333
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 41.69 KB | None | 0 0
  1.  
  2. //  Для dxdy, 10 апреля 2018 г.
  3. // Файл "jpg_coder_fp.c"
  4. // Положить 24-битный BMP-файл "in.bmp" и запустить программу без аргументов.
  5. // Или указать как аргумент имя какого-нибудь 24-битного BMP-файла. После
  6. // работы программы должны получиться JPEG-файлы "out.jpg" и "opt_out.jpg".
  7. // Вторым аргументом можно указать качество рисунка от 1 до 5.
  8. //
  9. // К программе подключен файл оптимизатора "jpg_opt.c", который по ссылке
  10. // https://pastebin.com/J2aHcGFr
  11. // В нем нужно отключить тестовую обёртку макросом в строке 920.
  12.  
  13. //   gcc jpg_coder_fp.c -o jpg_coder_fp.cgi -Wall -Werror -O3
  14. //   ./jpg_coder_fp.cgi
  15.  
  16.  
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <limits.h>
  21.  
  22.  
  23. /*****************************************
  24. * JPEG-кодер содержит 4-е функции кодирования и одну функцию распечатки ошибок.
  25. * Функции отличаются тем, что одни помещают JPEG-файл в предоставленный извне
  26. * буфер buf, а другие сразу пишут JPEG-файл в файл fp.
  27. * Функции отличаются еще наличием аргумента q (quality) -качаство рисунка.
  28. *
  29. * int jpg_coder(char *buf, int Sbuf, const char *in, int w, int h, int *err)
  30. *
  31. * int jpg_coder_q(char *buf, int Sbuf, const char *in, int w, int h, int *err,
  32. *                int q)
  33. *
  34. * int jpg_coder_q_fp(FILE *fp, const char *in, int w, int h, int *err, int q)
  35. *
  36. * int jpg_coder_fp(FILE *fp, const char *in, int w, int h, int *err)
  37. *
  38. *   buf  -выходной буфер для JPEG-файла;
  39. *   Sbuf -длина выходного буфера, должна быть достаточна для JPEG-файла;
  40. *   fp   -выходной JPEG-файл;
  41. *   in   -входной RGB-буфер;
  42. *   w, h -ширина и высота рисунка;
  43. *   err  -возвращает ошибку (можно NULL);
  44. *   q    -качество рисунка от 1 до 5 (5 -наилучшее качество, но плохое сжатие).
  45. *
  46. * Типичное значение q=3, подходит для большинства случаев. Функции, в которых
  47. * нет этого аргумента, внутри себя устанавливают  q=3.
  48. *
  49. * Возврат: длина JPEG-файла или -1.
  50. * Для распечатки ошибок есть функция
  51. * const char *jpc_strerror(int err);
  52. *******************************************/
  53.  
  54.  
  55. // макросы ошибок JPEG-кодера
  56. #define JPC_ERR_WR_FILE       61
  57. #define JPC_ERR_MEMORY        62
  58. #define JPC_ERR_INVAL         64
  59. #define JPC_ERR_CODE          65
  60.  
  61.  
  62. /*
  63.   Схема движения данных.
  64.  
  65.   |Входной RGB-буфер|
  66.         |
  67.         |<- Преобразование RGB ==> YCbCr
  68.         |
  69.   |s->comp[comp].mblok -буфер на один макроблок|
  70.         |
  71.         |<- Прореживние макроблока
  72.         |
  73.   |s->comp[comp].matr  -буфер на один макроблок|
  74.         |
  75.         |<- Дискретно-косинусное преобразование
  76.         |
  77.   |s->comp[comp].dctmatr  -буфер на один макроблок|
  78.         |
  79.         |<- Квантование и зигзаг
  80.         |
  81.   |s->comp[comp].matr  -буфер на один макроблок|
  82.         |
  83.         |<- Кодирование Хаффмана
  84.         |
  85.   |Выходной поток|
  86. */
  87.  
  88. //--- структура алфавита Хаффмана ---
  89. struct jpc_alf{
  90.     int   cod;  // код
  91.     int   bits; // длина кода
  92. };
  93.  
  94. //--- обобщенная структура ---
  95. struct jpc {
  96.     char   *pf0;          // начало выходного буфера
  97.     char   *pf1;          // текущая позиция выходного буфера
  98.     char   *pf2;          // за край выходного буфера
  99.     int    w;             // ширина
  100.     int    h;             // высота
  101.     int    xblok;         // x -размер макроблока
  102.     int    yblok;         // y -размер макроблока
  103.     char   qmatr[64*4];   // матрицы квантования
  104.     int    quality;       // качество рисунка, от 1 до 5, самое лучшее 5.
  105.     int    err;
  106.     int    bit_count;     // счетчик битов
  107.     unsigned int  ch;     // буфер битов
  108.     int    sizefile;      // длина выходного файла
  109.     FILE   *fp;           // выходной файл
  110.  
  111.     // указатели на функции записи
  112.     int (*jpc_fputc)(int ch, struct jpc *s);
  113.     int (*jpc_fwrite)(const char *buf, int Selem, int n, struct jpc *s);
  114.  
  115.  
  116.     //--- структура компонентов Y Cb Cr ---
  117.     struct{
  118.         int         n;             // число матриц 8x8 на макроблок
  119.         int         mdc;           // хранит последний dc-коэффициент
  120.         int         matr[64*4];    // матрицы коэффициентов
  121.         int         dctmatr[64*4]; // матрицы коэффициентов после DCT
  122.         int         mblok[256];    // матрица макроблока
  123.     } comp[3];
  124.  
  125.     //--- структуры алфавита Хаффмана ---
  126.     struct jpc_alf alf[4*256];
  127.  
  128.     char buf_hfm[16+16+16+16+12+12+162+162]; // буфер длин кодов символов и
  129.                                              // самих символов
  130.     const char *hfmtab[4]; // указатели на строку длин кодов в buf_hfm
  131.     int        dla[4];     // длины алфавитов
  132.  
  133. };
  134.  
  135. //------------- jpc_putc_buf -----------
  136.  
  137. int jpc_putc_buf(int ch, struct jpc *s)
  138. {
  139.     if(s->pf1 >= s->pf2){ s->err = JPC_ERR_WR_FILE; return(-1);}
  140.     *s->pf1++ = ch;
  141.     return(ch);
  142. }
  143.  
  144. //----------------- jpc_fwrite_buf ------------
  145.  
  146. int jpc_fwrite_buf(const char *buf, int Selem, int n, struct jpc *s)
  147. {
  148.     int len;
  149.     if(Selem<0 || n<0) return(0);
  150.     if(Selem==0 || n==0) return(n);
  151.     len = Selem * n;
  152.     if(len > (s->pf2 - s->pf1)){
  153.         s->err = JPC_ERR_WR_FILE;
  154.         return(-1);
  155.     }
  156.     memmove(s->pf1, buf, len);
  157.     s->pf1 += len;
  158.     return(n);
  159. }
  160.  
  161. //------------- jpc_putc_fp -----------
  162.  
  163. int jpc_putc_fp(int ch, struct jpc *s)
  164. {
  165.     int k;
  166.     k = fputc(ch, s->fp);
  167.     if(k < 0){ s->err = JPC_ERR_WR_FILE; return(-1);}
  168.     s->sizefile++;
  169.     return(k);
  170. }
  171.  
  172. //----------------- jpc_fwrite_fp ------------
  173.  
  174. int jpc_fwrite_fp(const char *buf, int Selem, int n, struct jpc *s)
  175. {
  176.     int k;
  177.     k = fwrite(buf, Selem, n, s->fp);
  178.     if(k != n){ s->err = JPC_ERR_WR_FILE; return(-1);}
  179.     s->sizefile += (Selem * n);
  180.     return(n);
  181. }
  182.  
  183. //------------- jpc_put_n_bits -------------
  184. // положить в выходной поток bits бит.
  185. int jpc_put_n_bits(int cod, int bits, struct jpc *s)
  186. {
  187.     int val;
  188.  
  189.     s->ch = (s->ch << bits) + (((1 << bits) - 1) & cod);
  190.     s->bit_count += bits;
  191.     while(s->bit_count >= 8){
  192.         s->bit_count -= 8;
  193.         val=(s->ch >> s->bit_count) & 255;
  194.         if(s->jpc_fputc(val, s) < 0) return(-1);
  195.         if(val==0xFF){
  196.             if(s->jpc_fputc(0, s) < 0) return(-1);
  197.         }
  198.     }
  199.     return(0);
  200. }
  201.  
  202. //------------- jpc_flush_bits --------------
  203. // сбросить в выходной поток оставшиеся биты
  204. int jpc_flush_bits(struct jpc *s)
  205. {
  206.     int val, bits;
  207.  
  208.     bits = s->bit_count;
  209.     if(bits > 0){
  210.         val = ((s->ch << (8-bits)) | ((1 << (8-bits)) - 1)) & 255;
  211.         if(s->jpc_fputc(val, s) < 0) return(-1);
  212.         if(val==0xFF){
  213.             if(s->jpc_fputc(0, s) < 0) return(-1);
  214.         }
  215.     }
  216.     s->bit_count = s->ch = 0;
  217.     return(0);
  218. }
  219.  
  220. //----------------- jpc_dct --------------
  221. // прямое DCT (дискретное косинусное преобразование)
  222. void jpc_dct(int *s, int *d)
  223. {
  224.     const int arr[64]={ // компенсация DCT преобразователя
  225.         // 4096 * 1/(2*sqrt(2)) * 1/(2*sqrt(2))
  226.         // 4096 * (1.0/(4.0*(cos(PI*y/16.0)))) * (1.0/(4.0*(cos(PI*x/16.0))))
  227.             512,     369,     392,     435,     512,     651,     945,    1849,
  228.             369,     266,     282,     314,     369,     469,     681,    1333,
  229.             392,     282,     300,     333,     392,     498,     723,    1415,
  230.             435,     314,     333,     370,     435,     554,     803,    1572,
  231.             512,     369,     392,     435,     512,     651,     944,    1849,
  232.             651,     469,     498,     554,     651,     828,    1201,    2352,
  233.             945,     681,     723,     803,     944,    1201,    1743,    3412,
  234.            1849,    1333,    1415,    1572,    1849,    2352,    3412,    6679,
  235.     };
  236.     int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
  237.     int tmp10, tmp11, tmp12, tmp13;
  238.     int z1, z2, z3, z4, z5, z11, z13;
  239.     const int *ps;
  240.     int *pd;
  241.     int i;
  242.     const int A1 = 181;  // 256 * cos(4*Pi/16)
  243.     const int A2 = 139;  // 256 * (cos(2*Pi/16) - cos(6*Pi/16))
  244.     const int A3 = 181;  // 256 * cos(4*Pi/16)
  245.     const int A4 = 334;  // 256 * (cos(2*Pi/16) + cos(6*Pi/16))
  246.     const int A5 =  98;  // 256 * cos(6*Pi/16)
  247.  
  248.     pd = d;
  249.     for(i=0; i<64; i+=8){
  250.         ps = s + i;
  251.         tmp0 = ps[0] + ps[7];
  252.         tmp7 = ps[0] - ps[7];
  253.         tmp1 = ps[1] + ps[6];
  254.         tmp6 = ps[1] - ps[6];
  255.         tmp2 = ps[2] + ps[5];
  256.         tmp5 = ps[2] - ps[5];
  257.         tmp3 = ps[3] + ps[4];
  258.         tmp4 = ps[3] - ps[4];
  259.  
  260.         tmp10 = tmp0 + tmp3;
  261.         tmp13 = tmp0 - tmp3;
  262.         tmp11 = tmp1 + tmp2;
  263.         tmp12 = tmp1 - tmp2;
  264.  
  265.         pd[0] = tmp10 + tmp11;
  266.         pd[4] = tmp10 - tmp11;
  267.  
  268.         z1 = ((tmp12 + tmp13) * A1)>>8;
  269.         pd[2] = tmp13 + z1;
  270.         pd[6] = tmp13 - z1;
  271.  
  272.         tmp10 = tmp4 + tmp5;
  273.         tmp11 = tmp5 + tmp6;
  274.         tmp12 = tmp6 + tmp7;
  275.  
  276.         z5 = ((tmp10 - tmp12) * A5)>>8;
  277.         z2 = ((tmp10 * A2)>>8) +z5;
  278.         z4 = ((tmp12 * A4)>>8) +z5;
  279.         z3 = (tmp11 * A3)>>8;
  280.  
  281.         z11 = tmp7 + z3;
  282.         z13 = tmp7 - z3;
  283.  
  284.         pd[5] = z13 + z2;
  285.         pd[3] = z13 - z2;
  286.         pd[1] = z11 + z4;
  287.         pd[7] = z11 - z4;
  288.  
  289.         pd += 8;
  290.     }
  291.  
  292.     pd = d;
  293.     for(i=0; i<8; i++){
  294.         tmp0 = pd[8*0] + pd[8*7];
  295.         tmp7 = pd[8*0] - pd[8*7];
  296.         tmp1 = pd[8*1] + pd[8*6];
  297.         tmp6 = pd[8*1] - pd[8*6];
  298.         tmp2 = pd[8*2] + pd[8*5];
  299.         tmp5 = pd[8*2] - pd[8*5];
  300.         tmp3 = pd[8*3] + pd[8*4];
  301.         tmp4 = pd[8*3] - pd[8*4];
  302.  
  303.         tmp10 = tmp0 + tmp3;
  304.         tmp13 = tmp0 - tmp3;
  305.         tmp11 = tmp1 + tmp2;
  306.         tmp12 = tmp1 - tmp2;
  307.  
  308.         pd[8*0] = tmp10 + tmp11;
  309.         pd[8*4] = tmp10 - tmp11;
  310.  
  311.         z1 = ((tmp12 + tmp13) * A1)>>8;
  312.         pd[8*2] = tmp13 + z1;
  313.         pd[8*6] = tmp13 - z1;
  314.  
  315.         tmp10 = tmp4 + tmp5;
  316.         tmp11 = tmp5 + tmp6;
  317.         tmp12 = tmp6 + tmp7;
  318.  
  319.         z5 = ((tmp10 - tmp12) * A5)>>8;
  320.         z2 = ((tmp10 * A2)>>8) +z5;
  321.         z4 = ((tmp12 * A4)>>8) +z5;
  322.         z3 = (tmp11 * A3)>>8;
  323.  
  324.         z11 = tmp7 + z3;
  325.         z13 = tmp7 - z3;
  326.  
  327.         pd[8*5] = z13 + z2;
  328.         pd[8*3] = z13 - z2;
  329.         pd[8*1] = z11 + z4;
  330.         pd[8*7] = z11 - z4;
  331.  
  332.         pd++;
  333.     }
  334.     for(i=0; i<64; i++) d[i] = (d[i] * arr[i] + 2048) >> 12;
  335.     return;
  336. }
  337.  
  338. //------------- jpc_dct_blok ----------------
  339. // DCT на один макроблок
  340. void jpc_dct_blok(struct jpc *s)
  341. {
  342.     int comp, n;
  343.  
  344.     for(comp=0; comp<3; comp++){
  345.         for(n=0; n < s->comp[comp].n; n++){
  346.             jpc_dct(s->comp[comp].matr + n*64,
  347.                     s->comp[comp].dctmatr + n*64);
  348.         }
  349.     }
  350.     return;
  351. }
  352.  
  353. //----------- jpc_get_hfm_cod -------------
  354. // инициализация структуры, коды Хаффмана
  355. void jpc_get_hfm_cod(struct jpc *s)
  356. {
  357.     //   http://www.impulseadventure.com/photo/optimized-jpeg.html
  358.     //   Standard
  359.     char *p1;
  360.  
  361.     //--- длины ---
  362.     const unsigned char DClenY[]={ // 12 (00) яркость
  363.         0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
  364.     };
  365.     const unsigned char DClenCh[]={ // 12 (01) цвет
  366.         0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
  367.     };
  368.     const unsigned char AClenY[]={ // 162 (10) яркость
  369.         0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125
  370.     };
  371.     const unsigned char AClenCh[]={ // 162 (11) цвет
  372.         0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119
  373.     };
  374.  
  375.     //--- символы ---
  376.     const unsigned char DCsymY[]={ // 12 (00) яркость
  377.         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
  378.     };
  379.     const unsigned char DCsymCh[]={ // 12 (01) цвет
  380.         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
  381.     };
  382.     const unsigned char ACsymY[]={ // 162 (10) яркость
  383.         0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
  384.         0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
  385.         0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08,
  386.         0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0,
  387.         0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16,
  388.         0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28,
  389.         0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
  390.         0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
  391.         0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
  392.         0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
  393.         0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
  394.         0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
  395.         0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
  396.         0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
  397.         0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
  398.         0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5,
  399.         0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4,
  400.         0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
  401.         0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
  402.         0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
  403.         0xF9, 0xFA
  404.     };
  405.     const unsigned char ACsymCh[]={ // 162 (11) цвет
  406.         0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
  407.         0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
  408.         0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
  409.         0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0,
  410.         0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34,
  411.         0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26,
  412.         0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38,
  413.         0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
  414.         0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
  415.         0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
  416.         0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
  417.         0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
  418.         0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
  419.         0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5,
  420.         0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4,
  421.         0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3,
  422.         0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2,
  423.         0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
  424.         0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9,
  425.         0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
  426.         0xF9, 0xFA
  427.     };
  428.     p1 = s->buf_hfm;
  429.     s->hfmtab[0] = p1; s->dla[0] = 12;
  430.     memcpy(p1, DClenY,  16); p1 += 16;
  431.     memcpy(p1, DCsymY,  12); p1 += 12;
  432.  
  433.     s->hfmtab[1] = p1; s->dla[1] = 12;
  434.     memcpy(p1, DClenCh, 16); p1 += 16;
  435.     memcpy(p1, DCsymCh, 12); p1 += 12;
  436.  
  437.     s->hfmtab[2] = p1; s->dla[2] = 162;
  438.     memcpy(p1, AClenY,  16); p1 += 16;
  439.     memcpy(p1, ACsymY,  162); p1 += 162;
  440.  
  441.     s->hfmtab[3] = p1; s->dla[3] = 162;
  442.     memcpy(p1, AClenCh, 16); p1 += 16;
  443.     memcpy(p1, ACsymCh, 162); p1 += 162;
  444.     return;
  445. }
  446.  
  447. //----------- jpc_make_h_tree ----------------
  448. // Таблицы Хаффмана. Заряжаем массив алфавита.
  449. int jpc_make_h_tree(struct jpc *s, int id)
  450. {
  451.     int  i, j, k, n, len, cod, dla;
  452.     const char *sym, *hfmtab;
  453.     struct jpc_alf *alf;
  454.  
  455.     alf = s->alf + id*256;
  456.     hfmtab = s->hfmtab[id];
  457.     dla = s->dla[id];
  458.  
  459.     for(i=0, n=0; i<16; i++) n=n+(hfmtab[i]&255); // подсчет символов
  460.     if(n==0 || n>dla || n>256){ s->err = JPC_ERR_CODE; return(-1);}
  461.  
  462.     sym = hfmtab + 16;
  463.     for(len=1, cod=0, i=0; len<=16; len++){
  464.         k = hfmtab[len-1] & 255; // число кодов текущей длины
  465.         if(k > 0){
  466.             for(; k>0; k--, i++){
  467.                 j = sym[i] & 255;
  468.                 alf[j].cod = cod++;
  469.                 alf[j].bits = len;  // j равно символу алфавита
  470.             }
  471.             if(cod > ((1 << len) - 1)){ s->err = JPC_ERR_CODE; return(-1);}
  472.         }
  473.         cod <<= 1;
  474.     }
  475.     return(n);
  476. }
  477.  
  478. //--------------- jpc_set_hfm ----------------
  479. // инициализация таблиц Хаффмана для кодирования
  480. int jpc_set_hfm(struct jpc *s)
  481. {
  482.     int i;
  483.  
  484.     jpc_get_hfm_cod(s); // таблицы длин и символов Хаффмана
  485.     for(i=0; i<4; i++){
  486.         if(jpc_make_h_tree(s, i) < 0) return(-1);
  487.     }
  488.     return(0);
  489. }
  490.  
  491. //------------ jpc_get_qmatr ---------------
  492. // инициирует таблицы квантования
  493. void jpc_get_qmatr(struct jpc *s)
  494. {
  495.     const char njZZ[64] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18,
  496.     11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
  497.     42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45,
  498.     38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 }; // зигзаг
  499.     int i;
  500.     const unsigned char *q0, *q1;
  501.  
  502.     // 5
  503.     const unsigned char q0_5[]={
  504.         1, 1, 1, 1, 1, 1, 1, 1,
  505.         1, 1, 1, 1, 1, 1, 1, 1,
  506.         1, 1, 1, 1, 1, 1, 1, 1,
  507.         1, 1, 1, 1, 1, 1, 1, 1,
  508.         1, 1, 1, 1, 1, 1, 1, 1,
  509.         1, 1, 1, 1, 1, 1, 1, 1,
  510.         1, 1, 1, 1, 1, 1, 1, 1,
  511.         1, 1, 1, 1, 1, 1, 1, 1
  512.     };
  513.     const unsigned char q1_5[]={
  514.         1, 1, 1, 1, 1, 1, 1, 1,
  515.         1, 1, 1, 1, 1, 1, 1, 1,
  516.         1, 1, 1, 1, 1, 1, 1, 1,
  517.         1, 1, 1, 1, 1, 1, 1, 1,
  518.         1, 1, 1, 1, 1, 1, 1, 1,
  519.         1, 1, 1, 1, 1, 1, 1, 1,
  520.         1, 1, 1, 1, 1, 1, 1, 1,
  521.         1, 1, 1, 1, 1, 1, 1, 1
  522.     };
  523.  
  524.     // 4
  525.     const unsigned char q0_4[]={
  526.         2,  1,  2,  3,  3,  4,  5,  6,
  527.         1,  2,  3,  3,  4,  5,  6,  7,
  528.         2,  3,  3,  4,  5,  6,  7,  8,
  529.         3,  3,  4,  5,  6,  7,  8,  9,
  530.         3,  4,  5,  6,  7,  8,  9, 10,
  531.         4,  5,  6,  7,  8,  9, 10, 11,
  532.         5,  6,  7,  8,  9, 10, 11, 12,
  533.         6,  7,  8,  9, 10, 11, 12, 12
  534.     };
  535.     const unsigned char q1_4[]={
  536.         1,  2,  3,  4,  6,  8, 12, 12,
  537.         2,  3,  4,  6,  8, 12, 12, 12,
  538.         3,  4,  6,  8, 12, 12, 12, 12,
  539.         4,  6,  8, 12, 12, 12, 12, 12,
  540.         6,  8, 12, 12, 12, 12, 12, 12,
  541.         8, 12, 12, 12, 12, 12, 12, 12,
  542.        12, 12, 12, 12, 12, 12, 12, 12,
  543.        12, 12, 12, 12, 12, 12, 12, 12
  544.     };
  545.  
  546.     // 3  Лучшее квантование
  547.     const unsigned char q0_3[]={
  548.          2,  2,  3,  4,  6,  8, 12, 16,
  549.          2,  3,  4,  6,  8, 12, 16, 20,
  550.          3,  4,  6,  8, 12, 16, 20, 24,
  551.          4,  6,  8, 12, 16, 20, 24, 28,
  552.          6,  8, 12, 16, 20, 24, 28, 32,
  553.          8, 12, 16, 20, 24, 28, 32, 36,
  554.         12, 16, 20, 24, 28, 32, 36, 36,
  555.         16, 20, 24, 28, 32, 36, 36, 36
  556.     };
  557.     const unsigned char q1_3[]={
  558.          16,  12,  14,  16,  18,  24,  32,  60,
  559.          12,  14,  16,  18,  24,  32,  60,  80,
  560.          14,  16,  18,  24,  32,  60,  80, 100,
  561.          16,  18,  24,  32,  60,  80, 100, 120,
  562.          18,  24,  32,  60,  80, 100, 120, 140,
  563.          24,  32,  60,  80, 100, 120, 140, 160,
  564.          32,  60,  80, 100, 120, 140, 160, 180,
  565.          60,  80, 100, 120, 140, 160, 180, 200
  566.     };
  567.  
  568.     // 2
  569.     const unsigned char q0_2[]={
  570.          12,  12,  14,  16,  18,  24,  32,  60,
  571.          12,  14,  16,  18,  24,  32,  60,  80,
  572.          14,  16,  18,  24,  32,  60,  80, 100,
  573.          16,  18,  24,  32,  60,  80, 100, 120,
  574.          18,  24,  32,  60,  80, 100, 120, 140,
  575.          24,  32,  60,  80, 100, 120, 140, 160,
  576.          32,  60,  80, 100, 120, 140, 160, 180,
  577.          60,  80, 100, 120, 140, 160, 180, 200
  578.     };
  579.     const unsigned char q1_2[]={
  580.          12,  12,  14,  16,  18,  24,  32,  60,
  581.          12,  14,  16,  18,  24,  32,  60,  80,
  582.          14,  16,  18,  24,  32,  60,  80, 100,
  583.          16,  18,  24,  32,  60,  80, 100, 120,
  584.          18,  24,  32,  60,  80, 100, 120, 140,
  585.          24,  32,  60,  80, 100, 120, 140, 160,
  586.          32,  60,  80, 100, 120, 140, 160, 180,
  587.          60,  80, 100, 120, 140, 160, 180, 200
  588.     };
  589.  
  590.     // 1
  591.     const unsigned char q0_1[]={
  592.          30,  30,  50,  80, 100, 200, 200, 200,
  593.          30,  50,  80, 100, 200, 200, 200, 200,
  594.          50,  80, 100, 200, 200, 200, 200, 200,
  595.          80, 100, 200, 200, 200, 200, 200, 200,
  596.         100, 200, 200, 200, 200, 200, 200, 200,
  597.         200, 200, 200, 200, 200, 200, 200, 200,
  598.         200, 200, 200, 200, 200, 200, 200, 200,
  599.         200, 200, 200, 200, 200, 200, 200, 200
  600.     };
  601.     const unsigned char q1_1[]={
  602.          50,  50,  50, 100, 200, 200, 200, 200,
  603.          50,  50, 100, 200, 200, 200, 200, 200,
  604.          50, 100, 200, 200, 200, 200, 200, 200,
  605.         100, 200, 200, 200, 200, 200, 200, 200,
  606.         200, 200, 200, 200, 200, 200, 200, 200,
  607.         200, 200, 200, 200, 200, 200, 200, 200,
  608.         200, 200, 200, 200, 200, 200, 200, 200,
  609.         200, 200, 200, 200, 200, 200, 200, 200
  610.     };
  611.  
  612.     q0=q0_3; q1=q1_3;
  613.     if(s->quality <= 1){ q0=q0_1; q1=q1_1;}
  614.     if(s->quality == 2){ q0=q0_2; q1=q1_2;}
  615.     if(s->quality == 3){ q0=q0_3; q1=q1_3;}
  616.     if(s->quality == 4){ q0=q0_4; q1=q1_4;}
  617.     if(s->quality >= 5){ q0=q0_5; q1=q1_5;}
  618.  
  619.     for(i=0; i<64; i++) s->qmatr[i]    = q0[(int)(njZZ[i])];
  620.     for(i=0; i<64; i++) s->qmatr[i+64] = q1[(int)(njZZ[i])];
  621.     return;
  622. }
  623.  
  624. //-------------------- jpc_get_blok ---------------------
  625. // RGB ==> jpc->comp[comp].mblok 16х16 пикселей Y Cb Cr
  626. // in -показывает место верхнего левого пикселя текущего макроблока
  627. // во входном RGB буфере
  628. void jpc_get_blok(struct jpc *s, int xblok, int yblok, const char *in)
  629. {
  630.     int *p, i, k, n;
  631.     int kr, kg, kb;
  632.     int *pY, *pB, *pR;
  633.     int x, y, xm, ym;
  634.     const char *pin;
  635.  
  636.     if(s->xblok > xblok) xm=xblok; else xm=s->xblok;
  637.     if(s->yblok > yblok) ym=yblok; else ym=s->yblok;
  638.     pY = s->comp[0].mblok;
  639.     pB = s->comp[1].mblok;
  640.     pR = s->comp[2].mblok;
  641.  
  642.     for(y=0; y < ym; y++){
  643.         pin=in +(s->w * 3 * y);
  644.         for(x=0; x < xm; x++){
  645.             kr = (*pin++)&255;
  646.             kg = (*pin++)&255;
  647.             kb = (*pin++)&255;
  648.             *pY++ = (( 77*kr + 150*kg +  29*kb + 128)>>8)-128;
  649.             *pB++ = ((-43*kr -  85*kg + 128*kb + 128)>>8);
  650.             *pR++ = ((128*kr - 107*kg -  21*kb + 128)>>8);
  651.         }
  652.         if(x < s->xblok){
  653.             n = s->xblok - x;
  654.             for(k = *(pY-1), i=0; i<n; i++) *pY++ = k;
  655.             for(k = *(pB-1), i=0; i<n; i++) *pB++ = k;
  656.             for(k = *(pR-1), i=0; i<n; i++) *pR++ = k;
  657.         }
  658.     }
  659.     if(y < s->yblok){
  660.         n = (s->yblok - y) * 16;
  661.         for(p=pY-16, i=0; i<n; i++) *pY++ = *p++;
  662.         for(p=pB-16, i=0; i<n; i++) *pB++ = *p++;
  663.         for(p=pR-16, i=0; i<n; i++) *pR++ = *p++;
  664.     }
  665.     return;
  666. }
  667.  
  668. //----------------- jpc_red_blok ----------------
  669. // прореживает массив jpc->comp[comp].mblok 16х16 и распределяет
  670. // по матрицам jpc->comp[comp].matr 8х8
  671. void jpc_red_blok(struct jpc *s)
  672. {
  673.     int *pin, *p0, *p1, *p2, y, i;
  674.  
  675.     // создаем четыре Y-матрицы
  676.     pin = s->comp[0].mblok;
  677.     p1 = s->comp[0].matr;
  678.     p0=p1;
  679.     for(y=0; y<16; y++){
  680.         if(y!=8) p1=p0;
  681.         for(p2=p1+8; p1<p2;) *p1++ = *pin++;
  682.         p0=p1;
  683.         p1 += 56;
  684.         for(p2=p1+8; p1<p2;) *p1++ = *pin++;
  685.     }
  686.     // создаем по одной Cb и Cr матрице
  687.     for(i=1; i<=2; i++){
  688.         pin = s->comp[i].mblok;
  689.         p1 = s->comp[i].matr;
  690.         for(y=0; y<8; y++){
  691.             for(p2=p1+8; p1<p2;){
  692.                 *p1++ = (*pin + *(pin+1) + *(pin+16) + *(pin+17) + 2)>>2;
  693.                 pin += 2;
  694.             }
  695.             pin += 16;
  696.         }
  697.     }
  698.     return;
  699. }
  700.  
  701. //------------- jpc_quant ------------
  702. // деление (a / q) с округлением
  703. int jpc_quant(int a, int q)
  704. {
  705.     int k;
  706.     q &=255;
  707.     k = q >> 1;
  708.     if(a<0) return((a - k) / q);
  709.     return((a + k) / q);
  710. }
  711.  
  712. //----------------- jpc_qnt_blok ----------------
  713. // квантует и зигзажит матрицы jpc->comp[comp].dctmatr 8х8
  714. // результат в матрицах jpc->comp[comp].matr (на один макроблок)
  715. void jpc_qnt_blok(struct jpc *s)
  716. {
  717.     const char njZZ[64] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18,
  718.     11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
  719.     42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45,
  720.     38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 }; // зигзаг
  721.  
  722.     int *p1;
  723.     int comp, i, k, n;
  724.     char *pq;
  725.     int *pin;
  726.  
  727.     for(comp=0; comp<3; comp++){
  728.         p1 = s->comp[comp].matr;
  729.         if(comp==0) pq = s->qmatr;
  730.         else pq = s->qmatr + 64;
  731.         for(n=0; n < s->comp[comp].n; n++){
  732.             pin = s->comp[comp].dctmatr + n*64;
  733.             k = jpc_quant(pin[0], pq[0]);
  734.             *p1++ = k - s->comp[comp].mdc;
  735.             s->comp[comp].mdc = k;
  736.             for(i=1; i<64; i++){
  737.                 *p1++ = jpc_quant(pin[(int)njZZ[i]], pq[i]);
  738.             };
  739.         }
  740.     }
  741.     return;
  742. }
  743.  
  744. //--------- conv_kf -----------------
  745. // преобразование коэффициента в дополнительный код и ограничение
  746. int conv_kf(int val, int *bits, int limit)
  747. {
  748.     int k, bits0=0;
  749.  
  750.     if(val < 0){
  751.         if(val < -limit) val = -limit;
  752.         for(k = -val; k != 0; k >>= 1) bits0++;
  753.         val = val - 1 - ((-1) << bits0);
  754.     }
  755.     else{
  756.         if(val > limit) val = limit;
  757.         for(k = val; k != 0; k >>= 1) bits0++;
  758.     }
  759.     *bits = bits0;
  760.     return(val);
  761. }
  762.  
  763. //------------- jpc_put_kf ----------------
  764. // положить в файл один коэффициент (код Хаффмана и EXTRA-биты)
  765. int jpc_put_kf(struct jpc *s, struct jpc_alf *alf, int hcod, int val, int bits)
  766. {
  767.     if(alf[hcod].bits <=0){ s->err = JPC_ERR_CODE; return(-1);}
  768.     if(jpc_put_n_bits(alf[hcod].cod, alf[hcod].bits, s) < 0) return(-1);
  769.     if(bits > 0){
  770.         if(jpc_put_n_bits(val, bits, s) < 0) return(-1);
  771.     }
  772.     return(0);
  773. }
  774.  
  775. //------------------- jpc_coding_matr ----------------
  776. // кодирует и пишет в файл матрицу 8х8, на которую показывает p0
  777. int jpc_coding_matr(struct jpc *s, int *p0, int comp)
  778. {
  779.     struct jpc_alf *pDC, *pAC;
  780.     int zn, hcod, bits, val;
  781.     int *p1, *p2;
  782.  
  783.     if(comp==0){  // выбираем подходящий алфавит Хаффмана
  784.         pDC = s->alf;
  785.         pAC = s->alf + 512;
  786.     }
  787.     else{
  788.         pDC = s->alf + 256;
  789.         pAC = s->alf + 768;
  790.     }
  791.  
  792.     // обработка DC коэффициента
  793.     if(*p0 == 0){  // DC=0 кодируется нулевым кодом Хаффмана
  794.         if(jpc_put_kf(s, pDC, 0, 0, 0) < 0) return(-1);
  795.     }
  796.     else{
  797.         val = conv_kf(*p0, &bits, 2047);
  798.         hcod = bits;
  799.         if(jpc_put_kf(s, pDC, hcod, val, bits) < 0) return(-1);
  800.     }
  801.     // обработка AC коэффициентов
  802.     for(zn=0, p1=p0+1, p2=p0+64; p1<p2; p1++){
  803.         if(*p1 != 0){
  804.             val = conv_kf(*p1, &bits, 1023);
  805.             while(zn >= 16){
  806.                 if(jpc_put_kf(s, pAC, 0xF0, 0, 0) < 0) return(-1);
  807.                 zn -= 16;
  808.             }
  809.             hcod = (zn << 4) | bits;
  810.             if(jpc_put_kf(s, pAC, hcod, val, bits) < 0) return(-1);
  811.             zn = 0;
  812.         }
  813.         else zn++;
  814.     }
  815.     if(zn != 0){
  816.         if(jpc_put_kf(s, pAC, 0, 0, 0) < 0) return(-1);
  817.     }
  818.     return(0);
  819. }
  820.  
  821. //------------------- jpc_coding_blok ----------------
  822. // кодирует и пишет в файл один макроблок
  823. int jpc_coding_blok(struct jpc *s)
  824. {
  825.     int i;
  826.     for(i=0; i<4; i++){
  827.         if(jpc_coding_matr(s, s->comp[0].matr + i*64, 0) < 0) return(-1);
  828.     }
  829.     if(jpc_coding_matr(s, s->comp[1].matr, 1) < 0) return(-1);
  830.     if(jpc_coding_matr(s, s->comp[2].matr, 2) < 0) return(-1);
  831.     return(0);
  832. }
  833.  
  834. //----------------- jpc_scan ------------
  835.  
  836. int jpc_scan(struct jpc *s, const char *in)
  837. {
  838.     const char *pin; // pin -показывает место верхнего левого пикселя
  839.                      // текущего макроблока во входном буфере
  840.     const char *pin0; // начало текущей полосы макроблоков
  841.     int x, y; // счетчики макроблоков по горизонтали и по вертикали
  842.     int xss, yss; // размер рабочей части текущего макроблока
  843.     int xm; // ширина рисунка в макроблоках
  844.     int ym; // высота рисунка в макроблоках
  845.     int xs; // рабочий кусок правых макроблоков
  846.     int ys; // рабочий кусок нижних макроблоков
  847.  
  848.     xm = (s->w + s->xblok - 1)/s->xblok;
  849.     ym = (s->h + s->yblok - 1)/s->yblok;
  850.     xs =  s->xblok - (xm * s->xblok - s->w);
  851.     ys =  s->yblok - (ym * s->yblok - s->h);
  852.     yss = s->yblok;
  853.     pin = pin0 = in;
  854.  
  855.     for(y=0; y<ym; y++){
  856.         if(y>0) pin = pin0 = pin0 + 3 * s->w * s->yblok;
  857.         if(y>=(ym-1)) yss = ys;
  858.         xss = s->xblok;
  859.         for(x=0; x<xm; x++){
  860.             if(x>0) pin += s->xblok * 3;
  861.             if(x>=(xm-1)) xss = xs;
  862.             jpc_get_blok(s, xss, yss, pin);
  863.             jpc_red_blok(s);
  864.             jpc_dct_blok(s);
  865.             jpc_qnt_blok(s);
  866.             if(jpc_coding_blok(s) < 0) return(-1);
  867.         }
  868.     }
  869.     return(0);
  870. }
  871.  
  872. //----------------------- jpc_hdr_jpg -----------------------
  873. // заголовок JPEG-файла
  874. int jpc_hdr_jpg(struct jpc *s)
  875. {
  876.     char buf[2];
  877.     unsigned char aC0[]={  //  общая часть (C0)
  878.                       //             |  высота  |   ширина  |
  879.         0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00,
  880.         0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01
  881.     };
  882.     const unsigned char aDA[]={  // скан (DA)
  883.         0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02,
  884.         0x11, 0x03, 0x11, 0x00, 0x3F, 0x00
  885.     };
  886.     const unsigned char aD8[]={0xFF, 0xD8};
  887.     const unsigned char aDB[]={0xFF, 0xDB, 0x00, 0x43};
  888.     const unsigned char aC4[]={0xFF, 0xC4};
  889.     int i, dl;
  890.  
  891.     if(s->jpc_fwrite((char*)aD8, 2, 1, s) < 0) return(-1);  //         (D8)
  892.     for(i=0; i < 2; i++){  // таблицы квантования                      (DB)
  893.         if(s->jpc_fwrite((char*)aDB, 4, 1, s) < 0) return(-1);
  894.         buf[0]=i;
  895.         if(s->jpc_fwrite(buf, 1, 1, s) < 0) return(-1);
  896.         if(s->jpc_fwrite(s->qmatr + 64*i, 64, 1, s) < 0) return(-1);
  897.     }
  898.  
  899.     aC0[5] = s->h >> 8; aC0[6] = s->h & 255;
  900.     aC0[7] = s->w >> 8; aC0[8] = s->w & 255;
  901.     if(s->jpc_fwrite((char*)aC0, sizeof(aC0), 1, s) < 0) return(-1); //(C0)
  902.  
  903.     for(i=0; i < 4; i++){  // таблицы Хаффмана                         (C4)
  904.         if(s->jpc_fwrite((char*)aC4, 2, 1, s) < 0) return(-1);
  905.         dl = 3 + 16 + s->dla[i];  // длина блока
  906.         buf[0]= dl>>8;
  907.         buf[1]= dl&255;
  908.         if(s->jpc_fwrite(buf, 2, 1, s) < 0) return(-1);
  909.         buf[0] = ((i<<3) & 16) + (i & 1); //класс и идентификатор
  910.         if(s->jpc_fwrite(buf, 1, 1, s) < 0) return(-1);
  911.         // длины и символы
  912.         if(s->jpc_fwrite(s->hfmtab[i], dl-3, 1, s) < 0) return(-1);
  913.     }
  914.  
  915.     if(s->jpc_fwrite((char*)aDA, sizeof(aDA), 1, s) < 0) return(-1); //(DA)
  916.     return(0);
  917. }
  918.  
  919. //------------------- jpc_fun_coder ------------------------
  920.  
  921. int jpc_fun_coder(struct jpc *s, const char *in)
  922. {
  923.     const unsigned char aD9[]={0xFF, 0xD9};
  924.  
  925.     jpc_get_qmatr(s); // таблицы квантования
  926.     if(jpc_set_hfm(s) < 0) return(-1); // таблицы Хаффмана
  927.     if(jpc_hdr_jpg(s) < 0) return(-1);
  928.  
  929.     if(jpc_scan(s, in) < 0) return(-1);
  930.     if(jpc_flush_bits(s) < 0) return(-1);
  931.     if(s->jpc_fwrite((char*)aD9, 2, 1, s) < 0) return(-1);
  932.     return(0);
  933. }
  934.  
  935. //-------------- jpc_init_jpc ------------------
  936.  
  937. void jpc_init_jpc(struct jpc *s, int w, int h, int q)
  938. {
  939.     memset(s, 0, sizeof(struct jpc));
  940.     s->w = w;
  941.     s->h = h;
  942.     s->xblok = 16;    // пикселей на макроблок по горизонтали
  943.     s->yblok = 16;    // пикселей на макроблок по вертикали
  944.     s->comp[0].n = 4; // матриц на макроблок для Y
  945.     s->comp[1].n = 1; // матриц на макроблок для Cb
  946.     s->comp[2].n = 1; // матриц на макроблок для Cr
  947.     s->quality = q;   //
  948.     return;
  949. }
  950.  
  951. //------------------ jpg_coder_q --------------------------
  952. // q -качество рисунка, от 1 до 5. Самое лучшее 5. Типичное 3.
  953. int jpg_coder_q(char *buf, int Sbuf, const char *in, int w, int h, int *err,
  954.                 int q)
  955. {
  956.     struct jpc *s = NULL;
  957.     int k, err0;
  958.  
  959.     if(buf==NULL || Sbuf<0 || in==NULL || w<1 || w>32767 || h<1 || h>32767 ||
  960.         q < 1 || q > 5 || (INT_MAX / 4 / (int)sizeof(short) / w) < h)
  961.     {
  962.         err0 = JPC_ERR_INVAL; goto ERR;
  963.     }
  964.  
  965.     s = (struct jpc*)malloc(sizeof(struct jpc));
  966.     if(s==NULL){ err0 = JPC_ERR_MEMORY; goto ERR;}
  967.  
  968.     // инициализация структуры jpc
  969.     jpc_init_jpc(s, w, h, q);
  970.  
  971.     s->pf0 = s->pf1 = buf; // на начало выходного буфера
  972.     s->pf2 = buf + Sbuf;   // за край выходного буфера
  973.     s->jpc_fputc  = jpc_putc_buf;
  974.     s->jpc_fwrite = jpc_fwrite_buf;
  975.  
  976.     k=jpc_fun_coder(s, in);
  977.     if(k<0){ err0 = s->err; goto ERR;}
  978.     k = s->pf1 - s->pf0; // длина файла в буфере buf
  979.     free(s);
  980.     if(err != NULL) *err=0;
  981.     return(k);
  982.  
  983. ERR:
  984.     if(s != NULL) free(s);
  985.     if(err != NULL) *err = err0;
  986.     return(-1);
  987. }
  988.  
  989. //------------------ jpg_coder --------------------------
  990.  
  991. int jpg_coder(char *buf, int Sbuf, const char *in, int w, int h, int *err)
  992. {
  993.     return(jpg_coder_q(buf, Sbuf, in, w, h, err, 3));
  994. }
  995.  
  996. //------------------ jpg_coder_q_fp --------------------------
  997. // q -качество рисунка, от 1 до 5. Самое лучшее 5. Типичное 3.
  998. int jpg_coder_q_fp(FILE *fp, const char *in, int w, int h, int *err, int q)
  999. {
  1000.     struct jpc *s = NULL;
  1001.     int k, err0;
  1002.  
  1003.     if(fp==NULL || in==NULL || w<1 || w>32767 || h<1 || h>32767 ||
  1004.         q < 1 || q > 5 || (INT_MAX / 4 / (int)sizeof(short) / w) < h)
  1005.     {
  1006.         err0 = JPC_ERR_INVAL; goto ERR;
  1007.     }
  1008.  
  1009.     s = (struct jpc*)malloc(sizeof(struct jpc));
  1010.     if(s==NULL){ err0 = JPC_ERR_MEMORY; goto ERR;}
  1011.  
  1012.     // инициализация структуры jpc
  1013.     jpc_init_jpc(s, w, h, q);
  1014.  
  1015.     s->fp = fp; // выходной файл
  1016.     s->jpc_fputc  = jpc_putc_fp;
  1017.     s->jpc_fwrite = jpc_fwrite_fp;
  1018.  
  1019.     k=jpc_fun_coder(s, in);
  1020.     if(k<0){ err0 = s->err; goto ERR;}
  1021.     k = s->sizefile; // длина JPEG-файла
  1022.     free(s);
  1023.     if(err != NULL) *err=0;
  1024.     return(k);
  1025.  
  1026. ERR:
  1027.     if(s != NULL) free(s);
  1028.     if(err != NULL) *err = err0;
  1029.     return(-1);
  1030. }
  1031.  
  1032. //------------------ jpg_coder_fp --------------------------
  1033.  
  1034. int jpg_coder_fp(FILE *fp, const char *in, int w, int h, int *err)
  1035. {
  1036.     return(jpg_coder_q_fp(fp, in, w, h, err, 3));
  1037. }
  1038.  
  1039. //------------------ jpc_strerror ---------------------
  1040.  
  1041. const char *jpc_strerror(int err)
  1042. {
  1043.     switch(err){
  1044.         case  JPC_ERR_WR_FILE     : return("JPC_ERR_WR_FILE");
  1045.         case  JPC_ERR_MEMORY      : return("JPC_ERR_MEMORY");
  1046.         case  JPC_ERR_CODE        : return("JPC_ERR_CODE");
  1047.         case  JPC_ERR_INVAL       : return("JPC_ERR_INVAL");
  1048.     }
  1049.     return("JPC: Unknow error");
  1050. }
  1051.  
  1052.  
  1053.  
  1054. //============= Тестовая обертка ====================
  1055.  
  1056.  
  1057. // Положить 24-битный BMP-файл "in.bmp" и запустить программу без аргументов.
  1058. // Или указать как аргумент имя какого-нибудь 24-битного BMP-файла. После
  1059. // работы программы должны получиться JPEG-файлы "out.jpg" и "opt_out.jpg".
  1060. // Вторым аргументом можно указать качество рисунка от 1 до 5.
  1061.  
  1062. #include <sys/time.h>
  1063. #include "jpg_opt.c"
  1064.  
  1065. //------------------ rd_bmp_24_RGB ------------------
  1066.  
  1067. char *rd_bmp_24_RGB(FILE *fp1, int *w, int *h)
  1068. {
  1069.     unsigned char buf[54];
  1070.     char *pic=NULL, *p1;
  1071.     int i, j, r, g, b, w1, w3, h1, pad=0, uk;
  1072.  
  1073.     if(fread(buf, 54, 1, fp1) != 1) goto ERR;
  1074.     if(memcmp(buf, "BM", 2)!=0) goto ERR;
  1075.     if(memcmp(buf+30, "\0\0\0\0", 4)!=0) goto ERR;
  1076.     if(memcmp(buf+28, "\x18\0", 2)!=0) goto ERR;
  1077.     w1 = buf[18] + (buf[19]<<8) + (buf[20]<<16) + (buf[21]<<24);
  1078.     h1 = buf[22] + (buf[23]<<8) + (buf[24]<<16) + (buf[25]<<24);
  1079.     uk = buf[10] + (buf[11]<<8) + (buf[12]<<16) + (buf[13]<<24);
  1080.     if(fseek(fp1, uk, 0) < 0) goto ERR;
  1081.     *w=w1; *h=h1;
  1082.     w3=w1*3;
  1083.     if(w3 & 3) pad = 4 - (w3 & 3);
  1084.  
  1085.     pic=(char*)malloc(w3*h1);
  1086.     if(pic==NULL) goto ERR;
  1087.     p1=pic + w3*h1;
  1088.     for(i=0; i<h1; i++){
  1089.         p1 -= w3;
  1090.         for(j=0; j<w1; j++){
  1091.             if((b = fgetc(fp1)) < 0) goto ERR;
  1092.             if((g = fgetc(fp1)) < 0) goto ERR;
  1093.             if((r = fgetc(fp1)) < 0) goto ERR;
  1094.             *p1++ = r; *p1++ = g; *p1++ = b;
  1095.         }
  1096.         p1 -= w3;
  1097.         if(pad>0) if(fread(buf, pad, 1, fp1) != 1) goto ERR;
  1098.     }
  1099.     return(pic);
  1100.  
  1101. ERR:
  1102.     if(pic != NULL) free(pic);
  1103.     *w=0; *h=0;
  1104.     return(NULL);
  1105. }
  1106.  
  1107. //------------------- gettime_dt_mks ----------------------
  1108. // разность двух временных меток в миллисекундах
  1109. int gettime_dt_msek(struct timeval *tv1, struct timeval *tv2)
  1110. {
  1111.     return((tv2->tv_sec - tv1->tv_sec)*1000 +
  1112.            (tv2->tv_usec - tv1->tv_usec + 500)/1000);
  1113. }
  1114.  
  1115. //--------------- main -----------------
  1116.  
  1117. int main(int argc, char const **argv)
  1118. {
  1119.     FILE *fp1=NULL, *fp2=NULL, *fp3=NULL;
  1120.     const char *f1;
  1121.     const char *f2="out.jpg";
  1122.     const char *f3="opt_out.jpg";
  1123.     int k, dl1, dl2, t, quality;
  1124.     int w, h, err;
  1125.     char *buf=NULL, *pic=NULL;
  1126.     int Sbuf;
  1127.     struct timeval tv1, tv2;
  1128.  
  1129.     printf("============================\n");
  1130.  
  1131.     if(argc<=1) f1 = "in.bmp";
  1132.     else f1 = argv[1];
  1133.     if(argc > 2) quality = atoi(argv[2]);
  1134.     else quality=3;
  1135.  
  1136.     fp1=fopen(f1, "r");
  1137.     if(fp1==NULL){ printf("fp1=fopen(%s)=NULL\n", f1); goto ERR;}
  1138.  
  1139.     // чтение BMP-файла
  1140.     pic = rd_bmp_24_RGB(fp1, &w, &h);
  1141.     if(pic==NULL){ printf("pic = rd_bmp_24_RGB(%s)=NULL\n", f1); goto ERR;}
  1142.     fclose(fp1); fp1=NULL;
  1143.  
  1144.     // буфер для JPEG-файла
  1145.     Sbuf = w*h + 1000;
  1146.     buf = (char*)malloc(Sbuf);
  1147.     if(buf==NULL){ printf("buf=NULL\n"); goto ERR;}
  1148.  
  1149.     // JPEG-кодирование
  1150.     gettimeofday(&tv1, NULL);
  1151.     dl1 = jpg_coder_q(buf, Sbuf, pic, w, h, &err, quality);
  1152.     printf("dl1=jpg_coder_q()=%d; err=%d", dl1, err);
  1153.     gettimeofday(&tv2, NULL);
  1154.     t = gettime_dt_msek(&tv1, &tv2);
  1155.     if(dl1<0) printf("; %s", jpc_strerror(err));
  1156.     printf("\n");
  1157.     printf("w=%d; h=%d\n", w, h);
  1158.     printf("t=%d.%03d sec\n", t/1000, t%1000);
  1159.     if(dl1>0 && (w*h)>0) printf("Compress=%0.2f %%\n", 100.0 * dl1 / (w*h*3));
  1160.     else goto ERR;
  1161.     free(pic); pic=NULL;
  1162.  
  1163.     // запись неоптимизированного файла
  1164.     fp2=fopen(f2, "w");
  1165.     if(fp2==NULL){ printf("fp2=fopen(%s)=NULL\n", f2); goto ERR;}
  1166.     k = fwrite(buf, 1, dl1, fp2);
  1167.     if(k != dl1){ printf("k = fwrite()=%d; dl1=%d\n", k, dl1); goto ERR;}
  1168.     fclose(fp2); fp2=NULL;
  1169.  
  1170.     //exit(0);
  1171.  
  1172.     // оптимизация
  1173.     printf("-------------\n");
  1174.     fp3=fopen(f3, "w");
  1175.     if(fp3==NULL){ printf("fp3=fopen(%s)=NULL\n", f3); goto ERR;}
  1176.  
  1177.     gettimeofday(&tv1, NULL);
  1178.     dl2 = fjp_opt_hfm(buf, dl1, fp3, &w, &h, &err); // оптимизация
  1179.     gettimeofday(&tv2, NULL);
  1180.     t = gettime_dt_msek(&tv1, &tv2);
  1181.  
  1182.     printf("-------------\n");
  1183.     printf("dl2 = fjp_opt_hfm()=%d; err=%d; ", dl2, err);
  1184.     printf("%s\n", err==0 ? "" : fjp_strerror(err));
  1185.     printf("w=%d; h=%d\n", w, h);
  1186.     printf("t=%d.%03d sec\n", t/1000, t%1000);
  1187.     printf("dl1=%d\n", dl1);
  1188.     printf("dl2=%d\n", dl2);
  1189.  
  1190.     printf("n1_FF=%d\n", n1_FF);
  1191.     printf("n2_FF=%d\n", n2_FF);
  1192.     printf("delta_FF=%d\n", n1_FF - n2_FF);
  1193.     printf("d1_DA=%d\n", e1_DA - b1_DA);
  1194.     printf("d2_DA=%d\n", e2_DA - b2_DA);
  1195.     printf("delta_DA=%d\n", (e1_DA - b1_DA) - (e2_DA - b2_DA));
  1196.     printf("delta_C4=%d\n", d1_C4 - d2_C4);
  1197.  
  1198.     printf("delta_dl=%d\n", dl1 - dl2);
  1199.     if(dl1>0 && dl2>0){
  1200.         printf("Compress=%0.2f\n", 100.0 * dl2 / dl1);
  1201.     }
  1202.     free(buf);
  1203.     fclose(fp3);
  1204.     printf("============================\n");
  1205.     exit(0);
  1206.  
  1207. ERR:
  1208.     if(pic!=NULL) free(pic);
  1209.     if(buf!=NULL) free(buf);
  1210.     if(fp1!=NULL) fclose(fp1);
  1211.     if(fp2!=NULL) fclose(fp2);
  1212.     if(fp3!=NULL) fclose(fp3);
  1213.     printf("============================\n");
  1214.     exit(0);
  1215. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement