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 */
init_buffer(jpeg_compress_struct *)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 */
empty_buffer(jpeg_compress_struct *)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 */
term_buffer(jpeg_compress_struct *)47 static void term_buffer(jpeg_compress_struct *) {
48 }
49
50 GLOBAL(void)
write_JPEG_Buff(ubyte * buffPtr,int quality,int image_width,int image_height,JSAMPLE * imageBuffer,int resolution,colorSpaceDisposition destCS,int * numCompBytes)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 .err = jpeg_std_error(&jerr),
58 .client_data = NULL,
59 };
60
61 // Now we can initialize the JPEG compression object.
62 jpeg_create_compress(&cinfo);
63
64 // Step 2: specify data destination (we will use a memory buffer)
65 struct jpeg_destination_mgr dm = {
66 .next_output_byte = buffPtr,
67 .free_in_buffer = (size_t) image_width * image_height * 3,
68 .init_destination = init_buffer, .empty_output_buffer = empty_buffer,
69 .term_destination = term_buffer,
70 };
71 cinfo.dest = &dm;
72
73 // Step 3: set parameters for compression
74
75 cinfo.image_width = (JDIMENSION) image_width;
76 cinfo.image_height = (JDIMENSION) image_height;
77 if (destCS == deviceRGB || destCS == adobeRGB) {
78 cinfo.in_color_space = JCS_RGB;
79 cinfo.jpeg_color_space = JCS_RGB;
80 cinfo.input_components = 3;
81 } else {
82 cinfo.in_color_space = JCS_GRAYSCALE;
83 cinfo.jpeg_color_space = JCS_GRAYSCALE;
84 cinfo.input_components = 1;
85 }
86
87 jpeg_set_defaults(&cinfo);
88
89 /* Now you can set any non-default parameters you wish to.
90 * Here we just illustrate the use of quality (quantization table) scaling:
91 */
92 jpeg_set_quality(&cinfo, quality, TRUE); // TRUE = limit to baseline-JPEG values
93
94 // Set the density so that the JFIF header has the correct settings
95 cinfo.density_unit = 1; // 1=dots-per-inch, 2=dots per cm
96 cinfo.X_density = (UINT16) resolution;
97 cinfo.Y_density = (UINT16) resolution;
98
99 // set the rows/columns setting to reflect the resolution
100 // MCU = Minimum Coded Unit
101 cinfo.MCUs_per_row = (JDIMENSION) image_width;
102 cinfo.MCU_rows_in_scan = (JDIMENSION) image_height;
103
104 // Step 4: Start compressor
105 jpeg_start_compress(&cinfo, TRUE);
106
107 // Step 5: Write scanlines
108
109 int row_stride; // physical row width in image buffer
110 row_stride = image_width * cinfo.input_components; // JSAMPLEs per row in imageBuffer
111
112 JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
113 while (cinfo.next_scanline < cinfo.image_height) {
114 row_pointer[0] = &imageBuffer[cinfo.next_scanline * row_stride];
115 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
116 }
117
118 // Step 6: Finish compression
119
120 jpeg_finish_compress(&cinfo);
121
122 // Step 7: release JPEG compression object
123
124 jpeg_destroy_compress(&cinfo);
125
126 *numCompBytes = (int) (cinfo.dest->next_output_byte - buffPtr);
127
128 LOGD("write_JPEG_Buff: w=%d, h=%d, r=%d, q=%d compressed to %d", image_width, image_height,
129 resolution, quality, *numCompBytes);
130 }
131