Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  * Copyright (C) 2016 Mopria Alliance, Inc.
      4  * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *      http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 
     19 #include <stdio.h>
     20 #include "common_defines.h"
     21 #include <wprint_debug.h>
     22 
     23 extern "C"
     24 {
     25 #include <jpeglib.h>
     26 }
     27 
     28 #define TAG "genJPEGStrips"
     29 
     30 /*
     31  * Function for setting up the buffer (which we already did)
     32  */
     33 static void init_buffer(jpeg_compress_struct *) {
     34 }
     35 
     36 /*
     37  * Function for handling buffer overlow (should not happen because we allocated a large
     38  * buffer)
     39  */
     40 static boolean empty_buffer(jpeg_compress_struct *) {
     41     return TRUE;
     42 }
     43 
     44 /*
     45  * Function for finalizing the buffer (which we do not need to do)
     46  */
     47 static void term_buffer(jpeg_compress_struct *) {
     48 }
     49 
     50 GLOBAL(void)
     51 write_JPEG_Buff(ubyte *buffPtr, int quality, int image_width, int image_height,
     52         JSAMPLE *imageBuffer, int resolution, colorSpaceDisposition destCS, int *numCompBytes) {
     53     struct jpeg_error_mgr jerr;
     54 
     55     // Step 1: allocate and initialize JPEG compression object
     56     struct jpeg_compress_struct cinfo = {
     57             .client_data = NULL, .err = jpeg_std_error(&jerr)
     58     };
     59 
     60     // Now we can initialize the JPEG compression object.
     61     jpeg_create_compress(&cinfo);
     62 
     63     // Step 2: specify data destination (we will use a memory buffer)
     64     struct jpeg_destination_mgr dm = {
     65             .init_destination = init_buffer, .empty_output_buffer = empty_buffer,
     66             .term_destination = term_buffer, .next_output_byte = buffPtr,
     67             .free_in_buffer = (size_t) image_width * image_height * 3
     68     };
     69     cinfo.dest = &dm;
     70 
     71     // Step 3: set parameters for compression
     72 
     73     cinfo.image_width = (JDIMENSION) image_width;
     74     cinfo.image_height = (JDIMENSION) image_height;
     75     if (destCS == deviceRGB || destCS == adobeRGB) {
     76         cinfo.in_color_space = JCS_RGB;
     77         cinfo.jpeg_color_space = JCS_RGB;
     78         cinfo.input_components = 3;
     79     } else {
     80         cinfo.in_color_space = JCS_GRAYSCALE;
     81         cinfo.jpeg_color_space = JCS_GRAYSCALE;
     82         cinfo.input_components = 1;
     83     }
     84 
     85     jpeg_set_defaults(&cinfo);
     86 
     87     /* Now you can set any non-default parameters you wish to.
     88      * Here we just illustrate the use of quality (quantization table) scaling:
     89      */
     90     jpeg_set_quality(&cinfo, quality, TRUE); // TRUE = limit to baseline-JPEG values
     91 
     92     // Set the density so that the JFIF header has the correct settings
     93     cinfo.density_unit = 1;      // 1=dots-per-inch, 2=dots per cm
     94     cinfo.X_density = (UINT16) resolution;
     95     cinfo.Y_density = (UINT16) resolution;
     96 
     97     // set the rows/columns setting to reflect the resolution
     98     // MCU = Minimum Coded Unit
     99     cinfo.MCUs_per_row = (JDIMENSION) image_width;
    100     cinfo.MCU_rows_in_scan = (JDIMENSION) image_height;
    101 
    102     // Step 4: Start compressor
    103     jpeg_start_compress(&cinfo, TRUE);
    104 
    105     // Step 5: Write scanlines
    106 
    107     int row_stride; // physical row width in image buffer
    108     row_stride = image_width * cinfo.input_components; // JSAMPLEs per row in imageBuffer
    109 
    110     JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
    111     while (cinfo.next_scanline < cinfo.image_height) {
    112         row_pointer[0] = &imageBuffer[cinfo.next_scanline * row_stride];
    113         (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
    114     }
    115 
    116     // Step 6: Finish compression
    117 
    118     jpeg_finish_compress(&cinfo);
    119 
    120     // Step 7: release JPEG compression object
    121 
    122     jpeg_destroy_compress(&cinfo);
    123 
    124     *numCompBytes = (int) (cinfo.dest->next_output_byte - buffPtr);
    125 
    126     LOGD("write_JPEG_Buff: w=%d, h=%d, r=%d, q=%d compressed to %d", image_width, image_height,
    127             resolution, quality, *numCompBytes);
    128 }